mirror of
https://github.com/better-auth/better-auth.git
synced 2026-07-17 08:20:03 -05:00
fix(oauth-provider): hide DCR endpoint unless enabled (#9448)
Co-authored-by: Gustavo Valverde <g.valverde02@gmail.com>
This commit is contained in:
5
.changeset/giant-canyons-report.md
Normal file
5
.changeset/giant-canyons-report.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@better-auth/oauth-provider": patch
|
||||
---
|
||||
|
||||
Remove registration_endpoint on .well-known config if `allowDynamicClientRegistration` is not true
|
||||
@@ -53,6 +53,7 @@ describe("oauth metadata", async () => {
|
||||
oauthAuthServerConfig: true,
|
||||
openidConfig: true,
|
||||
},
|
||||
allowDynamicClientRegistration: true,
|
||||
...opts?.oauthProviderConfig,
|
||||
}),
|
||||
...(opts?.oauthProviderConfig?.disableJwtPlugin
|
||||
@@ -154,6 +155,25 @@ describe("oauth metadata", async () => {
|
||||
expect(metadata.issuer).toBe(baseURL);
|
||||
});
|
||||
|
||||
it("should advertise dynamic client registration from direct OAuth metadata when enabled", async () => {
|
||||
const { customFetchImpl } = await createTestInstance({
|
||||
oauthProviderConfig: {
|
||||
scopes: ["create:test"],
|
||||
allowDynamicClientRegistration: true,
|
||||
},
|
||||
});
|
||||
const response = await customFetchImpl(
|
||||
`${baseURL}/.well-known/oauth-authorization-server`,
|
||||
{ method: "GET" },
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
const metadata = (await response.json()) as {
|
||||
registration_endpoint?: string;
|
||||
};
|
||||
expect(metadata.registration_endpoint).toBe(`${baseURL}/oauth2/register`);
|
||||
});
|
||||
|
||||
it("should serve OIDC metadata at the direct issuer well-known URL", async () => {
|
||||
const { customFetchImpl } = await createTestInstance();
|
||||
const response = await customFetchImpl(
|
||||
@@ -263,6 +283,30 @@ describe("oauth metadata", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should not provide dynamic client registration endpoint when disabled", async () => {
|
||||
const { auth } = await createTestInstance({
|
||||
oauthProviderConfig: {
|
||||
allowDynamicClientRegistration: false,
|
||||
},
|
||||
});
|
||||
const metadata = await auth.api.getOpenIdConfig();
|
||||
expect(metadata.registration_endpoint).toBeUndefined();
|
||||
const oauthMetadata = await auth.api.getOAuthServerConfig();
|
||||
expect(oauthMetadata.registration_endpoint).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should not provide dynamic client registration endpoint when undefined", async () => {
|
||||
const { auth } = await createTestInstance({
|
||||
oauthProviderConfig: {
|
||||
allowDynamicClientRegistration: undefined,
|
||||
},
|
||||
});
|
||||
const metadata = await auth.api.getOpenIdConfig();
|
||||
expect(metadata.registration_endpoint).toBeUndefined();
|
||||
const oauthMetadata = await auth.api.getOAuthServerConfig();
|
||||
expect(oauthMetadata.registration_endpoint).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should utilize advertised metadata fields", async () => {
|
||||
const advertisedScopes = ["email"];
|
||||
const advertisedClaims = ["sub", "iss", "aud", "exp", "iat", "scope"];
|
||||
|
||||
@@ -15,6 +15,7 @@ export function authServerMetadata(
|
||||
opts?: JwtOptions,
|
||||
overrides?: {
|
||||
scopes_supported?: AuthServerMetadata["scopes_supported"];
|
||||
dynamic_client_registration_supported?: boolean;
|
||||
public_client_supported?: boolean;
|
||||
grant_types_supported?: GrantType[];
|
||||
jwt_disabled?: boolean;
|
||||
@@ -30,7 +31,9 @@ export function authServerMetadata(
|
||||
? undefined
|
||||
: (opts?.jwks?.remoteUrl ??
|
||||
`${baseURL}${opts?.jwks?.jwksPath ?? "/jwks"}`),
|
||||
registration_endpoint: `${baseURL}/oauth2/register`,
|
||||
registration_endpoint: overrides?.dynamic_client_registration_supported
|
||||
? `${baseURL}/oauth2/register`
|
||||
: undefined,
|
||||
introspection_endpoint: `${baseURL}/oauth2/introspect`,
|
||||
revocation_endpoint: `${baseURL}/oauth2/revoke`,
|
||||
response_types_supported:
|
||||
@@ -75,6 +78,7 @@ export function oidcServerMetadata(
|
||||
: getJwtPlugin(ctx.context).options;
|
||||
const authMetadata = authServerMetadata(ctx, jwtPluginOptions, {
|
||||
scopes_supported: opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
|
||||
dynamic_client_registration_supported: opts.allowDynamicClientRegistration,
|
||||
public_client_supported: opts.allowUnauthenticatedClientRegistration,
|
||||
grant_types_supported: opts.grantTypes,
|
||||
jwt_disabled: opts.disableJwtPlugin,
|
||||
|
||||
@@ -240,6 +240,8 @@ export const oauthProvider = <O extends OAuthOptions<Scope[]>>(options: O) => {
|
||||
const metadata = authServerMetadata(endpointCtx, jwtPluginOptions, {
|
||||
scopes_supported:
|
||||
opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
|
||||
dynamic_client_registration_supported:
|
||||
opts.allowDynamicClientRegistration,
|
||||
public_client_supported: opts.allowUnauthenticatedClientRegistration,
|
||||
grant_types_supported: opts.grantTypes,
|
||||
jwt_disabled: opts.disableJwtPlugin,
|
||||
@@ -437,6 +439,8 @@ export const oauthProvider = <O extends OAuthOptions<Scope[]>>(options: O) => {
|
||||
const authMetadata = authServerMetadata(ctx, jwtPluginOptions, {
|
||||
scopes_supported:
|
||||
opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
|
||||
dynamic_client_registration_supported:
|
||||
opts.allowDynamicClientRegistration,
|
||||
public_client_supported:
|
||||
opts.allowUnauthenticatedClientRegistration,
|
||||
grant_types_supported: opts.grantTypes,
|
||||
|
||||
@@ -61,9 +61,11 @@ export interface AuthServerMetadata {
|
||||
/**
|
||||
* The URL of the dynamic client registration endpoint.
|
||||
*
|
||||
* This field is only present when `allowDynamicClientRegistration` is enabled.
|
||||
*
|
||||
* @default `/oauth2/register`
|
||||
*/
|
||||
registration_endpoint: string;
|
||||
registration_endpoint?: string;
|
||||
/**
|
||||
* Supported scopes.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user