feat(auth): implement email verification flow#39
Merged
ayshadogo merged 2 commits intoDfunder:mainfrom Mar 5, 2026
Merged
Conversation
- Rename User model fields to emailVerificationToken / emailVerificationExpires to match the issue spec and make intent explicit - Wire existing email.service and emailVerification.template into register handler so a verification link is sent on every new registration - Add GET /api/auth/verify-email/:token endpoint that validates the token, checks expiry in a single DB query, sets isVerified: true, and clears both token fields on success; returns 400 for invalid or expired tokens - Remove raw verificationToken from register response (security fix) - Unverified users are already blocked at login via the !user.isVerified guard — no change needed there - Add auth.verify.test.js (4 cases) and auth.register.test.js (5 cases)
…d jest setup file for environment variables
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the full email verification flow described in the issue.
Users receive a verification link on registration and cannot log in
until they click it. Invalid or expired tokens are rejected with 400.
Changes
src/models/User.model.jsRenamed
verificationToken→emailVerificationTokenandverificationTokenExpires→emailVerificationExpiresto match theissue spec exactly.
src/controllers/auth.controller.jsregister: uses new field names; sends verification email via theexisting (previously unwired)
email.service+ template; emailfailure is caught and logged without blocking registration; raw token
removed from the response body
verifyEmail(new): single-query expiry check with$gt: new Date();sets
isVerified: trueand nulls token fields; returns 400 for anynon-matching query result
login: unchanged —!user.isVerifiedguard already enforces theacceptance criterion
src/routes/auth.routes.jsAdded
GET /api/auth/verify-email/:token → verifyEmailsrc/__tests__/auth.verify.test.js(new)Covers: success path (field mutations + query shape), invalid token,
expired token, and re-use of an already-cleared token.
src/__tests__/auth.register.test.js(new)Covers: success path with email send assertion, token field validation
(64-char hex, 24h expiry), duplicate email, Joi validation failures,
and SMTP failure tolerance.
Acceptance criteria
GET /api/auth/verify-email/:tokencrypto.randomBytes(32)on registrationemailVerificationTokenandemailVerificationExpiressaved on User!isVerifiedguard)closes #19