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.
If you enjoy my content and would like to support my work, you can buy me a coffee. Your support is greatly appreciated!
Disclaimer: This content is generated by AI.
Top comments (0)