next-intl and role based API routes
Unanswered
Havana posted this in #help-forum
HavanaOP
I have some routes that are admin only access.
The route I want is http://localhost:3000/api/auth/providers and currently because of next-intl it becomes http://localhost:3000/en/api/auth/providers
Is this fine? Or should I remove localization from api routes? I do want API responses to be localized too.
This is my current middleware:
The route I want is http://localhost:3000/api/auth/providers and currently because of next-intl it becomes http://localhost:3000/en/api/auth/providers
Is this fine? Or should I remove localization from api routes? I do want API responses to be localized too.
This is my current middleware:
import NextAuth from "next-auth";
import authConfig from "@/auth.config";
import {
DEFAULT_LOGIN_REDIRECT,
API_AUTH_PREFIX,
AUTH_ROUTES,
PUBLIC_ROUTES,
routing,
} from "@/routes";
import createMiddleware from "next-intl/middleware";
// Initialize NextAuth with configuration.
const { auth } = NextAuth(authConfig);
/**
* Middleware to handle user authentication and route protections.
* It checks if the user is logged in and redirects or allows access based on route configurations.
* @param {NextApiRequest} req - The incoming HTTP request object.
* @returns {Response | void} - A HTTP response to redirect the user or void to allow the request to continue.
*/
export default auth((req) => {
const { nextUrl } = req;
const isLoggedIn = !!req.auth;
// Internationalization middleware
const intlMiddleware = createMiddleware(routing);
const intlResult = intlMiddleware(req);
// If intlMiddleware returns a response, return it immediately.
if (intlResult) return intlResult;
// Check if the request targets API authentication routes.
const isApiAuthRoute = nextUrl.pathname.startsWith(API_AUTH_PREFIX);
const isPublicRoute = PUBLIC_ROUTES.includes(nextUrl.pathname);
const isAuthRoute = AUTH_ROUTES.includes(nextUrl.pathname);
// API auth routes should not invoke this middleware.
if (isApiAuthRoute) return;
// Redirect logged-in users trying to access auth-specific routes to the default login redirect.
if (isAuthRoute) {
if (isLoggedIn) {
return Response.redirect(new URL(DEFAULT_LOGIN_REDIRECT, nextUrl));
}
return;
}
// Non-authenticated users are redirected to login except for public routes.
if (!isLoggedIn && !isPublicRoute) {
let callbackUrl = nextUrl.pathname;
if (nextUrl.search) {
callbackUrl += nextUrl.search; // Include query parameters if present.
}
const encodedCallbackUrl = encodeURIComponent(callbackUrl);
return Response.redirect(
new URL(`/auth/login?callbackUrl=${encodedCallbackUrl}`, nextUrl)
);
}
});
/**
* Configuration to selectively enable middleware based on request paths.
* This helps in avoiding the middleware activation on specified patterns like static files or specific API routes.
*/
export const config = {
matcher: [
// Skip Next.js internals and all static files, unless found in search params
"/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
// Always run for API routes
"/(api|trpc)(.*)",
// Match internationalized pathnames
"/(nl|en)/:path*",
// Always return the root
"/",
],
};4 Replies
Red harvester ant
Hello That is good. I think no need to change that.
@Red harvester ant Hello That is good. I think no need to change that.
HavanaOP
It's not good, the intl stuff changes my api route so I can't call it by using http://localhost:3000/api/auth/providers but because of next-intl this can change
And I cant exclude it from my matcher since that will also disable auth
HavanaOP
https://medium.com/@issam.ahw/simplifying-next-js-authentication-and-internationalization-with-next-auth-and-next-intl-0a01f1330e46
This document helped me.
Solution ended up being this:
This document helped me.
Solution ended up being this:
export const locales = ["en", "nl"] as const;
const intlMiddleware = createMiddleware({
locales: locales,
defaultLocale: "en",
localeDetection: false,
});
....
....
const intlMatcher = new RegExp("^/(?!api|trpc)(|nl|en)(/.*)?$");
const isNotAPImatcher = intlMatcher.test(nextUrl.pathname);
// Run the internationalization middleware for all non-API routes.
if (isNotAPImatcher) {
const intlResponse = intlMiddleware(req);
if (intlResponse) {
return intlResponse;
}
}