Below is a fully functional example of how you can create an authentication system in a Next.js application without using NextAuth. This example uses JWT (JSON Web Tokens) for authentication and cookie-based session management.
1. Install Dependencies
First, install the required dependencies:
npm install next react react-dom bcryptjs jsonwebtoken cookie
2. Directory Structure
Your project structure should look like this:
/pages
/api
/auth
login.js
register.js
logout.js
/protected
index.js
_app.js
index.js
/utils
auth.js
db.js
/middleware
auth.js
3. Create a Simple User Database
For simplicity, let's create a fake user database.
/utils/db.js
const users = [];
module.exports = {
users,
};
4. Create Authentication Utilities
/utils/auth.js
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const JWT_SECRET = 'your_jwt_secret';
const hashPassword = async (password) => {
return await bcrypt.hash(password, 10);
};
const verifyPassword = async (password, hashedPassword) => {
return await bcrypt.compare(password, hashedPassword);
};
const generateToken = (user) => {
return jwt.sign({ id: user.id, email: user.email }, JWT_SECRET, { expiresIn: '1h' });
};
const verifyToken = (token) => {
try {
return jwt.verify(token, JWT_SECRET);
} catch (error) {
return null;
}
};
module.exports = {
hashPassword,
verifyPassword,
generateToken,
verifyToken,
};
5. Create API Routes for Authentication
/pages/api/auth/register.js
import { users } from '../../../utils/db';
import { hashPassword } from '../../../utils/auth';
export default async (req, res) => {
if (req.method === 'POST') {
const { email, password } = req.body;
const userExists = users.find(user => user.email === email);
if (userExists) {
return res.status(400).json({ message: 'User already exists' });
}
const hashedPassword = await hashPassword(password);
const newUser = { id: users.length + 1, email, password: hashedPassword };
users.push(newUser);
res.status(201).json({ message: 'User registered successfully' });
} else {
res.status(405).json({ message: 'Method not allowed' });
}
};
/pages/api/auth/login.js
import { users } from '../../../utils/db';
import { verifyPassword, generateToken } from '../../../utils/auth';
import cookie from 'cookie';
export default async (req, res) => {
if (req.method === 'POST') {
const { email, password } = req.body;
const user = users.find(user => user.email === email);
if (!user) {
return res.status(400).json({ message: 'Invalid credentials' });
}
const isValid = await verifyPassword(password, user.password);
if (!isValid) {
return res.status(400).json({ message: 'Invalid credentials' });
}
const token = generateToken(user);
res.setHeader('Set-Cookie', cookie.serialize('token', token, {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: 3600,
sameSite: 'strict',
path: '/'
}));
res.status(200).json({ message: 'Logged in successfully' });
} else {
res.status(405).json({ message: 'Method not allowed' });
}
};
/pages/api/auth/logout.js
import cookie from 'cookie';
export default (req, res) => {
if (req.method === 'POST') {
res.setHeader('Set-Cookie', cookie.serialize('token', '', {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: -1,
sameSite: 'strict',
path: '/'
}));
res.status(200).json({ message: 'Logged out successfully' });
} else {
res.status(405).json({ message: 'Method not allowed' });
}
};
6. Middleware for Protected Routes
/middleware/auth.js
import { verifyToken } from '../utils/auth';
import cookie from 'cookie';
const authMiddleware = (handler) => {
return async (req, res) => {
const cookies = cookie.parse(req.headers.cookie || '');
const token = cookies.token;
if (!token) {
return res.status(401).json({ message: 'Authentication required' });
}
const user = verifyToken(token);
if (!user) {
return res.status(401).json({ message: 'Authentication required' });
}
req.user = user;
return handler(req, res);
};
};
export default authMiddleware;
7. Create a Protected Route
/pages/protected/index.js
import React from 'react';
import authMiddleware from '../../middleware/auth';
const ProtectedPage = ({ user }) => {
return (
<div>
<h1>Protected Page</h1>
<p>Welcome, {user.email}</p>
</div>
);
};
export const getServerSideProps = authMiddleware(async (context) => {
return {
props: { user: context.req.user },
};
});
export default ProtectedPage;
8. Create the Main Application File
/pages/_app.js
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
9. Create the Home Page with Login and Registration Forms
/pages/index.js
import { useState } from 'react';
import axios from 'axios';
const Home = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');
const handleRegister = async () => {
try {
const response = await axios.post('/api/auth/register', { email, password });
setMessage(response.data.message);
} catch (error) {
setMessage(error.response.data.message);
}
};
const handleLogin = async () => {
try {
const response = await axios.post('/api/auth/login', { email, password });
setMessage(response.data.message);
} catch (error) {
setMessage(error.response.data.message);
}
};
return (
<div>
<h1>Authentication Example</h1>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button onClick={handleRegister}>Register</button>
<button onClick={handleLogin}>Login</button>
{message && <p>{message}</p>}
</div>
);
};
export default Home;
10. Test Your Application
Now you can run your Next.js application and test the authentication system.
npm run dev
Navigate to http://localhost:3000 and test the registration and login functionality.
This setup provides a basic authentication system using JWT and cookies in a Next.js application. You can extend this example to include more features such as password reset, email verification, and social login integration.
Support My Work ❤️
If you enjoy my content and find it valuable, consider supporting me by buying me a coffee. Your support helps me continue creating and sharing useful resources. Thank you!
Connect with Me 🌍
Let’s stay connected! You can follow me or reach out on these platforms:
🔹 YouTube – Tutorials, insights & tech content
🔹 LinkedIn – Professional updates & networking
🔹 GitHub – My open-source projects & contributions
🔹 Instagram – Behind-the-scenes & personal updates
🔹 X (formerly Twitter) – Quick thoughts & tech discussions
I’d love to hear from you—whether it’s feedback, collaboration ideas, or just a friendly hello!
Disclaimer
This content has been generated with the assistance of AI. While I strive for accuracy and quality, please verify critical information independently.
Top comments (0)