mirror of
https://github.com/better-auth/better-auth.git
synced 2026-08-24 14:34:26 -05:00
> This is a re-do of #9418 for the `next` branch, where #8836 was merged. As discussed via Slack, backwards compatibility did not need to be maintained. This is based on RFC 7523 It allows configuring an OAuth2 provider with a `clientAssertionProvider` instead of a `clientSecret`, so omitting long-lived credentials. This PR is currently not concerned with what providers support (or will support) client assertions. It is also not concerned with _how_ the assertion is obtained: could be a Kubernetes token, a token from a cloud platform, etc. This PR refactors/extends #8836, which was limited to supporting assertions generated locally with a private key (which, while having broader support in the ecosystem, still involves long-lived secrets). Support for those assertions is available by passing `createPrivateKeyJwtClientAssertionProvider(opts)` to the `clientAssertionProvider` property. This was implemented by #8836 and it's refactored here so it works in a more generic way. With this PR, JWTs can be signed with a local assertion: ```ts import { betterAuth } from "better-auth"; import { genericOAuth } from "better-auth/plugins/generic-oauth"; import { createPrivateKeyJwtClientAssertionProvider } from "better-auth/oauth2"; genericOAuth({ config: [ { providerId: "my-idp", discoveryUrl: "https://idp.example.com/.well-known/openid-configuration", clientId: process.env.IDP_CLIENT_ID!, // Replaces clientSecret clientAssertionProvider: createPrivateKeyJwtClientAssertionProvider({ clientId: "your-client-id", tokenEndpoint: "https://idp.example.com/oauth/token", privateKeyJwk: { /* your JWK */ }, kid: "my-key-1", algorithm: "RS256", }), pkce: true, }, ], }); ``` For an application running on Vercel and authenticating with a generic OAuth2 provider (e.g. Pocket ID), you can now configure better-auth with: ```ts import { getVercelOidcToken } from '@vercel/oidc' genericOAuth({ config: [ { providerId: "my-idp", discoveryUrl: "https://idp.example.com/.well-known/openid-configuration", clientId: process.env.IDP_CLIENT_ID!, // Replaces clientSecret clientAssertionProvider: async (): Promise<string> => { return getVercelOidcToken() }, pkce: true, }, ], }); ``` You then just need to configure your application in the IdP to accept federation with these values: - Issuer: `https://oidc.vercel.com/<vercel-team>` - Audience: `https://vercel.com/<vercel-team>` - Subject: `owner:<vercel-team>:project:<project-name>:environment:production`