Closed
Description
Checklist
- The issue can be reproduced in the nextjs-auth0 sample app (or N/A).
- I have looked into the Readme, Examples, and FAQ and have not found a suitable solution or answer.
- I have looked into the API documentation and have not found a suitable solution or answer.
- I have searched the issues and have not found a suitable solution or answer.
- I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- I agree to the terms within the Auth0 Code of Conduct.
Description
When upgrading to v4 I noticed the name of the session cookie changed from appSession
-> __session
and I believe this is requiring users to re-authenticate after upgrade. When trying to access a page that requires auth, the new v4 middleware is not able to find an active session for a user that was previously authenticated with v3 session and redirects to /auth/login
.
We have not deployed to production, this observation is just from local testing, so want to raise this issue to make sure there isn't any technique to prevent this.
Reproduction
- Authenticate with a version of the application running v3
- Notice a valid session cookie in the user's browser. (note: I see the chunked appSession.0 and appSession.1)
- Switch branches to a version of the app running v4 (simulating an upgrade of our Next.js application)
- Refresh the same page and see that I am required to authenticate again.
- After authenticating I see both the appSession and __session cookies
Additional context
Here is our auth code in the middleware:
const authRes = await auth0.middleware(req);
if (req.nextUrl.pathname.startsWith('/auth')) {
// If the request is for the auth routes, short circuit the middleware chain and return the response
return authRes;
}
const session = await auth0.getSession(req);
/**
* It's important to call getAccessToken here in the middleware with the req and res objects as inputs.
* If the access token in the request is expired, getAccessToken will update it from Auth0 and set the new token in the response.
* This allows the new token to be accessed from server components and other middleware.
*
* If getAccessToken is called only in the server component, then the token will be refreshed but Server components cannot set cookies,
* so the updated token will not be persisted for subsequent requests.
*
* if getAccessToken is called without the req and res objects, the token will be updated but not persisted for other middleware or server components.
* See this issue for more details: https://github.com/auth0/nextjs-auth0/issues/1841
*/
const token = await getAccessToken({ req, res: authRes });
const isUserActive = session && token;
const isPublicRoute = PUBLIC_ROUTE_PREFIXES.find((path) =>
req.nextUrl?.pathname?.startsWith(path),
);
const isPublicPage = PUBLIC_PAGES.find(
(path) => req.nextUrl?.pathname === path,
);
if (!isPublicRoute && !isPublicPage && !isUserActive) {
// User does not have an active session — short circuit middleware and redirect to login
const { origin } = new URL(req.url);
return NextResponse.redirect(
`${origin}/auth/login?returnTo=${buildReturnTo(req)}`,
);
}
const finalResponse = await next(req, authRes, event);
// Auth0 middleware sets some headers that we need to pass along to the final response.
// Other middlewares may have generated new responses without these headers (like the locale middleware), so we need to
// copy the headers from the auth response to the final response.
for (const [key, value] of authRes.headers.entries()) {
finalResponse.headers.set(key, value);
}
return finalResponse;
}
export async function getAccessToken(
requestVars: { req: NextRequest; res: NextResponse } | undefined = undefined,
) {
try {
const result =
requestVars != null
? await auth0.getAccessToken(requestVars.req, requestVars.res)
: await auth0.getAccessToken();
return result.token;
} catch (error) {
authLogger.error(error, `Error retrieving access token`);
authLogger.info(`Session details: ${getSessionDetails()};`);
return undefined;
}
}
async function getSessionDetails(): Promise<string> {
const session = await auth0.getSession();
return JSON.stringify({
email: session?.user?.email,
name: session?.user?.name,
hasAccessToken: Boolean(session?.tokenSet.accessToken),
accessTokenExpirationTime: String(session?.tokenSet.expiresAt),
hasRefreshToken: Boolean(session?.refreshToken),
hasSession: Boolean(session),
runtime: process.env.NEXT_RUNTIME,
});
}
nextjs-auth0 version
4.0.0
Next.js version
15.1.6
Node.js version
20.9.0