Authentication is an essential component of contemporary web applications. In this detailed tutorial, we will discuss how to add authentication to Next.js using its server side rendering (SSR) features, API routes and native support for libraries such as NextAuth.js, Firebase or custom strategies.
Next.js, with its hybrid static and server rendering, makes authentication efficient and secure. Its API routes and middleware features enable you to authenticate on the server side, which improves security and supports features such as role based access control.
Major advantages of using Next.js for authentication:
1. Client-Side Authentication
Client-side authentication involves storing authentication tokens in the browser (e.g., cookies or localStorage). The user’s session is verified on the client side, which is simple to implement but less secure than server side approaches.
2. Server-Side Authentication
Server side authentication involves verifying the user’s identity on the server. Protected content is rendered only after verification. This is more secure, as it minimizes exposure of sensitive information.
3. Third-Party Authentication Providers
Using third-party services like Google, Facebook, or GitHub for authentication simplifies the process by offloading authentication logic to trusted providers.
Authentication with NextAuth.js
NextAuth.js is a full-featured authentication library designed specifically for Next.js. It supports multiple providers and is highly customizable.
Steps to Set Up NextAuth.js:
1.Install NextAuth.js:
npm install next-auth
2. Configure API Route: Create a new file at pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';
export default NextAuth({
providers: [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
callbacks: {
async session(session, token) {
session.user.id = token.id;
return session;
},
},
});
3. Protect Pages: Use the useSession hook to check authentication status:
import { useSession } from 'next-auth/react';
export default function ProtectedPage() {
const { data: session } = useSession();
if (!session) return <p>You need to be signed in to access this page.</p>;
return <div>Welcome, {session.user.name}!</div>;
}
Authentication with Firebase
Firebase provides robust authentication services with built in support for popular providers like Google, Facebook and email/password.
Steps to Set Up Firebase Authentication:
1. Install Firebase:
npm install firebase
2. Initialize Firebase: Create a firebase.js file:
import firebase from 'firebase/app';
import 'firebase/auth';
const firebaseConfig = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
projectId: process.env.FIREBASE_PROJECT_ID,
};
const app = !firebase.apps.length ? firebase.initializeApp(firebaseConfig) : firebase.app();
export const auth = app.auth();
3. Authenticate Users: Create a login component:
import { auth } from './firebase';
const signInWithGoogle = async () => {
const provider = new firebase.auth.GoogleAuthProvider();
await auth.signInWithPopup(provider);
};
export default function Login() {
return <button onClick={signInWithGoogle}>Sign in with Google</button>;
}
4. Protect Pages with Firebase: Use Firebase’s onAuthStateChanged method to monitor the user’s authentication state.
Custom Authentication Logic
For advanced use cases, you can build a custom authentication system using JWTs and API routes.
Steps for Custom Authentication:
1. Create an API Route: In pages/api/auth/login.js:
import jwt from 'jsonwebtoken';
export default function handler(req, res) {
const { username, password } = req.body;
if (username === 'admin' && password === 'password') {
const token = jwt.sign({ username }, process.env.JWT_SECRET, { expiresIn: '1h' });
return res.status(200).json({ token });
}
return res.status(401).json({ message: 'Invalid credentials' });
}
2. Secure API Routes: Protect API routes by validating the JWT:
import jwt from 'jsonwebtoken';
export default function handler(req, res) {
const { authorization } = req.headers;
if (!authorization) return res.status(401).json({ message: 'Unauthorized' });
try {
jwt.verify(authorization.split(' ')[1], process.env.JWT_SECRET);
return res.status(200).json({ message: 'Success' });
} catch (error) {
return res.status(401).json({ message: 'Unauthorized' });
}
}
3. Store Tokens Securely: Use HttpOnly cookies to store tokens securely and minimize exposure to cross site scripting (XSS) attacks.
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url));
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/about/:path*',
};
Next.js authentication can be adapted to suit different application needs, ranging from straightforward client side implementations to secure server side solutions. By taking advantage of Next.js's native features and widely used libraries, you can create scalable and secure authentication mechanisms that improve user experience.
Ready to transform your business with our technology solutions? Contact Us today to Leverage Our ReactJS Expertise.