@leanmcp/auth 0.4.2 → 0.4.4-alpha.6.6dae082
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.
- package/README.md +37 -23
- package/dist/{auth0-UTD4QBG6.mjs → auth0-DWCHZ7IN.mjs} +1 -1
- package/dist/{chunk-RGCCBQWG.mjs → chunk-MXTUNMHA.mjs} +4 -4
- package/dist/{chunk-P4HFKA5R.mjs → chunk-ZJYMG6ZM.mjs} +4 -4
- package/dist/{clerk-3SDKGD6C.mjs → clerk-YVTZMRLF.mjs} +1 -1
- package/dist/client/index.d.mts +499 -0
- package/dist/client/index.d.ts +499 -0
- package/dist/client/index.js +56 -56
- package/dist/client/index.mjs +53 -53
- package/dist/{cognito-QQT7LK2Y.mjs → cognito-XKPEG6UH.mjs} +1 -1
- package/dist/index.d.mts +181 -0
- package/dist/index.d.ts +181 -0
- package/dist/index.js +8 -8
- package/dist/index.mjs +1 -1
- package/dist/{leanmcp-Y7TXNSTD.mjs → leanmcp-73RUGZ2B.mjs} +9 -9
- package/dist/proxy/index.d.mts +376 -0
- package/dist/proxy/index.d.ts +376 -0
- package/dist/proxy/index.js +36 -36
- package/dist/proxy/index.mjs +36 -36
- package/dist/server/index.d.mts +496 -0
- package/dist/server/index.d.ts +496 -0
- package/dist/server/index.js +69 -69
- package/dist/server/index.mjs +69 -69
- package/dist/storage/index.d.mts +181 -0
- package/dist/storage/index.d.ts +181 -0
- package/dist/storage/index.js +24 -24
- package/dist/storage/index.mjs +21 -21
- package/dist/types-DMpGN530.d.mts +122 -0
- package/dist/types-DMpGN530.d.ts +122 -0
- package/package.json +2 -1
|
@@ -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 };
|
package/dist/proxy/index.js
CHANGED
|
@@ -233,28 +233,28 @@ var OAuthProxy = class {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
/**
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
* Get configured providers
|
|
237
|
+
*/
|
|
238
238
|
getProviders() {
|
|
239
239
|
return this.config.providers;
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
* Get a provider by ID
|
|
243
|
+
*/
|
|
244
244
|
getProvider(id) {
|
|
245
245
|
return this.providersMap.get(id);
|
|
246
246
|
}
|
|
247
247
|
/**
|
|
248
|
-
|
|
249
|
-
|
|
248
|
+
* Generate state parameter with signature
|
|
249
|
+
*/
|
|
250
250
|
generateState() {
|
|
251
251
|
const nonce = (0, import_crypto2.randomUUID)();
|
|
252
252
|
const signature = (0, import_crypto2.createHmac)("sha256", this.config.sessionSecret).update(nonce).digest("hex").substring(0, 8);
|
|
253
253
|
return `${nonce}.${signature}`;
|
|
254
254
|
}
|
|
255
255
|
/**
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
* Verify state parameter signature
|
|
257
|
+
*/
|
|
258
258
|
verifyState(state) {
|
|
259
259
|
const [nonce, signature] = state.split(".");
|
|
260
260
|
if (!nonce || !signature) return false;
|
|
@@ -262,13 +262,13 @@ var OAuthProxy = class {
|
|
|
262
262
|
return signature === expectedSignature;
|
|
263
263
|
}
|
|
264
264
|
/**
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
265
|
+
* Handle authorization request
|
|
266
|
+
*
|
|
267
|
+
* Redirects the user to the external provider's authorization page.
|
|
268
|
+
*
|
|
269
|
+
* @param params - Request parameters
|
|
270
|
+
* @returns URL to redirect the user to
|
|
271
|
+
*/
|
|
272
272
|
handleAuthorize(params) {
|
|
273
273
|
const provider = this.providersMap.get(params.provider);
|
|
274
274
|
if (!provider) {
|
|
@@ -311,13 +311,13 @@ var OAuthProxy = class {
|
|
|
311
311
|
return authUrl.toString();
|
|
312
312
|
}
|
|
313
313
|
/**
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
314
|
+
* Handle callback from external provider
|
|
315
|
+
*
|
|
316
|
+
* Exchanges the authorization code for tokens and maps them.
|
|
317
|
+
*
|
|
318
|
+
* @param params - Callback query parameters
|
|
319
|
+
* @returns Result with redirect URI and tokens
|
|
320
|
+
*/
|
|
321
321
|
async handleCallback(params) {
|
|
322
322
|
const { code, state, error, error_description } = params;
|
|
323
323
|
if (error) {
|
|
@@ -372,8 +372,8 @@ var OAuthProxy = class {
|
|
|
372
372
|
};
|
|
373
373
|
}
|
|
374
374
|
/**
|
|
375
|
-
|
|
376
|
-
|
|
375
|
+
* Exchange authorization code for tokens with external provider
|
|
376
|
+
*/
|
|
377
377
|
async exchangeCodeForTokens(provider, code, redirectUri, codeVerifier) {
|
|
378
378
|
const tokenPayload = {
|
|
379
379
|
grant_type: "authorization_code",
|
|
@@ -394,7 +394,7 @@ var OAuthProxy = class {
|
|
|
394
394
|
}
|
|
395
395
|
const headers = {
|
|
396
396
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
397
|
-
|
|
397
|
+
Accept: "application/json"
|
|
398
398
|
};
|
|
399
399
|
if (provider.tokenEndpointAuthMethod === "client_secret_basic") {
|
|
400
400
|
const credentials = Buffer.from(`${provider.clientId}:${provider.clientSecret}`).toString("base64");
|
|
@@ -412,8 +412,8 @@ var OAuthProxy = class {
|
|
|
412
412
|
return response.json();
|
|
413
413
|
}
|
|
414
414
|
/**
|
|
415
|
-
|
|
416
|
-
|
|
415
|
+
* Fetch user info from external provider
|
|
416
|
+
*/
|
|
417
417
|
async fetchUserInfo(provider, accessToken) {
|
|
418
418
|
if (!provider.userInfoEndpoint) {
|
|
419
419
|
return {
|
|
@@ -422,8 +422,8 @@ var OAuthProxy = class {
|
|
|
422
422
|
}
|
|
423
423
|
const response = await fetch(provider.userInfoEndpoint, {
|
|
424
424
|
headers: {
|
|
425
|
-
|
|
426
|
-
|
|
425
|
+
Authorization: `Bearer ${accessToken}`,
|
|
426
|
+
Accept: "application/json"
|
|
427
427
|
}
|
|
428
428
|
});
|
|
429
429
|
if (!response.ok) {
|
|
@@ -443,9 +443,9 @@ var OAuthProxy = class {
|
|
|
443
443
|
};
|
|
444
444
|
}
|
|
445
445
|
/**
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
446
|
+
* Generate an internal authorization code for the mapped tokens
|
|
447
|
+
* This code can be exchanged via the token endpoint
|
|
448
|
+
*/
|
|
449
449
|
generateInternalCode(tokens) {
|
|
450
450
|
const code = (0, import_crypto2.randomUUID)();
|
|
451
451
|
const signature = (0, import_crypto2.createHmac)("sha256", this.config.sessionSecret).update(code).update(JSON.stringify(tokens)).digest("hex").substring(0, 16);
|
|
@@ -462,8 +462,8 @@ var OAuthProxy = class {
|
|
|
462
462
|
return fullCode;
|
|
463
463
|
}
|
|
464
464
|
/**
|
|
465
|
-
|
|
466
|
-
|
|
465
|
+
* Handle token request (exchange internal code for tokens)
|
|
466
|
+
*/
|
|
467
467
|
async handleToken(params) {
|
|
468
468
|
const { grant_type, code, refresh_token } = params;
|
|
469
469
|
if (grant_type === "authorization_code") {
|
|
@@ -486,8 +486,8 @@ var OAuthProxy = class {
|
|
|
486
486
|
throw new Error(`Unsupported grant_type: ${grant_type}`);
|
|
487
487
|
}
|
|
488
488
|
/**
|
|
489
|
-
|
|
490
|
-
|
|
489
|
+
* Express/Connect middleware factory
|
|
490
|
+
*/
|
|
491
491
|
createMiddleware() {
|
|
492
492
|
return {
|
|
493
493
|
authorize: /* @__PURE__ */ __name((req, res) => {
|
package/dist/proxy/index.mjs
CHANGED
|
@@ -178,28 +178,28 @@ var OAuthProxy = class {
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
/**
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
* Get configured providers
|
|
182
|
+
*/
|
|
183
183
|
getProviders() {
|
|
184
184
|
return this.config.providers;
|
|
185
185
|
}
|
|
186
186
|
/**
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
* Get a provider by ID
|
|
188
|
+
*/
|
|
189
189
|
getProvider(id) {
|
|
190
190
|
return this.providersMap.get(id);
|
|
191
191
|
}
|
|
192
192
|
/**
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
* Generate state parameter with signature
|
|
194
|
+
*/
|
|
195
195
|
generateState() {
|
|
196
196
|
const nonce = randomUUID();
|
|
197
197
|
const signature = createHmac("sha256", this.config.sessionSecret).update(nonce).digest("hex").substring(0, 8);
|
|
198
198
|
return `${nonce}.${signature}`;
|
|
199
199
|
}
|
|
200
200
|
/**
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
* Verify state parameter signature
|
|
202
|
+
*/
|
|
203
203
|
verifyState(state) {
|
|
204
204
|
const [nonce, signature] = state.split(".");
|
|
205
205
|
if (!nonce || !signature) return false;
|
|
@@ -207,13 +207,13 @@ var OAuthProxy = class {
|
|
|
207
207
|
return signature === expectedSignature;
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
* Handle authorization request
|
|
211
|
+
*
|
|
212
|
+
* Redirects the user to the external provider's authorization page.
|
|
213
|
+
*
|
|
214
|
+
* @param params - Request parameters
|
|
215
|
+
* @returns URL to redirect the user to
|
|
216
|
+
*/
|
|
217
217
|
handleAuthorize(params) {
|
|
218
218
|
const provider = this.providersMap.get(params.provider);
|
|
219
219
|
if (!provider) {
|
|
@@ -256,13 +256,13 @@ var OAuthProxy = class {
|
|
|
256
256
|
return authUrl.toString();
|
|
257
257
|
}
|
|
258
258
|
/**
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
259
|
+
* Handle callback from external provider
|
|
260
|
+
*
|
|
261
|
+
* Exchanges the authorization code for tokens and maps them.
|
|
262
|
+
*
|
|
263
|
+
* @param params - Callback query parameters
|
|
264
|
+
* @returns Result with redirect URI and tokens
|
|
265
|
+
*/
|
|
266
266
|
async handleCallback(params) {
|
|
267
267
|
const { code, state, error, error_description } = params;
|
|
268
268
|
if (error) {
|
|
@@ -317,8 +317,8 @@ var OAuthProxy = class {
|
|
|
317
317
|
};
|
|
318
318
|
}
|
|
319
319
|
/**
|
|
320
|
-
|
|
321
|
-
|
|
320
|
+
* Exchange authorization code for tokens with external provider
|
|
321
|
+
*/
|
|
322
322
|
async exchangeCodeForTokens(provider, code, redirectUri, codeVerifier) {
|
|
323
323
|
const tokenPayload = {
|
|
324
324
|
grant_type: "authorization_code",
|
|
@@ -339,7 +339,7 @@ var OAuthProxy = class {
|
|
|
339
339
|
}
|
|
340
340
|
const headers = {
|
|
341
341
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
342
|
-
|
|
342
|
+
Accept: "application/json"
|
|
343
343
|
};
|
|
344
344
|
if (provider.tokenEndpointAuthMethod === "client_secret_basic") {
|
|
345
345
|
const credentials = Buffer.from(`${provider.clientId}:${provider.clientSecret}`).toString("base64");
|
|
@@ -357,8 +357,8 @@ var OAuthProxy = class {
|
|
|
357
357
|
return response.json();
|
|
358
358
|
}
|
|
359
359
|
/**
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
* Fetch user info from external provider
|
|
361
|
+
*/
|
|
362
362
|
async fetchUserInfo(provider, accessToken) {
|
|
363
363
|
if (!provider.userInfoEndpoint) {
|
|
364
364
|
return {
|
|
@@ -367,8 +367,8 @@ var OAuthProxy = class {
|
|
|
367
367
|
}
|
|
368
368
|
const response = await fetch(provider.userInfoEndpoint, {
|
|
369
369
|
headers: {
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
Authorization: `Bearer ${accessToken}`,
|
|
371
|
+
Accept: "application/json"
|
|
372
372
|
}
|
|
373
373
|
});
|
|
374
374
|
if (!response.ok) {
|
|
@@ -388,9 +388,9 @@ var OAuthProxy = class {
|
|
|
388
388
|
};
|
|
389
389
|
}
|
|
390
390
|
/**
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
391
|
+
* Generate an internal authorization code for the mapped tokens
|
|
392
|
+
* This code can be exchanged via the token endpoint
|
|
393
|
+
*/
|
|
394
394
|
generateInternalCode(tokens) {
|
|
395
395
|
const code = randomUUID();
|
|
396
396
|
const signature = createHmac("sha256", this.config.sessionSecret).update(code).update(JSON.stringify(tokens)).digest("hex").substring(0, 16);
|
|
@@ -407,8 +407,8 @@ var OAuthProxy = class {
|
|
|
407
407
|
return fullCode;
|
|
408
408
|
}
|
|
409
409
|
/**
|
|
410
|
-
|
|
411
|
-
|
|
410
|
+
* Handle token request (exchange internal code for tokens)
|
|
411
|
+
*/
|
|
412
412
|
async handleToken(params) {
|
|
413
413
|
const { grant_type, code, refresh_token } = params;
|
|
414
414
|
if (grant_type === "authorization_code") {
|
|
@@ -431,8 +431,8 @@ var OAuthProxy = class {
|
|
|
431
431
|
throw new Error(`Unsupported grant_type: ${grant_type}`);
|
|
432
432
|
}
|
|
433
433
|
/**
|
|
434
|
-
|
|
435
|
-
|
|
434
|
+
* Express/Connect middleware factory
|
|
435
|
+
*/
|
|
436
436
|
createMiddleware() {
|
|
437
437
|
return {
|
|
438
438
|
authorize: /* @__PURE__ */ __name((req, res) => {
|