next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Infinite redirect with middleware and basePath

Open nicks6853 opened this issue 2 years ago • 7 comments

Question 💬

I have a NextJS app setup to run under the /admin basepath. Whenever I use the middleware, I am having problems with it sending me to the wrong url for the login page. If I try passing a custom sign in page to the options, it redirects me infinitely. Can anyone point me in the right direction? Is this even possible?

How to reproduce ☕️

I am running [email protected], [email protected]

_app.js

import { SessionProvider } from 'next-auth/react';
import '../styles/globals.css';

function App({ Component, pageProps: { session, ...pageProps } }) {
  return (
    <SessionProvider
      session={session}
      basePath="/admin/api/auth"
    >
      <Component {...pageProps} session={session} />
    </SessionProvider>
  );
}

export default App;

_middleware.js

Note that without the custom signin page, the app redirects me to /api/auth/signin which does not exists (I can see the page if I manually go to /admin/api/auth/signin) and with the custom signin page I get an infinite redirect error.

import withAuth from 'next-auth/middleware';

export default withAuth({
  pages: {
    signIn: '/admin/signin',
  },
});

next.config.js

/** @type {import('next').NextConfig} */

const nextConfig = {
  reactStrictMode: true,
  env: {
    COGNITO_CLIENT_ID: '<removed>',
    COGNITO_CLIENT_SECRET: '<removed>',
    COGNITO_ISSUER: '<removed>',
    COGNITO_DOMAIN: '<removed>',
    NEXTAUTH_URL: 'http://localhost:3000/admin/api/auth',
    NEXTAUTH_SECRET: '<removed>',
  },
  basePath: '/admin',
};

module.exports = nextConfig;

pages/signin.js

import { Button } from '@mantine/core';
import { signIn } from 'next-auth/react';

export default function SignIn({ providers }) {
  return (
    <Button onClick={() => signIn('cognito')}>
      Sign in with Cognito
    </Button>
  );
}

pages/api/auth

import NextAuth from 'next-auth/next';
import CognitoProvider from 'next-auth/providers/cognito';

export default NextAuth({
  providers: [
    CognitoProvider({
      clientId: process.env.COGNITO_CLIENT_ID,
      clientSecret: process.env.COGNITO_CLIENT_SECRET,
      issuer: process.env.COGNITO_ISSUER,
      domain: process.env.COGNITO_DOMAIN,
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  debug: true,
});

Contributing 🙌🏽

No, I am afraid I cannot help regarding this

nicks6853 avatar Mar 22 '22 16:03 nicks6853

@nicks6853 thanks for reaching out. So this should theoretically be possible. I was successfully able to recreate and reproduce your infinite refresh / forwarding problem.

I think I've boiled it down to packages/next-auth/src/next/middleware.ts:L65-L68 - this check isn't being hit and so its not early returning. Therefore its continuing on until a few lines further down it appends another copy of the callbackUrl query param and redirect's to the signInUrl over and over again..

Unfortunately I haven't been abel to get any further tonight. I'll take another look at this tomorrow :+1:

ndom91 avatar Mar 22 '22 23:03 ndom91

Hi @ndom91, were you able to find anything for this? Let me know if there is anything else I could provide to help solve this issue.

nicks6853 avatar Mar 28 '22 12:03 nicks6853

@nicks6853 sorry I haven't had the bandwidth to take another look at this yet. Its on my todo list though!

ndom91 avatar Mar 29 '22 08:03 ndom91

No worries, I was just curious. I'll be on the lookout!

nicks6853 avatar Mar 29 '22 20:03 nicks6853

I tested the no parameter option export { default } from "next-auth/middleware" and found that this would cause infinite redirection If you pass parameters to withAuth, the execution would pass without an infinite redirect even though both non parameter and parameters call the handleMiddleware function. That may be something to look at.

import type { NextRequest } from "next/server"
import type { JWT } from "next-auth/jwt"

import { withAuth } from "next-auth/middleware"

export default withAuth(
  function middleware(req: NextRequest & { nextauth: { token: JWT } }) {
    console.log(req.nextauth.token)
  },
  {
    callbacks: {
      authorized: ({ token }) => token?.role === "admin",
    },
  }
)

this would work correctly

KingPinged avatar Apr 14 '22 02:04 KingPinged

@nicks6853 I just realized (thanks to @ThangHuuVu in #4366) that you also have to pass the callbackUrl as a param to the signin() function in the custom login page.

i.e.

pages/signin.js

import { Button } from '@mantine/core';
import { signIn } from 'next-auth/react';
import { useRouter } from 'next';

export default function SignIn({ providers }) {
  const { callbackUrl }  = useRouter().query
  return (
    <div className='max-w-2xl mx-auto'>
      <div className='flex items-center justify-center px-8 py-8 mt-4 rounded bg-content bg-base-200'>
        {Object.values(providers).map((provider) => (
          <div key={provider.name}>
            <button className='btn' onClick={() => signIn(provider.id, { callbackUrl })}>
              Sign in with {provider.name}
            </button>
          </div>
        ))}
      </div>
    </div>
  );
}

I wasn't able to test it, but I see we weren't doing that in your login example so maybe this will help :+1:

ndom91 avatar Apr 19 '22 16:04 ndom91

Hey, any updates on this?

TheBorsuk avatar Jun 03 '22 11:06 TheBorsuk

I have the same issue by just using export { default } from "next-auth/middleware" in my middleware.

Angeschossen avatar Oct 06 '22 06:10 Angeschossen

any update on this?

jporcelli1120 avatar Dec 16 '22 01:12 jporcelli1120

Still having issues with default export { default } from "next-auth/middleware"

I ends up having to use server side props in nextjs to simply check for existence of session

pencilcheck avatar Jan 07 '23 12:01 pencilcheck

Currently, on [email protected] and [email protected], I am having this issue as well using only export { default } from "next-auth/middleware", it makes my app break, and it gets into a cycle of “localhost redirected you too many times” error.

Using the matcher config for example export const config = { matcher: ["/dashboard"] }, makes it semi work, I can go to / with no issue since it wasn't defined but going to the /dashboard directory with a successful login brings me back to the sign-in page, upon inspecting the console I can see a lot of re-renders, it seems it redirects it infinitely even when on the sign-in page.

AbrahamX3 avatar Jan 09 '23 12:01 AbrahamX3

I am facing the same issue, after defining the middleware with a protected route, I am no longer able to access it even though the signIn is successful. The app goes in a signIn loop again and again.

ashiishme avatar Jan 09 '23 23:01 ashiishme

When can we expect this to work? I've stumbled on the same issue.

patrykczubek avatar Jan 10 '23 04:01 patrykczubek

Same as @AbrahamX3. Any workarounds so far?

nikbogman avatar Jan 10 '23 20:01 nikbogman

@one-moonman I have not found any workarounds to make it work, unfortunately. I gave up and protected routes the usual way without middleware.

AbrahamX3 avatar Jan 10 '23 21:01 AbrahamX3

I have the same issue, i'm using latest next and next-auth modules and then just write export { default } from "next-auth/middleware" in my middleware file :(

mononoke-choi avatar Jan 24 '23 08:01 mononoke-choi

Maybe try using an adapter like prisma or mongodb. I suppose that this might have fixed something for me.

nikbogman avatar Jan 24 '23 12:01 nikbogman

I have the same issue, i'm using latest next and next-auth modules and then just write export { default } from "next-auth/middleware" in my middleware file :(

Same issue on my end. I am using DynamoDB adapter with Email provider. My other instance of this exact same middleware running google Auth has no problems.

Tigatok avatar Jan 26 '23 00:01 Tigatok

I have the same issue, i'm using latest next and next-auth modules and then just write export { default } from "next-auth/middleware" in my middleware file :(

I faced the same issue. Overriding the session strategy to "jwt" in the authOptions solved the issue.

rusiaaman avatar Feb 05 '23 16:02 rusiaaman

I have the same issue, i'm using latest next and next-auth modules and then just write export { default } from "next-auth/middleware" in my middleware file :(

I faced the same issue. Overriding the session strategy to "jwt" in the authOptions solved the issue.

This solved my issue (I think I glanced over with the explicit mention that JWT needs to be enabled for this to work (I understood its just withAuth.

I have created a PR on the docs to be more explicit that this should be added.

nickparkin avatar Feb 06 '23 10:02 nickparkin

oh, i missed caveats section ....! yeah, i'm using database strategy with mongodb adapter. no wonder i tried to use edge function with mongodb driver but it couldn't work at all. i didn't know what exactly happened, but I just though it is immature to use both of them together yet. anyway, thanks for sharing your experience

mononoke-choi avatar Feb 06 '23 11:02 mononoke-choi

I'm explicitly using "JWT" as the session strategy but facing the same infinite redirection issue. Is there any known workaround for this issue? I'm on the brink of abandoning the middleware to try another approach.

I'm using an auth0 provider, My current versions are:

"next": "13.1.6",
"next-auth": "^4.19.2",

jonasrdm avatar Feb 22 '23 19:02 jonasrdm

also facing same issue when using middleware, basepath and custom signin page as described in the inital question and explicitly using "JWT" as the session strategy. passing callback url to signIn as @ndom91 recommends did not help either.

how to workaround that? to me this looks like a bug.

i guess none of the maintainers will have a deeper look as long as this issue is of type question. can someone confirm its a bug and change the issue type?

really hope it will get fixed soon

christian-draeger avatar Mar 02 '23 13:03 christian-draeger

for anyone stumbling on this, i've created a custom adapter for google firestore following this implementation. After configuration i was at the point, where a user session would be created after sign-in, but the callback url would keep me on the sign-in route (because the session could not be retrieved). After i changed the session-strategy (as described here) to jwt everything was working fine, apart from custom properties in my session (coming from the firestore user object). Adding a custom api/token endpoint like so finally made the stone drop.

Hope that helps!

Eagl9Eye avatar Mar 18 '23 16:03 Eagl9Eye

We cannot recreate the issue with the provided information. Please add a reproduction in order for us to be able to investigate.

Why was this issue marked with the incomplete label?

To be able to investigate, we need access to a reproduction to identify what triggered the issue. We prefer a link to a public GitHub repository (template), but you can also use a tool like CodeSandbox or StackBlitz.

To make sure the issue is resolved as quickly as possible, please make sure that the reproduction is as minimal as possible. This means that you should remove unnecessary code, files, and dependencies that do not contribute to the issue.

Please test your reproduction against the latest version of NextAuth.js (next-auth@latest) to make sure your issue has not already been fixed.

I added a link, why was it still marked?

Ensure the link is pointing to a codebase that is accessible (e.g. not a private repository). "example.com", "n/a", "will add later", etc. are not acceptable links -- we need to see a public codebase. See the above section for accepted links.

What happens if I don't provide a sufficient minimal reproduction?

Issues with the incomplete label that receives no meaningful activity (e.g. new comments with a reproduction link) are closed after 7 days.

If your issue has not been resolved in that time and it has been closed/locked, please open a new issue with the required reproduction. (It's less likely that we check back on already closed issues.)

I did not open this issue, but it is relevant to me, what can I do to help?

Anyone experiencing the same issue is welcome to provide a minimal reproduction following the above steps. Furthermore, you can upvote the issue using the :+1: reaction on the topmost comment (please do not comment "I have the same issue" without repro steps). Then, we can sort issues by votes to prioritize.

I think my reproduction is good enough, why aren't you looking into it quicker?

We look into every NextAuth.js issue and constantly monitor open issues for new comments.

However, sometimes we might miss one or two. We apologize, and kindly ask you to refrain from tagging core maintainers, as that will usually not result in increased priority.

Upvoting issues to show your interest will help us prioritize and address them as quickly as possible. That said, every issue is important to us, and if an issue gets closed by accident, we encourage you to open a new one linking to the old issue and we will look into it.

Useful Resources

github-actions[bot] avatar Mar 25 '23 09:03 github-actions[bot]

Closing as this issue is kinda old. Let's open a new one with a fresh, minimal reproduction, if it still exists.

balazsorban44 avatar Mar 25 '23 20:03 balazsorban44