@absolutejs/auth 0.74.0 → 0.75.1
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 +21 -6
- package/dist/agents/index.js +46 -11
- package/dist/agents/index.js.map +4 -4
- package/dist/agents/oidcAdapter.d.ts +3 -1
- package/dist/apikeys/routes.d.ts +1 -1
- package/dist/compliance/routes.d.ts +1 -1
- package/dist/credentials/emailVerification.d.ts +1 -1
- package/dist/credentials/login.d.ts +1 -1
- package/dist/credentials/passwordReset.d.ts +1 -1
- package/dist/credentials/register.d.ts +1 -1
- package/dist/htmx/configuredRoutes.d.ts +1 -1
- package/dist/htmx/routes.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +166 -68
- package/dist/index.js.map +8 -8
- package/dist/mfa/challenge.d.ts +1 -1
- package/dist/mfa/management.d.ts +1 -1
- package/dist/mfa/sms.d.ts +1 -1
- package/dist/mfa/totp.d.ts +1 -1
- package/dist/nativePush.d.ts +500 -20
- package/dist/oidc/dpop.d.ts +6 -2
- package/dist/oidc/index.d.ts +1 -0
- package/dist/oidc/index.js +130 -1
- package/dist/oidc/index.js.map +4 -3
- package/dist/organizations/routes.d.ts +1 -1
- package/dist/portal/routes.d.ts +1 -1
- package/dist/roles/routes.d.ts +1 -1
- package/dist/routes/authorize.d.ts +1 -1
- package/dist/routes/callback.d.ts +1 -1
- package/dist/routes/profile.d.ts +1 -1
- package/dist/routes/refresh.d.ts +1 -1
- package/dist/routes/revoke.d.ts +1 -1
- package/dist/routes/sessions.d.ts +1 -1
- package/dist/routes/signout.d.ts +1 -1
- package/dist/routes/userStatus.d.ts +1 -1
- package/dist/scim/routes.d.ts +1 -1
- package/dist/server.js +164 -68
- package/dist/server.js.map +8 -8
- package/dist/sso/discoveryRoute.d.ts +1 -1
- package/dist/sso/oidcRoutes.d.ts +1 -1
- package/dist/sso/samlIdpRoutes.d.ts +1 -1
- package/dist/sso/samlRoutes.d.ts +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/vc/statusListRoutes.d.ts +1 -1
- package/dist/vc/vpRoutes.d.ts +1 -1
- package/dist/webauthn/routes.d.ts +1 -1
- package/package.json +1 -1
package/dist/oidc/dpop.d.ts
CHANGED
|
@@ -10,10 +10,14 @@ export declare const verifyDpopNonce: ({ now, nonce, secret }: {
|
|
|
10
10
|
}) => Promise<boolean>;
|
|
11
11
|
export type DpopResult = {
|
|
12
12
|
jkt: string;
|
|
13
|
-
jti
|
|
13
|
+
jti: string;
|
|
14
14
|
};
|
|
15
|
-
export
|
|
15
|
+
export type DpopJti = DpopResult & {
|
|
16
|
+
expiresAt: number;
|
|
17
|
+
};
|
|
18
|
+
export declare const verifyDpopProof: ({ accessToken, consumeJti, htm, htu, isUsedJti, maxAgeMs, now, proof }: {
|
|
16
19
|
accessToken?: string;
|
|
20
|
+
consumeJti?: (jti: DpopJti) => boolean | Promise<boolean>;
|
|
17
21
|
htm: string;
|
|
18
22
|
htu: string;
|
|
19
23
|
isUsedJti?: (jti: string) => boolean | Promise<boolean>;
|
package/dist/oidc/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* through the package root.
|
|
7
7
|
*/
|
|
8
8
|
export type { OidcProviderConfig } from './config';
|
|
9
|
+
export { extractDpopNonceClaim, mintDpopNonce, verifyDpopNonce, verifyDpopProof, type DpopJti, type DpopResult } from './dpop';
|
|
9
10
|
export { generateSigningKey, jwkThumbprint, signJwt, signingVerificationKeys, toPublicJwk, verifyJwt, verifyJwtWithKeys, type SigningKey, type SigningKeyIdentity } from './keys';
|
|
10
11
|
export { revokeOAuthClientCredentials } from './operator';
|
|
11
12
|
export { createNeonAuthorizationCodeStore, createNeonClientAssertionJtiStore, createNeonClientRegistrationTokenStore, createNeonDeviceAuthorizationStore, createNeonInitialAccessTokenStore, createNeonOAuthClientStore, createNeonOidcRefreshTokenStore, createNeonSocketTicketStore, createPostgresAuthorizationCodeStore, createPostgresClientAssertionJtiStore, createPostgresClientRegistrationTokenStore, createPostgresDeviceAuthorizationStore, createPostgresInitialAccessTokenStore, createPostgresOAuthClientStore, createPostgresOidcRefreshTokenStore, createPostgresSocketTicketStore } from './postgresStores';
|
package/dist/oidc/index.js
CHANGED
|
@@ -181,6 +181,9 @@ var init_crypto = __esm(() => {
|
|
|
181
181
|
textDecoder3 = new TextDecoder;
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
// src/oidc/dpop.ts
|
|
185
|
+
init_constants();
|
|
186
|
+
|
|
184
187
|
// src/oidc/keys.ts
|
|
185
188
|
var ENCODER = new TextEncoder;
|
|
186
189
|
var ES256 = { hash: "SHA-256", name: "ECDSA" };
|
|
@@ -280,6 +283,128 @@ var verifyJwtWithKeys = async (token, keys) => {
|
|
|
280
283
|
return;
|
|
281
284
|
return verifyJwt(token, key.publicJwk);
|
|
282
285
|
};
|
|
286
|
+
|
|
287
|
+
// src/oidc/dpop.ts
|
|
288
|
+
var DEFAULT_MAX_AGE_MS = 60000;
|
|
289
|
+
var MAX_JTI_LENGTH = 128;
|
|
290
|
+
var SECONDS_TO_MS = 1000;
|
|
291
|
+
var NONCE_WINDOW_SECONDS = 120;
|
|
292
|
+
var NONCE_WINDOW_MS = NONCE_WINDOW_SECONDS * MILLISECONDS_IN_A_SECOND;
|
|
293
|
+
var NONCE_PREVIOUS_WINDOWS_ACCEPTED = 1;
|
|
294
|
+
var hmacSha256 = async (secret, message) => {
|
|
295
|
+
const encoder = new TextEncoder;
|
|
296
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
|
|
297
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(message));
|
|
298
|
+
return Buffer.from(new Uint8Array(signature)).toString("base64url");
|
|
299
|
+
};
|
|
300
|
+
var extractDpopNonceClaim = (proof) => {
|
|
301
|
+
const [, payloadSegment] = proof.split(".");
|
|
302
|
+
if (payloadSegment === undefined)
|
|
303
|
+
return;
|
|
304
|
+
try {
|
|
305
|
+
const payload = JSON.parse(Buffer.from(payloadSegment, "base64url").toString("utf8"));
|
|
306
|
+
if (typeof payload !== "object" || payload === null)
|
|
307
|
+
return;
|
|
308
|
+
const value = Reflect.get(payload, "nonce");
|
|
309
|
+
return typeof value === "string" ? value : undefined;
|
|
310
|
+
} catch {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
var mintDpopNonce = async ({
|
|
315
|
+
now = Date.now(),
|
|
316
|
+
secret
|
|
317
|
+
}) => {
|
|
318
|
+
const window = Math.floor(now / NONCE_WINDOW_MS);
|
|
319
|
+
return hmacSha256(secret, String(window));
|
|
320
|
+
};
|
|
321
|
+
var verifyDpopNonce = async ({
|
|
322
|
+
now = Date.now(),
|
|
323
|
+
nonce,
|
|
324
|
+
secret
|
|
325
|
+
}) => {
|
|
326
|
+
const currentWindow = Math.floor(now / NONCE_WINDOW_MS);
|
|
327
|
+
const candidates = await Promise.all(Array.from({ length: NONCE_PREVIOUS_WINDOWS_ACCEPTED + 1 }, (_, offset) => hmacSha256(secret, String(currentWindow - offset))));
|
|
328
|
+
return candidates.some((expected) => expected === nonce);
|
|
329
|
+
};
|
|
330
|
+
var decodeHeader = (segment) => {
|
|
331
|
+
try {
|
|
332
|
+
const value = JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
|
|
333
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
334
|
+
} catch {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
var normalizeHtu = (value, proofClaim = false) => {
|
|
339
|
+
try {
|
|
340
|
+
const url = new URL(String(value));
|
|
341
|
+
if (url.username || url.password || proofClaim && (url.search.length > 0 || url.hash.length > 0))
|
|
342
|
+
return;
|
|
343
|
+
return `${url.origin}${url.pathname}`;
|
|
344
|
+
} catch {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
var isPublicEs256Jwk = (value) => {
|
|
349
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
350
|
+
return false;
|
|
351
|
+
const kty = Reflect.get(value, "kty");
|
|
352
|
+
const crv = Reflect.get(value, "crv");
|
|
353
|
+
const xCoordinate = Reflect.get(value, "x");
|
|
354
|
+
const yCoordinate = Reflect.get(value, "y");
|
|
355
|
+
const privateComponent = Reflect.get(value, "d");
|
|
356
|
+
const alg = Reflect.get(value, "alg");
|
|
357
|
+
return kty === "EC" && crv === "P-256" && typeof xCoordinate === "string" && xCoordinate.length > 0 && typeof yCoordinate === "string" && yCoordinate.length > 0 && privateComponent === undefined && (alg === undefined || alg === "ES256");
|
|
358
|
+
};
|
|
359
|
+
var verifyDpopProof = async ({
|
|
360
|
+
accessToken,
|
|
361
|
+
consumeJti,
|
|
362
|
+
htm,
|
|
363
|
+
htu,
|
|
364
|
+
isUsedJti,
|
|
365
|
+
maxAgeMs = DEFAULT_MAX_AGE_MS,
|
|
366
|
+
now = Date.now(),
|
|
367
|
+
proof
|
|
368
|
+
}) => {
|
|
369
|
+
if (proof === undefined)
|
|
370
|
+
return;
|
|
371
|
+
const segments = proof.split(".");
|
|
372
|
+
if (segments.length !== 3)
|
|
373
|
+
return;
|
|
374
|
+
const [headerSegment] = segments;
|
|
375
|
+
if (headerSegment === undefined)
|
|
376
|
+
return;
|
|
377
|
+
const header = decodeHeader(headerSegment);
|
|
378
|
+
const publicJwk = header === undefined ? undefined : Reflect.get(header, "jwk");
|
|
379
|
+
if (header === undefined || Reflect.get(header, "typ") !== "dpop+jwt" || Reflect.get(header, "alg") !== "ES256" || !isPublicEs256Jwk(publicJwk)) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const verified = await verifyJwt(proof, publicJwk).catch(() => {
|
|
383
|
+
return;
|
|
384
|
+
});
|
|
385
|
+
if (verified === undefined)
|
|
386
|
+
return;
|
|
387
|
+
const { payload } = verified;
|
|
388
|
+
if (accessToken !== undefined) {
|
|
389
|
+
const expectedAth = Buffer.from(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(accessToken))).toString("base64url");
|
|
390
|
+
if (payload.ath !== expectedAth)
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const iatMs = typeof payload.iat === "number" ? payload.iat * SECONDS_TO_MS : 0;
|
|
394
|
+
const claimedHtu = normalizeHtu(payload.htu, true);
|
|
395
|
+
const expectedHtu = normalizeHtu(htu);
|
|
396
|
+
const jti = typeof payload.jti === "string" ? payload.jti : undefined;
|
|
397
|
+
if (payload.htm !== htm || claimedHtu === undefined || expectedHtu === undefined || claimedHtu !== expectedHtu || iatMs === 0 || Math.abs(now - iatMs) > maxAgeMs || jti === undefined || jti.length === 0 || jti.length > MAX_JTI_LENGTH) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
const jkt = await jwkThumbprint(publicJwk);
|
|
401
|
+
if (isUsedJti !== undefined && await isUsedJti(jti)) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (consumeJti !== undefined && !await consumeJti({ expiresAt: iatMs + maxAgeMs, jkt, jti }))
|
|
405
|
+
return;
|
|
406
|
+
return { jkt, jti };
|
|
407
|
+
};
|
|
283
408
|
// src/oidc/operator.ts
|
|
284
409
|
var operatorDelete = (store, storeName) => {
|
|
285
410
|
if (!store.deleteForClient)
|
|
@@ -12788,13 +12913,17 @@ var issueSocketTicket = async ({
|
|
|
12788
12913
|
export {
|
|
12789
12914
|
verifyJwtWithKeys,
|
|
12790
12915
|
verifyJwt,
|
|
12916
|
+
verifyDpopProof,
|
|
12917
|
+
verifyDpopNonce,
|
|
12791
12918
|
toPublicJwk,
|
|
12792
12919
|
signingVerificationKeys,
|
|
12793
12920
|
signJwt,
|
|
12794
12921
|
revokeOAuthClientCredentials,
|
|
12922
|
+
mintDpopNonce,
|
|
12795
12923
|
jwkThumbprint,
|
|
12796
12924
|
issueSocketTicket,
|
|
12797
12925
|
generateSigningKey,
|
|
12926
|
+
extractDpopNonceClaim,
|
|
12798
12927
|
createPostgresSocketTicketStore,
|
|
12799
12928
|
createPostgresOidcRefreshTokenStore,
|
|
12800
12929
|
createPostgresOAuthClientStore,
|
|
@@ -12815,5 +12944,5 @@ export {
|
|
|
12815
12944
|
consumeSocketTicket
|
|
12816
12945
|
};
|
|
12817
12946
|
|
|
12818
|
-
//# debugId=
|
|
12947
|
+
//# debugId=9914FF0D8636BBE564756E2164756E21
|
|
12819
12948
|
//# sourceMappingURL=index.js.map
|