How to Implement Server-Side Authentication in Next.js

Written by

Shreya
Front End Developer
Table of contents
Build with Radial Code
Authentication is a fundamental component of modern web applications, ensuring that only authorized users can access certain resources. In Next.js, authentication can be implemented on both the client-side and server-side. Opting for server-side authentication enhances security by safeguarding sensitive user data and minimizing exposure to client-side vulnerabilities. This guide will walk you through the process of implementing server-side authentication in Next.js using NextAuth.js, middleware, and API routes.
Why Choose Server-Side Authentication?
Server-side authentication provides several advantages:
- Enhanced Security: User authentication and session management occur on the server, reducing exposure to client-side attacks.
- Better Performance: Authentication logic runs before rendering, ensuring that only authorized users access protected pages.
- Improved SEO: Ensures that only authenticated content is served to search engines, preventing unnecessary redirects.
Setting Up Next.js and NextAuth.js

1. Install Dependencies
Before implementing authentication, install the required dependencies:
npm install next-auth @next-auth/prisma-adapter prisma
Prisma is used as the database ORM, but you can use other providers like MongoDB, Firebase, or a custom database.
2. Configure NextAuth.js
Create an API route to handle authentication.
pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "../../../lib/prisma";
export default NextAuth({
providers: [
Providers.Credentials({
name: "Credentials",
credentials: {
email: { label: "Email", type: "email" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
const user = await prisma.user.findUnique({ where: { email: credentials.email } });
if (user && user.password === credentials.password) {
return user;
}
return null;
}
})
],
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" },
callbacks: {
async session({ session, user }) {
session.user.id = user.id;
return session;
}
}
});
This configuration:
- Uses NextAuth.js with credential-based authentication.
- Connects to a Prisma database.
- Stores session data in a JWT token.
Protecting Pages Using Server-Side Authentication

Next.js provides to getServerSideProps handle authentication before rendering a page.
Example: Protecting a Dashboard Page
import { getSession } from "next-auth/react";
export async function getServerSideProps(context) {
const session = await getSession(context);
if (!session) {
return {
redirect: {
destination: "/login",
permanent: false,
},
};
}
return { props: { session } };
}
export default function Dashboard({ session }) {
return Welcome, {session.user.email}
;
}
- The getSession function checks for a valid session.
- If no session is found, the user is redirected to the login page.
- If authenticated, the page renders normally.
Protecting API Routes

If you want to secure an API route, you can check the session inside the API function.
Example: Secured API Route
import { getSession } from "next-auth/react";
export default async function handler(req, res) {
const session = await getSession({ req });
if (!session) {
return res.status(401).json({ error: "Unauthorized" });
}
res.status(200).json({ message: "Welcome to the protected API!" });
}
- The API will only respond to authenticated requests.
- If the session is invalid, it returns a 401 Unauthorized response.
Using Middleware for Route Protection
Next.js middleware provides another way to protect pages and API routes by checking authentication before a request reaches the server.
Example: Middleware for Authentication
Create a _middleware.js file inside the pagesdirectory.
import { getToken } from "next-auth/jwt";
import { NextResponse } from "next/server";
export async function middleware(req) {
const token = await getToken({ req, secret: process.env.NEXTAUTH_SECRET });
const isAuthPage = req.nextUrl.pathname.startsWith("/login");
if (!token && !isAuthPage) {
return NextResponse.redirect("/login");
}
return NextResponse.next();
- The middleware checks if the user is authenticated.
- If not, they are redirected to the login page before the request reaches the server.
- Authenticated users proceed normally.