@leanmcp/auth 0.4.2 → 0.4.4-alpha.10.96d2437
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 +3 -2
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 || [];
|
package/dist/server/index.mjs
CHANGED
|
@@ -114,11 +114,11 @@ var DynamicClientRegistration = class {
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
* Register a new OAuth client (stateless)
|
|
118
|
+
*
|
|
119
|
+
* @param request - Client registration request per RFC 7591
|
|
120
|
+
* @returns Client registration response with JWT credentials
|
|
121
|
+
*/
|
|
122
122
|
register(request) {
|
|
123
123
|
const now = Date.now();
|
|
124
124
|
const nowSeconds = Math.floor(now / 1e3);
|
|
@@ -160,12 +160,12 @@ var DynamicClientRegistration = class {
|
|
|
160
160
|
return response;
|
|
161
161
|
}
|
|
162
162
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
163
|
+
* Validate client credentials (stateless)
|
|
164
|
+
*
|
|
165
|
+
* @param clientId - Client ID (JWT with prefix)
|
|
166
|
+
* @param clientSecret - Client secret (optional for public clients)
|
|
167
|
+
* @returns Whether credentials are valid
|
|
168
|
+
*/
|
|
169
169
|
validate(clientId, clientSecret) {
|
|
170
170
|
try {
|
|
171
171
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -182,8 +182,8 @@ var DynamicClientRegistration = class {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
/**
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
* Get a registered client by ID (stateless)
|
|
186
|
+
*/
|
|
187
187
|
getClient(clientId) {
|
|
188
188
|
try {
|
|
189
189
|
const jwtWithoutPrefix = this.extractJWT(clientId);
|
|
@@ -205,8 +205,8 @@ var DynamicClientRegistration = class {
|
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
/**
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
* Validate redirect URI for a client
|
|
209
|
+
*/
|
|
210
210
|
validateRedirectUri(clientId, redirectUri) {
|
|
211
211
|
const client = this.getClient(clientId);
|
|
212
212
|
if (!client) return false;
|
|
@@ -214,29 +214,29 @@ var DynamicClientRegistration = class {
|
|
|
214
214
|
return client.redirect_uris.includes(redirectUri);
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
217
|
+
* Delete a client (no-op in stateless mode)
|
|
218
|
+
*
|
|
219
|
+
* In stateless mode, clients cannot be truly "deleted" because
|
|
220
|
+
* their credentials are self-contained. They will expire naturally
|
|
221
|
+
* or when the signing secret is rotated.
|
|
222
|
+
*/
|
|
223
223
|
delete(clientId) {
|
|
224
224
|
return this.getClient(clientId) !== void 0;
|
|
225
225
|
}
|
|
226
226
|
/**
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
* List all registered clients (not supported in stateless mode)
|
|
228
|
+
*/
|
|
229
229
|
listClients() {
|
|
230
230
|
throw new Error("listClients() is not supported in stateless DCR mode");
|
|
231
231
|
}
|
|
232
232
|
/**
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
* Clear all clients (no-op in stateless mode)
|
|
234
|
+
*/
|
|
235
235
|
clearAll() {
|
|
236
236
|
}
|
|
237
237
|
/**
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
* Extract JWT from prefixed client_id
|
|
239
|
+
*/
|
|
240
240
|
extractJWT(clientId) {
|
|
241
241
|
if (!clientId.startsWith(this.options.clientIdPrefix)) {
|
|
242
242
|
return null;
|
|
@@ -244,11 +244,11 @@ var DynamicClientRegistration = class {
|
|
|
244
244
|
return clientId.slice(this.options.clientIdPrefix.length);
|
|
245
245
|
}
|
|
246
246
|
/**
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
247
|
+
* Derive client secret from client_id JWT
|
|
248
|
+
*
|
|
249
|
+
* Uses HMAC to create a deterministic secret that can be
|
|
250
|
+
* validated without storage.
|
|
251
|
+
*/
|
|
252
252
|
deriveClientSecret(clientIdJWT) {
|
|
253
253
|
const { createHmac: createHmac3 } = __require("crypto");
|
|
254
254
|
return createHmac3("sha256", this.options.signingSecret).update(clientIdJWT).digest("hex");
|
|
@@ -297,16 +297,16 @@ var OAuthAuthorizationServer = class {
|
|
|
297
297
|
});
|
|
298
298
|
}
|
|
299
299
|
/**
|
|
300
|
-
|
|
301
|
-
|
|
300
|
+
* Generate state parameter with HMAC signature
|
|
301
|
+
*/
|
|
302
302
|
generateState() {
|
|
303
303
|
const nonce = randomUUID2();
|
|
304
304
|
const signature = createHmac2("sha256", this.options.sessionSecret).update(nonce).digest("hex").substring(0, 8);
|
|
305
305
|
return `${nonce}.${signature}`;
|
|
306
306
|
}
|
|
307
307
|
/**
|
|
308
|
-
|
|
309
|
-
|
|
308
|
+
* Verify state parameter signature
|
|
309
|
+
*/
|
|
310
310
|
verifyState(state) {
|
|
311
311
|
const [nonce, signature] = state.split(".");
|
|
312
312
|
if (!nonce || !signature) return false;
|
|
@@ -314,14 +314,14 @@ var OAuthAuthorizationServer = class {
|
|
|
314
314
|
return signature === expectedSignature;
|
|
315
315
|
}
|
|
316
316
|
/**
|
|
317
|
-
|
|
318
|
-
|
|
317
|
+
* Generate an authorization code
|
|
318
|
+
*/
|
|
319
319
|
generateAuthCode() {
|
|
320
320
|
return randomBytes2(32).toString("hex");
|
|
321
321
|
}
|
|
322
322
|
/**
|
|
323
|
-
|
|
324
|
-
|
|
323
|
+
* Generate JWT access token with encrypted upstream credentials
|
|
324
|
+
*/
|
|
325
325
|
generateAccessToken(claims, upstreamToken) {
|
|
326
326
|
const now = Math.floor(Date.now() / 1e3);
|
|
327
327
|
const jwtSigningSecret = this.options.jwtSigningSecret || this.options.sessionSecret;
|
|
@@ -348,8 +348,8 @@ var OAuthAuthorizationServer = class {
|
|
|
348
348
|
return signJWT(payload, jwtSigningSecret);
|
|
349
349
|
}
|
|
350
350
|
/**
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
* Get authorization server metadata (RFC 8414)
|
|
352
|
+
*/
|
|
353
353
|
getMetadata() {
|
|
354
354
|
const issuer = this.options.issuer;
|
|
355
355
|
return {
|
|
@@ -376,8 +376,8 @@ var OAuthAuthorizationServer = class {
|
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
378
|
/**
|
|
379
|
-
|
|
380
|
-
|
|
379
|
+
* Get Express router with all OAuth endpoints
|
|
380
|
+
*/
|
|
381
381
|
getRouter() {
|
|
382
382
|
const router = express.Router();
|
|
383
383
|
router.get("/.well-known/oauth-authorization-server", (_req, res) => {
|
|
@@ -410,8 +410,8 @@ var OAuthAuthorizationServer = class {
|
|
|
410
410
|
return router;
|
|
411
411
|
}
|
|
412
412
|
/**
|
|
413
|
-
|
|
414
|
-
|
|
413
|
+
* Handle authorization request
|
|
414
|
+
*/
|
|
415
415
|
handleAuthorize(req, res) {
|
|
416
416
|
const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method, resource } = req.query;
|
|
417
417
|
if (response_type !== "code") {
|
|
@@ -480,8 +480,8 @@ var OAuthAuthorizationServer = class {
|
|
|
480
480
|
res.redirect(authUrl.toString());
|
|
481
481
|
}
|
|
482
482
|
/**
|
|
483
|
-
|
|
484
|
-
|
|
483
|
+
* Handle callback from upstream provider
|
|
484
|
+
*/
|
|
485
485
|
async handleCallback(req, res) {
|
|
486
486
|
const { code, state, error, error_description } = req.query;
|
|
487
487
|
if (error) {
|
|
@@ -533,7 +533,7 @@ var OAuthAuthorizationServer = class {
|
|
|
533
533
|
const tokenResponse = await fetch(upstream.tokenEndpoint, {
|
|
534
534
|
method: "POST",
|
|
535
535
|
headers: {
|
|
536
|
-
|
|
536
|
+
Accept: "application/json",
|
|
537
537
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
538
538
|
},
|
|
539
539
|
body: new URLSearchParams({
|
|
@@ -553,8 +553,8 @@ var OAuthAuthorizationServer = class {
|
|
|
553
553
|
if (upstream.userInfoEndpoint && upstreamTokens.access_token) {
|
|
554
554
|
const userInfoResponse = await fetch(upstream.userInfoEndpoint, {
|
|
555
555
|
headers: {
|
|
556
|
-
|
|
557
|
-
|
|
556
|
+
Authorization: `Bearer ${upstreamTokens.access_token}`,
|
|
557
|
+
Accept: "application/json"
|
|
558
558
|
}
|
|
559
559
|
});
|
|
560
560
|
if (userInfoResponse.ok) {
|
|
@@ -591,8 +591,8 @@ var OAuthAuthorizationServer = class {
|
|
|
591
591
|
}
|
|
592
592
|
}
|
|
593
593
|
/**
|
|
594
|
-
|
|
595
|
-
|
|
594
|
+
* Handle token request
|
|
595
|
+
*/
|
|
596
596
|
async handleToken(req, res) {
|
|
597
597
|
const { grant_type, code, redirect_uri, client_id, client_secret, code_verifier } = req.body;
|
|
598
598
|
let clientId = client_id;
|
|
@@ -638,8 +638,8 @@ var OAuthAuthorizationServer = class {
|
|
|
638
638
|
}
|
|
639
639
|
}
|
|
640
640
|
/**
|
|
641
|
-
|
|
642
|
-
|
|
641
|
+
* Handle authorization code grant
|
|
642
|
+
*/
|
|
643
643
|
async handleAuthCodeGrant(res, clientId, code, redirectUri, codeVerifier) {
|
|
644
644
|
if (!code) {
|
|
645
645
|
res.status(400).json({
|
|
@@ -742,11 +742,11 @@ var TokenVerifier = class {
|
|
|
742
742
|
};
|
|
743
743
|
}
|
|
744
744
|
/**
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
745
|
+
* Verify a JWT access token
|
|
746
|
+
*
|
|
747
|
+
* @param token - The JWT access token to verify
|
|
748
|
+
* @returns Verification result with claims and decrypted upstream token if valid
|
|
749
|
+
*/
|
|
750
750
|
async verify(token) {
|
|
751
751
|
if (!token) {
|
|
752
752
|
return {
|
|
@@ -809,13 +809,13 @@ var TokenVerifier = class {
|
|
|
809
809
|
}
|
|
810
810
|
}
|
|
811
811
|
/**
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
812
|
+
* Generate WWW-Authenticate header for 401 responses
|
|
813
|
+
*
|
|
814
|
+
* Per RFC 9728, this should include the resource_metadata URL
|
|
815
|
+
*
|
|
816
|
+
* @param options - Header options
|
|
817
|
+
* @returns WWW-Authenticate header value
|
|
818
|
+
*/
|
|
819
819
|
static getWWWAuthenticateHeader(options) {
|
|
820
820
|
const parts = [
|
|
821
821
|
`Bearer resource_metadata="${options.resourceMetadataUrl}"`
|
|
@@ -832,8 +832,8 @@ var TokenVerifier = class {
|
|
|
832
832
|
return parts.join(", ");
|
|
833
833
|
}
|
|
834
834
|
/**
|
|
835
|
-
|
|
836
|
-
|
|
835
|
+
* Check if token has required scopes
|
|
836
|
+
*/
|
|
837
837
|
hasScopes(claims, requiredScopes) {
|
|
838
838
|
if (requiredScopes.length === 0) return true;
|
|
839
839
|
const tokenScopes = typeof claims.scope === "string" ? claims.scope.split(" ") : claims.scope || [];
|