TokenHandler
createTokenHandler est le coeur de la librairie. Là où beaucoup de bibliothèques exposent surtout des fonctions utilitaires à assembler, ici l'idée est inverse : on commence par créer un handler qui porte déjà la politique de gestion du token.
Ce handler regroupe au même endroit :
- la signature ;
- le chiffrement ;
- la durée de vie du token ;
- la gestions des claims (header/payload) ;
Autrement dit, le but est de construire un contrat clair que l'on peut réutiliser.
Création au démarrage
createTokenHandler est pensé pour être appelé au démarrage d'une l'application. La configuration est validée immédiatement, et une configuration invalide provoque un throw dès la création du handler.
Exemple simple
import { D, DPE } from "@duplojs/utils";
import { Signer, createTokenHandler } from "@duplojs/json-web-token";
const tokenHandler = createTokenHandler({
maxAge: D.createTime(15, "minute"),
signer: Signer.createHS256({ secret: "my-secret" }),
issuer: "my-app",
audience: ["web"],
customPayloadShape: {
userId: DPE.string(),
},
});
const token = await tokenHandler.createOrThrow({
userId: "1",
});
// send to client ...
const verifiedToken = await tokenHandler.verify("receive-token");Ce qui se passe ici
Au moment du create, le handler ajoute lui-même les claims standards comme iat et exp, puis signe le contenu.
Au moment du verify, il redécode le token, vérifie la signature, puis applique les contrôles de configuration comme l'expiration, l'issuer, le subject ou l'audience.
create ou createOrThrow
create retourne un Left si la création échoue.createOrThrow fait la même chose, mais lève une erreur si la création échoue. C'est utile si tu préfères un flux orienté exception à un flux orienté Either.
Paramètres
interface TokenHandlerParams {
maxAge: D.TheTime;
signer: Signer<string> | CreateSigner<string, unknown>;
cipher?: Cipher<string> | CreateCipher<string, unknown>;
issuer?: string;
subject?: string;
audience?: string | string[];
now?: () => D.TheDate;
customPayloadShape: DP.DataParserObjectShape;
customHeaderShape?: DP.DataParserObjectShape;
};Le handler retourné expose ensuite quatre méthodes :
createcreateOrThrowverifydecode
Exemple avec custom shapes
import { asserts, D, DPE } from "@duplojs/utils";
import { Signer, createTokenHandler } from "@duplojs/json-web-token";
const tokenHandler = createTokenHandler({
maxAge: D.createTime(1, "hour"),
signer: Signer.createHS256({ secret: "my-secret" }),
issuer: "admin-app",
customPayloadShape: {
userId: DPE.string(),
role: DPE.literal("admin"),
},
customHeaderShape: {
kid: DPE.string().optional(),
},
});
const token = await tokenHandler.create(
{
userId: "42",
role: "admin",
},
{
header: {
kid: "main",
},
},
);
// send to client ...
const decodedToken = await tokenHandler.decode("receive-token");Ce qui se passe ici
customPayloadShape et customHeaderShape définissent ce que ton application a le droit de mettre dans le token.
Les clés réservées du JWT, comme exp, iat, iss, sub, aud, typ ou alg, restent gérées par le handler lui-même.
Exemple avec des "creators"
import { D, DPE } from "@duplojs/utils";
import { Cipher, Signer, createTokenHandler } from "@duplojs/json-web-token";
const tokenHandler = createTokenHandler({
maxAge: D.createTime(10, "minute"),
signer: Signer.createHS256,
cipher: Cipher.createRSAOAEP,
customPayloadShape: {
userId: DPE.string(),
},
});
const token = await tokenHandler.create(
{
userId: "1",
},
{
signer: {
secret: "my-secret",
},
cipher: {
privateKey: "private-key",
publicKey: "public-key",
},
},
);
// send to client ...
const verifiedToken = await tokenHandler.verify("receive-token", {
signer: {
secret: "my-secret",
},
cipher: {
privateKey: "private-key",
publicKey: "public-key",
},
});Ce qui se passe ici
Quand tu passes un CreateSigner ou un CreateCipher au lieu d'une instance déjà configurée, les paramètres sont déplacés vers create, createOrThrow, verify et decode.
Cela permet de créer le handler une seule fois, tout en injectant plus tard les secrets, les clés ou d'autres paramètres nécessaires.
