Email verification (code not link one) with lucia help #1768
Unanswered
Siddhisalvi
asked this question in
Help
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Can anyone please help me with email verification I am using next.js 15, lucia, typescript not javascript.
Email verification codes
We recommend reading through the email verification guide in the Copenhagen Book.
Update database
User table
Add a
email_verified
column (boolean).Email verification code table
Create a table for storing for email verification codes.
Generate verification code
The code should be valid for few minutes and linked to a single email.
You can also use alphanumeric codes.
When a user signs up, set
email_verified
tofalse
, create and send a verification code, and create a new session.When resending verification emails, make sure to implement rate limiting based on user ID and IP address.
Verify code and email
Make sure to implement throttling to prevent brute-force attacks.
Validate the verification code by comparing it against your database and checking the expiration and email. Make sure to invalidate all user sessions.
Update database
User table
Add a email_verified column (boolean).
import { Lucia } from "lucia";
export const lucia = new Lucia(adapter, {
sessionCookie: {
attributes: {
secure: env === "PRODUCTION" // set
Secure
flag in HTTPS}
},
getUserAttributes: (attributes) => {
return {
emailVerified: attributes.email_verified,
email: attributes.email
};
}
});
declare module "lucia" {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: {
email: string;
email_verified: boolean;
};
}
}
Email verification code table
Create a table for storing for email verification codes.
column type attributes
id any auto increment, etc
code string
user_id any unique
email string
expires_at Date
Generate verification code
The code should be valid for few minutes and linked to a single email.
import { TimeSpan, createDate } from "oslo";
import { generateRandomString, alphabet } from "oslo/crypto";
async function generateEmailVerificationCode(userId: string, email: string): Promise {
await db.table("email_verification_code").where("user_id", "=", userId).deleteAll();
const code = generateRandomString(8, alphabet("0-9"));
await db.table("email_verification_code").insert({
user_id: userId,
email,
code,
expires_at: createDate(new TimeSpan(15, "m")) // 15 minutes
});
return code;
}
You can also use alphanumeric codes.
const code = generateRandomString(6, alphabet("0-9", "A-Z"));
When a user signs up, set email_verified to false, create and send a verification code, and create a new session.
import { generateIdFromEntropySize } from "lucia";
app.post("/signup", async () => {
// ...
});
When resending verification emails, make sure to implement rate limiting based on user ID and IP address.
Verify code and email
Make sure to implement throttling to prevent brute-force attacks.
Validate the verification code by comparing it against your database and checking the expiration and email. Make sure to invalidate all user sessions.
import { isWithinExpirationDate } from "oslo";
import type { User } from "lucia";
app.post("/email-verification", async () => {
// ...
const { user } = await lucia.validateSession(sessionId);
if (!user) {
return new Response(null, {
status: 401
});
}
});
async function verifyVerificationCode(user: User, code: string): Promise {
await db.beginTransaction();
const databaseCode = await db
.table("email_verification_code")
.where("user_id", "=", user.id)
.get();
if (!databaseCode || databaseCode.code !== code) {
await db.commit();
return false;
}
await db.table("email_verification_code").where("id", "=", databaseCode.id).delete();
await db.commit();
}
Beta Was this translation helpful? Give feedback.
All reactions