Can't access current pathname in Server Component for redirect after session check failure #77950
-
Hi 😁 I'm working on an authentication setup using the App Router in Next.js 15. I’m implementing a custom verifySession() function that runs in a protected page (i.e., not middleware or a route handler). The goal is to:
What I’ve tried
CodeHere is my middleware: [...]
export default async function middleware(request) {
const path = request.nextUrl.pathname
const isStaticPublic = staticPublicRoutes.includes(path)
const isPrefixPublic = prefixPublicRoutes.some((prefix) => path.startsWith(prefix))
const isPublicRoute = isStaticPublic || isPrefixPublic
const cookie = request.cookies.has(SESSION_COOKIE)
if (!isPublicRoute && !cookie) {
const loginUrl = new URL("/login", request.url)
if (path !== "/") {
loginUrl.searchParams.set("redirect", path)
}
return NextResponse.redirect(loginUrl)
}
return NextResponse.next()
}
export const config = {
matcher: ["/((?!api|_next/static|_next/image|.*\\.png$).*)"],
} And my verifySession: import "server-only"
[...]
export const verifySession = cache(async (needRedirect = true) => {
try {
const cookieStore = await cookies()
const sessionCookie = cookieStore.get(SESSION_COOKIE)
if (!sessionCookie) throw new AuthError("No session cookie found") // shouldn't happen unless someone bypassed middleware
const token = await decrypt(sessionCookie.value)
if (!token) throw new AuthError("Invalid session token")
const dbSession = await getSessionByToken(token)
if (!dbSession) throw new AuthError("Session not found")
if (dbSession.expiresAt < new Date()) throw new AuthError("Session expired")
const { user } = dbSession
if (!user) throw new AuthError("User not associated with session")
return { token, user }
} catch (err) {
console.error("Session verification failed:", err.message)
const headersList = await headers()
console.log(Object.fromEntries(headersList.entries()))
const pathname = "I dont know"
if (needRedirect) {
if (pathname && pathname !== "/") {
const encodedRedirect = encodeURIComponent(pathname)
redirect(`/login?redirect=${encodedRedirect}`)
} else {
redirect("/login")
}
}
}
}) Knowing that the console log of the headers return that:
Thanks so much in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
EditI may have found a potential workaround, and I’d really appreciate your thoughts on whether this is a reasonable approach. In middleware, I’m now setting a cookie (origin) with the current request.nextUrl.pathname, like so: const path = request.nextUrl.pathname
if (path !== "/login") {
const response = NextResponse.next()
response.cookies.set({
name: "origin",
value: path,
httpOnly: true,
secure: true,
sameSite: "lax",
path: "/",
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000),
}) Then in verifySession(), I access the origin cookie using cookies().get("origin") and use that as the fallback for ?redirect= when redirecting to /login. } catch (err) {
console.error("Session verification failed:", err.message)
const origin = (await cookies()).get("origin")?.value
if (needRedirect) {
if (origin && origin !== "/") {
const encodedRedirect = encodeURIComponent(origin)
redirect(`/login?redirect=${encodedRedirect}`)
} else {
redirect("/login")
}
}
} But I’m not sure if this is the best practice, because the cookie get recreated on every call. |
Beta Was this translation helpful? Give feedback.
-
How did you go about adding the header? import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
// Clone the request headers and set a new header `x-hello-from-middleware1`
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-hello-from-middleware1', 'hello')
// You can also set request headers in NextResponse.next
const response = NextResponse.next({
request: {
// New request headers
headers: requestHeaders,
},
})
// Set a new response header `x-hello-from-middleware2`
response.headers.set('x-hello-from-middleware2', 'hello')
return response
} Note, how the NextResponse, receives the modified headers, which are forwarded to the server component, IIRC. |
Beta Was this translation helpful? Give feedback.
How did you go about adding the header?