
- Next.js - Home
- Next.js - Overview
- Next.js - Project Setup
- Next.js - Folder Structure
- Next.js - App Router
- Next.js - Page Router
- Next.js Features
- Next.js - Pages
- Next.js - Data Fetching
- Next.js - ISR
- Next.js - Static File Serving
- Next.js - Pre-Rendering
- Next.js - Partial Pre Rendering
- Next.js - Server Side Rendering
- Next.js - Client Side Rendering
- Next.js Routing
- Next.js - Routing
- Next.js - Nested Routing
- Next.js - Dynamic Routing
- Next.js - Parallel Routing
- Next.js - Imperative Routing
- Next.js - Shallow Routing
- Next.js - Intercepting Routes
- Next.js - Redirecting Routes
- Next.js - Navigation and Linking
- Next.js Configuration
- Next.js - TypeScript
- Next.js - Environment Variables
- Next.js - File Conventions
- Next.js - ESLint
- Next.js API & Backend
- Next.js - API Routes
- Next.js - Dynamic API Routes
- Next.js - Route Handlers
- Next.js - API MiddleWares
- Next.js - Response Helpers
- Next.js API Reference
- Next.js - CLI Commands
- Next.js - Functions
- Next.js - Directives
- Next.js - Components
- Next.js - Image Component
- Next.js - Font Component
- Next.js - Head Component
- Next.js - Form Component
- Next.js - Link Component
- Next.js - Script Component
- Next.js Styling & SEO
- Next.js - CSS Support
- Next.js - Global CSS Support
- Next.js - Meta Data
- Next.js Advanced Topics
- Next.js - Error Handling
- Next.js - Server Actions
- Next.js - Fast Refresh
- Next.js - Internationalization
- Next.js - Authentication
- Next.js - Session Management
- Next.js - Authorization
- Next.js - Caching
- Next.js - Data Caching
- Next.js - Router Caching
- Next.js - Full Route Caching
- Next.js - Request Memoization
- Next.js Performance Optimization
- Next.js - Optimizations
- Next.js - Image Optimization
- Next.js - Lazy Loading
- Next.js - Font Optimization
- Next.js - Video Optimization
- Next.js - Script Optimization
- Next.js - Memory Optimization
- Next.js - Using OpenTelemetry
- Next.js - Package Bundling Optimization
- Next.js Testing
- Next.js - Testing
- Next.js - Testing with Jest
- Next.js - Testing with Cypress
- Next.js - Testing with Vitest
- Next.js - Testing with Playwright
- Next.js Debugging & Deployment
- Next.js - Debugging
- Next.js - Deployment
- Next.js Useful Resources
- Next.js - Interview Questions
- Next.js - Quick Guide
- Next.js - Useful Resources
- Next.js - Discussion
Next.js - Session Management
What is Session Management?
Session management is a step to ensure the user authenticated state is maintained across multiple sessions. This involves preserving the user's state while reloading the page or closing the browser. There are two types of sessions:
Stateless Session
In stateless session management, the session data is stored in the browser's cookies. For each request to the server, the cookies are sent, which allow the session to be verified at server. This session is stateless, meaning that the session data is not stored on the server. This method is simpler, but can be less secure if not implemented correctly.
To create and manage stateless sessions, there are a few steps you need to follow:
- Generate a secret key, which will be used to sign your session, and store it as an environment variable.
- Write logic to encrypt/decrypt session data using a session management library.
- Manage cookies using the Next.js cookies API.
Create a Secret Key
There are several ways to create a secret key. One way is to use the openssl command line tool. Run the following command in your terminal.
openssl rand -base64 32
This command will generate a 32-character random string that you can use as your secret key and store in your environment variables file.
// /.env SESSION_SECRET=your_secret_key
Now you can use the key in session management logic
const Key = process.env.SESSION_SECRET
Encrypt/Decrypt Session Data
After creating a secret key, you can use it to encrypt/decrypt session data. You can use your preferred session management library to do this. In the code below, we have used jose, which is a popular library for encrypting/decrypting JSON Web Tokens (JWT). JWT is a standard for securely transmitting data between parties.
// app/lib/session.ts import 'server-only' import { SignJWT, jwtVerify } from 'jose' import { SessionPayload } from '@/app/lib/definitions' const secretKey = process.env.SESSION_SECRET const encodedKey = new TextEncoder().encode(secretKey) export async function encrypt(payload: SessionPayload) { return new SignJWT(payload) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() .setExpirationTime('7d') .sign(encodedKey) } export async function decrypt(session: string | undefined = '') { try { const { payload } = await jwtVerify(session, encodedKey, { algorithms: ['HS256'], }) return payload } catch (error) { console.log('Failed to verify session') } }
Setting Cookies
Next step is to create a cookie to store the session data. You can use the Next.js cookies API to do this. The cookie should be set on server and it should include following properties:
- Name: session
- Value: The encrypted session data
- Max-Age: The number of seconds until the cookie expires
- HttpOnly: Set to true to prevent JavaScript from accessing the cookie
- Secure: Set to true to use HTTPS
- SameSite: Set to 'lax' to prevent CSRF attacks
// app/lib/session.ts import 'server-only' import { cookies } from 'next/headers' export async function createSession(userId: string) { const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) const session = await encrypt({ userId, expiresAt }) const cookieStore = await cookies() cookieStore.set('session', session, { httpOnly: true, secure: true, expires: expiresAt, sameSite: 'lax', path: '/', }) }
Database Session
In database session management, the session data is stored in a database on the server. This method is more secure than stateless session management, but it requires more resources and is more complex to implement.
To create and manage database sessions, there are a few steps you need to follow:
- Create a table in your database to store session and data related to the session.
- Implement functionality to insert, update, and delete sessions
- Encrypt the session ID before storing it in the user's browser, and ensure the database and cookie stay in sync
In the code below, we have implemented a database session management system. This system uses a table called sessions
to store session data. The table has the following columns:
-
id
: The primary key -
userId
: The user ID -
expiresAt
: The date and time when the session expires -
sessionId
: The encrypted session ID
The createSession
function is responsible for creating a new session in the database. It takes the user ID as an argument and returns the session ID. The function first creates a new session in the database, then encrypts the session ID, and finally stores the encrypted session ID in the user's browser. The function also returns the session ID.
import cookies from 'next/headers' import { db } from '@/app/lib/db' import { encrypt } from '@/app/lib/session' export async function createSession(id: number) { const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 1. Create a session in the database const data = await db .insert(sessions) .values({ userId: id, expiresAt, }) // Return the session ID .returning({ id: sessions.id }) const sessionId = data[0].id // 2. Encrypt the session ID const session = await encrypt({ sessionId, expiresAt }) // 3. Store the session in cookies for optimistic auth checks const cookieStore = await cookies() cookieStore.set('session', session, { httpOnly: true, secure: true, expires: expiresAt, sameSite: 'lax', path: '/', }) }