setting up middleware to authenticate pages
Unanswered
Morelet’s Crocodile posted this in #help-forum
Morelet’s CrocodileOP
I am trying to authenticate dashboard and its relevant pages on the basis of jwt token that is stored in cookies on login. But even if user is logged in i still get the cookies undefined, even though cookies are set and i can see it in application cookies storage.
How do i add matchers for protected routes?
How do i add matchers for protected routes?
// middleware.js
import { NextResponse } from 'next/server';
import { USER_AUTH_TOKEN } from './constants';
export async function middleware(request) {
// Getting the authentication token from cookies
const authToken = request.cookies.get(USER_AUTH_TOKEN);
// Check if the route starts with /pdftoolsdashboard
const isProtectedRoute = request.nextUrl.pathname.startsWith('/pdftoolsdashboard');
// If the route is protected and there's no authentication token, redirect to the home page
if (isProtectedRoute && !authToken) {
return NextResponse.redirect('/');
}
}
export const config = {
matcher: '/pdftoolsdashboard/:path*',
}15 Replies
https://nextjs.org/docs/app/building-your-application/routing/middleware#matcher
This is the matching docs btw
This is the matching docs btw
Morelet’s CrocodileOP
i'm getting the cookie undefined always. even though it exists, @Arinji do you know anything about it?
import { NextResponse } from 'next/server';
import { USER_AUTH_TOKEN } from './constants';
export default function middleware(req) {
let verify = req.cookies.get('auth_token');
const url = req.nextUrl.clone();
const url2 = JSON.stringify(url);
console.log('verify', verify)
// console.log('url', url)
if (!verify?.value && url2.includes('/dashboard/pdftoolsdashboard')) {
console.log('user not authenticated')
url.pathname = '/dashboard/login';
return NextResponse.redirect(url);
}
// if (verify?.value && url2.includes('/dashboard/signup')) {
// url.pathname = '/dashboards/login';
// return NextResponse.redirect(url);
// }
if (verify?.value && url2.includes('/dashboard/login')) {
console.log('user authenticated')
url.pathname = '/dashboard/pdftoolsdashboard';
return NextResponse.redirect(url);
}
}
export const config = {
matcher: '/dashboard/pdftoolsdashboard/:path*',
}so verify is undefined?
which page are you on
Morelet’s CrocodileOP
@Arinji when i login, the user must be redirected on dashboard/pdftoolsdashboard page if authenticated and i get the token. auth_token is set on login but in middleware i get it undefined. Because of that i stays on login page even if the user is authenticated
Or make any requests after the cookie was added?
Morelet’s CrocodileOP
yes i added a redirect when user is successfully logged in on the login page
i saw someone was also facing this issue but i don't understand the solution
https://github.com/vercel/next.js/discussions/38690
https://github.com/vercel/next.js/discussions/38690
@Morelet’s Crocodile yes i added a redirect when user is successfully logged in on the login page
So the user is redirected to which page?
Morelet’s CrocodileOP
const signInhandler = async (data) => {
setIsLoading(true);
const response = await postDataApiCall('/api/dashboard/auth/login',data);
const { error } = response;
if(!response.error){
const user = response;
localStorage.setItem('currentUser' , JSON.stringify(user))
localStorage.setItem('token' , JSON.stringify(user.token))
await push('/dashboard/pdftoolsdashboard') //here
toast.success(`Welcome ${user.userName} `, { position: toast.POSITION.TOP_RIGHT } );
}else{
toast.error(`${error}`, { position: toast.POSITION.TOP_RIGHT });
}
setIsLoading(false);
};The api code as well
Morelet’s CrocodileOP
const bcrypt = require("bcryptjs")
const jwt = require("jsonwebtoken")
import { serialize } from 'cookie';
import { exceptions } from '../../../../libs/exception';
import { responseMessages } from '../../../../libs/messages';
import { getUserByEmail } from '../../../../services/authServices';
import { USER_AUTH_TOKEN } from '../../../../constants';
const handler = async (req, res) => {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res
.status(exceptions.BAD_REQUEST_EXCEPTION)
.json({ error: responseMessages.MISSING_FIELDS });
}
const user = await getUserByEmail(email);
if (!user) {
return res
.status(exceptions.BAD_REQUEST_EXCEPTION)
.json({ error: responseMessages.ENTER_VALIDE_CREDENTIALS });
}
const passwordIsValid = bcrypt.compareSync(password, user.password);
if (!passwordIsValid) {
return res
.status(exceptions.BAD_REQUEST_EXCEPTION)
.json({ error: responseMessages.ENTER_VALIDE_CREDENTIALS });
}
if (!user.isActive) {
return res
.status(exceptions.FORBIDDEN_EXCEPTION)
.json({ error: responseMessages.ACCOUNT_IS_INACTIVE });
}
const token = jwt.sign({ _id: user.id, _role: user.role }, process.env.JWT_SECRET, {
algorithm: 'HS256',
allowInsecureKeySizes: true,
expiresIn: '24h',
});
const cookieOptions = {
expires: new Date(Date.now() + 86400000),
secure: true,
httpOnly: true,
sameSite: 'Strict', // Adjust based on your requirements
path: '/dashboard',
};
const serialized = serialize( USER_AUTH_TOKEN, token, cookieOptions )
// req.cookies.set('auth-user', serializedUserData)
const data = {
userName: user.name,
};
res.setHeader("Set-Cookie", serialized)
res.status(exceptions.OK).json({
data: data
});
};
export default handler;updated middleware code @Arinji
import { NextResponse } from 'next/server';
import { jwtDecode } from 'jwt-decode';
export default function middleware(req) {
const authToken = req.cookies.get('auth_token');
const url = req.nextUrl.clone();
const url2 = JSON.stringify(url);
console.log('request', req.nextUrl.pathname)
const decodedUser = authToken && jwtDecode(authToken.value)
console.log('decoded', decodedUser)
//access users list page only if user role is admin
if (authToken && decodedUser?._role !== 'ADMIN' && url2.includes('/dashboard/pdftoolsdashboard/users')) {
url.pathname = '/dashboard/pdftoolsdashboard';
return NextResponse.redirect(url);
}
//if user not authenticated, redirect to login page
if (!authToken && url2.includes('/dashboard/pdftoolsdashboard')) {
url.pathname = '/dashboard/login'
return NextResponse.redirect(url)
}
//if user successfully authenticated, redirect to dashboard
if (authToken && decodedUser._role && url2.includes('/dashboard/login')) {
console.log('authenticated')
url.pathname = '/dashboard/pdftoolsdashboard'
return NextResponse.redirect(url)
}
}
export const config = {
matcher: ['/dashboard/pdftoolsdashboard/:path*', '/dashboard/:path*'],
}Morelet’s CrocodileOP
@Arinji i am not using NextJsAuth for this. Whenever i'm done login and its time to redirect, middleware is very fast and don't see the cookie on the first request. I'm thinking of using zustand persist to store cookies on login. How does that sound?