unable to use next-auth with i18n
Unanswered
Naeemgg posted this in #help-forum
NaeemggOP
I can't use next-auth and i18n together because of a middleware issue.
I've to use this for next-auth:
And this for i18n:
when I combine both middleware next-auth protected routes aren't working, I can still go to /dashboard without being logged in.
I've to use this for next-auth:
export { default } from "next-auth/middleware"
export const config = { matcher: ["/dashboard"] }
And this for i18n:
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { i18n } from '@/i18n.config'
import { match as matchLocale } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
function getLocale(request: NextRequest): string | undefined {
const negotiatorHeaders: Record<string, string> = {}
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value))
// @ts-ignore locales are readonly
const locales: string[] = i18n.locales
const languages = new Negotiator({ headers: negotiatorHeaders }).languages()
const locale = matchLocale(languages, locales, i18n.defaultLocale)
return locale
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname
const pathnameIsMissingLocale = i18n.locales.every(
locale => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
const locale = getLocale(request)
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`,
request.url
)
)
}
}
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher: ['/((?!api|_next/static|_next/image|images).*)']
}
when I combine both middleware next-auth protected routes aren't working, I can still go to /dashboard without being logged in.
8 Replies
NaeemggOP
Anyone...
Next Auth provides a
Hence, try the following:
withAuth
function which allows you to wrap an existing middleware inside.Hence, try the following:
import { withAuth } from "next-auth/middleware"
const middleware = withAuth((req) => ...)
export default middleware;
Next.js doesn't support multiple middlewares, you must combine them into a middleware in this case
NaeemggOP
Okay got it but what about Matcher???
I got negative loop regex for i18n and for next-auth just protected routes array...
I got negative loop regex for i18n and for next-auth just protected routes array...
import {withAuth} from "next-auth/middleware"
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { i18n } from '@/i18n.config'
import { match as matchLocale } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
function getLocale(request: NextRequest): string | undefined {
const negotiatorHeaders: Record<string, string> = {}
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value))
// @ts-ignore locales are readonly
const locales: string[] = i18n.locales
const languages = new Negotiator({ headers: negotiatorHeaders }).languages()
const locale = matchLocale(languages, locales, i18n.defaultLocale)
return locale
}
const middleware = withAuth((request: NextRequest)=> {
const pathname = request.nextUrl.pathname
const pathnameIsMissingLocale = i18n.locales.every(
locale => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
)
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
const locale = getLocale(request)
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`,
request.url
)
)
}
})
export default middleware;
what about this
for i18n:
export const config = {
// Matcher ignoring `/_next/` and `/api/`
matcher: ['/((?!api|_next/static|_next/image|images).*)']
}
for next-auth:
export const config = { matcher: ["/dashboard"] }
NaeemggOP
@fuma 💙 joulev ?
You may combine the matcher if they both share the same routes, but seems in your case, you only wanna protect the dashboard page.
Actually
so that instead of wrapping your middleware inside of
Actually
withAuth
also offers a simple method to achieve it, you can use withAuth
in this way:if (request.nextUrl.pathname === "/dashboard")
return withAuth(request)
so that instead of wrapping your middleware inside of
withAuth
, you can use it as a functionCheck its type definitions for other usages