Skip to content

Commit 0bc3a74

Browse files
committed
OAuth metadata discovery
1 parent 0db3da4 commit 0bc3a74

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed

src/client/auth/auth.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { z } from "zod";
2+
3+
export const OAuthMetadataSchema = z
4+
.object({
5+
issuer: z.string(),
6+
authorization_endpoint: z.string(),
7+
token_endpoint: z.string(),
8+
registration_endpoint: z.string().optional(),
9+
scopes_supported: z.array(z.string()).optional(),
10+
response_types_supported: z.array(z.string()),
11+
response_modes_supported: z.array(z.string()).optional(),
12+
grant_types_supported: z.array(z.string()).optional(),
13+
token_endpoint_auth_methods_supported: z.array(z.string()).optional(),
14+
token_endpoint_auth_signing_alg_values_supported: z
15+
.array(z.string())
16+
.optional(),
17+
service_documentation: z.string().optional(),
18+
revocation_endpoint: z.string().optional(),
19+
revocation_endpoint_auth_methods_supported: z.array(z.string()).optional(),
20+
revocation_endpoint_auth_signing_alg_values_supported: z
21+
.array(z.string())
22+
.optional(),
23+
introspection_endpoint: z.string().optional(),
24+
introspection_endpoint_auth_methods_supported: z
25+
.array(z.string())
26+
.optional(),
27+
introspection_endpoint_auth_signing_alg_values_supported: z
28+
.array(z.string())
29+
.optional(),
30+
code_challenge_methods_supported: z.array(z.string()).optional(),
31+
})
32+
.passthrough();
33+
34+
export type OAuthMetadata = z.infer<typeof OAuthMetadataSchema>;
35+
36+
/**
37+
* Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
38+
*
39+
* If the server returns a 404 for the well-known endpoint, this function will
40+
* return `undefined`. Any other errors will be thrown as exceptions.
41+
*/
42+
export async function discoverOAuthMetadata(
43+
serverUrl: string | URL,
44+
): Promise<OAuthMetadata | undefined> {
45+
const url = new URL("/.well-known/oauth-authorization-server", serverUrl);
46+
const response = await fetch(url);
47+
if (response.status === 404) {
48+
return undefined;
49+
}
50+
51+
if (!response.ok) {
52+
throw new Error(
53+
`HTTP ${response.status} trying to load well-known OAuth metadata`,
54+
);
55+
}
56+
57+
return OAuthMetadataSchema.parse(await response.json());
58+
}

0 commit comments

Comments
 (0)