feat(jwt): add disableSettingJwtHeader flag to prevent issuance of signed jwt (#4072)

This commit is contained in:
Dylan Vanmali
2025-08-18 14:17:30 -07:00
committed by GitHub
parent da52400a51
commit 4b8a2f62b9
3 changed files with 36 additions and 1 deletions
+15
View File
@@ -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
+6 -1
View File
@@ -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({
@@ -114,6 +114,17 @@ export interface JwtOptions {
session: Session & Record<string, any>;
}) => Promise<string> | 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);