1
1
import pkceChallenge from "pkce-challenge" ;
2
- import { z } from "zod" ;
3
2
import { LATEST_PROTOCOL_VERSION } from "../types.js" ;
4
-
5
- export const OAuthMetadataSchema = z
6
- . object ( {
7
- issuer : z . string ( ) ,
8
- authorization_endpoint : z . string ( ) ,
9
- token_endpoint : z . string ( ) ,
10
- registration_endpoint : z . string ( ) . optional ( ) ,
11
- scopes_supported : z . array ( z . string ( ) ) . optional ( ) ,
12
- response_types_supported : z . array ( z . string ( ) ) ,
13
- response_modes_supported : z . array ( z . string ( ) ) . optional ( ) ,
14
- grant_types_supported : z . array ( z . string ( ) ) . optional ( ) ,
15
- token_endpoint_auth_methods_supported : z . array ( z . string ( ) ) . optional ( ) ,
16
- token_endpoint_auth_signing_alg_values_supported : z
17
- . array ( z . string ( ) )
18
- . optional ( ) ,
19
- service_documentation : z . string ( ) . optional ( ) ,
20
- revocation_endpoint : z . string ( ) . optional ( ) ,
21
- revocation_endpoint_auth_methods_supported : z . array ( z . string ( ) ) . optional ( ) ,
22
- revocation_endpoint_auth_signing_alg_values_supported : z
23
- . array ( z . string ( ) )
24
- . optional ( ) ,
25
- introspection_endpoint : z . string ( ) . optional ( ) ,
26
- introspection_endpoint_auth_methods_supported : z
27
- . array ( z . string ( ) )
28
- . optional ( ) ,
29
- introspection_endpoint_auth_signing_alg_values_supported : z
30
- . array ( z . string ( ) )
31
- . optional ( ) ,
32
- code_challenge_methods_supported : z . array ( z . string ( ) ) . optional ( ) ,
33
- } )
34
- . passthrough ( ) ;
35
-
36
- export const OAuthTokensSchema = z
37
- . object ( {
38
- access_token : z . string ( ) ,
39
- token_type : z . string ( ) ,
40
- expires_in : z . number ( ) . optional ( ) ,
41
- scope : z . string ( ) . optional ( ) ,
42
- refresh_token : z . string ( ) . optional ( ) ,
43
- } )
44
- . strip ( ) ;
45
-
46
- /**
47
- * Client metadata schema according to RFC 7591 OAuth 2.0 Dynamic Client Registration
48
- */
49
- export const OAuthClientMetadataSchema = z . object ( {
50
- redirect_uris : z . array ( z . string ( ) ) ,
51
- token_endpoint_auth_method : z . string ( ) . optional ( ) ,
52
- grant_types : z . array ( z . string ( ) ) . optional ( ) ,
53
- response_types : z . array ( z . string ( ) ) . optional ( ) ,
54
- client_name : z . string ( ) . optional ( ) ,
55
- client_uri : z . string ( ) . optional ( ) ,
56
- logo_uri : z . string ( ) . optional ( ) ,
57
- scope : z . string ( ) . optional ( ) ,
58
- contacts : z . array ( z . string ( ) ) . optional ( ) ,
59
- tos_uri : z . string ( ) . optional ( ) ,
60
- policy_uri : z . string ( ) . optional ( ) ,
61
- jwks_uri : z . string ( ) . optional ( ) ,
62
- jwks : z . any ( ) . optional ( ) ,
63
- software_id : z . string ( ) . optional ( ) ,
64
- software_version : z . string ( ) . optional ( ) ,
65
- } ) . passthrough ( ) ;
66
-
67
- /**
68
- * Client information response schema according to RFC 7591
69
- */
70
- export const OAuthClientInformationSchema = z . object ( {
71
- client_id : z . string ( ) ,
72
- client_secret : z . string ( ) . optional ( ) ,
73
- client_id_issued_at : z . number ( ) . optional ( ) ,
74
- client_secret_expires_at : z . number ( ) . optional ( ) ,
75
- } ) . passthrough ( ) ;
76
-
77
- export type OAuthMetadata = z . infer < typeof OAuthMetadataSchema > ;
78
- export type OAuthTokens = z . infer < typeof OAuthTokensSchema > ;
79
-
80
- export type OAuthClientMetadata = z . infer < typeof OAuthClientMetadataSchema > ;
81
- export type OAuthClientInformation = z . infer < typeof OAuthClientInformationSchema > ;
3
+ import type { OAuthClientMetadata , OAuthClientInformation , OAuthTokens , OAuthMetadata , OAuthClientInformationFull } from "../shared/auth.js" ;
4
+ import { OAuthClientInformationFullSchema , OAuthMetadataSchema , OAuthTokensSchema } from "../shared/auth.js" ;
82
5
83
6
/**
84
7
* Implements an end-to-end OAuth client to be used with one MCP server.
@@ -113,7 +36,7 @@ export interface OAuthClientProvider {
113
36
* This method is not required to be implemented if client information is
114
37
* statically known (e.g., pre-registered).
115
38
*/
116
- saveClientInformation ?( clientInformation : OAuthClientInformation ) : void | Promise < void > ;
39
+ saveClientInformation ?( clientInformation : OAuthClientInformationFull ) : void | Promise < void > ;
117
40
118
41
/**
119
42
* Loads any existing OAuth tokens for the current session, or returns
@@ -175,12 +98,13 @@ export async function auth(
175
98
throw new Error ( "OAuth client information must be saveable for dynamic registration" ) ;
176
99
}
177
100
178
- clientInformation = await registerClient ( serverUrl , {
101
+ const fullInformation = await registerClient ( serverUrl , {
179
102
metadata,
180
103
clientMetadata : provider . clientMetadata ,
181
104
} ) ;
182
105
183
- await provider . saveClientInformation ( clientInformation ) ;
106
+ await provider . saveClientInformation ( fullInformation ) ;
107
+ clientInformation = fullInformation ;
184
108
}
185
109
186
110
// Exchange authorization code for tokens
@@ -448,7 +372,7 @@ export async function registerClient(
448
372
metadata ?: OAuthMetadata ;
449
373
clientMetadata : OAuthClientMetadata ;
450
374
} ,
451
- ) : Promise < OAuthClientInformation > {
375
+ ) : Promise < OAuthClientInformationFull > {
452
376
let registrationUrl : URL ;
453
377
454
378
if ( metadata ) {
@@ -473,5 +397,5 @@ export async function registerClient(
473
397
throw new Error ( `Dynamic client registration failed: HTTP ${ response . status } ` ) ;
474
398
}
475
399
476
- return OAuthClientInformationSchema . parse ( await response . json ( ) ) ;
400
+ return OAuthClientInformationFullSchema . parse ( await response . json ( ) ) ;
477
401
}
0 commit comments