Skip to content

feat(auth): implement email verification flow#39

Merged
ayshadogo merged 2 commits intoDfunder:mainfrom
portableDD:feat/email-verification
Mar 5, 2026
Merged

feat(auth): implement email verification flow#39
ayshadogo merged 2 commits intoDfunder:mainfrom
portableDD:feat/email-verification

Conversation

@portableDD
Copy link
Contributor

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.js
Renamed verificationTokenemailVerificationToken and
verificationTokenExpiresemailVerificationExpires to match the
issue spec exactly.

src/controllers/auth.controller.js

  • register: uses new field names; sends verification email via the
    existing (previously unwired) email.service + template; email
    failure 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: true and nulls token fields; returns 400 for any
    non-matching query result
  • login: unchanged — !user.isVerified guard already enforces the
    acceptance criterion

src/routes/auth.routes.js
Added GET /api/auth/verify-email/:token → verifyEmail

src/__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

  • Users can verify their email via GET /api/auth/verify-email/:token
  • Token generated with crypto.randomBytes(32) on registration
  • emailVerificationToken and emailVerificationExpires saved on User
  • Returns 400 for invalid or expired tokens
  • Unverified users cannot log in (enforced by existing !isVerified guard)

closes #19

- 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)
@ayshadogo ayshadogo merged commit c06df53 into Dfunder:main Mar 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Email Verification Flow

2 participants