OAuth metadata discovery

This commit is contained in:
Justin Spahr-Summers 2025-02-06 13:38:21 +00:00
commit 0bc3a74ac3
No known key found for this signature in database

58
src/client/auth/auth.ts Normal file
View file

@ -0,0 +1,58 @@
import { z } from "zod";
export const OAuthMetadataSchema = z
.object({
issuer: z.string(),
authorization_endpoint: z.string(),
token_endpoint: z.string(),
registration_endpoint: z.string().optional(),
scopes_supported: z.array(z.string()).optional(),
response_types_supported: z.array(z.string()),
response_modes_supported: z.array(z.string()).optional(),
grant_types_supported: z.array(z.string()).optional(),
token_endpoint_auth_methods_supported: z.array(z.string()).optional(),
token_endpoint_auth_signing_alg_values_supported: z
.array(z.string())
.optional(),
service_documentation: z.string().optional(),
revocation_endpoint: z.string().optional(),
revocation_endpoint_auth_methods_supported: z.array(z.string()).optional(),
revocation_endpoint_auth_signing_alg_values_supported: z
.array(z.string())
.optional(),
introspection_endpoint: z.string().optional(),
introspection_endpoint_auth_methods_supported: z
.array(z.string())
.optional(),
introspection_endpoint_auth_signing_alg_values_supported: z
.array(z.string())
.optional(),
code_challenge_methods_supported: z.array(z.string()).optional(),
})
.passthrough();
export type OAuthMetadata = z.infer<typeof OAuthMetadataSchema>;
/**
* Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
*
* If the server returns a 404 for the well-known endpoint, this function will
* return `undefined`. Any other errors will be thrown as exceptions.
*/
export async function discoverOAuthMetadata(
serverUrl: string | URL,
): Promise<OAuthMetadata | undefined> {
const url = new URL("/.well-known/oauth-authorization-server", serverUrl);
const response = await fetch(url);
if (response.status === 404) {
return undefined;
}
if (!response.ok) {
throw new Error(
`HTTP ${response.status} trying to load well-known OAuth metadata`,
);
}
return OAuthMetadataSchema.parse(await response.json());
}