Frequently Asked Questions
Implement 2FA by integrating NextAuth.js for authentication, Plivo for SMS delivery, and Prisma for database management. This setup enables a secure login flow where users verify their identity with an OTP sent via SMS after entering their credentials, enhancing account security.
Plivo is the communications platform API used to send SMS messages containing the One-Time Passwords (OTPs) for two-factor authentication. It's a key component for delivering the verification codes to users' phones.
NextAuth.js uses JSON Web Tokens (JWT) to manage session state and store authentication information, including whether 2FA has been verified in the current session. This approach enhances security by encoding user data and verification status within the token itself.
Use SMS-based OTP authentication to enhance security when users log in with credentials. After initial login, if 2FA is enabled, an OTP is required before granting full access to protected resources like a dashboard.
Yes, Prisma supports multiple database providers including PostgreSQL, MySQL, and SQLite. While the example uses PostgreSQL, you can adapt the schema and database URL in schema.prisma
and .env
to your preferred database.
Configure the Plivo Node.js client by setting environment variables (PLIVO_AUTH_ID
, PLIVO_AUTH_TOKEN
, PLIVO_PHONE_NUMBER
) with your Plivo credentials. The sendSms
utility function in plivo.ts
then handles sending SMS messages using these credentials.
Hashing the OTP with bcrypt before storing it in the database significantly enhances security by preventing the storage of sensitive information in plain text. Only the hash is stored, and the submitted OTP is compared against the hash for verification.
The verifyOtp
utility function handles OTP expiry by comparing the current time to the stored twoFactorExpiry
timestamp. If expired, it clears the OTP data and returns false, prompting the user to request a new code.
The provided code uses next-auth@beta
, specifically for compatibility with the Next.js App Router and Server Actions. The beta version supports the latest features and conventions of the App Router.
The middleware.ts
file configures route protection by checking the twoFactorVerified
status within the session. If 2FA is enabled but not verified, the middleware redirects to the /verify-otp page.
The twoFactorVerified
flag in both the session and JWT indicates whether a user has successfully completed 2FA for the current session. This ensures protected routes are only accessible after both credential and OTP verification.
The generateOtp
utility function uses the otp-generator
library to create secure, numeric OTPs of a specified length (default is 6 digits). This function ensures the randomness and format of the codes.
Two configurations (auth.config.ts
, auth.ts
) are used to accommodate Next.js middleware. auth.config.ts
contains minimal callbacks and settings needed for early checks before full initialization in auth.ts
.
If Plivo credentials are missing during development, the sendSms
function logs a warning and simulates sending the SMS instead of throwing an error. This allows development to proceed without actual SMS delivery.
How to Implement SMS Two-Factor Authentication with Plivo, NextAuth.js & Next.js
Introduction
Implement SMS-based two-factor authentication (2FA) in your Next.js application using Plivo's SMS API and NextAuth.js for session management. This tutorial demonstrates how to build a secure authentication system where users verify their identity through SMS one-time passwords (OTP) after entering their login credentials.
Two-factor authentication significantly strengthens application security by requiring both knowledge-based credentials (email and password) and possession-based verification (mobile device with SMS access). This guide covers Next.js 15 project setup, Plivo SMS integration, NextAuth.js authentication flow customization, OTP generation and verification, user 2FA preference management, and production deployment strategies.
What You'll Build:
Create a production-ready Next.js authentication system with:
Technologies & Requirements:
create-next-app
).System Architecture:
Prerequisites:
node --version
.shadcn/ui
for UI components, or adapt examples to your preferred library.Final Outcome:
A Next.js application where users can:
Verification Date: All technology versions and requirements verified as of January 2025.
How to Set Up Your Next.js Project with Plivo SMS Authentication
Initialize your Next.js 15 application and install the required dependencies for SMS-based two-factor authentication.
Step 1: Create Your Next.js Application
Open your terminal and create a new Next.js project with TypeScript and Tailwind CSS:
This command scaffolds a Next.js application using the App Router architecture, TypeScript for type safety, Tailwind CSS for styling, and ESLint for code quality.
Step 2: Install Required Dependencies for SMS 2FA
Install NextAuth.js, Prisma ORM, Plivo SDK, and authentication utility libraries:
Package explanations:
next-auth@beta
: Authentication library for Next.js. Install the beta version for Next.js 14+ and App Router compatibility. NextAuth.js v5 is rebranding as Auth.js (documentation at authjs.dev).@auth/prisma-adapter
: Connects NextAuth with Prisma database.prisma
: Database ORM for PostgreSQL, MySQL, or SQLite (Prisma 6.x supports PostgreSQL 9.6+).plivo-node
: Official Plivo Node.js SDK for SMS messaging.bcrypt
: Password and OTP hashing library for secure storage.zod
: Runtime type validation and schema validation.otp-generator
: Generate secure numeric one-time passwords.@types/*
: TypeScript type definitions for development.Step 3: Initialize Prisma Database
Set up Prisma with PostgreSQL as your database provider:
This command creates:
prisma/schema.prisma
: Database schema definition file..env
: Environment configuration file withDATABASE_URL
.Environment variable details:
DATABASE_URL
: PostgreSQL connection string for your database. Update with your actual credentials and host information.NEXTAUTH_SECRET
: Random secret string for encrypting JWT tokens and session cookies. Critical for authentication security. Generate usingopenssl rand -base64 32
on Linux/macOS.NEXTAUTH_URL
: Your application's canonical URL. Required for NextAuth callback URLs and redirects.PLIVO_AUTH_ID
/PLIVO_AUTH_TOKEN
: Plivo API credentials from your dashboard. Keep these secure and never commit to version control.PLIVO_PHONE_NUMBER
: Your Plivo SMS-enabled phone number in E.164 format (e.g., +12345678900).OTP_EXPIRY_MINUTES
: OTP validity duration in minutes (default: 5 minutes).Step 4: Configure Environment Variables for Plivo
Open the
.env
file and add your database connection string and Plivo API credentials. Obtain Plivo credentials from your Plivo Console (Dashboard → API Keys & Credentials).Step 5: Define Database Schema for 2FA Authentication
Update
prisma/schema.prisma
to include NextAuth models and custom fields for SMS two-factor authentication.Database schema key components:
Account
,Session
,User
, andVerificationToken
for authentication state management.password
field toUser
model for email/password login.User
model:phoneNumber
: Stores user's verified phone number for SMS OTP delivery (unique constraint).twoFactorEnabled
: Boolean flag indicating whether SMS 2FA is active for the user account.twoFactorSecret
: Stores hashed OTP temporarily during verification (never store plain text OTPs).twoFactorExpiry
: Timestamp for OTP expiration validation.twoFactorVerified
field toSession
model to track 2FA completion status per login session.Step 6: Run Database Migrations
Generate and apply your Prisma database schema:
This command performs three operations:
schema.prisma
definition.Step 7: Understand the Project Structure
Your Next.js application structure organizes authentication components as follows:
This architecture separates authentication concerns using Next.js App Router route groups:
(auth)
for public authentication pages and(protected)
for secured application routes.How to Configure NextAuth.js with Plivo SMS Integration
Configure NextAuth.js v5 (Auth.js) to handle credential authentication and integrate Plivo for SMS-based OTP delivery.
Configure Prisma Client Singleton
Create a singleton Prisma client instance to prevent connection pool exhaustion in development:
Set Up Plivo Client for SMS Delivery
Configure the Plivo SMS client using your API credentials from environment variables:
Configure NextAuth.js Session and JWT Types
NextAuth.js v5 requires two configuration files:
auth.config.ts
for middleware andauth.ts
for the main authentication logic.First, extend the Session and JWT types using TypeScript module augmentation to add custom 2FA properties:
Create NextAuth Configuration for Middleware (auth.config.ts)
This configuration file handles route protection and session checks in Next.js middleware:
Create Main NextAuth Configuration (auth.ts)
Implement the Credentials provider with Plivo SMS integration for OTP delivery:
Key authentication flow elements:
PrismaAdapter
to synchronize NextAuth session state with your PostgreSQL database.Credentials
provider with Zod schema validation for email and password.twoFactorEnabled
flag set.twoFactorVerified: false
to trigger middleware redirect to verification page.Configure Next.js Middleware for Route Protection
Create middleware to protect authenticated routes based on 2FA verification status:
Implement OTP Generation and Verification Utilities
Create utility functions for secure OTP generation and validation against stored hashes: