[PR #8678] feat(oauth-provider): extensible grant types, metadata, and token claims #25040

Open
opened 2026-04-15 22:42:07 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8678
Author: @gustavovalverde
Created: 3/18/2026
Status: 🔄 Open

Base: nextHead: feat/oauth-provider-extensibility


📝 Commits (2)

  • 78bb334 feat(core): add plugin extension registry and dependency validation
  • 9ceb4c0 feat(oauth-provider): extensible grant types, metadata, and token claims

📊 Changes

17 files changed (+1173 additions, -44 deletions)

View changed files

📝 .cspell/auth-terms.txt (+1 -0)
📝 docs/content/docs/concepts/plugins.mdx (+47 -0)
docs/content/docs/guides/extending-plugins.mdx (+260 -0)
📝 docs/content/docs/plugins/index.mdx (+7 -0)
📝 docs/content/docs/plugins/oauth-provider.mdx (+19 -0)
📝 packages/better-auth/src/context/create-context.test.ts (+86 -0)
📝 packages/better-auth/src/context/create-context.ts (+8 -0)
📝 packages/better-auth/src/context/helpers.ts (+13 -0)
📝 packages/core/src/types/context.ts (+29 -0)
📝 packages/core/src/types/index.ts (+1 -0)
📝 packages/core/src/types/plugin.ts (+27 -1)
📝 packages/oauth-provider/src/index.ts (+13 -0)
📝 packages/oauth-provider/src/oauth.ts (+116 -26)
📝 packages/oauth-provider/src/token.test.ts (+392 -0)
📝 packages/oauth-provider/src/token.ts (+75 -11)
packages/oauth-provider/src/types/extension.ts (+77 -0)
📝 packages/oauth-provider/src/types/oauth.ts (+2 -6)

📄 Description

Summary

Opens the oauth-provider for plugin-based extension. After this change, a third-party developer can create a custom OAuth grant type plugin in ~30 lines with no PRs to better-auth.

Merge order: #8677 must merge first.

Problem

The oauth-provider is sealed: z.enum() rejects unknown grant types at the schema level, the switch default throws, metadata accepts four narrow override fields, and internal utilities (createUserTokens, validateClientCredentials) are unexported. Adding a custom grant type requires forking the package.

Solution

OAuthProviderExtension contract with five extension points:

  • grantTypes: register custom handlers on the token endpoint
  • grantTypeURIs: add to the allowlist and grant_types_supported
  • metadata: contribute fields to discovery endpoints
  • tokenClaims: inject claims into access/ID tokens before signing (user's customAccessTokenClaims always overrides)
  • tokenEndpointAuthMethods: advertise additional auth methods

Token body schema changes from z.enum() to z.string() + .passthrough(). The grantTypes allowlist still rejects unknown types before the switch, so runtime behavior for valid requests is unchanged.

Exported utilities: createUserTokens, validateClientCredentials, basicToClientCredentials, getClient, checkResource, storeToken, getStoredToken.

Why this approach

Host-aggregates, guest-declares. A plugin declares contributions as static data (extensions: { "oauth-provider": { ... } satisfies OAuthProviderExtension }); the host collects via getExtensions during init. No runtime mutation, no after-hook patching, no JWT re-signing. Full compile-time checking at the producer side.

The alternative (options on OAuthOptions) requires users to coordinate between plugin config and oauth-provider config. Third-party plugins cannot self-register.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8678 **Author:** [@gustavovalverde](https://github.com/gustavovalverde) **Created:** 3/18/2026 **Status:** 🔄 Open **Base:** `next` ← **Head:** `feat/oauth-provider-extensibility` --- ### 📝 Commits (2) - [`78bb334`](https://github.com/better-auth/better-auth/commit/78bb334f0a2ba80654c8f3d5cad5a3b7ffdf1a10) feat(core): add plugin extension registry and dependency validation - [`9ceb4c0`](https://github.com/better-auth/better-auth/commit/9ceb4c0246080f9262c7e45bdad5cd5e54f6195a) feat(oauth-provider): extensible grant types, metadata, and token claims ### 📊 Changes **17 files changed** (+1173 additions, -44 deletions) <details> <summary>View changed files</summary> 📝 `.cspell/auth-terms.txt` (+1 -0) 📝 `docs/content/docs/concepts/plugins.mdx` (+47 -0) ➕ `docs/content/docs/guides/extending-plugins.mdx` (+260 -0) 📝 `docs/content/docs/plugins/index.mdx` (+7 -0) 📝 `docs/content/docs/plugins/oauth-provider.mdx` (+19 -0) 📝 `packages/better-auth/src/context/create-context.test.ts` (+86 -0) 📝 `packages/better-auth/src/context/create-context.ts` (+8 -0) 📝 `packages/better-auth/src/context/helpers.ts` (+13 -0) 📝 `packages/core/src/types/context.ts` (+29 -0) 📝 `packages/core/src/types/index.ts` (+1 -0) 📝 `packages/core/src/types/plugin.ts` (+27 -1) 📝 `packages/oauth-provider/src/index.ts` (+13 -0) 📝 `packages/oauth-provider/src/oauth.ts` (+116 -26) 📝 `packages/oauth-provider/src/token.test.ts` (+392 -0) 📝 `packages/oauth-provider/src/token.ts` (+75 -11) ➕ `packages/oauth-provider/src/types/extension.ts` (+77 -0) 📝 `packages/oauth-provider/src/types/oauth.ts` (+2 -6) </details> ### 📄 Description ## Summary Opens the oauth-provider for plugin-based extension. After this change, a third-party developer can create a custom OAuth grant type plugin in ~30 lines with no PRs to better-auth. > **Merge order**: #8677 must merge first. ## Problem The oauth-provider is sealed: `z.enum()` rejects unknown grant types at the schema level, the switch `default` throws, metadata accepts four narrow override fields, and internal utilities (`createUserTokens`, `validateClientCredentials`) are unexported. Adding a custom grant type requires forking the package. ## Solution `OAuthProviderExtension` contract with five extension points: - **`grantTypes`**: register custom handlers on the token endpoint - **`grantTypeURIs`**: add to the allowlist and `grant_types_supported` - **`metadata`**: contribute fields to discovery endpoints - **`tokenClaims`**: inject claims into access/ID tokens before signing (user's `customAccessTokenClaims` always overrides) - **`tokenEndpointAuthMethods`**: advertise additional auth methods Token body schema changes from `z.enum()` to `z.string()` + `.passthrough()`. The `grantTypes` allowlist still rejects unknown types before the switch, so runtime behavior for valid requests is unchanged. Exported utilities: `createUserTokens`, `validateClientCredentials`, `basicToClientCredentials`, `getClient`, `checkResource`, `storeToken`, `getStoredToken`. ## Why this approach Host-aggregates, guest-declares. A plugin declares contributions as static data (`extensions: { "oauth-provider": { ... } satisfies OAuthProviderExtension }`); the host collects via `getExtensions` during `init`. No runtime mutation, no after-hook patching, no JWT re-signing. Full compile-time checking at the producer side. The alternative (options on `OAuthOptions`) requires users to coordinate between plugin config and oauth-provider config. Third-party plugins cannot self-register. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-15 22:42:07 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#25040