diff --git a/docs/content/docs/plugins/jwt.mdx b/docs/content/docs/plugins/jwt.mdx index 7608982823..523b620fee 100644 --- a/docs/content/docs/plugins/jwt.mdx +++ b/docs/content/docs/plugins/jwt.mdx @@ -111,6 +111,21 @@ In case a JWT with a different `kid` is received, it is recommended to fetch the } ``` +### OAuth Provider Mode + +If you are making your system oAuth compliant (such as when utilizing the OIDC or MCP plugins), you **MUST** disable the `/token` endpoint (oAuth equivalent `/oauth2/token`) and disable setting the jwt header (oAuth equivalent `/oauth2/userinfo`). + +```ts title="auth.ts" +betterAuth({ + disabledPaths: [ + "/token", + ], + plugins: [jwt({ + disableSettingJwtHeader: true, + })] +}) +``` + #### Example using jose with remote JWKS ```ts diff --git a/docs/content/docs/plugins/oidc-provider.mdx b/docs/content/docs/plugins/oidc-provider.mdx index 2742f72900..d3e526bddb 100644 --- a/docs/content/docs/plugins/oidc-provider.mdx +++ b/docs/content/docs/plugins/oidc-provider.mdx @@ -339,7 +339,9 @@ export const auth = betterAuth({ ### JWKS Endpoint -The OIDC Provider plugin can integrate with the JWT plugin to provide proper asymmetric key signing for ID tokens. When enabled, ID tokens will be signed using RSA/EdDSA keys and can be verified using the JWKS endpoint. +The OIDC Provider plugin can integrate with the JWT plugin to provide asymmetric key signing for ID tokens verifiable at a JWKS endpoint. + +To make your plugin OIDC compliant, you **MUST** disable the `/token` endpoint, the OAuth equivalent is located at `/oauth2/token` instead. ```ts title="auth.ts" import { betterAuth } from "better-auth"; @@ -347,6 +349,9 @@ import { oidcProvider } from "better-auth/plugins"; import { jwt } from "better-auth/plugins"; export const auth = betterAuth({ + disabledPaths: [ + "/token", + ], plugins: [ jwt(), // Make sure to add the JWT plugin oidcProvider({ diff --git a/packages/better-auth/src/plugins/jwt/index.ts b/packages/better-auth/src/plugins/jwt/index.ts index d1fec2343a..8f9da64bec 100644 --- a/packages/better-auth/src/plugins/jwt/index.ts +++ b/packages/better-auth/src/plugins/jwt/index.ts @@ -114,6 +114,17 @@ export interface JwtOptions { session: Session & Record; }) => Promise | string; }; + + /** + * Disables setting JWTs through middleware. + * + * Recommended to set `true` when using an oAuth provider plugin + * like OIDC or MCP where session payloads should not be signed. + * + * @default false + */ + disableSettingJwtHeader?: boolean; + /** * Custom schema for the admin plugin */ @@ -365,6 +376,10 @@ export const jwt = (options?: JwtOptions) => { return context.path === "/get-session"; }, handler: createAuthMiddleware(async (ctx) => { + if (options?.disableSettingJwtHeader) { + return; + } + const session = ctx.context.session || ctx.context.newSession; if (session && session.session) { const jwt = await getJwtToken(ctx, options);