UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

1 lines • 15.7 kB
{"version":3,"file":"index.mjs","names":["jwt","verifyJWTHelper"],"sources":["../../../src/plugins/jwt/index.ts"],"sourcesContent":["import type { BetterAuthPlugin } from \"@better-auth/core\";\nimport {\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n} from \"@better-auth/core/api\";\nimport { BetterAuthError } from \"@better-auth/core/error\";\nimport type { JSONWebKeySet, JWTPayload } from \"jose\";\nimport * as z from \"zod\";\nimport { APIError, sessionMiddleware } from \"../../api\";\nimport { mergeSchema } from \"../../db/schema\";\nimport { getJwksAdapter } from \"./adapter\";\nimport { schema } from \"./schema\";\nimport { getJwtToken, signJWT } from \"./sign\";\nimport type { JwtOptions } from \"./types\";\nimport { createJwk } from \"./utils\";\nimport { verifyJWT as verifyJWTHelper } from \"./verify\";\n\nexport { signJWT } from \"./sign\";\nexport type * from \"./types\";\nexport { createJwk, generateExportedKeyPair, toExpJWT } from \"./utils\";\nexport { verifyJWT } from \"./verify\";\n\nconst signJWTBodySchema = z.object({\n\tpayload: z.record(z.string(), z.any()),\n\toverrideOptions: z.record(z.string(), z.any()).optional(),\n});\n\nconst verifyJWTBodySchema = z.object({\n\ttoken: z.string(),\n\tissuer: z.string().optional(),\n});\n\nexport const jwt = <O extends JwtOptions>(options?: O) => {\n\t// Remote url must be set when using signing function\n\tif (options?.jwt?.sign && !options.jwks?.remoteUrl) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"jwks_config\",\n\t\t\t\"jwks.remoteUrl must be set when using jwt.sign\",\n\t\t);\n\t}\n\n\t// Alg is required to be specified when using remote url (needed in openid metadata)\n\tif (options?.jwks?.remoteUrl && !options.jwks?.keyPairConfig?.alg) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"jwks_config\",\n\t\t\t\"must specify alg when using the oidc plugin and jwks.remoteUrl\",\n\t\t);\n\t}\n\n\tconst jwksPath = options?.jwks?.jwksPath ?? \"/jwks\";\n\tif (\n\t\ttypeof jwksPath !== \"string\" ||\n\t\tjwksPath.length === 0 ||\n\t\t!jwksPath.startsWith(\"/\") ||\n\t\tjwksPath.includes(\"..\")\n\t) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"jwks_config\",\n\t\t\t\"jwksPath must be a non-empty string starting with '/' and not contain '..'\",\n\t\t);\n\t}\n\n\treturn {\n\t\tid: \"jwt\",\n\t\toptions: options as NoInfer<O>,\n\t\tendpoints: {\n\t\t\tgetJwks: createAuthEndpoint(\n\t\t\t\tjwksPath,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\toperationId: \"getJSONWebKeySet\",\n\t\t\t\t\t\t\tdescription: \"Get the JSON Web Key Set\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\t\t\tdescription: \"JSON Web Key Set retrieved successfully\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\tkeys: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription: \"Array of public JSON Web Keys\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Key ID uniquely identifying the key, corresponds to the 'id' from the stored Jwk\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tkty: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Key type (e.g., 'RSA', 'EC', 'OKP')\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\talg: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Algorithm intended for use with the key (e.g., 'EdDSA', 'RS256')\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuse: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Intended use of the public key (e.g., 'sig' for signature)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum: [\"sig\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tn: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Modulus for RSA keys (base64url-encoded)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\te: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Exponent for RSA keys (base64url-encoded)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcrv: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Curve name for elliptic curve keys (e.g., 'Ed25519', 'P-256')\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tx: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"X coordinate for elliptic curve keys (base64url-encoded)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ty: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"Y coordinate for elliptic curve keys (base64url-encoded)\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"kid\", \"kty\", \"alg\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\trequired: [\"keys\"],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\t// Disables endpoint if using remote url strategy\n\t\t\t\t\tif (options?.jwks?.remoteUrl) {\n\t\t\t\t\t\tthrow new APIError(\"NOT_FOUND\");\n\t\t\t\t\t}\n\n\t\t\t\t\tconst adapter = getJwksAdapter(ctx.context.adapter, options);\n\n\t\t\t\t\tlet keySets = await adapter.getAllKeys(ctx);\n\n\t\t\t\t\tif (!keySets || keySets?.length === 0) {\n\t\t\t\t\t\tawait createJwk(ctx, options);\n\t\t\t\t\t\tkeySets = await adapter.getAllKeys(ctx);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!keySets?.length) {\n\t\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\t\"No key sets found. Make sure you have a key in your database.\",\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tconst DEFAULT_GRACE_PERIOD = 60 * 60 * 24 * 30;\n\t\t\t\t\tconst gracePeriod =\n\t\t\t\t\t\t(options?.jwks?.gracePeriod ?? DEFAULT_GRACE_PERIOD) * 1000;\n\n\t\t\t\t\tconst keys = keySets.filter((key) => {\n\t\t\t\t\t\tif (!key.expiresAt) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn key.expiresAt.getTime() + gracePeriod > now;\n\t\t\t\t\t});\n\n\t\t\t\t\tconst keyPairConfig = options?.jwks?.keyPairConfig;\n\t\t\t\t\tconst defaultCrv = keyPairConfig\n\t\t\t\t\t\t? \"crv\" in keyPairConfig\n\t\t\t\t\t\t\t? (keyPairConfig as { crv: string }).crv\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t: undefined;\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tkeys: keys.map((keySet) => {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\talg: keySet.alg ?? options?.jwks?.keyPairConfig?.alg ?? \"EdDSA\",\n\t\t\t\t\t\t\t\tcrv: keySet.crv ?? defaultCrv,\n\t\t\t\t\t\t\t\t...JSON.parse(keySet.publicKey),\n\t\t\t\t\t\t\t\tkid: keySet.id,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t} satisfies JSONWebKeySet as JSONWebKeySet);\n\t\t\t\t},\n\t\t\t),\n\n\t\t\tgetToken: createAuthEndpoint(\n\t\t\t\t\"/token\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\trequireHeaders: true,\n\t\t\t\t\tuse: [sessionMiddleware],\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\topenapi: {\n\t\t\t\t\t\t\toperationId: \"getJSONWebToken\",\n\t\t\t\t\t\t\tdescription: \"Get a JWT token\",\n\t\t\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\t\t200: {\n\t\t\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst jwt = await getJwtToken(ctx, options);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\ttoken: jwt,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t),\n\t\t\tsignJWT: createAuthEndpoint(\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t$Infer: {\n\t\t\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\t\t\tpayload: JWTPayload;\n\t\t\t\t\t\t\t\toverrideOptions?: JwtOptions | undefined;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbody: signJWTBodySchema,\n\t\t\t\t},\n\t\t\t\tasync (c) => {\n\t\t\t\t\tconst jwt = await signJWT(c, {\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t...c.body.overrideOptions,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpayload: c.body.payload,\n\t\t\t\t\t});\n\t\t\t\t\treturn c.json({ token: jwt });\n\t\t\t\t},\n\t\t\t),\n\t\t\tverifyJWT: createAuthEndpoint(\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t$Infer: {\n\t\t\t\t\t\t\tbody: {} as {\n\t\t\t\t\t\t\t\ttoken: string;\n\t\t\t\t\t\t\t\tissuer?: string;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tresponse: {} as {\n\t\t\t\t\t\t\t\tpayload: {\n\t\t\t\t\t\t\t\t\tsub: string;\n\t\t\t\t\t\t\t\t\taud: string;\n\t\t\t\t\t\t\t\t\t[key: string]: any;\n\t\t\t\t\t\t\t\t} | null;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbody: verifyJWTBodySchema,\n\t\t\t\t},\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst overrideOptions = ctx.body.issuer\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t...options,\n\t\t\t\t\t\t\t\tjwt: {\n\t\t\t\t\t\t\t\t\t...options?.jwt,\n\t\t\t\t\t\t\t\t\tissuer: ctx.body.issuer,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: options;\n\n\t\t\t\t\tconst payload = await verifyJWTHelper(\n\t\t\t\t\t\tctx.body.token,\n\t\t\t\t\t\toverrideOptions,\n\t\t\t\t\t);\n\n\t\t\t\t\treturn ctx.json({ payload });\n\t\t\t\t},\n\t\t\t),\n\t\t},\n\t\thooks: {\n\t\t\tafter: [\n\t\t\t\t{\n\t\t\t\t\tmatcher(context) {\n\t\t\t\t\t\treturn context.path === \"/get-session\";\n\t\t\t\t\t},\n\t\t\t\t\thandler: createAuthMiddleware(async (ctx) => {\n\t\t\t\t\t\tif (options?.disableSettingJwtHeader) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst session = ctx.context.session || ctx.context.newSession;\n\t\t\t\t\t\tif (session && session.session) {\n\t\t\t\t\t\t\tconst jwt = await getJwtToken(ctx, options);\n\t\t\t\t\t\t\tconst exposedHeaders =\n\t\t\t\t\t\t\t\tctx.context.responseHeaders?.get(\n\t\t\t\t\t\t\t\t\t\"access-control-expose-headers\",\n\t\t\t\t\t\t\t\t) || \"\";\n\t\t\t\t\t\t\tconst headersSet = new Set(\n\t\t\t\t\t\t\t\texposedHeaders\n\t\t\t\t\t\t\t\t\t.split(\",\")\n\t\t\t\t\t\t\t\t\t.map((header) => header.trim())\n\t\t\t\t\t\t\t\t\t.filter(Boolean),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\theadersSet.add(\"set-auth-jwt\");\n\t\t\t\t\t\t\tctx.setHeader(\"set-auth-jwt\", jwt);\n\t\t\t\t\t\t\tctx.setHeader(\n\t\t\t\t\t\t\t\t\"Access-Control-Expose-Headers\",\n\t\t\t\t\t\t\t\tArray.from(headersSet).join(\", \"),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\tschema: mergeSchema(schema, options?.schema),\n\t} satisfies BetterAuthPlugin;\n};\n\nexport { getJwtToken };\n"],"mappings":"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"}