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
-
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