@leanmcp/auth 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,376 @@
1
+ /**
2
+ * OAuth Proxy Types
3
+ *
4
+ * Types and interfaces for the OAuth proxy that enables
5
+ * MCP servers to authenticate via external identity providers.
6
+ */
7
+ /**
8
+ * OAuth provider configuration
9
+ */
10
+ interface OAuthProviderConfig {
11
+ /** Display name of the provider */
12
+ name: string;
13
+ /** Provider identifier (e.g., 'google', 'github') */
14
+ id: string;
15
+ /** OAuth authorization endpoint */
16
+ authorizationEndpoint: string;
17
+ /** OAuth token endpoint */
18
+ tokenEndpoint: string;
19
+ /** UserInfo endpoint (optional, for fetching user profile) */
20
+ userInfoEndpoint?: string;
21
+ /** OAuth client ID */
22
+ clientId: string;
23
+ /** OAuth client secret */
24
+ clientSecret: string;
25
+ /** Scopes to request */
26
+ scopes: string[];
27
+ /** Token endpoint authentication method */
28
+ tokenEndpointAuthMethod?: 'client_secret_basic' | 'client_secret_post';
29
+ /** Whether the provider supports PKCE */
30
+ supportsPkce?: boolean;
31
+ /** Custom parameters for authorization */
32
+ authorizationParams?: Record<string, string>;
33
+ /** Custom parameters for token exchange */
34
+ tokenParams?: Record<string, string>;
35
+ }
36
+ /**
37
+ * User info from external provider
38
+ */
39
+ interface ExternalUserInfo {
40
+ /** User's unique ID from the provider */
41
+ sub: string;
42
+ /** User's email address */
43
+ email?: string;
44
+ /** Whether email is verified */
45
+ email_verified?: boolean;
46
+ /** User's display name */
47
+ name?: string;
48
+ /** User's profile picture URL */
49
+ picture?: string;
50
+ /** Provider-specific raw data */
51
+ raw?: Record<string, unknown>;
52
+ }
53
+ /**
54
+ * Token mapping function
55
+ * Maps external provider tokens to internal MCP tokens
56
+ */
57
+ type TokenMapper = (externalTokens: ExternalTokens, userInfo: ExternalUserInfo, provider: OAuthProviderConfig) => Promise<MappedTokens>;
58
+ /**
59
+ * External provider tokens
60
+ */
61
+ interface ExternalTokens {
62
+ access_token: string;
63
+ token_type: string;
64
+ expires_in?: number;
65
+ refresh_token?: string;
66
+ id_token?: string;
67
+ scope?: string;
68
+ }
69
+ /**
70
+ * Internal MCP tokens after mapping
71
+ */
72
+ interface MappedTokens {
73
+ /** Access token to use with MCP server */
74
+ access_token: string;
75
+ /** Token type (usually Bearer) */
76
+ token_type: string;
77
+ /** Token lifetime in seconds */
78
+ expires_in?: number;
79
+ /** Refresh token for obtaining new tokens */
80
+ refresh_token?: string;
81
+ /** MCP user ID */
82
+ user_id?: string;
83
+ }
84
+ /**
85
+ * OAuth proxy configuration
86
+ */
87
+ interface OAuthProxyConfig {
88
+ /** Base URL where the proxy is hosted */
89
+ baseUrl: string;
90
+ /** Path for authorization endpoint (default: /authorize) */
91
+ authorizePath?: string;
92
+ /** Path for token endpoint (default: /token) */
93
+ tokenPath?: string;
94
+ /** Path for callback from external provider (default: /callback) */
95
+ callbackPath?: string;
96
+ /** Configured upstream providers */
97
+ providers: OAuthProviderConfig[];
98
+ /** Custom token mapper (optional) */
99
+ tokenMapper?: TokenMapper;
100
+ /** Session storage for OAuth state */
101
+ sessionSecret: string;
102
+ /** Whether to forward PKCE to upstream provider */
103
+ forwardPkce?: boolean;
104
+ }
105
+ /**
106
+ * Pending authorization request
107
+ */
108
+ interface PendingAuthRequest {
109
+ /** Provider ID */
110
+ providerId: string;
111
+ /** Original client redirect URI */
112
+ clientRedirectUri: string;
113
+ /** Original client state */
114
+ clientState?: string;
115
+ /** PKCE code verifier (if forwarding PKCE) */
116
+ codeVerifier?: string;
117
+ /** Internal state for proxy */
118
+ proxyState: string;
119
+ /** Created timestamp */
120
+ createdAt: number;
121
+ }
122
+
123
+ /**
124
+ * Pre-configured OAuth Providers
125
+ *
126
+ * Ready-to-use configurations for popular identity providers.
127
+ * Just add your client credentials.
128
+ */
129
+
130
+ /**
131
+ * Google OAuth provider configuration
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * const google = googleProvider({
136
+ * clientId: process.env.GOOGLE_CLIENT_ID!,
137
+ * clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
138
+ * scopes: ['email', 'profile'],
139
+ * });
140
+ * ```
141
+ */
142
+ declare function googleProvider(options: {
143
+ clientId: string;
144
+ clientSecret: string;
145
+ scopes?: string[];
146
+ }): OAuthProviderConfig;
147
+ /**
148
+ * GitHub OAuth provider configuration
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const github = githubProvider({
153
+ * clientId: process.env.GITHUB_CLIENT_ID!,
154
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
155
+ * });
156
+ * ```
157
+ */
158
+ declare function githubProvider(options: {
159
+ clientId: string;
160
+ clientSecret: string;
161
+ scopes?: string[];
162
+ }): OAuthProviderConfig;
163
+ /**
164
+ * Microsoft Azure AD / Entra ID provider configuration
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const azure = azureProvider({
169
+ * clientId: process.env.AZURE_CLIENT_ID!,
170
+ * clientSecret: process.env.AZURE_CLIENT_SECRET!,
171
+ * tenantId: process.env.AZURE_TENANT_ID ?? 'common',
172
+ * });
173
+ * ```
174
+ */
175
+ declare function azureProvider(options: {
176
+ clientId: string;
177
+ clientSecret: string;
178
+ tenantId?: string;
179
+ scopes?: string[];
180
+ }): OAuthProviderConfig;
181
+ /**
182
+ * GitLab OAuth provider configuration
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * const gitlab = gitlabProvider({
187
+ * clientId: process.env.GITLAB_CLIENT_ID!,
188
+ * clientSecret: process.env.GITLAB_CLIENT_SECRET!,
189
+ * // Optional: use self-hosted GitLab
190
+ * baseUrl: 'https://gitlab.mycompany.com',
191
+ * });
192
+ * ```
193
+ */
194
+ declare function gitlabProvider(options: {
195
+ clientId: string;
196
+ clientSecret: string;
197
+ baseUrl?: string;
198
+ scopes?: string[];
199
+ }): OAuthProviderConfig;
200
+ /**
201
+ * Slack OAuth provider configuration
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const slack = slackProvider({
206
+ * clientId: process.env.SLACK_CLIENT_ID!,
207
+ * clientSecret: process.env.SLACK_CLIENT_SECRET!,
208
+ * });
209
+ * ```
210
+ */
211
+ declare function slackProvider(options: {
212
+ clientId: string;
213
+ clientSecret: string;
214
+ scopes?: string[];
215
+ }): OAuthProviderConfig;
216
+ /**
217
+ * Discord OAuth provider configuration
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * const discord = discordProvider({
222
+ * clientId: process.env.DISCORD_CLIENT_ID!,
223
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET!,
224
+ * });
225
+ * ```
226
+ */
227
+ declare function discordProvider(options: {
228
+ clientId: string;
229
+ clientSecret: string;
230
+ scopes?: string[];
231
+ }): OAuthProviderConfig;
232
+ /**
233
+ * Create a custom OAuth provider
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const custom = customProvider({
238
+ * id: 'my-idp',
239
+ * name: 'My Identity Provider',
240
+ * authorizationEndpoint: 'https://idp.example.com/authorize',
241
+ * tokenEndpoint: 'https://idp.example.com/token',
242
+ * clientId: process.env.MY_IDP_CLIENT_ID!,
243
+ * clientSecret: process.env.MY_IDP_CLIENT_SECRET!,
244
+ * scopes: ['openid', 'profile'],
245
+ * });
246
+ * ```
247
+ */
248
+ declare function customProvider(config: OAuthProviderConfig): OAuthProviderConfig;
249
+
250
+ /**
251
+ * OAuth Proxy
252
+ *
253
+ * Enables MCP servers to authenticate users via external identity providers.
254
+ * Acts as an intermediary between MCP clients and providers like Google, GitHub, etc.
255
+ */
256
+
257
+ /**
258
+ * OAuth Proxy class
259
+ *
260
+ * Handles OAuth flows with external identity providers and maps
261
+ * their tokens to internal MCP tokens.
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * import { OAuthProxy, googleProvider, githubProvider } from '@leanmcp/auth/proxy';
266
+ *
267
+ * const proxy = new OAuthProxy({
268
+ * baseUrl: 'https://mcp.example.com/auth',
269
+ * sessionSecret: process.env.SESSION_SECRET!,
270
+ * providers: [
271
+ * googleProvider({ clientId: '...', clientSecret: '...' }),
272
+ * githubProvider({ clientId: '...', clientSecret: '...' }),
273
+ * ],
274
+ * });
275
+ *
276
+ * // Express integration
277
+ * app.get('/auth/authorize', (req, res) => {
278
+ * const url = proxy.handleAuthorize(req.query);
279
+ * res.redirect(url);
280
+ * });
281
+ *
282
+ * app.get('/auth/callback', async (req, res) => {
283
+ * const result = await proxy.handleCallback(req.query);
284
+ * res.redirect(result.redirectUri);
285
+ * });
286
+ * ```
287
+ */
288
+ declare class OAuthProxy {
289
+ private config;
290
+ private providersMap;
291
+ constructor(config: OAuthProxyConfig);
292
+ /**
293
+ * Get configured providers
294
+ */
295
+ getProviders(): OAuthProviderConfig[];
296
+ /**
297
+ * Get a provider by ID
298
+ */
299
+ getProvider(id: string): OAuthProviderConfig | undefined;
300
+ /**
301
+ * Generate state parameter with signature
302
+ */
303
+ private generateState;
304
+ /**
305
+ * Verify state parameter signature
306
+ */
307
+ private verifyState;
308
+ /**
309
+ * Handle authorization request
310
+ *
311
+ * Redirects the user to the external provider's authorization page.
312
+ *
313
+ * @param params - Request parameters
314
+ * @returns URL to redirect the user to
315
+ */
316
+ handleAuthorize(params: {
317
+ provider: string;
318
+ redirect_uri: string;
319
+ state?: string;
320
+ scope?: string;
321
+ code_challenge?: string;
322
+ code_challenge_method?: string;
323
+ }): string;
324
+ /**
325
+ * Handle callback from external provider
326
+ *
327
+ * Exchanges the authorization code for tokens and maps them.
328
+ *
329
+ * @param params - Callback query parameters
330
+ * @returns Result with redirect URI and tokens
331
+ */
332
+ handleCallback(params: {
333
+ code?: string;
334
+ state?: string;
335
+ error?: string;
336
+ error_description?: string;
337
+ }): Promise<{
338
+ redirectUri: string;
339
+ tokens?: MappedTokens;
340
+ error?: string;
341
+ }>;
342
+ /**
343
+ * Exchange authorization code for tokens with external provider
344
+ */
345
+ private exchangeCodeForTokens;
346
+ /**
347
+ * Fetch user info from external provider
348
+ */
349
+ private fetchUserInfo;
350
+ /**
351
+ * Generate an internal authorization code for the mapped tokens
352
+ * This code can be exchanged via the token endpoint
353
+ */
354
+ private generateInternalCode;
355
+ /**
356
+ * Handle token request (exchange internal code for tokens)
357
+ */
358
+ handleToken(params: {
359
+ grant_type: string;
360
+ code?: string;
361
+ redirect_uri?: string;
362
+ client_id?: string;
363
+ client_secret?: string;
364
+ refresh_token?: string;
365
+ }): Promise<MappedTokens>;
366
+ /**
367
+ * Express/Connect middleware factory
368
+ */
369
+ createMiddleware(): {
370
+ authorize: (req: any, res: any) => void;
371
+ callback: (req: any, res: any) => Promise<void>;
372
+ token: (req: any, res: any) => Promise<void>;
373
+ };
374
+ }
375
+
376
+ export { type ExternalTokens, type ExternalUserInfo, type MappedTokens, type OAuthProviderConfig, OAuthProxy, type OAuthProxyConfig, type PendingAuthRequest, type TokenMapper, azureProvider, customProvider, discordProvider, githubProvider, gitlabProvider, googleProvider, slackProvider };