Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

This file was deleted.

13 changes: 0 additions & 13 deletions modules/auth_email_password/db/migrations/meta/_journal.json

This file was deleted.

18 changes: 0 additions & 18 deletions modules/auth_email_password/db/schema.ts

This file was deleted.

3 changes: 2 additions & 1 deletion modules/auth_email_password/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"users": {},
"tokens": {},
"user_passwords": {},
"rate_limit": {}
"rate_limit": {},
"verifications": {}
},
"defaultConfig": {
"fromEmail": "hello@test.com",
Expand Down
18 changes: 10 additions & 8 deletions modules/auth_email_password/scripts/send_verification.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import { ScriptContext } from "../module.gen.ts";
import { createVerification } from "../utils/code_management.ts";
import { Verification } from "../utils/types.ts";

export interface Request {
email: string;
userToken?: string;
}

export interface Response {
verification: Verification;
token: string;
}

const HOUR_MS = 60 * 60 * 1000 * 1000;
const ATTEMPTS = 3;

export async function run(
ctx: ScriptContext,
req: Request,
): Promise<Response> {
await ctx.modules.rateLimit.throttlePublic({});

const { code, verification } = await createVerification(
ctx,
req.email,
);
const { code, token } = await ctx.modules.verifications.create({
data: { email: req.email },
expireAt: new Date(Date.now() + HOUR_MS).toISOString(),
maxAttempts: ATTEMPTS,
});

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

return { verification };
return { token };
}
20 changes: 14 additions & 6 deletions modules/auth_email_password/scripts/verify_add_email_pass.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Empty, RuntimeError, ScriptContext } from "../module.gen.ts";
import { verifyCode } from "../utils/code_management.ts";
import { IDENTITY_INFO_PASSWORD } from "../utils/provider.ts";
import { ensureNotAssociatedAll } from "../utils/link_assertions.ts";

Expand All @@ -10,7 +9,7 @@ export interface Request {
password: string;
oldPassword: string | null;

verificationToken: string;
token: string;
code: string;
}

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

// Check the verification code. If it is valid, but for the wrong email, say
// the verification failed.
const { email } = await verifyCode(ctx, req.verificationToken, req.code);
if (!compareConstantTime(req.email, email)) {
const { data, succeeded } = await ctx.modules.verifications.attempt({ token: req.token, code: req.code });
if (!succeeded) throw new RuntimeError("invalid_code");

if (
typeof data !== "object" ||
data === null ||
!("email" in data) ||
typeof data.email !== "string"
) throw new RuntimeError("unknown_err");

if (!compareConstantTime(req.email, data.email)) {
throw new RuntimeError("verification_failed");
}

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

// If an old password was provided, ensure it was correct and update it.
// If one was not, register the user with the `userPasswords` module.
Expand All @@ -58,7 +66,7 @@ export async function run(
userToken: req.userToken,
info: IDENTITY_INFO_PASSWORD,
uniqueData: {
identifier: email,
identifier: data.email,
},
additionalData: {},
});
Expand Down
20 changes: 14 additions & 6 deletions modules/auth_email_password/scripts/verify_sign_up_email_pass.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { RuntimeError, ScriptContext } from "../module.gen.ts";
import { verifyCode } from "../utils/code_management.ts";
import { IDENTITY_INFO_PASSWORD } from "../utils/provider.ts";
import { ensureNotAssociatedAll } from "../utils/link_assertions.ts";

export interface Request {
email: string;
password: string;

verificationToken: string;
token: string;
code: string;
}

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

// Check the verification code. If it is valid, but for the wrong email, say
// the verification failed.
const { email } = await verifyCode(ctx, req.verificationToken, req.code);
if (!compareConstantTime(req.email, email)) {
const { data, succeeded } = await ctx.modules.verifications.attempt({ token: req.token, code: req.code });
if (!succeeded) throw new RuntimeError("invalid_code");

if (
typeof data !== "object" ||
data === null ||
!("email" in data) ||
typeof data.email !== "string"
) throw new RuntimeError("unknown_err");

if (!compareConstantTime(req.email, data.email)) {
throw new RuntimeError("verification_failed");
}

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

// Sign up the user with the passwordless email identity
const { userToken, userId } = await ctx.modules.identities.signUp({
info: IDENTITY_INFO_PASSWORD,
uniqueData: {
identifier: email,
identifier: data.email,
},
additionalData: {},
});
Expand Down
76 changes: 0 additions & 76 deletions modules/auth_email_password/utils/code_management.ts

This file was deleted.

This file was deleted.

Loading