@absolutejs/auth 0.65.4 → 0.65.6
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 +62 -44
- 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 +79 -20
- package/dist/index.js.map +11 -11
- package/dist/server.js +79 -20
- package/dist/server.js.map +11 -11
- package/package.json +1 -1
|
@@ -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,
|
|
@@ -31531,7 +31572,7 @@ var createNeonLinkedProviderGrantStore = (db) => ({
|
|
|
31531
31572
|
owner_ref: grant.ownerRef,
|
|
31532
31573
|
provider_family: grant.providerFamily,
|
|
31533
31574
|
provider_subject: grant.providerSubject,
|
|
31534
|
-
refresh_token_ciphertext:
|
|
31575
|
+
refresh_token_ciphertext: sql`coalesce(excluded.refresh_token_ciphertext, ${linkedProviderGrantsTable.refresh_token_ciphertext})`,
|
|
31535
31576
|
status: grant.status,
|
|
31536
31577
|
token_type: grant.tokenType ?? null,
|
|
31537
31578
|
updated_at: new Date(grant.updatedAt)
|
|
@@ -31590,7 +31631,11 @@ var createInMemoryLinkedProviderStores = (input = {}) => {
|
|
|
31590
31631
|
[...bindings.entries()].filter(([, binding]) => binding.grantId === id).forEach(([bindingId2]) => bindings.delete(bindingId2));
|
|
31591
31632
|
},
|
|
31592
31633
|
saveGrant: async (grant) => {
|
|
31593
|
-
grants.
|
|
31634
|
+
const existing = grants.get(grant.id);
|
|
31635
|
+
grants.set(grant.id, cloneGrant({
|
|
31636
|
+
...grant,
|
|
31637
|
+
refreshTokenCiphertext: grant.refreshTokenCiphertext ?? existing?.refreshTokenCiphertext
|
|
31638
|
+
}));
|
|
31594
31639
|
}
|
|
31595
31640
|
};
|
|
31596
31641
|
const bindingStore = {
|
|
@@ -32010,7 +32055,8 @@ var validateEmailDeliverability = async (email, options) => {
|
|
|
32010
32055
|
};
|
|
32011
32056
|
// src/credentials/inMemoryCredentialStore.ts
|
|
32012
32057
|
var cloneCredential = (value) => ({
|
|
32013
|
-
...value
|
|
32058
|
+
...value,
|
|
32059
|
+
registrationData: value.registrationData === undefined ? undefined : structuredClone(value.registrationData)
|
|
32014
32060
|
});
|
|
32015
32061
|
var cloneToken = (value) => ({ ...value });
|
|
32016
32062
|
var consumeToken = (tokens, tokenHash) => {
|
|
@@ -32065,6 +32111,7 @@ var credentialsTable = pgTable("auth_credentials", {
|
|
|
32065
32111
|
email_verified: boolean("email_verified").notNull().default(false),
|
|
32066
32112
|
organization_id: varchar("organization_id", { length: ID_LENGTH2 }),
|
|
32067
32113
|
password_hash: text("password_hash").notNull(),
|
|
32114
|
+
registration_data: jsonb("registration_data").$type(),
|
|
32068
32115
|
status: varchar("status", { length: STATUS_LENGTH }).notNull().default("active"),
|
|
32069
32116
|
updated_at_ms: bigint("updated_at_ms", { mode: "number" }).notNull(),
|
|
32070
32117
|
user_id: varchar("user_id", { length: ID_LENGTH2 })
|
|
@@ -32086,6 +32133,7 @@ var toCredentialRecord = (row) => ({
|
|
|
32086
32133
|
emailVerified: row.email_verified,
|
|
32087
32134
|
organizationId: row.organization_id ?? undefined,
|
|
32088
32135
|
passwordHash: row.password_hash,
|
|
32136
|
+
registrationData: row.registration_data ?? undefined,
|
|
32089
32137
|
status: isCredentialStatus(row.status) ? row.status : "active",
|
|
32090
32138
|
updatedAt: row.updated_at_ms,
|
|
32091
32139
|
userId: row.user_id ?? undefined
|
|
@@ -32127,6 +32175,7 @@ var createPostgresCredentialStore = (db) => ({
|
|
|
32127
32175
|
email_verified: credential.emailVerified,
|
|
32128
32176
|
organization_id: credential.organizationId ?? null,
|
|
32129
32177
|
password_hash: credential.passwordHash,
|
|
32178
|
+
registration_data: credential.registrationData ?? null,
|
|
32130
32179
|
status: credential.status,
|
|
32131
32180
|
updated_at_ms: credential.updatedAt,
|
|
32132
32181
|
user_id: credential.userId ?? null
|
|
@@ -36771,6 +36820,10 @@ var mfaSmsColumnsMigration = {
|
|
|
36771
36820
|
].join(`
|
|
36772
36821
|
`)
|
|
36773
36822
|
};
|
|
36823
|
+
var credentialDeferredUserMigration = {
|
|
36824
|
+
id: "0002_deferred_user_creation",
|
|
36825
|
+
sql: 'ALTER TABLE "auth_credentials" ADD COLUMN IF NOT EXISTS "registration_data" jsonb;'
|
|
36826
|
+
};
|
|
36774
36827
|
var mfaTotpLockoutMigration = {
|
|
36775
36828
|
id: "0003_totp_lockout",
|
|
36776
36829
|
sql: 'ALTER TABLE "auth_mfa_enrollments" ADD COLUMN IF NOT EXISTS "totp_failed_attempts" smallint NOT NULL DEFAULT 0;'
|
|
@@ -36826,11 +36879,17 @@ var blockMigrations = {
|
|
|
36826
36879
|
apiKeysTable
|
|
36827
36880
|
]),
|
|
36828
36881
|
audit: initMigration("audit", [auditEventsTable]),
|
|
36829
|
-
credentials:
|
|
36830
|
-
|
|
36831
|
-
|
|
36832
|
-
|
|
36833
|
-
|
|
36882
|
+
credentials: {
|
|
36883
|
+
block: "credentials",
|
|
36884
|
+
migrations: [
|
|
36885
|
+
...initMigration("credentials", [
|
|
36886
|
+
credentialsTable,
|
|
36887
|
+
credentialResetTokensTable,
|
|
36888
|
+
credentialVerificationTokensTable
|
|
36889
|
+
]).migrations,
|
|
36890
|
+
credentialDeferredUserMigration
|
|
36891
|
+
]
|
|
36892
|
+
},
|
|
36834
36893
|
fga: initMigration("fga", [warrantsTable]),
|
|
36835
36894
|
linkedProviders: initMigration("linkedProviders", [
|
|
36836
36895
|
linkedProviderBindingsTable,
|
|
@@ -38181,5 +38240,5 @@ export {
|
|
|
38181
38240
|
AGENT_CLAIM_GRANT_TYPE
|
|
38182
38241
|
};
|
|
38183
38242
|
|
|
38184
|
-
//# debugId=
|
|
38243
|
+
//# debugId=9CCB3DA09AA91A9764756E2164756E21
|
|
38185
38244
|
//# sourceMappingURL=index.js.map
|