Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.

Commit 8b5d6a5

Browse files
committed
feat: Create verifications module to streamline auth_email_* and auth_sms_*
1 parent 31ebc1e commit 8b5d6a5

32 files changed

+751
-476
lines changed

modules/auth_email_password/db/migrations/1724526776_powerful_maverick.sql

Lines changed: 0 additions & 15 deletions
This file was deleted.

modules/auth_email_password/db/migrations/meta/1724526776_snapshot.json

Lines changed: 0 additions & 100 deletions
This file was deleted.

modules/auth_email_password/db/migrations/meta/_journal.json

Lines changed: 0 additions & 13 deletions
This file was deleted.

modules/auth_email_password/db/schema.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

modules/auth_email_password/module.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"users": {},
1919
"tokens": {},
2020
"user_passwords": {},
21-
"rate_limit": {}
21+
"rate_limit": {},
22+
"verifications": {}
2223
},
2324
"defaultConfig": {
2425
"fromEmail": "hello@test.com",
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
import { ScriptContext } from "../module.gen.ts";
2-
import { createVerification } from "../utils/code_management.ts";
3-
import { Verification } from "../utils/types.ts";
42

53
export interface Request {
64
email: string;
75
userToken?: string;
86
}
97

108
export interface Response {
11-
verification: Verification;
9+
token: string;
1210
}
1311

12+
const HOUR_MS = 60 * 60 * 1000 * 1000;
13+
const ATTEMPTS = 3;
14+
1415
export async function run(
1516
ctx: ScriptContext,
1617
req: Request,
1718
): Promise<Response> {
1819
await ctx.modules.rateLimit.throttlePublic({});
1920

20-
const { code, verification } = await createVerification(
21-
ctx,
22-
req.email,
23-
);
21+
const { code, token } = await ctx.modules.verifications.create({
22+
data: { email: req.email },
23+
expireAt: new Date(Date.now() + HOUR_MS).toISOString(),
24+
maxAttempts: ATTEMPTS,
25+
});
2426

2527
// Send email
2628
await ctx.modules.email.sendEmail({
@@ -34,5 +36,5 @@ export async function run(
3436
html: `Your verification code is: <b>${code}</b>`,
3537
});
3638

37-
return { verification };
39+
return { token };
3840
}

modules/auth_email_password/scripts/verify_add_email_pass.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Empty, RuntimeError, ScriptContext } from "../module.gen.ts";
2-
import { verifyCode } from "../utils/code_management.ts";
32
import { IDENTITY_INFO_PASSWORD } from "../utils/provider.ts";
43
import { ensureNotAssociatedAll } from "../utils/link_assertions.ts";
54

@@ -10,7 +9,7 @@ export interface Request {
109
password: string;
1110
oldPassword: string | null;
1211

13-
verificationToken: string;
12+
token: string;
1413
code: string;
1514
}
1615

@@ -24,16 +23,25 @@ export async function run(
2423

2524
// Check the verification code. If it is valid, but for the wrong email, say
2625
// the verification failed.
27-
const { email } = await verifyCode(ctx, req.verificationToken, req.code);
28-
if (!compareConstantTime(req.email, email)) {
26+
const { data, succeeded } = await ctx.modules.verifications.attempt({ token: req.token, code: req.code });
27+
if (!succeeded) throw new RuntimeError("invalid_code");
28+
29+
if (
30+
typeof data !== "object" ||
31+
data === null ||
32+
!("email" in data) ||
33+
typeof data.email !== "string"
34+
) throw new RuntimeError("unknown_err");
35+
36+
if (!compareConstantTime(req.email, data.email)) {
2937
throw new RuntimeError("verification_failed");
3038
}
3139

3240
// Ensure that the email is not associated with ANY accounts in ANY way.
3341
const providedUser = await ctx.modules.users.authenticateToken({
3442
userToken: req.userToken,
3543
});
36-
await ensureNotAssociatedAll(ctx, email, new Set([providedUser.userId]));
44+
await ensureNotAssociatedAll(ctx, data.email, new Set([providedUser.userId]));
3745

3846
// If an old password was provided, ensure it was correct and update it.
3947
// If one was not, register the user with the `userPasswords` module.
@@ -58,7 +66,7 @@ export async function run(
5866
userToken: req.userToken,
5967
info: IDENTITY_INFO_PASSWORD,
6068
uniqueData: {
61-
identifier: email,
69+
identifier: data.email,
6270
},
6371
additionalData: {},
6472
});

modules/auth_email_password/scripts/verify_sign_up_email_pass.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { RuntimeError, ScriptContext } from "../module.gen.ts";
2-
import { verifyCode } from "../utils/code_management.ts";
32
import { IDENTITY_INFO_PASSWORD } from "../utils/provider.ts";
43
import { ensureNotAssociatedAll } from "../utils/link_assertions.ts";
54

65
export interface Request {
76
email: string;
87
password: string;
98

10-
verificationToken: string;
9+
token: string;
1110
code: string;
1211
}
1312

@@ -23,19 +22,28 @@ export async function run(
2322

2423
// Check the verification code. If it is valid, but for the wrong email, say
2524
// the verification failed.
26-
const { email } = await verifyCode(ctx, req.verificationToken, req.code);
27-
if (!compareConstantTime(req.email, email)) {
25+
const { data, succeeded } = await ctx.modules.verifications.attempt({ token: req.token, code: req.code });
26+
if (!succeeded) throw new RuntimeError("invalid_code");
27+
28+
if (
29+
typeof data !== "object" ||
30+
data === null ||
31+
!("email" in data) ||
32+
typeof data.email !== "string"
33+
) throw new RuntimeError("unknown_err");
34+
35+
if (!compareConstantTime(req.email, data.email)) {
2836
throw new RuntimeError("verification_failed");
2937
}
3038

3139
// Ensure that the email is not associated with ANY accounts in ANY way.
32-
await ensureNotAssociatedAll(ctx, email, new Set());
40+
await ensureNotAssociatedAll(ctx, data.email, new Set());
3341

3442
// Sign up the user with the passwordless email identity
3543
const { userToken, userId } = await ctx.modules.identities.signUp({
3644
info: IDENTITY_INFO_PASSWORD,
3745
uniqueData: {
38-
identifier: email,
46+
identifier: data.email,
3947
},
4048
additionalData: {},
4149
});

modules/auth_email_password/utils/code_management.ts

Lines changed: 0 additions & 76 deletions
This file was deleted.

modules/auth_email_passwordless/db/migrations/1724526776_powerful_maverick.sql

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)