I'm working on a project with NestJS as the backend and Next.js 14 (app router) for the frontend. My backend implements cookie-based session authentication, where the session ID is stored in a cookie. I need help setting up role-based access control for protected routes in my Next.js app, utilizing session validation from my NestJS backend.
Here's the flow I'm trying to achieve:
Additionally, I'm using next-intl for internationalization, with the following middleware setup for locale handling:
import createMiddleware from "next-intl/middleware";
export default createMiddleware({
locales: ["en", "uk"],
defaultLocale: "en",
});
export const config = {
matcher: ["/", "/(uk|en)/:path*"],
};
And my i18n.ts for locale validation:
import { notFound } from "next/navigation";
import { getRequestConfig } from "next-intl/server";
const locales = ["en", "uk"];
export default getRequestConfig(async ({ locale }) => {
if (!locales.includes(locale as any)) notFound();
return {
messages: (await import(`../messages/${locale}.json`)).default,
};
});
In your Next.js app, create a middleware function to handle session validation. This middleware should extract the session cookie from the request and forward it to the NestJS backend for validation. If the validation is successful, store the user's session data, including roles, in the request object for later use.
it can look something like this
// sessionValidationMiddleware.js
import axios from 'axios';
const sessionValidationMiddleware = async (req, res, next) => {
const sessionId = req.cookies.sessionId;
try {
// Forward session validation request to NestJS backend
const response = await axios.post('http://nestjs-backend.com/validate-session', { sessionId });
if (response.status === 200) {
req.user = response.data; // Store user data in the request object
next();
} else {
res.redirect('/login'); // Redirect to login for unauthorized users
}
} catch (error) {
console.error('Error validating session:', error);
res.redirect('/login'); // Redirect to login on error
}
};
export default sessionValidationMiddleware;
In your middleware.ts file, import and use the session validation middleware for the routes that require authentication:
// middleware.ts
import { createMiddleware } from 'next';
import sessionValidationMiddleware from './path-to-your-session-validation-middleware';
const middleware = createMiddleware();
// Apply session validation middleware to protected routes
middleware.get('/admin', sessionValidationMiddleware);
middleware.get('/student', sessionValidationMiddleware);
middleware.get('/teacher', sessionValidationMiddleware);
export default middleware;
For each of your route files (e.g., admin.tsx, student.tsx, teacher.tsx), check the user's roles and handle access control:
// admin.tsx
const AdminPage = ({ user }) => {
// Check if the user has the required role (adminId) for this route
if (user.roles && user.roles.adminId) {
return {
props: { user },
};
} else {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
};
export default AdminPage;
Hope this helps