[GH-ISSUE #8335] oauth-provider: OIDC Discovery and JWT signing conformance gaps #28382

Open
opened 2026-04-17 19:49:40 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @gustavovalverde on GitHub (Mar 3, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8335

Originally assigned to: @gustavovalverde on GitHub.

Summary

The @better-auth/oauth-provider plugin combined with the jwt() plugin has several deviations from the OIDC specifications that prevent relying parties from integrating with standard OAuth libraries without workarounds.

1. Discovery metadata omits RS256 (OIDC Discovery 1.0 violation)

oidcServerMetadata in metadata.ts derives id_token_signing_alg_values_supported from keyPairConfig.alg, producing a single-element array. The jwt plugin defaults to EdDSA, so the discovery document advertises ["EdDSA"].

OIDC Discovery 1.0 states:

id_token_signing_alg_values_supported — REQUIRED. [...] The algorithm RS256 MUST be included.

Any deployment using the default jwt plugin config is non-conformant.

Consequence: OIDC conformance test suites fail. Standard RP libraries (openid-client, next-auth, Spring Security) that default to RS256 for ID Token verification reject tokens signed with an unadvertised algorithm.

2. No per-client id_token_signed_response_alg

The oauthClient schema has no id_token_signed_response_alg field. OIDC Dynamic Client Registration 1.0 defines this as standard client metadata with a default of RS256.

Consequence: Clients cannot negotiate their preferred signing algorithm during registration. Providers that support multiple algorithms (e.g., RS256 + EdDSA) have no mechanism to sign per-client.

3. Discovery only supports advertising a single algorithm

oidcServerMetadata reads one alg from keyPairConfig and wraps it in an array. There is no way to advertise multiple supported algorithms (e.g., ["RS256", "EdDSA"]), even though OIDC Discovery defines id_token_signing_alg_values_supported as an array for this purpose.

4. Custom sign requires remoteUrl, which disables built-in JWKS

The jwt plugin enforces: jwt.sign → requires jwks.remoteUrl → disables the built-in /jwks endpoint (returns 404). This means adding a secondary signing algorithm (e.g., a post-quantum algorithm alongside EdDSA) forces the developer to take over the entire key management and JWKS serving stack, even for the standard algorithm that the built-in path already handles.

Consequence: There is no way to extend the signing capabilities incrementally. Any custom algorithm requires replacing the entire JWT infrastructure.

Spec references

Originally created by @gustavovalverde on GitHub (Mar 3, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8335 Originally assigned to: @gustavovalverde on GitHub. ## Summary The `@better-auth/oauth-provider` plugin combined with the `jwt()` plugin has several deviations from the OIDC specifications that prevent relying parties from integrating with standard OAuth libraries without workarounds. ## 1. Discovery metadata omits RS256 (OIDC Discovery 1.0 violation) `oidcServerMetadata` in `metadata.ts` derives `id_token_signing_alg_values_supported` from `keyPairConfig.alg`, producing a single-element array. The jwt plugin defaults to `EdDSA`, so the discovery document advertises `["EdDSA"]`. [OIDC Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0.html) states: > `id_token_signing_alg_values_supported` — REQUIRED. [...] **The algorithm RS256 MUST be included.** Any deployment using the default jwt plugin config is non-conformant. **Consequence:** OIDC conformance test suites fail. Standard RP libraries (`openid-client`, `next-auth`, Spring Security) that default to RS256 for ID Token verification reject tokens signed with an unadvertised algorithm. ## 2. No per-client `id_token_signed_response_alg` The `oauthClient` schema has no `id_token_signed_response_alg` field. [OIDC Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html) defines this as standard client metadata with a default of RS256. **Consequence:** Clients cannot negotiate their preferred signing algorithm during registration. Providers that support multiple algorithms (e.g., RS256 + EdDSA) have no mechanism to sign per-client. ## 3. Discovery only supports advertising a single algorithm `oidcServerMetadata` reads one `alg` from `keyPairConfig` and wraps it in an array. There is no way to advertise multiple supported algorithms (e.g., `["RS256", "EdDSA"]`), even though OIDC Discovery defines `id_token_signing_alg_values_supported` as an array for this purpose. ## 4. Custom `sign` requires `remoteUrl`, which disables built-in JWKS The jwt plugin enforces: `jwt.sign` → requires `jwks.remoteUrl` → disables the built-in `/jwks` endpoint (returns 404). This means adding a secondary signing algorithm (e.g., a post-quantum algorithm alongside EdDSA) forces the developer to take over the entire key management and JWKS serving stack, even for the standard algorithm that the built-in path already handles. **Consequence:** There is no way to extend the signing capabilities incrementally. Any custom algorithm requires replacing the entire JWT infrastructure. ## Spec references - [OIDC Discovery 1.0 — Provider Metadata](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata) — RS256 MUST requirement - [OIDC Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html) — `id_token_signed_response_alg` definition, RS256 default - [OIDC Core 1.0 §3.1.3.7](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation) — "The alg value SHOULD be the default of RS256 or the algorithm sent by the Client in the `id_token_signed_response_alg` parameter during Registration"
GiteaMirror added the identity label 2026-04-17 19:49:40 -05:00
Author
Owner

@dvanmali commented on GitHub (Mar 3, 2026):

  1. Custom sign requires remoteUrl, which disables built-in JWKS

jwt.sign and jwks.remoteUrl were designed for remote signing for key management systems like Google KMS and Amazon EKS, hence /jwks endpoint is disabled since public key logic should be hosted on a CDN or other custom endpoint. PR #4748 related to JWT custom verification could solve custom verification but it appears closed now.

<!-- gh-comment-id:3992737416 --> @dvanmali commented on GitHub (Mar 3, 2026): > 4. Custom sign requires remoteUrl, which disables built-in JWKS `jwt.sign` and `jwks.remoteUrl` were designed for remote signing for key management systems like Google KMS and Amazon EKS, hence `/jwks` endpoint is disabled since public key logic should be hosted on a CDN or other custom endpoint. PR #4748 related to JWT custom verification could solve custom verification but it appears closed now.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#28382