@absolutejs/auth 0.61.0 → 0.62.0
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 +15 -0
- package/dist/credentials/login.d.ts +2 -2
- package/dist/credentials/register.d.ts +1 -1
- package/dist/credentials/routes.d.ts +1 -1
- package/dist/csrf.d.ts +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +30 -3
- package/dist/index.js.map +9 -8
- package/dist/server.js +29 -3
- package/dist/server.js.map +9 -8
- package/package.json +1 -1
|
@@ -41,6 +41,13 @@ export type CredentialsConfig<UserType> = {
|
|
|
41
41
|
onEmailVerified?: (context: {
|
|
42
42
|
email: string;
|
|
43
43
|
}) => void | Promise<void>;
|
|
44
|
+
/** Called (in the enumeration-safe default) when someone tries to register an
|
|
45
|
+
* email that already exists — send the real owner a "you already have an
|
|
46
|
+
* account, sign in" email out-of-band. Not called when
|
|
47
|
+
* `revealRegistrationConflicts` is true. */
|
|
48
|
+
onExistingAccount?: (context: {
|
|
49
|
+
email: string;
|
|
50
|
+
}) => void | Promise<void>;
|
|
44
51
|
onPasswordReset?: (context: {
|
|
45
52
|
email: string;
|
|
46
53
|
}) => void | Promise<void>;
|
|
@@ -55,9 +62,17 @@ export type CredentialsConfig<UserType> = {
|
|
|
55
62
|
* rejected until the email is verified. Default false = auto-login on register and
|
|
56
63
|
* verification acts as a soft, later gate. */
|
|
57
64
|
requireEmailVerification?: boolean;
|
|
65
|
+
/** When true, `POST /register` returns 409 "Email is already registered" for a
|
|
66
|
+
* known email. Default false = enumeration-safe: return the same generic
|
|
67
|
+
* response a new pending registration does and call `onExistingAccount`
|
|
68
|
+
* instead of confirming the account exists. */
|
|
69
|
+
revealRegistrationConflicts?: boolean;
|
|
58
70
|
resetPasswordRoute?: RouteString;
|
|
59
71
|
resetTokenDurationMs?: number;
|
|
60
72
|
sessionDurationMs?: number;
|
|
73
|
+
/** When set, login/register reject requests whose `Origin` header is not in
|
|
74
|
+
* this list (defense against login/registration CSRF). Omit to disable. */
|
|
75
|
+
trustedOrigins?: readonly string[];
|
|
61
76
|
verificationTokenDurationMs?: number;
|
|
62
77
|
verifyEmailRoute?: RouteString;
|
|
63
78
|
};
|
|
@@ -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, cookieSecure, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, passwordVerifier, rehashOnLogin, requireEmailVerification, sessionDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
3
|
+
export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreachesOnLogin, cookieSecure, credentialStore, getUserByEmail, isMfaRequired, lockoutGuard, loginRoute, onCredentialsLoginError, onCredentialsLoginSuccess, passwordVerifier, rehashOnLogin, requireEmailVerification, sessionDurationMs, trustedOrigins }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
4
4
|
decorator: {};
|
|
5
5
|
store: {
|
|
6
6
|
session: import("..").SessionRecord<UserType>;
|
|
@@ -30,7 +30,7 @@ export declare const credentialsLogin: <UserType>({ authSessionStore, checkBreac
|
|
|
30
30
|
headers: unknown;
|
|
31
31
|
response: {
|
|
32
32
|
401: "Invalid email or password";
|
|
33
|
-
403: {
|
|
33
|
+
403: "Request origin is not allowed" | {
|
|
34
34
|
readonly status: "email_not_verified";
|
|
35
35
|
};
|
|
36
36
|
200: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
2
|
import { type CredentialRouteProps } from './config';
|
|
3
|
-
export declare const credentialsRegister: <UserType>({ authSessionStore, cookieSecure, credentialStore, onCreateCredentialUser, onCredentialsLoginSuccess, onRegistrationSuccess, onSendEmail, passwordPolicy, registerRoute, requireEmailVerification, sessionDurationMs, verificationTokenDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
3
|
+
export declare const credentialsRegister: <UserType>({ authSessionStore, cookieSecure, credentialStore, onCreateCredentialUser, onCredentialsLoginSuccess, onExistingAccount, onRegistrationSuccess, onSendEmail, passwordPolicy, registerRoute, requireEmailVerification, revealRegistrationConflicts, sessionDurationMs, trustedOrigins, verificationTokenDurationMs }: CredentialRouteProps<UserType>) => Elysia<"", {
|
|
4
4
|
decorator: {};
|
|
5
5
|
store: {
|
|
6
6
|
session: import("..").SessionRecord<UserType>;
|
|
@@ -98,7 +98,7 @@ export declare const credentialRoutes: <UserType>(config: CredentialRouteProps<U
|
|
|
98
98
|
headers: unknown;
|
|
99
99
|
response: {
|
|
100
100
|
401: "Invalid email or password";
|
|
101
|
-
403: {
|
|
101
|
+
403: "Request origin is not allowed" | {
|
|
102
102
|
readonly status: "email_not_verified";
|
|
103
103
|
};
|
|
104
104
|
200: {
|
package/dist/csrf.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isTrustedOrigin: (request: Request, trustedOrigins?: readonly string[]) => boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -815,7 +815,7 @@ export declare const createAuthApplications: <UserType>(configuration: AuthConfi
|
|
|
815
815
|
headers: unknown;
|
|
816
816
|
response: {
|
|
817
817
|
401: "Invalid email or password";
|
|
818
|
-
403: {
|
|
818
|
+
403: "Request origin is not allowed" | {
|
|
819
819
|
readonly status: "email_not_verified";
|
|
820
820
|
};
|
|
821
821
|
200: {
|
|
@@ -3468,6 +3468,7 @@ export { resolveAuthHtmxRenderers } from './htmx/renderers';
|
|
|
3468
3468
|
export type { AuthHtmxConfig, AuthHtmxConnectorTarget, AuthHtmxProviderData, AuthHtmxProviderInfo, AuthHtmxRenderOverrides, AuthHtmxRenderersConfig, AuthHtmxUser, AuthIdentityPayload, LinkedProviderPayload } from './htmx/types';
|
|
3469
3469
|
export * from './utils';
|
|
3470
3470
|
export * from './redirect';
|
|
3471
|
+
export * from './csrf';
|
|
3471
3472
|
export { buildClientProviders, resolveClientProviderEntry, resolveProviderClientConfiguration } from './providers/clients';
|
|
3472
3473
|
export type { OAuth2TokenResponse, OAuth2Client, OAuth2ClientForConfig, CustomProviderCredentials, ProviderConfig, ProviderOption, PKCEProvider, OIDCProvider, RefreshableProvider, RevocableProvider, ScopeRequiredProvider, ProvidersMap, ProviderConfiguration, CredentialsFor } from 'citra';
|
|
3473
3474
|
export { providers, providerOptions, createCustomOAuth2Client, defineProvider, refreshableProviderOptions, revocableProviderOptions, oidcProviderOptions, pkceProviderOptions, scopeRequiredProviderOptions, decodeJWT, extractPropFromIdentity, isValidProviderOption, isRefreshableOAuth2Client, isRefreshableProviderOption, isOIDCProviderOption, isPKCEProviderOption, isRevocableProviderOption, isRevocableOAuth2Client } from 'citra';
|
package/dist/index.js
CHANGED
|
@@ -5145,6 +5145,15 @@ init_constants();
|
|
|
5145
5145
|
init_crypto();
|
|
5146
5146
|
import { Elysia as Elysia11, t as t8 } from "elysia";
|
|
5147
5147
|
|
|
5148
|
+
// src/csrf.ts
|
|
5149
|
+
var isTrustedOrigin = (request, trustedOrigins) => {
|
|
5150
|
+
if (trustedOrigins === undefined || trustedOrigins.length === 0) {
|
|
5151
|
+
return true;
|
|
5152
|
+
}
|
|
5153
|
+
const origin = request.headers.get("origin");
|
|
5154
|
+
return origin !== null && trustedOrigins.includes(origin);
|
|
5155
|
+
};
|
|
5156
|
+
|
|
5148
5157
|
// src/credentials/import.ts
|
|
5149
5158
|
init_crypto();
|
|
5150
5159
|
var normalizeEmail = (email) => email.trim().toLowerCase();
|
|
@@ -5349,7 +5358,8 @@ var credentialsLogin = ({
|
|
|
5349
5358
|
passwordVerifier,
|
|
5350
5359
|
rehashOnLogin = false,
|
|
5351
5360
|
requireEmailVerification = false,
|
|
5352
|
-
sessionDurationMs = DEFAULT_CREDENTIAL_SESSION_TTL_MS
|
|
5361
|
+
sessionDurationMs = DEFAULT_CREDENTIAL_SESSION_TTL_MS,
|
|
5362
|
+
trustedOrigins
|
|
5353
5363
|
}) => new Elysia11().use(sessionStore()).post(loginRoute, async ({
|
|
5354
5364
|
body: { email, password },
|
|
5355
5365
|
cookie: { user_session_id },
|
|
@@ -5357,6 +5367,9 @@ var credentialsLogin = ({
|
|
|
5357
5367
|
status,
|
|
5358
5368
|
store: { session, unregisteredSession }
|
|
5359
5369
|
}) => withSpan("auth.credentials.login", undefined, async (span) => {
|
|
5370
|
+
if (!isTrustedOrigin(request, trustedOrigins)) {
|
|
5371
|
+
return status("Forbidden", "Request origin is not allowed");
|
|
5372
|
+
}
|
|
5360
5373
|
const headerBag = {};
|
|
5361
5374
|
request.headers.forEach((value, key) => {
|
|
5362
5375
|
headerBag[key] = value;
|
|
@@ -5514,19 +5527,26 @@ var credentialsRegister = ({
|
|
|
5514
5527
|
credentialStore,
|
|
5515
5528
|
onCreateCredentialUser,
|
|
5516
5529
|
onCredentialsLoginSuccess,
|
|
5530
|
+
onExistingAccount,
|
|
5517
5531
|
onRegistrationSuccess,
|
|
5518
5532
|
onSendEmail,
|
|
5519
5533
|
passwordPolicy,
|
|
5520
5534
|
registerRoute = "/auth/register",
|
|
5521
5535
|
requireEmailVerification = false,
|
|
5536
|
+
revealRegistrationConflicts = false,
|
|
5522
5537
|
sessionDurationMs = DEFAULT_CREDENTIAL_SESSION_TTL_MS,
|
|
5538
|
+
trustedOrigins,
|
|
5523
5539
|
verificationTokenDurationMs = DEFAULT_VERIFICATION_TOKEN_TTL_MS
|
|
5524
5540
|
}) => new Elysia13().use(sessionStore()).post(registerRoute, async ({
|
|
5525
5541
|
body: { email, password, ...extraFields },
|
|
5526
5542
|
cookie: { user_session_id },
|
|
5543
|
+
request,
|
|
5527
5544
|
status,
|
|
5528
5545
|
store: { session }
|
|
5529
5546
|
}) => withSpan("auth.credentials.register", undefined, async () => {
|
|
5547
|
+
if (!isTrustedOrigin(request, trustedOrigins)) {
|
|
5548
|
+
return status("Forbidden", "Request origin is not allowed");
|
|
5549
|
+
}
|
|
5530
5550
|
const normalizedEmail = email.trim().toLowerCase();
|
|
5531
5551
|
if (!normalizedEmail.includes("@")) {
|
|
5532
5552
|
return status("Bad Request", "A valid email is required");
|
|
@@ -5540,7 +5560,13 @@ var credentialsRegister = ({
|
|
|
5540
5560
|
}
|
|
5541
5561
|
const existing = await credentialStore.getCredentialByEmail(normalizedEmail);
|
|
5542
5562
|
if (existing) {
|
|
5543
|
-
|
|
5563
|
+
if (revealRegistrationConflicts) {
|
|
5564
|
+
return status("Conflict", "Email is already registered");
|
|
5565
|
+
}
|
|
5566
|
+
await onExistingAccount?.({ email: normalizedEmail });
|
|
5567
|
+
return status("Created", {
|
|
5568
|
+
status: "verification_required"
|
|
5569
|
+
});
|
|
5544
5570
|
}
|
|
5545
5571
|
const created = await onCreateCredentialUser({
|
|
5546
5572
|
...extraFields,
|
|
@@ -37716,6 +37742,7 @@ export {
|
|
|
37716
37742
|
isValidUser,
|
|
37717
37743
|
isValidProviderOption,
|
|
37718
37744
|
isUserSessionId,
|
|
37745
|
+
isTrustedOrigin,
|
|
37719
37746
|
isSafeLocalPath,
|
|
37720
37747
|
isRevocableProviderOption,
|
|
37721
37748
|
isRevocableOAuth2Client,
|
|
@@ -38057,5 +38084,5 @@ export {
|
|
|
38057
38084
|
AGENT_CLAIM_GRANT_TYPE
|
|
38058
38085
|
};
|
|
38059
38086
|
|
|
38060
|
-
//# debugId=
|
|
38087
|
+
//# debugId=A62F57FCBD818EE864756E2164756E21
|
|
38061
38088
|
//# sourceMappingURL=index.js.map
|