nextauthjs / nextauthjs/next-auth
next/link prefetch cause to infinite redirects when using `withAuth` middleware
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 28.4k
- Forks
- 4k
- PR merge metrics
- No merged PRs in 30d
Description
Environment
nextjs13, nextauth@4.20.1
Reproduction URL
See [How to reproduce] & [Sugguestion]
Describe the issue
Vercel put out a warning here regarding using middleware for authentication.
General speaking, if the state of user authentication when next/link do prefetching versus when user actual clicking differs (IE: unauthenticated then user login in another tab), nextjs always use prefetched data which is redirect to /login page.
That combines with ?callbackUrl= params would leads to infinite redirections.
How to reproduce
- Create custom
/loginwith callbackUrl params
export const getServerSideProps: GetServerSideProps = async (context) => {
const session = await getServerSession(context.req, context.res, authConfig)
if (session) {
// redirect if authenticated
return {
redirect: {
destination: context.query.calbackUrl ?? '/',
permanent: false
}
}
}
// other stuffs ...
}
- Apply withAuth
export { default } from "next-auth/middleware"
- Add an next/link to protected route
<Link href={'/protected'}>Protected</Link>
- Open the page with the link, next/link prefetch will received a redirect due to user not authenticated
/protected -> /login?callbackUrl=/protected
- User do authentication in another tab then go back and click the link in the first one
Cached response is used, leading to infinite redirects
/protected -> /login?callbackUrl=/protected -(as user already authenticated)->
/protected -> /login?callbackUrl=/protected -> ...
Expected behavior
User should be redirected to /protected as usual.
Workarounds
Mentioned in the warning, dev can work around by render url based on user's authentication status
function ProtectedLink() {
const {data: session} = useSession()
return <Link href={session ? '/protected' : '/login?callbackUrl=/protected'} prefetch={!!session}}
}
But that would take aways most of the reasons to use middleware.
Suggestion
When withAuth failed to check user authentication (unauthenticated, error), don't cache the response.
headers.set('x-middleware-cache', 'no-cache')
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the withAuth middleware and next/link prefetch flow described in the reproduction; no repository file or test is named, so begin by reproducing the cross-tab authentication sequence. Done means the authenticated user can click the protected link and reach /protected without the cached redirect causing an infinite loop.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nextjs, react, typescript
- Domain
- authentication, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100