@leanmcp/auth 0.4.3 → 0.4.4-alpha.8.f4673cd
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/LICENSE +21 -21
- package/README.md +410 -396
- 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.js +56 -56
- package/dist/client/index.mjs +53 -53
- package/dist/{cognito-QQT7LK2Y.mjs → cognito-XKPEG6UH.mjs} +1 -1
- 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.js +36 -36
- package/dist/proxy/index.mjs +36 -36
- package/dist/server/index.js +69 -69
- package/dist/server/index.mjs +69 -69
- package/dist/storage/index.js +24 -24
- package/dist/storage/index.mjs +21 -21
- package/package.json +121 -121
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) => {
|
package/dist/server/index.js
CHANGED
|
@@ -148,11 +148,11 @@ var DynamicClientRegistration = class {
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
151
|
+
* Register a new OAuth client (stateless)
|
|
152
|
+
*
|
|
153
|
+
* @param request - Client registration request per RFC 7591
|
|
154
|
+
* @returns Client registration response with JWT credentials
|
|
155
|
+
*/
|
|
156
156
|
register(request) {
|
|
157
157
|
const now = Date.now();
|
|
158
158
|
const nowSeconds = Math.floor(now / 1e3);
|
|
@@ -194,12 +194,12 @@ var DynamicClientRegistration = class {
|
|
|
194
194
|
return response;
|
|
195
195
|
}
|
|
196
196
|
/**
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
197
|
+
* Validate client credentials (stateless)
|
|
198
|
+
*
|
|
199
|
+
* @param clientId - Client ID (JWT with prefix)
|
|
200
|
+
* @param clientSecret - Client secret (optional for public clients)
|
|
201
|
+
* @returns Whether credentials are valid
|
|
202
|
+
*/
|
|
203
203
|
validate(clientId, clientSecret) {
|
|
204
204
|
try {
|
|
205
205
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -216,8 +216,8 @@ var DynamicClientRegistration = class {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
/**
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
* Get a registered client by ID (stateless)
|
|
220
|
+
*/
|
|
221
221
|
getClient(clientId) {
|
|
222
222
|
try {
|
|
223
223
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -239,8 +239,8 @@ var DynamicClientRegistration = class {
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
* Validate redirect URI for a client
|
|
243
|
+
*/
|
|
244
244
|
validateRedirectUri(clientId, redirectUri) {
|
|
245
245
|
const client = this.getClient(clientId);
|
|
246
246
|
if (!client) return false;
|
|
@@ -248,29 +248,29 @@ var DynamicClientRegistration = class {
|
|
|
248
248
|
return client.redirect_uris.includes(redirectUri);
|
|
249
249
|
}
|
|
250
250
|
/**
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
251
|
+
* Delete a client (no-op in stateless mode)
|
|
252
|
+
*
|
|
253
|
+
* In stateless mode, clients cannot be truly "deleted" because
|
|
254
|
+
* their credentials are self-contained. They will expire naturally
|
|
255
|
+
* or when the signing secret is rotated.
|
|
256
|
+
*/
|
|
257
257
|
delete(clientId) {
|
|
258
258
|
return this.getClient(clientId) !== void 0;
|
|
259
259
|
}
|
|
260
260
|
/**
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
* List all registered clients (not supported in stateless mode)
|
|
262
|
+
*/
|
|
263
263
|
listClients() {
|
|
264
264
|
throw new Error("listClients() is not supported in stateless DCR mode");
|
|
265
265
|
}
|
|
266
266
|
/**
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
* Clear all clients (no-op in stateless mode)
|
|
268
|
+
*/
|
|
269
269
|
clearAll() {
|
|
270
270
|
}
|
|
271
271
|
/**
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
* Extract JWT from prefixed client_id
|
|
273
|
+
*/
|
|
274
274
|
extractJWT(clientId) {
|
|
275
275
|
if (!clientId.startsWith(this.options.clientIdPrefix)) {
|
|
276
276
|
return null;
|
|
@@ -278,11 +278,11 @@ var DynamicClientRegistration = class {
|
|
|
278
278
|
return clientId.slice(this.options.clientIdPrefix.length);
|
|
279
279
|
}
|
|
280
280
|
/**
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
281
|
+
* Derive client secret from client_id JWT
|
|
282
|
+
*
|
|
283
|
+
* Uses HMAC to create a deterministic secret that can be
|
|
284
|
+
* validated without storage.
|
|
285
|
+
*/
|
|
286
286
|
deriveClientSecret(clientIdJWT) {
|
|
287
287
|
const { createHmac: createHmac3 } = require("crypto");
|
|
288
288
|
return createHmac3("sha256", this.options.signingSecret).update(clientIdJWT).digest("hex");
|
|
@@ -331,16 +331,16 @@ var OAuthAuthorizationServer = class {
|
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
333
|
/**
|
|
334
|
-
|
|
335
|
-
|
|
334
|
+
* Generate state parameter with HMAC signature
|
|
335
|
+
*/
|
|
336
336
|
generateState() {
|
|
337
337
|
const nonce = (0, import_crypto3.randomUUID)();
|
|
338
338
|
const signature = (0, import_crypto3.createHmac)("sha256", this.options.sessionSecret).update(nonce).digest("hex").substring(0, 8);
|
|
339
339
|
return `${nonce}.${signature}`;
|
|
340
340
|
}
|
|
341
341
|
/**
|
|
342
|
-
|
|
343
|
-
|
|
342
|
+
* Verify state parameter signature
|
|
343
|
+
*/
|
|
344
344
|
verifyState(state) {
|
|
345
345
|
const [nonce, signature] = state.split(".");
|
|
346
346
|
if (!nonce || !signature) return false;
|
|
@@ -348,14 +348,14 @@ var OAuthAuthorizationServer = class {
|
|
|
348
348
|
return signature === expectedSignature;
|
|
349
349
|
}
|
|
350
350
|
/**
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
* Generate an authorization code
|
|
352
|
+
*/
|
|
353
353
|
generateAuthCode() {
|
|
354
354
|
return (0, import_crypto3.randomBytes)(32).toString("hex");
|
|
355
355
|
}
|
|
356
356
|
/**
|
|
357
|
-
|
|
358
|
-
|
|
357
|
+
* Generate JWT access token with encrypted upstream credentials
|
|
358
|
+
*/
|
|
359
359
|
generateAccessToken(claims, upstreamToken) {
|
|
360
360
|
const now = Math.floor(Date.now() / 1e3);
|
|
361
361
|
const jwtSigningSecret = this.options.jwtSigningSecret || this.options.sessionSecret;
|
|
@@ -382,8 +382,8 @@ var OAuthAuthorizationServer = class {
|
|
|
382
382
|
return signJWT(payload, jwtSigningSecret);
|
|
383
383
|
}
|
|
384
384
|
/**
|
|
385
|
-
|
|
386
|
-
|
|
385
|
+
* Get authorization server metadata (RFC 8414)
|
|
386
|
+
*/
|
|
387
387
|
getMetadata() {
|
|
388
388
|
const issuer = this.options.issuer;
|
|
389
389
|
return {
|
|
@@ -410,8 +410,8 @@ var OAuthAuthorizationServer = class {
|
|
|
410
410
|
};
|
|
411
411
|
}
|
|
412
412
|
/**
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
* Get Express router with all OAuth endpoints
|
|
414
|
+
*/
|
|
415
415
|
getRouter() {
|
|
416
416
|
const router = import_express.default.Router();
|
|
417
417
|
router.get("/.well-known/oauth-authorization-server", (_req, res) => {
|
|
@@ -444,8 +444,8 @@ var OAuthAuthorizationServer = class {
|
|
|
444
444
|
return router;
|
|
445
445
|
}
|
|
446
446
|
/**
|
|
447
|
-
|
|
448
|
-
|
|
447
|
+
* Handle authorization request
|
|
448
|
+
*/
|
|
449
449
|
handleAuthorize(req, res) {
|
|
450
450
|
const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method, resource } = req.query;
|
|
451
451
|
if (response_type !== "code") {
|
|
@@ -514,8 +514,8 @@ var OAuthAuthorizationServer = class {
|
|
|
514
514
|
res.redirect(authUrl.toString());
|
|
515
515
|
}
|
|
516
516
|
/**
|
|
517
|
-
|
|
518
|
-
|
|
517
|
+
* Handle callback from upstream provider
|
|
518
|
+
*/
|
|
519
519
|
async handleCallback(req, res) {
|
|
520
520
|
const { code, state, error, error_description } = req.query;
|
|
521
521
|
if (error) {
|
|
@@ -567,7 +567,7 @@ var OAuthAuthorizationServer = class {
|
|
|
567
567
|
const tokenResponse = await fetch(upstream.tokenEndpoint, {
|
|
568
568
|
method: "POST",
|
|
569
569
|
headers: {
|
|
570
|
-
|
|
570
|
+
Accept: "application/json",
|
|
571
571
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
572
572
|
},
|
|
573
573
|
body: new URLSearchParams({
|
|
@@ -587,8 +587,8 @@ var OAuthAuthorizationServer = class {
|
|
|
587
587
|
if (upstream.userInfoEndpoint && upstreamTokens.access_token) {
|
|
588
588
|
const userInfoResponse = await fetch(upstream.userInfoEndpoint, {
|
|
589
589
|
headers: {
|
|
590
|
-
|
|
591
|
-
|
|
590
|
+
Authorization: `Bearer ${upstreamTokens.access_token}`,
|
|
591
|
+
Accept: "application/json"
|
|
592
592
|
}
|
|
593
593
|
});
|
|
594
594
|
if (userInfoResponse.ok) {
|
|
@@ -625,8 +625,8 @@ var OAuthAuthorizationServer = class {
|
|
|
625
625
|
}
|
|
626
626
|
}
|
|
627
627
|
/**
|
|
628
|
-
|
|
629
|
-
|
|
628
|
+
* Handle token request
|
|
629
|
+
*/
|
|
630
630
|
async handleToken(req, res) {
|
|
631
631
|
const { grant_type, code, redirect_uri, client_id, client_secret, code_verifier } = req.body;
|
|
632
632
|
let clientId = client_id;
|
|
@@ -672,8 +672,8 @@ var OAuthAuthorizationServer = class {
|
|
|
672
672
|
}
|
|
673
673
|
}
|
|
674
674
|
/**
|
|
675
|
-
|
|
676
|
-
|
|
675
|
+
* Handle authorization code grant
|
|
676
|
+
*/
|
|
677
677
|
async handleAuthCodeGrant(res, clientId, code, redirectUri, codeVerifier) {
|
|
678
678
|
if (!code) {
|
|
679
679
|
res.status(400).json({
|
|
@@ -776,11 +776,11 @@ var TokenVerifier = class {
|
|
|
776
776
|
};
|
|
777
777
|
}
|
|
778
778
|
/**
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
779
|
+
* Verify a JWT access token
|
|
780
|
+
*
|
|
781
|
+
* @param token - The JWT access token to verify
|
|
782
|
+
* @returns Verification result with claims and decrypted upstream token if valid
|
|
783
|
+
*/
|
|
784
784
|
async verify(token) {
|
|
785
785
|
if (!token) {
|
|
786
786
|
return {
|
|
@@ -843,13 +843,13 @@ var TokenVerifier = class {
|
|
|
843
843
|
}
|
|
844
844
|
}
|
|
845
845
|
/**
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
846
|
+
* Generate WWW-Authenticate header for 401 responses
|
|
847
|
+
*
|
|
848
|
+
* Per RFC 9728, this should include the resource_metadata URL
|
|
849
|
+
*
|
|
850
|
+
* @param options - Header options
|
|
851
|
+
* @returns WWW-Authenticate header value
|
|
852
|
+
*/
|
|
853
853
|
static getWWWAuthenticateHeader(options) {
|
|
854
854
|
const parts = [
|
|
855
855
|
`Bearer resource_metadata="${options.resourceMetadataUrl}"`
|
|
@@ -866,8 +866,8 @@ var TokenVerifier = class {
|
|
|
866
866
|
return parts.join(", ");
|
|
867
867
|
}
|
|
868
868
|
/**
|
|
869
|
-
|
|
870
|
-
|
|
869
|
+
* Check if token has required scopes
|
|
870
|
+
*/
|
|
871
871
|
hasScopes(claims, requiredScopes) {
|
|
872
872
|
if (requiredScopes.length === 0) return true;
|
|
873
873
|
const tokenScopes = typeof claims.scope === "string" ? claims.scope.split(" ") : claims.scope || [];
|