import { create, decode, verify } from "../djwt.js"; import { importJWK, importJWKFromString } from "./keys.ts"; export interface JwtPayload { [key: string]: any; iss?: string | undefined; sub?: string | undefined; aud?: string | string[] | undefined; exp?: number | undefined; nbf?: number | undefined; iat?: number | undefined; jti?: string | undefined; scopes?: string[] | undefined; } export interface JwtIssuerKeyPair { public: string | JsonWebKey; private: string | JsonWebKey; } export type JwtPayloadWithClaims< TClaims extends Record = Record, > = JwtPayload & TClaims; export interface JwtVerifier { verify: = Record>( jwt: string, ) => Promise>; decode: = Record>( jwt: string, ) => JwtPayloadWithClaims; } export interface JwtIssuer extends JwtVerifier { issue: = Record>( payload: JwtPayloadWithClaims, ) => Promise; } export const newJwtVerifier = (key: CryptoKey): JwtVerifier => { return { verify: (str: string) => { return verify(str, key); }, decode: (str: string) => { return decode(str); }, }; }; export const newJwtVerifierWithJWK = async ( pubKey: string | JsonWebKey, ): Promise => { const pub = await importKey( pubKey, ["verify"], ); return newJwtVerifier(pub); }; const importKey = ( key: string | JsonWebKey, usages: string[], ): Promise => { if (typeof key === "string") { return importJWKFromString(key, usages); } return importJWK(key, usages); }; export const newJwtIssuer = async ( { private: privkey, public: pubkey }: JwtIssuerKeyPair, issuer?: string, ): Promise => { const [verifier, priv] = await Promise.all([ newJwtVerifierWithJWK(pubkey), importKey(privkey, ["sign"]), ]); return { ...verifier, issue: (payload) => { return create({ alg: "RS256", typ: "JWT" }, { ...payload, issuer }, priv); }, }; };