@absolutejs/auth 0.65.3 → 0.65.5
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/cli/migrate.js +61 -43
- package/dist/cli/migrate.js.map +5 -5
- package/dist/credentials/config.d.ts +4 -3
- package/dist/credentials/emailVerification.d.ts +2 -14
- package/dist/credentials/postgresCredentialStore.d.ts +15 -0
- package/dist/credentials/routes.d.ts +1 -13
- package/dist/credentials/types.d.ts +6 -0
- package/dist/index.d.ts +1 -13
- package/dist/index.js +75 -20
- package/dist/index.js.map +12 -12
- package/dist/linkedProviders/index.js +3 -3
- package/dist/linkedProviders/index.js.map +4 -4
- package/dist/linkedProviders/neonStores.d.ts +5 -5
- package/dist/linkedProviders/oauthAccountResolver.d.ts +2 -2
- package/dist/server.js +75 -20
- package/dist/server.js.map +12 -12
- package/package.json +2 -2
|
@@ -69,9 +69,10 @@ export type CredentialsConfig<UserType> = {
|
|
|
69
69
|
}) => void | Promise<void>;
|
|
70
70
|
passwordPolicy?: PasswordPolicy;
|
|
71
71
|
registerRoute?: RouteString;
|
|
72
|
-
/** When true, registration
|
|
73
|
-
*
|
|
74
|
-
*
|
|
72
|
+
/** When true, registration stores only a pending credential and does NOT call
|
|
73
|
+
* `onCreateCredentialUser` until a verification token is accepted. No user
|
|
74
|
+
* account or session exists before email ownership is proven. Default false
|
|
75
|
+
* creates the user immediately and auto-logs them in. */
|
|
75
76
|
requireEmailVerification?: boolean;
|
|
76
77
|
/** When true, `POST /register` returns 409 "Email is already registered" for a
|
|
77
78
|
* known email. Default false = enumeration-safe: return the same generic
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Elysia } from 'elysia';
|
|
2
2
|
import { type CredentialsConfig } from './config';
|
|
3
|
-
export declare const credentialsEmailVerification: <UserType>({ credentialStore, onEmailVerified, onSendEmail, verificationTokenDurationMs, verifyEmailRoute }: CredentialsConfig<UserType>) => Elysia<"", {
|
|
3
|
+
export declare const credentialsEmailVerification: <UserType>({ credentialStore, getUserByEmail, onCreateCredentialUser, onEmailVerified, onRegistrationSuccess, onSendEmail, requireEmailVerification, verificationTokenDurationMs, verifyEmailRoute }: CredentialsConfig<UserType>) => Elysia<"", {
|
|
4
4
|
decorator: {};
|
|
5
5
|
store: {};
|
|
6
6
|
derive: {};
|
|
@@ -25,19 +25,7 @@ export declare const credentialsEmailVerification: <UserType>({ credentialStore,
|
|
|
25
25
|
query: unknown;
|
|
26
26
|
headers: unknown;
|
|
27
27
|
response: {
|
|
28
|
-
|
|
29
|
-
200: {
|
|
30
|
-
readonly status: "email_verified";
|
|
31
|
-
};
|
|
32
|
-
422: {
|
|
33
|
-
type: "validation";
|
|
34
|
-
on: string;
|
|
35
|
-
summary?: string;
|
|
36
|
-
message?: string;
|
|
37
|
-
found?: unknown;
|
|
38
|
-
property?: string;
|
|
39
|
-
expected?: string;
|
|
40
|
-
};
|
|
28
|
+
[x: number]: {};
|
|
41
29
|
};
|
|
42
30
|
};
|
|
43
31
|
};
|
|
@@ -79,6 +79,21 @@ export declare const credentialsTable: import("drizzle-orm/pg-core").PgTableWith
|
|
|
79
79
|
identity: undefined;
|
|
80
80
|
generated: undefined;
|
|
81
81
|
}>;
|
|
82
|
+
registration_data: import("drizzle-orm/pg-core").PgBuildColumn<"auth_credentials", import("drizzle-orm/pg-core").Set$Type<import("drizzle-orm/pg-core").PgJsonbBuilder, Record<string, unknown>>, {
|
|
83
|
+
name: string;
|
|
84
|
+
tableName: "auth_credentials";
|
|
85
|
+
dataType: "object json";
|
|
86
|
+
data: Record<string, unknown>;
|
|
87
|
+
driverParam: unknown;
|
|
88
|
+
notNull: false;
|
|
89
|
+
hasDefault: false;
|
|
90
|
+
isPrimaryKey: false;
|
|
91
|
+
isAutoincrement: false;
|
|
92
|
+
hasRuntimeDefault: false;
|
|
93
|
+
enumValues: undefined;
|
|
94
|
+
identity: undefined;
|
|
95
|
+
generated: undefined;
|
|
96
|
+
}>;
|
|
82
97
|
status: import("drizzle-orm/pg-core").PgBuildColumn<"auth_credentials", import("drizzle-orm/pg-core").SetHasDefault<import("drizzle-orm/pg-core").SetNotNull<import("drizzle-orm/pg-core").PgVarcharBuilder<[string, ...string[]]>>>, {
|
|
83
98
|
name: string;
|
|
84
99
|
tableName: "auth_credentials";
|
|
@@ -43,19 +43,7 @@ export declare const credentialRoutes: <UserType>(config: CredentialRouteProps<U
|
|
|
43
43
|
query: unknown;
|
|
44
44
|
headers: unknown;
|
|
45
45
|
response: {
|
|
46
|
-
|
|
47
|
-
200: {
|
|
48
|
-
readonly status: "email_verified";
|
|
49
|
-
};
|
|
50
|
-
422: {
|
|
51
|
-
type: "validation";
|
|
52
|
-
on: string;
|
|
53
|
-
summary?: string;
|
|
54
|
-
message?: string;
|
|
55
|
-
found?: unknown;
|
|
56
|
-
property?: string;
|
|
57
|
-
expected?: string;
|
|
58
|
-
};
|
|
46
|
+
[x: number]: {};
|
|
59
47
|
};
|
|
60
48
|
};
|
|
61
49
|
};
|
|
@@ -6,6 +6,12 @@ export type CredentialRecord = {
|
|
|
6
6
|
emailVerified: boolean;
|
|
7
7
|
organizationId?: OrganizationId;
|
|
8
8
|
passwordHash: string;
|
|
9
|
+
/**
|
|
10
|
+
* Signup fields held until email ownership is proven. This is deliberately
|
|
11
|
+
* stored with the credential rather than in the consumer's user table so
|
|
12
|
+
* `requireEmailVerification` does not create an impersonatable account.
|
|
13
|
+
*/
|
|
14
|
+
registrationData?: Record<string, unknown>;
|
|
9
15
|
status: CredentialStatus;
|
|
10
16
|
updatedAt: number;
|
|
11
17
|
userId?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -760,19 +760,7 @@ export declare const createAuthApplications: <UserType>(configuration: AuthConfi
|
|
|
760
760
|
query: unknown;
|
|
761
761
|
headers: unknown;
|
|
762
762
|
response: {
|
|
763
|
-
|
|
764
|
-
200: {
|
|
765
|
-
readonly status: "email_verified";
|
|
766
|
-
};
|
|
767
|
-
422: {
|
|
768
|
-
type: "validation";
|
|
769
|
-
on: string;
|
|
770
|
-
summary?: string;
|
|
771
|
-
message?: string;
|
|
772
|
-
found?: unknown;
|
|
773
|
-
property?: string;
|
|
774
|
-
expected?: string;
|
|
775
|
-
};
|
|
763
|
+
[x: number]: {};
|
|
776
764
|
};
|
|
777
765
|
};
|
|
778
766
|
};
|
package/dist/index.js
CHANGED
|
@@ -5124,8 +5124,12 @@ var DEFAULT_VERIFICATION_TOKEN_TTL_MS = MILLISECONDS_IN_A_DAY;
|
|
|
5124
5124
|
// src/credentials/emailVerification.ts
|
|
5125
5125
|
var credentialsEmailVerification = ({
|
|
5126
5126
|
credentialStore,
|
|
5127
|
+
getUserByEmail,
|
|
5128
|
+
onCreateCredentialUser,
|
|
5127
5129
|
onEmailVerified,
|
|
5130
|
+
onRegistrationSuccess,
|
|
5128
5131
|
onSendEmail,
|
|
5132
|
+
requireEmailVerification = false,
|
|
5129
5133
|
verificationTokenDurationMs = DEFAULT_VERIFICATION_TOKEN_TTL_MS,
|
|
5130
5134
|
verifyEmailRoute = "/auth/verify-email"
|
|
5131
5135
|
}) => new Elysia10().post(verifyEmailRoute, async ({ body: { token }, status }) => {
|
|
@@ -5136,7 +5140,36 @@ var credentialsEmailVerification = ({
|
|
|
5136
5140
|
if (consumed.expiresAt < Date.now()) {
|
|
5137
5141
|
return status("Bad Request", "Invalid or expired verification token");
|
|
5138
5142
|
}
|
|
5143
|
+
const credential = await credentialStore.getCredentialByEmail(consumed.email);
|
|
5144
|
+
if (!credential) {
|
|
5145
|
+
return status("Bad Request", "Invalid or expired verification token");
|
|
5146
|
+
}
|
|
5147
|
+
let user = await getUserByEmail(consumed.email);
|
|
5148
|
+
if (requireEmailVerification && !user && credential.registrationData !== undefined) {
|
|
5149
|
+
const created = await onCreateCredentialUser({
|
|
5150
|
+
...credential.registrationData,
|
|
5151
|
+
email: consumed.email
|
|
5152
|
+
});
|
|
5153
|
+
if (created instanceof Response || isStatusResponse(created)) {
|
|
5154
|
+
return created;
|
|
5155
|
+
}
|
|
5156
|
+
user = created;
|
|
5157
|
+
}
|
|
5139
5158
|
await credentialStore.setEmailVerified(consumed.email);
|
|
5159
|
+
if (credential.registrationData !== undefined) {
|
|
5160
|
+
await credentialStore.saveCredential({
|
|
5161
|
+
...credential,
|
|
5162
|
+
emailVerified: true,
|
|
5163
|
+
registrationData: undefined,
|
|
5164
|
+
updatedAt: Date.now()
|
|
5165
|
+
});
|
|
5166
|
+
}
|
|
5167
|
+
if (user && credential.registrationData !== undefined) {
|
|
5168
|
+
await onRegistrationSuccess?.({
|
|
5169
|
+
email: consumed.email,
|
|
5170
|
+
user
|
|
5171
|
+
});
|
|
5172
|
+
}
|
|
5140
5173
|
await onEmailVerified?.({ email: consumed.email });
|
|
5141
5174
|
return status("OK", { status: "email_verified" });
|
|
5142
5175
|
}, { body: t7.Object({ token: t7.String() }) }).post(`${verifyEmailRoute}/request`, async ({ body: { email }, status }) => {
|
|
@@ -5510,7 +5543,7 @@ var credentialsPasswordReset = ({
|
|
|
5510
5543
|
}) => new Elysia12().post(`${resetPasswordRoute}/request`, async ({ body: { email }, status }) => {
|
|
5511
5544
|
const normalizedEmail = email.trim().toLowerCase();
|
|
5512
5545
|
const credential = await credentialStore.getCredentialByEmail(normalizedEmail);
|
|
5513
|
-
if (credential && credential.status === "active") {
|
|
5546
|
+
if (credential && credential.status === "active" && credential.registrationData === undefined) {
|
|
5514
5547
|
const token = generateSecureToken();
|
|
5515
5548
|
const expiresAt = Date.now() + resetTokenDurationMs;
|
|
5516
5549
|
await credentialStore.saveResetToken({
|
|
@@ -5620,12 +5653,16 @@ var credentialsRegister = ({
|
|
|
5620
5653
|
status: "verification_required"
|
|
5621
5654
|
});
|
|
5622
5655
|
}
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5656
|
+
let created;
|
|
5657
|
+
if (!requireEmailVerification) {
|
|
5658
|
+
const result = await onCreateCredentialUser({
|
|
5659
|
+
...extraFields,
|
|
5660
|
+
email: normalizedEmail
|
|
5661
|
+
});
|
|
5662
|
+
if (result instanceof Response || isStatusResponse(result)) {
|
|
5663
|
+
return result;
|
|
5664
|
+
}
|
|
5665
|
+
created = result;
|
|
5629
5666
|
}
|
|
5630
5667
|
const now = Date.now();
|
|
5631
5668
|
await credentialStore.saveCredential({
|
|
@@ -5633,6 +5670,7 @@ var credentialsRegister = ({
|
|
|
5633
5670
|
email: normalizedEmail,
|
|
5634
5671
|
emailVerified: false,
|
|
5635
5672
|
passwordHash: await hashPassword(password),
|
|
5673
|
+
registrationData: requireEmailVerification ? extraFields : undefined,
|
|
5636
5674
|
status: "active",
|
|
5637
5675
|
updatedAt: now
|
|
5638
5676
|
});
|
|
@@ -5649,15 +5687,18 @@ var credentialsRegister = ({
|
|
|
5649
5687
|
token,
|
|
5650
5688
|
type: "verify_email"
|
|
5651
5689
|
});
|
|
5652
|
-
await onRegistrationSuccess?.({
|
|
5653
|
-
email: normalizedEmail,
|
|
5654
|
-
user: created
|
|
5655
|
-
});
|
|
5656
5690
|
if (requireEmailVerification) {
|
|
5657
5691
|
return status("Created", {
|
|
5658
5692
|
status: "verification_required"
|
|
5659
5693
|
});
|
|
5660
5694
|
}
|
|
5695
|
+
if (created === undefined) {
|
|
5696
|
+
throw new Error("Credential user was not created");
|
|
5697
|
+
}
|
|
5698
|
+
await onRegistrationSuccess?.({
|
|
5699
|
+
email: normalizedEmail,
|
|
5700
|
+
user: created
|
|
5701
|
+
});
|
|
5661
5702
|
const userSessionId = await promoteToSession({
|
|
5662
5703
|
authSessionStore,
|
|
5663
5704
|
cookie: user_session_id,
|
|
@@ -31044,8 +31085,8 @@ var annotateFailureMetadata = (metadata, report, now) => ({
|
|
|
31044
31085
|
...metadata ?? {},
|
|
31045
31086
|
lastCredentialFailureAt: now,
|
|
31046
31087
|
lastCredentialFailureCode: report.code,
|
|
31047
|
-
lastCredentialFailureMessage: report.message,
|
|
31048
|
-
lastCredentialFailureRetryAt: report.retryAt
|
|
31088
|
+
...report.message === undefined ? {} : { lastCredentialFailureMessage: report.message },
|
|
31089
|
+
...report.retryAt === undefined ? {} : { lastCredentialFailureRetryAt: report.retryAt }
|
|
31049
31090
|
});
|
|
31050
31091
|
var sortNewestFirst = (items) => [...items].sort((left, right) => right.updatedAt - left.updatedAt);
|
|
31051
31092
|
var resolveGrantFailureStatus = (grant, report) => {
|
|
@@ -32010,7 +32051,8 @@ var validateEmailDeliverability = async (email, options) => {
|
|
|
32010
32051
|
};
|
|
32011
32052
|
// src/credentials/inMemoryCredentialStore.ts
|
|
32012
32053
|
var cloneCredential = (value) => ({
|
|
32013
|
-
...value
|
|
32054
|
+
...value,
|
|
32055
|
+
registrationData: value.registrationData === undefined ? undefined : structuredClone(value.registrationData)
|
|
32014
32056
|
});
|
|
32015
32057
|
var cloneToken = (value) => ({ ...value });
|
|
32016
32058
|
var consumeToken = (tokens, tokenHash) => {
|
|
@@ -32065,6 +32107,7 @@ var credentialsTable = pgTable("auth_credentials", {
|
|
|
32065
32107
|
email_verified: boolean("email_verified").notNull().default(false),
|
|
32066
32108
|
organization_id: varchar("organization_id", { length: ID_LENGTH2 }),
|
|
32067
32109
|
password_hash: text("password_hash").notNull(),
|
|
32110
|
+
registration_data: jsonb("registration_data").$type(),
|
|
32068
32111
|
status: varchar("status", { length: STATUS_LENGTH }).notNull().default("active"),
|
|
32069
32112
|
updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
|
|
32070
32113
|
user_id: varchar("user_id", { length: ID_LENGTH2 })
|
|
@@ -32086,6 +32129,7 @@ var toCredentialRecord = (row) => ({
|
|
|
32086
32129
|
emailVerified: row.email_verified,
|
|
32087
32130
|
organizationId: row.organization_id ?? undefined,
|
|
32088
32131
|
passwordHash: row.password_hash,
|
|
32132
|
+
registrationData: row.registration_data ?? undefined,
|
|
32089
32133
|
status: isCredentialStatus(row.status) ? row.status : "active",
|
|
32090
32134
|
updatedAt: row.updated_at_ms,
|
|
32091
32135
|
userId: row.user_id ?? undefined
|
|
@@ -32127,6 +32171,7 @@ var createPostgresCredentialStore = (db) => ({
|
|
|
32127
32171
|
email_verified: credential.emailVerified,
|
|
32128
32172
|
organization_id: credential.organizationId ?? null,
|
|
32129
32173
|
password_hash: credential.passwordHash,
|
|
32174
|
+
registration_data: credential.registrationData ?? null,
|
|
32130
32175
|
status: credential.status,
|
|
32131
32176
|
updated_at_ms: credential.updatedAt,
|
|
32132
32177
|
user_id: credential.userId ?? null
|
|
@@ -36771,6 +36816,10 @@ var mfaSmsColumnsMigration = {
|
|
|
36771
36816
|
].join(`
|
|
36772
36817
|
`)
|
|
36773
36818
|
};
|
|
36819
|
+
var credentialDeferredUserMigration = {
|
|
36820
|
+
id: "0002_deferred_user_creation",
|
|
36821
|
+
sql: 'ALTER TABLE "auth_credentials" ADD COLUMN IF NOT EXISTS "registration_data" jsonb;'
|
|
36822
|
+
};
|
|
36774
36823
|
var mfaTotpLockoutMigration = {
|
|
36775
36824
|
id: "0003_totp_lockout",
|
|
36776
36825
|
sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "totp_failed_attempts" smallint NOT NULL DEFAULT 0;'
|
|
@@ -36826,11 +36875,17 @@ var blockMigrations = {
|
|
|
36826
36875
|
apiKeysTable
|
|
36827
36876
|
]),
|
|
36828
36877
|
audit: initMigration("audit", [auditEventsTable]),
|
|
36829
|
-
credentials:
|
|
36830
|
-
|
|
36831
|
-
|
|
36832
|
-
|
|
36833
|
-
|
|
36878
|
+
credentials: {
|
|
36879
|
+
block: "credentials",
|
|
36880
|
+
migrations: [
|
|
36881
|
+
...initMigration("credentials", [
|
|
36882
|
+
credentialsTable,
|
|
36883
|
+
credentialResetTokensTable,
|
|
36884
|
+
credentialVerificationTokensTable
|
|
36885
|
+
]).migrations,
|
|
36886
|
+
credentialDeferredUserMigration
|
|
36887
|
+
]
|
|
36888
|
+
},
|
|
36834
36889
|
fga: initMigration("fga", [warrantsTable]),
|
|
36835
36890
|
linkedProviders: initMigration("linkedProviders", [
|
|
36836
36891
|
linkedProviderBindingsTable,
|
|
@@ -38181,5 +38236,5 @@ export {
|
|
|
38181
38236
|
AGENT_CLAIM_GRANT_TYPE
|
|
38182
38237
|
};
|
|
38183
38238
|
|
|
38184
|
-
//# debugId=
|
|
38239
|
+
//# debugId=BB9E2E153512DF2164756E2164756E21
|
|
38185
38240
|
//# sourceMappingURL=index.js.map
|