better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 6.34 kB
Source Map (JSON)
{"version":3,"file":"sign.mjs","names":[],"sources":["../../../src/plugins/jwt/sign.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport type { JWTPayload } from \"jose\";\nimport { importJWK, SignJWT } from \"jose\";\nimport { symmetricDecrypt } from \"../../crypto\";\nimport { getJwksAdapter } from \"./adapter\";\nimport type { JwtOptions } from \"./types\";\nimport { createJwk, toExpJWT } from \"./utils\";\n\ntype JWTPayloadWithOptional = {\n\t/**\n\t * JWT Issuer\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.1 RFC7519#section-4.1.1}\n\t */\n\tiss?: string | undefined;\n\n\t/**\n\t * JWT Subject\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.2 RFC7519#section-4.1.2}\n\t */\n\tsub?: string | undefined;\n\n\t/**\n\t * JWT Audience\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.3 RFC7519#section-4.1.3}\n\t */\n\taud?: string | string[] | undefined;\n\n\t/**\n\t * JWT ID\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7 RFC7519#section-4.1.7}\n\t */\n\tjti?: string | undefined;\n\n\t/**\n\t * JWT Not Before\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.5 RFC7519#section-4.1.5}\n\t */\n\tnbf?: number | undefined;\n\n\t/**\n\t * JWT Expiration Time\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4 RFC7519#section-4.1.4}\n\t */\n\texp?: number | undefined;\n\n\t/**\n\t * JWT Issued At\n\t *\n\t * @see {@link https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6 RFC7519#section-4.1.6}\n\t */\n\tiat?: number | undefined;\n\n\t/** Any other JWT Claim Set member. */\n\t[propName: string]: unknown | undefined;\n};\n\nexport async function signJWT(\n\tctx: GenericEndpointContext,\n\tconfig: {\n\t\toptions?: JwtOptions | undefined;\n\t\tpayload: JWTPayloadWithOptional;\n\t},\n) {\n\tconst { options } = config;\n\tconst payload = config.payload as JWTPayload;\n\n\t// Iat\n\tconst nowSeconds = Math.floor(Date.now() / 1000);\n\tconst iat = payload.iat!;\n\n\t// Exp\n\tlet exp = payload.exp;\n\tconst defaultExp = toExpJWT(\n\t\toptions?.jwt?.expirationTime ?? \"15m\",\n\t\tiat ?? nowSeconds,\n\t);\n\texp = exp ?? defaultExp;\n\n\t// Nbf\n\tconst nbf = payload.nbf!;\n\n\t// Iss\n\tconst iss = payload.iss;\n\tconst defaultIss = options?.jwt?.issuer ?? ctx.context.options.baseURL!;\n\n\t// Aud\n\tconst aud = payload.aud;\n\tconst defaultAud = options?.jwt?.audience ?? ctx.context.options.baseURL!;\n\n\t// Custom/remote signing function\n\tif (options?.jwt?.sign) {\n\t\tconst jwtPayload = {\n\t\t\t...payload,\n\t\t\tiat,\n\t\t\texp,\n\t\t\tnbf,\n\t\t\tiss: iss ?? defaultIss,\n\t\t\taud: aud ?? defaultAud,\n\t\t};\n\t\treturn options.jwt.sign(jwtPayload);\n\t}\n\n\tconst adapter = getJwksAdapter(ctx.context.adapter, options);\n\tlet key = await adapter.getLatestKey(ctx);\n\tif (!key || (key.expiresAt && key.expiresAt < new Date())) {\n\t\tkey = await createJwk(ctx, options);\n\t}\n\tconst privateKeyEncryptionEnabled =\n\t\t!options?.jwks?.disablePrivateKeyEncryption;\n\n\tlet privateWebKey = privateKeyEncryptionEnabled\n\t\t? await symmetricDecrypt({\n\t\t\t\tkey: ctx.context.secret,\n\t\t\t\tdata: JSON.parse(key.privateKey),\n\t\t\t}).catch(() => {\n\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\"Failed to decrypt private key. Make sure the secret currently in use is the same as the one used to encrypt the private key. If you are using a different secret, either clean up your JWKS or disable private key encryption.\",\n\t\t\t\t);\n\t\t\t})\n\t\t: key.privateKey;\n\tconst alg = key.alg ?? options?.jwks?.keyPairConfig?.alg ?? \"EdDSA\";\n\tconst privateKey = await importJWK(JSON.parse(privateWebKey), alg);\n\n\tconst jwt = new SignJWT(payload)\n\t\t.setProtectedHeader({\n\t\t\talg,\n\t\t\tkid: key.id,\n\t\t})\n\t\t.setExpirationTime(exp)\n\t\t.setIssuer(iss ?? defaultIss)\n\t\t.setAudience(aud ?? defaultAud);\n\tif (iat) jwt.setIssuedAt(iat);\n\tif (payload.sub) jwt.setSubject(payload.sub);\n\tif (payload.nbf) jwt.setNotBefore(payload.nbf);\n\tif (payload.jti) jwt.setJti(payload.jti);\n\treturn await jwt.sign(privateKey);\n}\n\nexport async function getJwtToken(\n\tctx: GenericEndpointContext,\n\toptions?: JwtOptions | undefined,\n) {\n\tconst payload = !options?.jwt?.definePayload\n\t\t? ctx.context.session!.user\n\t\t: await options.jwt.definePayload(ctx.context.session!);\n\n\treturn await signJWT(ctx, {\n\t\toptions,\n\t\tpayload: {\n\t\t\tiat: Math.floor(Date.now() / 1000),\n\t\t\t...payload,\n\t\t\tsub:\n\t\t\t\t(await options?.jwt?.getSubject?.(ctx.context.session!)) ??\n\t\t\t\tctx.context.session!.user.id,\n\t\t},\n\t});\n}\n"],"mappings":";;;;;;;AA+DA,eAAsB,QACrB,KACA,QAIC;CACD,MAAM,EAAE,YAAY;CACpB,MAAM,UAAU,OAAO;CAGvB,MAAM,aAAa,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;CAChD,MAAM,MAAM,QAAQ;CAGpB,IAAI,MAAM,QAAQ;CAClB,MAAM,aAAa,SAClB,SAAS,KAAK,kBAAkB,OAChC,OAAO,WACP;AACD,OAAM,OAAO;CAGb,MAAM,MAAM,QAAQ;CAGpB,MAAM,MAAM,QAAQ;CACpB,MAAM,aAAa,SAAS,KAAK,UAAU,IAAI,QAAQ,QAAQ;CAG/D,MAAM,MAAM,QAAQ;CACpB,MAAM,aAAa,SAAS,KAAK,YAAY,IAAI,QAAQ,QAAQ;AAGjE,KAAI,SAAS,KAAK,MAAM;EACvB,MAAM,aAAa;GAClB,GAAG;GACH;GACA;GACA;GACA,KAAK,OAAO;GACZ,KAAK,OAAO;GACZ;AACD,SAAO,QAAQ,IAAI,KAAK,WAAW;;CAIpC,IAAI,MAAM,MADM,eAAe,IAAI,QAAQ,SAAS,QAAQ,CACpC,aAAa,IAAI;AACzC,KAAI,CAAC,OAAQ,IAAI,aAAa,IAAI,4BAAY,IAAI,MAAM,CACvD,OAAM,MAAM,UAAU,KAAK,QAAQ;CAKpC,IAAI,gBAFH,CAAC,SAAS,MAAM,8BAGd,MAAM,iBAAiB;EACvB,KAAK,IAAI,QAAQ;EACjB,MAAM,KAAK,MAAM,IAAI,WAAW;EAChC,CAAC,CAAC,YAAY;AACd,QAAM,IAAI,gBACT,iOACA;GACA,GACD,IAAI;CACP,MAAM,MAAM,IAAI,OAAO,SAAS,MAAM,eAAe,OAAO;CAC5D,MAAM,aAAa,MAAM,UAAU,KAAK,MAAM,cAAc,EAAE,IAAI;CAElE,MAAM,MAAM,IAAI,QAAQ,QAAQ,CAC9B,mBAAmB;EACnB;EACA,KAAK,IAAI;EACT,CAAC,CACD,kBAAkB,IAAI,CACtB,UAAU,OAAO,WAAW,CAC5B,YAAY,OAAO,WAAW;AAChC,KAAI,IAAK,KAAI,YAAY,IAAI;AAC7B,KAAI,QAAQ,IAAK,KAAI,WAAW,QAAQ,IAAI;AAC5C,KAAI,QAAQ,IAAK,KAAI,aAAa,QAAQ,IAAI;AAC9C,KAAI,QAAQ,IAAK,KAAI,OAAO,QAAQ,IAAI;AACxC,QAAO,MAAM,IAAI,KAAK,WAAW;;AAGlC,eAAsB,YACrB,KACA,SACC;CACD,MAAM,UAAU,CAAC,SAAS,KAAK,gBAC5B,IAAI,QAAQ,QAAS,OACrB,MAAM,QAAQ,IAAI,cAAc,IAAI,QAAQ,QAAS;AAExD,QAAO,MAAM,QAAQ,KAAK;EACzB;EACA,SAAS;GACR,KAAK,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK;GAClC,GAAG;GACH,KACE,MAAM,SAAS,KAAK,aAAa,IAAI,QAAQ,QAAS,IACvD,IAAI,QAAQ,QAAS,KAAK;GAC3B;EACD,CAAC"}