0
# Authentication
1
2
Complete OAuth 2.0 support: authorization code flow with PKCE, client registration, token management, and revocation.
3
4
## Server-Side OAuth
5
6
### OAuth Router
7
8
```typescript { .api }
9
import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
10
11
function mcpAuthRouter(options: {
12
provider: OAuthServerProvider;
13
issuerUrl: URL;
14
baseUrl: URL;
15
serviceDocumentationUrl?: URL;
16
rateLimit?: RateLimitOptions;
17
}): express.Router;
18
```
19
20
### OAuth Server Provider Interface
21
22
```typescript { .api }
23
interface OAuthServerProvider {
24
get clientsStore(): OAuthRegisteredClientsStore;
25
authorize(client: OAuthClientInformationFull, params: AuthorizationParams, res: Response): Promise<void>;
26
challengeForAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string): Promise<string>;
27
exchangeAuthorizationCode(client: OAuthClientInformationFull, authorizationCode: string, codeVerifier?: string, redirectUri?: string, resource?: URL): Promise<OAuthTokens>;
28
exchangeRefreshToken(client: OAuthClientInformationFull, refreshToken: string, scopes?: string[], resource?: URL): Promise<OAuthTokens>;
29
verifyAccessToken(token: string): Promise<AuthInfo>;
30
revokeToken?(client: OAuthClientInformationFull, request: OAuthTokenRevocationRequest): Promise<void>;
31
skipLocalPkceValidation?: boolean;
32
}
33
34
interface AuthorizationParams {
35
state?: string;
36
scopes?: string[];
37
codeChallenge: string;
38
redirectUri: string;
39
resource?: URL;
40
}
41
42
interface OAuthTokenVerifier {
43
verifyAccessToken(token: string): Promise<AuthInfo>;
44
}
45
```
46
47
### Proxy OAuth Provider
48
49
```typescript { .api }
50
import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
51
52
class ProxyOAuthServerProvider implements OAuthServerProvider {
53
constructor(options: {
54
endpoints: {
55
authorizationUrl: string;
56
tokenUrl: string;
57
revocationUrl: string;
58
};
59
verifyAccessToken: (token: string) => Promise<TokenInfo>;
60
getClient: (clientId: string) => Promise<OAuthClient | undefined>;
61
tokens?: OAuthTokens;
62
});
63
}
64
```
65
66
### OAuth Middleware
67
68
```typescript { .api }
69
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
70
71
function requireBearerAuth(options: {
72
verifier: OAuthTokenVerifier;
73
requiredScopes?: string[];
74
resourceMetadataUrl?: string;
75
}): express.RequestHandler;
76
```
77
78
### Complete Server Example
79
80
```typescript
81
import express from 'express';
82
import { mcpAuthRouter } from '@modelcontextprotocol/sdk/server/auth/router.js';
83
import { ProxyOAuthServerProvider } from '@modelcontextprotocol/sdk/server/auth/providers/proxyProvider.js';
84
import { requireBearerAuth } from '@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js';
85
86
const app = express();
87
88
const provider = new ProxyOAuthServerProvider({
89
endpoints: {
90
authorizationUrl: 'https://auth.example.com/oauth2/authorize',
91
tokenUrl: 'https://auth.example.com/oauth2/token',
92
revocationUrl: 'https://auth.example.com/oauth2/revoke'
93
},
94
verifyAccessToken: async (token) => ({
95
token,
96
clientId: 'client-123',
97
scopes: ['openid', 'profile']
98
}),
99
getClient: async (clientId) => ({
100
client_id: clientId,
101
redirect_uris: ['http://localhost:3000/callback']
102
})
103
});
104
105
// Mount OAuth router
106
app.use(mcpAuthRouter({
107
provider,
108
issuerUrl: new URL('https://auth.example.com'),
109
baseUrl: new URL('https://mcp.example.com'),
110
serviceDocumentationUrl: new URL('https://docs.example.com')
111
}));
112
113
// Protect MCP endpoint
114
app.post('/mcp',
115
requireBearerAuth({
116
verifier: provider,
117
requiredScopes: ['mcp:read', 'mcp:write']
118
}),
119
async (req, res) => {
120
await transport.handleRequest(req, res, req.body);
121
}
122
);
123
124
app.listen(3000);
125
```
126
127
## Client-Side OAuth
128
129
### OAuth Client Provider Interface
130
131
```typescript { .api }
132
interface OAuthClientProvider {
133
get redirectUrl(): string | URL;
134
get clientMetadata(): OAuthClientMetadata;
135
state?(): string | Promise<string>;
136
clientInformation(): OAuthClientInformation | undefined | Promise<OAuthClientInformation | undefined>;
137
saveClientInformation?(clientInformation: OAuthClientInformationFull): void | Promise<void>;
138
tokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;
139
saveTokens(tokens: OAuthTokens): void | Promise<void>;
140
redirectToAuthorization(authorizationUrl: URL): void | Promise<void>;
141
saveCodeVerifier(codeVerifier: string): void | Promise<void>;
142
codeVerifier(): string | Promise<string>;
143
addClientAuthentication?(headers: Headers, params: URLSearchParams, url: string | URL, metadata?: AuthorizationServerMetadata): void | Promise<void>;
144
validateResourceURL?(serverUrl: string | URL, resource?: string): Promise<URL | undefined>;
145
invalidateCredentials?(scope: 'all' | 'client' | 'tokens' | 'verifier'): void | Promise<void>;
146
}
147
```
148
149
### OAuth Authentication Flow
150
151
```typescript { .api }
152
import { auth } from '@modelcontextprotocol/sdk/client/auth.js';
153
154
async function auth(
155
provider: OAuthClientProvider,
156
options: {
157
serverUrl: URL;
158
forceRefresh?: boolean;
159
fetch?: FetchLike;
160
}
161
): Promise<{
162
tokens: OAuthTokens;
163
metadata: OAuthMetadata | OAuthProtectedResourceMetadata;
164
}>;
165
```
166
167
### OAuth HTTP Middleware
168
169
```typescript { .api }
170
import { withOAuth } from '@modelcontextprotocol/sdk/client/middleware.js';
171
172
function withOAuth(provider: OAuthClientProvider, baseUrl?: string | URL): Middleware;
173
```
174
175
### Client Example
176
177
```typescript
178
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
179
180
const transport = new StreamableHTTPClientTransport(
181
new URL('http://localhost:3000/mcp'),
182
{ authProvider: myOAuthProvider }
183
);
184
185
// OAuth is automatically handled by the transport
186
await client.connect(transport);
187
```
188
189
## OAuth Types
190
191
```typescript { .api }
192
interface OAuthTokens {
193
access_token: string;
194
token_type: string;
195
expires_in?: number;
196
refresh_token?: string;
197
scope?: string;
198
}
199
200
interface OAuthClientMetadata {
201
client_name?: string;
202
redirect_uris?: string[];
203
token_endpoint_auth_method?: string;
204
grant_types?: string[];
205
response_types?: string[];
206
client_uri?: string;
207
logo_uri?: string;
208
scope?: string;
209
contacts?: string[];
210
tos_uri?: string;
211
policy_uri?: string;
212
jwks_uri?: string;
213
software_id?: string;
214
software_version?: string;
215
}
216
217
interface OAuthClientInformation {
218
client_id: string;
219
redirect_uris?: string[];
220
}
221
222
interface OAuthClientInformationFull extends OAuthClientInformation {
223
client_secret?: string;
224
client_secret_expires_at?: number;
225
registration_access_token?: string;
226
registration_client_uri?: string;
227
}
228
229
interface OAuthMetadata {
230
issuer: string;
231
authorization_endpoint: string;
232
token_endpoint: string;
233
revocation_endpoint?: string;
234
registration_endpoint?: string;
235
scopes_supported?: string[];
236
response_types_supported: string[];
237
grant_types_supported?: string[];
238
token_endpoint_auth_methods_supported?: string[];
239
code_challenge_methods_supported?: string[];
240
service_documentation?: string;
241
}
242
243
interface OAuthProtectedResourceMetadata {
244
resource: string;
245
authorization_servers?: string[];
246
bearer_methods_supported?: string[];
247
resource_documentation?: string;
248
scopes_supported?: string[];
249
}
250
251
interface TokenInfo {
252
token: string;
253
clientId: string;
254
scopes: string[];
255
userId?: string;
256
expiresAt?: number;
257
}
258
```
259
260
## OAuth Error Classes
261
262
```typescript { .api }
263
class OAuthError extends Error { }
264
class InvalidRequestError extends OAuthError { }
265
class InvalidClientError extends OAuthError { }
266
class InvalidGrantError extends OAuthError { }
267
class UnauthorizedClientError extends OAuthError { }
268
class UnsupportedGrantTypeError extends OAuthError { }
269
class InvalidScopeError extends OAuthError { }
270
class AccessDeniedError extends OAuthError { }
271
class ServerError extends OAuthError { }
272
class TemporarilyUnavailableError extends OAuthError { }
273
class UnsupportedResponseTypeError extends OAuthError { }
274
class UnsupportedTokenTypeError extends OAuthError { }
275
class InvalidTokenError extends OAuthError { }
276
class MethodNotAllowedError extends OAuthError { }
277
class TooManyRequestsError extends OAuthError { }
278
class InvalidClientMetadataError extends OAuthError { }
279
class InsufficientScopeError extends OAuthError { }
280
```
281
282
## Metadata Discovery
283
284
```typescript { .api }
285
import { extractResourceMetadataUrl } from '@modelcontextprotocol/sdk/client/auth.js';
286
import { resourceUrlFromServerUrl } from '@modelcontextprotocol/sdk/shared/auth-utils.js';
287
288
function extractResourceMetadataUrl(response: Response): URL | undefined;
289
function resourceUrlFromServerUrl(url: URL | string): URL;
290
```
291