@absolutejs/auth 0.29.3 → 0.30.0-beta.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/dist/credentials/config.d.ts +2 -0
- package/dist/credentials/import.d.ts +34 -0
- package/dist/credentials/legacyHashers.d.ts +3 -0
- package/dist/credentials/login.d.ts +1 -1
- package/dist/index.d.ts +58 -2
- package/dist/index.js +234 -10
- package/dist/index.js.map +11 -8
- package/dist/oidc/config.d.ts +1 -0
- package/dist/oidc/routes.d.ts +53 -2
- package/dist/oidc/userinfo.d.ts +21 -0
- package/package.json +1 -1
|
@@ -26,6 +26,8 @@ export type CredentialsConfig<UserType> = {
|
|
|
26
26
|
headers: Record<string, string | undefined>;
|
|
27
27
|
ip?: string;
|
|
28
28
|
}) => boolean | Promise<boolean>;
|
|
29
|
+
passwordVerifier?: (plainPassword: string, storedHash: string) => Promise<boolean>;
|
|
30
|
+
rehashOnLogin?: boolean;
|
|
29
31
|
loginRoute?: RouteString;
|
|
30
32
|
onCreateCredentialUser: (identity: CredentialIdentity & Record<string, unknown>) => Promise<Response | StatusReturn | UserType> | Response | StatusReturn | UserType;
|
|
31
33
|
onCredentialsLoginError?: (context: {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CredentialRecord, CredentialStore } from './types';
|
|
2
|
+
export type ImportableUser<UserType> = {
|
|
3
|
+
passwordHash?: string;
|
|
4
|
+
user: UserType;
|
|
5
|
+
};
|
|
6
|
+
export type ImportUserResult<UserType> = {
|
|
7
|
+
error: string;
|
|
8
|
+
ok: false;
|
|
9
|
+
user: UserType;
|
|
10
|
+
} | {
|
|
11
|
+
credential?: CredentialRecord;
|
|
12
|
+
ok: true;
|
|
13
|
+
user: UserType;
|
|
14
|
+
};
|
|
15
|
+
export type ImportUsersOptions<UserType> = {
|
|
16
|
+
onCreateUser: (input: ImportableUser<UserType>) => Promise<{
|
|
17
|
+
email: string;
|
|
18
|
+
emailVerified?: boolean;
|
|
19
|
+
userId?: string;
|
|
20
|
+
} | null>;
|
|
21
|
+
concurrency?: number;
|
|
22
|
+
credentialStore: CredentialStore;
|
|
23
|
+
};
|
|
24
|
+
export declare const importUser: <UserType>(input: ImportableUser<UserType>, options: ImportUsersOptions<UserType>) => Promise<ImportUserResult<UserType>>;
|
|
25
|
+
export declare const importUsers: <UserType>(inputs: readonly ImportableUser<UserType>[], options: ImportUsersOptions<UserType>) => Promise<{
|
|
26
|
+
failed: number;
|
|
27
|
+
results: ImportUserResult<UserType>[];
|
|
28
|
+
succeeded: number;
|
|
29
|
+
}>;
|
|
30
|
+
export declare const rehashCredentialPassword: ({ credentialStore, current, plainPassword }: {
|
|
31
|
+
credentialStore: CredentialStore;
|
|
32
|
+
current: CredentialRecord;
|
|
33
|
+
plainPassword: string;
|
|
34
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const isLegacyHash: (storedHash: string) => boolean;
|
|
2
|
+
export declare const verifyAuth0Pbkdf2: (plainPassword: string, wrappedHash: string) => Promise<boolean>;
|
|
3
|
+
export declare const verifyCognitoSha256: (plainPassword: string, wrappedHash: string) => Promise<boolean>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
2
|
import { type CredentialRouteProps } from './config';
|
|
3
|
-
export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreachesOnLogin, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, requireEmailVerification, sessionDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
3
|
+
export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreachesOnLogin, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, passwordVerifier, rehashOnLogin, requireEmailVerification, sessionDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
4
4
|
decorator: {};
|
|
5
5
|
store: {
|
|
6
6
|
session: import("..").SessionRecord<UserType>;
|
package/dist/index.d.ts
CHANGED
|
@@ -13458,6 +13458,9 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
|
|
|
13458
13458
|
acr_values?: string | undefined;
|
|
13459
13459
|
code_challenge?: string | undefined;
|
|
13460
13460
|
code_challenge_method?: string | undefined;
|
|
13461
|
+
id_token_hint?: string | undefined;
|
|
13462
|
+
max_age?: string | undefined;
|
|
13463
|
+
prompt?: string | undefined;
|
|
13461
13464
|
request_uri?: string | undefined;
|
|
13462
13465
|
response_type?: string | undefined;
|
|
13463
13466
|
state?: string | undefined;
|
|
@@ -13667,8 +13670,8 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
|
|
|
13667
13670
|
params: {};
|
|
13668
13671
|
query: {
|
|
13669
13672
|
client_id?: string | undefined;
|
|
13670
|
-
state?: string | undefined;
|
|
13671
13673
|
id_token_hint?: string | undefined;
|
|
13674
|
+
state?: string | undefined;
|
|
13672
13675
|
post_logout_redirect_uri?: string | undefined;
|
|
13673
13676
|
};
|
|
13674
13677
|
headers: unknown;
|
|
@@ -13691,8 +13694,8 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
|
|
|
13691
13694
|
post: {
|
|
13692
13695
|
body: {
|
|
13693
13696
|
client_id?: string | undefined;
|
|
13694
|
-
state?: string | undefined;
|
|
13695
13697
|
id_token_hint?: string | undefined;
|
|
13698
|
+
state?: string | undefined;
|
|
13696
13699
|
post_logout_redirect_uri?: string | undefined;
|
|
13697
13700
|
};
|
|
13698
13701
|
params: {};
|
|
@@ -13832,6 +13835,54 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
|
|
|
13832
13835
|
};
|
|
13833
13836
|
};
|
|
13834
13837
|
};
|
|
13838
|
+
} & {
|
|
13839
|
+
[x: string]: {
|
|
13840
|
+
get: {
|
|
13841
|
+
body: unknown;
|
|
13842
|
+
params: {};
|
|
13843
|
+
query: unknown;
|
|
13844
|
+
headers: {
|
|
13845
|
+
authorization?: string | undefined;
|
|
13846
|
+
};
|
|
13847
|
+
response: {
|
|
13848
|
+
200: Response;
|
|
13849
|
+
422: {
|
|
13850
|
+
type: "validation";
|
|
13851
|
+
on: string;
|
|
13852
|
+
summary?: string;
|
|
13853
|
+
message?: string;
|
|
13854
|
+
found?: unknown;
|
|
13855
|
+
property?: string;
|
|
13856
|
+
expected?: string;
|
|
13857
|
+
};
|
|
13858
|
+
};
|
|
13859
|
+
};
|
|
13860
|
+
};
|
|
13861
|
+
} & {
|
|
13862
|
+
[x: string]: {
|
|
13863
|
+
post: {
|
|
13864
|
+
body: {
|
|
13865
|
+
access_token?: string | undefined;
|
|
13866
|
+
};
|
|
13867
|
+
params: {};
|
|
13868
|
+
query: unknown;
|
|
13869
|
+
headers: {
|
|
13870
|
+
authorization?: string | undefined;
|
|
13871
|
+
};
|
|
13872
|
+
response: {
|
|
13873
|
+
200: Response;
|
|
13874
|
+
422: {
|
|
13875
|
+
type: "validation";
|
|
13876
|
+
on: string;
|
|
13877
|
+
summary?: string;
|
|
13878
|
+
message?: string;
|
|
13879
|
+
found?: unknown;
|
|
13880
|
+
property?: string;
|
|
13881
|
+
expected?: string;
|
|
13882
|
+
};
|
|
13883
|
+
};
|
|
13884
|
+
};
|
|
13885
|
+
};
|
|
13835
13886
|
} & {
|
|
13836
13887
|
[x: string]: {
|
|
13837
13888
|
get: {
|
|
@@ -14999,6 +15050,9 @@ export * from './tenancy';
|
|
|
14999
15050
|
export * from './credentials/config';
|
|
15000
15051
|
export * from './credentials/passwordPolicy';
|
|
15001
15052
|
export * from './credentials/emailValidation';
|
|
15053
|
+
export { importUser, importUsers, rehashCredentialPassword } from './credentials/import';
|
|
15054
|
+
export type { ImportUserResult, ImportUsersOptions, ImportableUser } from './credentials/import';
|
|
15055
|
+
export { isLegacyHash, verifyAuth0Pbkdf2, verifyCognitoSha256 } from './credentials/legacyHashers';
|
|
15002
15056
|
export * from './credentials/types';
|
|
15003
15057
|
export { credentialRoutes } from './credentials/routes';
|
|
15004
15058
|
export { credentialsEmailVerification } from './credentials/emailVerification';
|
|
@@ -15067,6 +15121,8 @@ export type { DpopResult } from './oidc/dpop';
|
|
|
15067
15121
|
export { CLIENT_ASSERTION_TYPE, verifyClientAssertion } from './oidc/clientAuth';
|
|
15068
15122
|
export { createInMemoryAuthorizationCodeStore, createInMemoryClientAssertionJtiStore, createInMemoryClientRegistrationTokenStore, createInMemoryDeviceAuthorizationStore, createInMemoryInitialAccessTokenStore, createInMemoryLogoutDeliveryStore, createInMemoryOAuthClientStore, createInMemoryOidcRefreshTokenStore, createInMemoryPushedAuthorizationRequestStore } from './oidc/inMemoryStores';
|
|
15069
15123
|
export { consumePushedRequest, pushAuthorizationRequest, DEFAULT_PAR_TTL_MS, REQUEST_URI_PREFIX } from './oidc/par';
|
|
15124
|
+
export { fetchUserInfo, readUserInfoBearer, userInfoChallengeHeader } from './oidc/userinfo';
|
|
15125
|
+
export type { UserInfoResult } from './oidc/userinfo';
|
|
15070
15126
|
export { fanOutBackchannelLogout, mintLogoutToken, resolvePostLogoutRedirect, verifyIdTokenHint } from './oidc/logout';
|
|
15071
15127
|
export { createNeonAuthorizationCodeStore, createNeonClientAssertionJtiStore, createNeonClientRegistrationTokenStore, createNeonDeviceAuthorizationStore, createNeonInitialAccessTokenStore, createNeonLogoutDeliveryStore, createNeonOAuthClientStore, createNeonOidcRefreshTokenStore, createNeonPushedAuthorizationRequestStore, createPostgresAuthorizationCodeStore, createPostgresClientAssertionJtiStore, createPostgresClientRegistrationTokenStore, createPostgresDeviceAuthorizationStore, createPostgresInitialAccessTokenStore, createPostgresLogoutDeliveryStore, createPostgresOAuthClientStore, createPostgresOidcRefreshTokenStore, createPostgresPushedAuthorizationRequestStore, oauthClientAssertionJtisTable, oauthClientRegistrationTokensTable, oauthClientsTable, oauthCodesTable, oauthDeviceAuthorizationsTable, oauthInitialAccessTokensTable, oauthLogoutDeliveriesTable, oauthPushedAuthorizationRequestsTable, oauthRefreshTokensTable } from './oidc/postgresStores';
|
|
15072
15128
|
export { deleteRegisteredClient, getRegisteredClient, registerClient, updateRegisteredClient, type ClientRegistrationDecision, type ClientRegistrationMetadata, type OnClientRegistration, type RegisterClientResult } from './oidc/registration';
|
package/dist/index.js
CHANGED
|
@@ -3392,6 +3392,110 @@ var credentialsEmailVerification = ({
|
|
|
3392
3392
|
// src/credentials/login.ts
|
|
3393
3393
|
import { Elysia as Elysia6, t as t6 } from "elysia";
|
|
3394
3394
|
|
|
3395
|
+
// src/credentials/import.ts
|
|
3396
|
+
var normalizeEmail = (email) => email.trim().toLowerCase();
|
|
3397
|
+
var buildCredential = (email, emailVerified, passwordHash, userId) => ({
|
|
3398
|
+
createdAt: Date.now(),
|
|
3399
|
+
email,
|
|
3400
|
+
emailVerified,
|
|
3401
|
+
passwordHash,
|
|
3402
|
+
status: "active",
|
|
3403
|
+
updatedAt: Date.now(),
|
|
3404
|
+
userId
|
|
3405
|
+
});
|
|
3406
|
+
var importUser = async (input, options) => {
|
|
3407
|
+
try {
|
|
3408
|
+
const created = await options.onCreateUser(input);
|
|
3409
|
+
if (created === null)
|
|
3410
|
+
return {
|
|
3411
|
+
error: "onCreateUser returned null",
|
|
3412
|
+
ok: false,
|
|
3413
|
+
user: input.user
|
|
3414
|
+
};
|
|
3415
|
+
const email = normalizeEmail(created.email);
|
|
3416
|
+
const emailVerified = created.emailVerified ?? true;
|
|
3417
|
+
if (input.passwordHash === undefined) {
|
|
3418
|
+
return { ok: true, user: input.user };
|
|
3419
|
+
}
|
|
3420
|
+
const credential = buildCredential(email, emailVerified, input.passwordHash, created.userId);
|
|
3421
|
+
await options.credentialStore.saveCredential(credential);
|
|
3422
|
+
return { credential, ok: true, user: input.user };
|
|
3423
|
+
} catch (err) {
|
|
3424
|
+
return {
|
|
3425
|
+
error: err instanceof Error ? err.message : String(err),
|
|
3426
|
+
ok: false,
|
|
3427
|
+
user: input.user
|
|
3428
|
+
};
|
|
3429
|
+
}
|
|
3430
|
+
};
|
|
3431
|
+
var importUsers = async (inputs, options) => {
|
|
3432
|
+
const concurrency = Math.max(1, options.concurrency ?? 1);
|
|
3433
|
+
const results = [];
|
|
3434
|
+
for (let cursor = 0;cursor < inputs.length; cursor += concurrency) {
|
|
3435
|
+
const slice = inputs.slice(cursor, cursor + concurrency);
|
|
3436
|
+
const batch = await Promise.all(slice.map((input) => importUser(input, options)));
|
|
3437
|
+
results.push(...batch);
|
|
3438
|
+
}
|
|
3439
|
+
return {
|
|
3440
|
+
failed: results.filter((result) => !result.ok).length,
|
|
3441
|
+
results,
|
|
3442
|
+
succeeded: results.filter((result) => result.ok).length
|
|
3443
|
+
};
|
|
3444
|
+
};
|
|
3445
|
+
var rehashCredentialPassword = async ({
|
|
3446
|
+
credentialStore,
|
|
3447
|
+
current,
|
|
3448
|
+
plainPassword
|
|
3449
|
+
}) => {
|
|
3450
|
+
const passwordHash = await hashPassword(plainPassword);
|
|
3451
|
+
await credentialStore.saveCredential({
|
|
3452
|
+
...current,
|
|
3453
|
+
passwordHash,
|
|
3454
|
+
updatedAt: Date.now()
|
|
3455
|
+
});
|
|
3456
|
+
};
|
|
3457
|
+
|
|
3458
|
+
// src/credentials/legacyHashers.ts
|
|
3459
|
+
var PBKDF2_DEFAULT_ITERATIONS = 1e5;
|
|
3460
|
+
var PBKDF2_KEY_LENGTH_BYTES = 32;
|
|
3461
|
+
var constantTimeEqualBytes = (left, right) => {
|
|
3462
|
+
if (left.byteLength !== right.byteLength)
|
|
3463
|
+
return false;
|
|
3464
|
+
let diff = 0;
|
|
3465
|
+
for (let index = 0;index < left.byteLength; index++) {
|
|
3466
|
+
diff |= (left[index] ?? 0) ^ (right[index] ?? 0);
|
|
3467
|
+
}
|
|
3468
|
+
return diff === 0;
|
|
3469
|
+
};
|
|
3470
|
+
var base64Decode = (encoded) => new Uint8Array(Buffer.from(encoded, "base64"));
|
|
3471
|
+
var sha256Bytes = async (input) => new Uint8Array(await crypto.subtle.digest("SHA-256", input));
|
|
3472
|
+
var isLegacyHash = (storedHash) => !storedHash.startsWith("$argon2id$") && !storedHash.startsWith("$2");
|
|
3473
|
+
var verifyAuth0Pbkdf2 = async (plainPassword, wrappedHash) => {
|
|
3474
|
+
const parts = wrappedHash.split(":");
|
|
3475
|
+
if (parts.length !== 4 || parts[0] !== "auth0_pbkdf2")
|
|
3476
|
+
return false;
|
|
3477
|
+
const salt = base64Decode(parts[1] ?? "");
|
|
3478
|
+
const expected = base64Decode(parts[2] ?? "");
|
|
3479
|
+
const iterations = Number(parts[3] ?? PBKDF2_DEFAULT_ITERATIONS);
|
|
3480
|
+
if (Number.isNaN(iterations) || iterations <= 0)
|
|
3481
|
+
return false;
|
|
3482
|
+
const key = await crypto.subtle.importKey("raw", new TextEncoder().encode(plainPassword), { name: "PBKDF2" }, false, ["deriveBits"]);
|
|
3483
|
+
const derivedBits = await crypto.subtle.deriveBits({ hash: "SHA-256", iterations, name: "PBKDF2", salt }, key, PBKDF2_KEY_LENGTH_BYTES * 8);
|
|
3484
|
+
return constantTimeEqualBytes(new Uint8Array(derivedBits), expected);
|
|
3485
|
+
};
|
|
3486
|
+
var verifyCognitoSha256 = async (plainPassword, wrappedHash) => {
|
|
3487
|
+
const parts = wrappedHash.split(":");
|
|
3488
|
+
if (parts.length !== 3 || parts[0] !== "cognito_sha256")
|
|
3489
|
+
return false;
|
|
3490
|
+
const salt = base64Decode(parts[1] ?? "");
|
|
3491
|
+
const expected = base64Decode(parts[2] ?? "");
|
|
3492
|
+
const payload = new Uint8Array(salt.byteLength + plainPassword.length);
|
|
3493
|
+
payload.set(salt, 0);
|
|
3494
|
+
payload.set(new TextEncoder().encode(plainPassword), salt.byteLength);
|
|
3495
|
+
const derived = await sha256Bytes(payload);
|
|
3496
|
+
return constantTimeEqualBytes(derived, expected);
|
|
3497
|
+
};
|
|
3498
|
+
|
|
3395
3499
|
// src/credentials/passwordPolicy.ts
|
|
3396
3500
|
var DEFAULT_MIN_LENGTH = 12;
|
|
3397
3501
|
var HEX_RADIX = 16;
|
|
@@ -3452,6 +3556,8 @@ var credentialsLogin = ({
|
|
|
3452
3556
|
loginRoute = "/auth/login",
|
|
3453
3557
|
onCredentialsLoginError,
|
|
3454
3558
|
onCredentialsLoginSuccess,
|
|
3559
|
+
passwordVerifier,
|
|
3560
|
+
rehashOnLogin = false,
|
|
3455
3561
|
requireEmailVerification = false,
|
|
3456
3562
|
sessionDurationMs = DEFAULT_CREDENTIAL_SESSION_TTL_MS
|
|
3457
3563
|
}) => new Elysia6().use(sessionStore()).post(loginRoute, async ({
|
|
@@ -3479,7 +3585,8 @@ var credentialsLogin = ({
|
|
|
3479
3585
|
}
|
|
3480
3586
|
const credential = await credentialStore.getCredentialByEmail(normalizedEmail);
|
|
3481
3587
|
const user = await getUserByEmail(normalizedEmail);
|
|
3482
|
-
const
|
|
3588
|
+
const verifyHash = passwordVerifier ?? verifyPassword;
|
|
3589
|
+
const passwordValid = credential === undefined ? false : await verifyHash(password, credential.passwordHash);
|
|
3483
3590
|
if (!credential || !user || credential.status !== "active" || !passwordValid) {
|
|
3484
3591
|
await lockoutGuard?.recordFailure(normalizedEmail);
|
|
3485
3592
|
await onCredentialsLoginError?.({
|
|
@@ -3489,6 +3596,13 @@ var credentialsLogin = ({
|
|
|
3489
3596
|
return status("Unauthorized", "Invalid email or password");
|
|
3490
3597
|
}
|
|
3491
3598
|
await lockoutGuard?.recordSuccess(normalizedEmail);
|
|
3599
|
+
if (rehashOnLogin && isLegacyHash(credential.passwordHash)) {
|
|
3600
|
+
await rehashCredentialPassword({
|
|
3601
|
+
credentialStore,
|
|
3602
|
+
current: credential,
|
|
3603
|
+
plainPassword: password
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3492
3606
|
if (requireEmailVerification && !credential.emailVerified) {
|
|
3493
3607
|
return status("Forbidden", { status: "email_not_verified" });
|
|
3494
3608
|
}
|
|
@@ -4843,6 +4957,51 @@ var pushAuthorizationRequest = async ({
|
|
|
4843
4957
|
};
|
|
4844
4958
|
};
|
|
4845
4959
|
|
|
4960
|
+
// src/oidc/userinfo.ts
|
|
4961
|
+
var BEARER_PREFIX2 = "Bearer ";
|
|
4962
|
+
var readBearer = (authorization) => {
|
|
4963
|
+
if (authorization === undefined || !authorization.startsWith(BEARER_PREFIX2)) {
|
|
4964
|
+
return;
|
|
4965
|
+
}
|
|
4966
|
+
return authorization.slice(BEARER_PREFIX2.length).trim();
|
|
4967
|
+
};
|
|
4968
|
+
var readUserInfoBearer = readBearer;
|
|
4969
|
+
var fetchUserInfo = async ({
|
|
4970
|
+
config,
|
|
4971
|
+
now = Date.now(),
|
|
4972
|
+
token
|
|
4973
|
+
}) => {
|
|
4974
|
+
if (token === undefined) {
|
|
4975
|
+
return {
|
|
4976
|
+
body: { error: "invalid_request" },
|
|
4977
|
+
error: "invalid_request",
|
|
4978
|
+
ok: false
|
|
4979
|
+
};
|
|
4980
|
+
}
|
|
4981
|
+
const verified = await verifyJwt(token, config.signingKey.publicJwk);
|
|
4982
|
+
if (verified === undefined) {
|
|
4983
|
+
return {
|
|
4984
|
+
body: { error: "invalid_token" },
|
|
4985
|
+
error: "invalid_token",
|
|
4986
|
+
ok: false
|
|
4987
|
+
};
|
|
4988
|
+
}
|
|
4989
|
+
const { payload } = verified;
|
|
4990
|
+
if (typeof payload.sub !== "string" || typeof payload.exp !== "number" || payload.exp * 1000 <= now) {
|
|
4991
|
+
return {
|
|
4992
|
+
body: { error: "invalid_token" },
|
|
4993
|
+
error: "invalid_token",
|
|
4994
|
+
ok: false
|
|
4995
|
+
};
|
|
4996
|
+
}
|
|
4997
|
+
const enriched = await config.getUserInfo?.(payload.sub);
|
|
4998
|
+
return {
|
|
4999
|
+
body: { ...enriched ?? {}, sub: payload.sub },
|
|
5000
|
+
ok: true
|
|
5001
|
+
};
|
|
5002
|
+
};
|
|
5003
|
+
var userInfoChallengeHeader = (error) => `Bearer realm="userinfo", error="${error}"`;
|
|
5004
|
+
|
|
4846
5005
|
// src/oidc/registration.ts
|
|
4847
5006
|
var REG_TOKEN_BYTES = 32;
|
|
4848
5007
|
var CLIENT_ID_BYTES = 16;
|
|
@@ -5106,6 +5265,7 @@ var oidcProviderRoutes = (config) => {
|
|
|
5106
5265
|
const endSessionRoute = `${oidcRoute}/end_session`;
|
|
5107
5266
|
const parRoute = `${oidcRoute}/par`;
|
|
5108
5267
|
const registrationRoute = `${oidcRoute}/register`;
|
|
5268
|
+
const userinfoRoute = `${oidcRoute}/userinfo`;
|
|
5109
5269
|
const registrationBaseUrl = `${issuer}${registrationRoute}`;
|
|
5110
5270
|
const tokenUrl = `${issuer}${oidcRoute}/token`;
|
|
5111
5271
|
const authenticateClient = async (clientId, clientSecret) => {
|
|
@@ -5317,7 +5477,8 @@ var oidcProviderRoutes = (config) => {
|
|
|
5317
5477
|
"none",
|
|
5318
5478
|
"private_key_jwt"
|
|
5319
5479
|
],
|
|
5320
|
-
token_endpoint_auth_signing_alg_values_supported: ["ES256"]
|
|
5480
|
+
token_endpoint_auth_signing_alg_values_supported: ["ES256"],
|
|
5481
|
+
userinfo_endpoint: `${issuer}${userinfoRoute}`
|
|
5321
5482
|
};
|
|
5322
5483
|
if (config.deviceAuthorizationStore) {
|
|
5323
5484
|
discovery.device_authorization_endpoint = `${issuer}${deviceAuthorizationRoute}`;
|
|
@@ -5422,7 +5583,21 @@ var oidcProviderRoutes = (config) => {
|
|
|
5422
5583
|
session: store.session,
|
|
5423
5584
|
userSessionId: user_session_id.value
|
|
5424
5585
|
});
|
|
5425
|
-
|
|
5586
|
+
const promptValues = effectiveQuery.prompt === undefined ? [] : effectiveQuery.prompt.split(" ");
|
|
5587
|
+
const wantsSilent = promptValues.includes("none");
|
|
5588
|
+
const wantsLogin = promptValues.includes("login") || promptValues.includes("consent");
|
|
5589
|
+
const maxAge = effectiveQuery.max_age === undefined ? undefined : Number(effectiveQuery.max_age);
|
|
5590
|
+
const sessionStaleByMaxAge = userSession !== undefined && maxAge !== undefined && !Number.isNaN(maxAge) && maxAge >= 0 && (userSession.authenticatedAt ?? 0) < Date.now() - maxAge * 1000;
|
|
5591
|
+
const hintSub = effectiveQuery.id_token_hint === undefined ? undefined : (await verifyIdTokenHint({
|
|
5592
|
+
config,
|
|
5593
|
+
idTokenHint: effectiveQuery.id_token_hint
|
|
5594
|
+
}))?.sub;
|
|
5595
|
+
const hintMismatch = userSession !== undefined && hintSub !== undefined && hintSub !== getUserId(userSession.user);
|
|
5596
|
+
const needsReauth = wantsLogin || sessionStaleByMaxAge || hintMismatch;
|
|
5597
|
+
if (userSession === undefined || needsReauth) {
|
|
5598
|
+
if (wantsSilent) {
|
|
5599
|
+
return errorRedirect(userSession === undefined ? "login_required" : "interaction_required");
|
|
5600
|
+
}
|
|
5426
5601
|
return loginUrl === undefined ? jsonResponse({ error: "login_required" }, HTTP_UNAUTHORIZED2) : redirectTo(`${loginUrl}?return_to=${encodeURIComponent(request.url)}`);
|
|
5427
5602
|
}
|
|
5428
5603
|
const requested = scope === undefined || scope.length === 0 ? client.scopes : scope.split(" ").filter((entry) => client.scopes.includes(entry));
|
|
@@ -5472,7 +5647,10 @@ var oidcProviderRoutes = (config) => {
|
|
|
5472
5647
|
client_id: t12.Optional(t12.String()),
|
|
5473
5648
|
code_challenge: t12.Optional(t12.String()),
|
|
5474
5649
|
code_challenge_method: t12.Optional(t12.String()),
|
|
5650
|
+
id_token_hint: t12.Optional(t12.String()),
|
|
5651
|
+
max_age: t12.Optional(t12.String()),
|
|
5475
5652
|
nonce: t12.Optional(t12.String()),
|
|
5653
|
+
prompt: t12.Optional(t12.String()),
|
|
5476
5654
|
redirect_uri: t12.Optional(t12.String()),
|
|
5477
5655
|
request_uri: t12.Optional(t12.String()),
|
|
5478
5656
|
response_type: t12.Optional(t12.String()),
|
|
@@ -5813,6 +5991,43 @@ var oidcProviderRoutes = (config) => {
|
|
|
5813
5991
|
authorization: t12.Optional(t12.String())
|
|
5814
5992
|
}),
|
|
5815
5993
|
params: t12.Object({ clientId: t12.String() })
|
|
5994
|
+
}).get(userinfoRoute, async ({ headers }) => {
|
|
5995
|
+
const token = readUserInfoBearer(headers.authorization);
|
|
5996
|
+
const result = await fetchUserInfo({ config, token });
|
|
5997
|
+
if (!result.ok) {
|
|
5998
|
+
return new Response(JSON.stringify(result.body), {
|
|
5999
|
+
headers: {
|
|
6000
|
+
"content-type": "application/json",
|
|
6001
|
+
"www-authenticate": userInfoChallengeHeader(result.error)
|
|
6002
|
+
},
|
|
6003
|
+
status: HTTP_UNAUTHORIZED2
|
|
6004
|
+
});
|
|
6005
|
+
}
|
|
6006
|
+
return jsonResponse(result.body, HTTP_OK2);
|
|
6007
|
+
}, {
|
|
6008
|
+
headers: t12.Object({
|
|
6009
|
+
authorization: t12.Optional(t12.String())
|
|
6010
|
+
})
|
|
6011
|
+
}).post(userinfoRoute, async ({ headers, body }) => {
|
|
6012
|
+
const token = readUserInfoBearer(headers.authorization) ?? body.access_token;
|
|
6013
|
+
const result = await fetchUserInfo({ config, token });
|
|
6014
|
+
if (!result.ok) {
|
|
6015
|
+
return new Response(JSON.stringify(result.body), {
|
|
6016
|
+
headers: {
|
|
6017
|
+
"content-type": "application/json",
|
|
6018
|
+
"www-authenticate": userInfoChallengeHeader(result.error)
|
|
6019
|
+
},
|
|
6020
|
+
status: HTTP_UNAUTHORIZED2
|
|
6021
|
+
});
|
|
6022
|
+
}
|
|
6023
|
+
return jsonResponse(result.body, HTTP_OK2);
|
|
6024
|
+
}, {
|
|
6025
|
+
body: t12.Object({
|
|
6026
|
+
access_token: t12.Optional(t12.String())
|
|
6027
|
+
}),
|
|
6028
|
+
headers: t12.Object({
|
|
6029
|
+
authorization: t12.Optional(t12.String())
|
|
6030
|
+
})
|
|
5816
6031
|
}).get(jwksRoute, () => ({ keys: [toPublicJwk(signingKey)] })).get("/.well-known/openid-configuration", () => discovery);
|
|
5817
6032
|
};
|
|
5818
6033
|
|
|
@@ -6314,7 +6529,7 @@ import { Elysia as Elysia18, t as t15 } from "elysia";
|
|
|
6314
6529
|
// src/scim/config.ts
|
|
6315
6530
|
var DEFAULT_SCIM_ROUTE = "/scim/v2";
|
|
6316
6531
|
var SCIM_TOKEN_BYTES = 32;
|
|
6317
|
-
var
|
|
6532
|
+
var BEARER_PREFIX3 = "Bearer ";
|
|
6318
6533
|
var createScimToken = async (scimTokenStore, organizationId) => {
|
|
6319
6534
|
const token = generateSecureToken(SCIM_TOKEN_BYTES);
|
|
6320
6535
|
const record = {
|
|
@@ -6327,10 +6542,10 @@ var createScimToken = async (scimTokenStore, organizationId) => {
|
|
|
6327
6542
|
return { token, tokenId: record.tokenId };
|
|
6328
6543
|
};
|
|
6329
6544
|
var resolveScimOrganization = async (scimTokenStore, authorization) => {
|
|
6330
|
-
if (authorization === undefined || !authorization.startsWith(
|
|
6545
|
+
if (authorization === undefined || !authorization.startsWith(BEARER_PREFIX3)) {
|
|
6331
6546
|
return;
|
|
6332
6547
|
}
|
|
6333
|
-
const token = authorization.slice(
|
|
6548
|
+
const token = authorization.slice(BEARER_PREFIX3.length).trim();
|
|
6334
6549
|
if (token.length === 0)
|
|
6335
6550
|
return;
|
|
6336
6551
|
const record = await scimTokenStore.findByHashedToken(await hashToken(token));
|
|
@@ -6347,7 +6562,7 @@ var DEFAULT_PORTAL_ROUTE = "/auth/portal";
|
|
|
6347
6562
|
var DEFAULT_SETUP_SESSION_TTL_MS = MILLISECONDS_IN_A_DAY * SETUP_TTL_DAYS;
|
|
6348
6563
|
|
|
6349
6564
|
// src/portal/operations.ts
|
|
6350
|
-
var
|
|
6565
|
+
var BEARER_PREFIX4 = "Bearer ";
|
|
6351
6566
|
var createSetupSession = async ({
|
|
6352
6567
|
capabilities,
|
|
6353
6568
|
createdBy,
|
|
@@ -6373,10 +6588,10 @@ var resolveSetupSession = async ({
|
|
|
6373
6588
|
authorization,
|
|
6374
6589
|
setupSessionStore
|
|
6375
6590
|
}) => {
|
|
6376
|
-
if (authorization === undefined || !authorization.startsWith(
|
|
6591
|
+
if (authorization === undefined || !authorization.startsWith(BEARER_PREFIX4)) {
|
|
6377
6592
|
return;
|
|
6378
6593
|
}
|
|
6379
|
-
const token = authorization.slice(
|
|
6594
|
+
const token = authorization.slice(BEARER_PREFIX4.length).trim();
|
|
6380
6595
|
if (token.length === 0)
|
|
6381
6596
|
return;
|
|
6382
6597
|
const session = await setupSessionStore.getSetupSessionByTokenHash(await hashToken(token));
|
|
@@ -22896,7 +23111,9 @@ export {
|
|
|
22896
23111
|
verifyHcaptcha,
|
|
22897
23112
|
verifyDpopProof,
|
|
22898
23113
|
verifyDpopNonce,
|
|
23114
|
+
verifyCognitoSha256,
|
|
22899
23115
|
verifyClientAssertion,
|
|
23116
|
+
verifyAuth0Pbkdf2,
|
|
22900
23117
|
verifyAuditChain,
|
|
22901
23118
|
verifyApiKey,
|
|
22902
23119
|
verifyAccessToken,
|
|
@@ -22904,6 +23121,7 @@ export {
|
|
|
22904
23121
|
validateSession,
|
|
22905
23122
|
validateEmailDeliverability,
|
|
22906
23123
|
userSessionIdTypebox,
|
|
23124
|
+
userInfoChallengeHeader,
|
|
22907
23125
|
updateRegisteredClient,
|
|
22908
23126
|
trustDevice,
|
|
22909
23127
|
toPublicJwk,
|
|
@@ -22942,9 +23160,11 @@ export {
|
|
|
22942
23160
|
resolveAuthHtmxRenderers,
|
|
22943
23161
|
resolveApiPrincipal,
|
|
22944
23162
|
removeFromSessionRing,
|
|
23163
|
+
rehashCredentialPassword,
|
|
22945
23164
|
registerClient,
|
|
22946
23165
|
refreshableProviderOptions,
|
|
22947
23166
|
recordLoginAttempt,
|
|
23167
|
+
readUserInfoBearer,
|
|
22948
23168
|
readSessionRing,
|
|
22949
23169
|
pushAuthorizationRequest,
|
|
22950
23170
|
providers,
|
|
@@ -23001,6 +23221,7 @@ export {
|
|
|
23001
23221
|
isPKCEProviderOption,
|
|
23002
23222
|
isOIDCProviderOption,
|
|
23003
23223
|
isMfaEnrolled,
|
|
23224
|
+
isLegacyHash,
|
|
23004
23225
|
isImpersonating,
|
|
23005
23226
|
isDisposableEmail,
|
|
23006
23227
|
isAuthIntent,
|
|
@@ -23008,6 +23229,8 @@ export {
|
|
|
23008
23229
|
inviteToOrganization,
|
|
23009
23230
|
introspectToken,
|
|
23010
23231
|
instantiateUserSession,
|
|
23232
|
+
importUsers,
|
|
23233
|
+
importUser,
|
|
23011
23234
|
hashToken,
|
|
23012
23235
|
hashPassword,
|
|
23013
23236
|
hashAuditEvent,
|
|
@@ -23023,6 +23246,7 @@ export {
|
|
|
23023
23246
|
generateEncryptionKey,
|
|
23024
23247
|
generateBackupCodes,
|
|
23025
23248
|
fingerprintDevice,
|
|
23249
|
+
fetchUserInfo,
|
|
23026
23250
|
fanOutBackchannelLogout,
|
|
23027
23251
|
extractPropFromIdentity,
|
|
23028
23252
|
extractDpopNonceClaim,
|
|
@@ -23226,5 +23450,5 @@ export {
|
|
|
23226
23450
|
AuthIdentityConflictError
|
|
23227
23451
|
};
|
|
23228
23452
|
|
|
23229
|
-
//# debugId=
|
|
23453
|
+
//# debugId=658AE7172110F24564756E2164756E21
|
|
23230
23454
|
//# sourceMappingURL=index.js.map
|