Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v5] Throwing error with custom sign in page leads to undefined route #11008

Closed
peguerosdc opened this issue May 25, 2024 · 5 comments · Fixed by #11010
Closed

[v5] Throwing error with custom sign in page leads to undefined route #11008

peguerosdc opened this issue May 25, 2024 · 5 comments · Fixed by #11010
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@peguerosdc
Copy link

Environment

  System:
    OS: macOS 14.4.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 102.29 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.1.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.7.0 - /usr/local/bin/npm
  Browsers:
    Chrome: 125.0.6422.77
    Safari: 17.4.1
  npmPackages:
    @auth/prisma-adapter: ^2.1.0 => 2.1.0
    next: 14.2.3 => 14.2.3
    next-auth: ^5.0.0-beta.18 => 5.0.0-beta.18
    react: ^18 => 18.3.1

Reproduction URL

https://github.com/peguerosdc/nextauth-bug-error-undefined

Describe the issue

When logging in via Magic Links using Resend, a custom sendVerificationRequest (following this official guide) and NOT using a custom sign in page, if I throw an error inside sendVerificationRequest like this:

export const { handlers, signIn, signOut, auth } = NextAuth({
  debug: true,
  adapter: PrismaAdapter(prisma),
  providers: [
    Resend({
      from: "dummy@domain.com",
      sendVerificationRequest: async (params) => {
        throw new Error("Error");
      }
    })
  ],
})

I am redirected to a default Error page with a configuration error in the search params: /api/auth/error?error=Configuration.

But when I use a custom login page like this:

export const { handlers, signIn, signOut, auth } = NextAuth({
  /* same settings as above */,
  pages: {
    signIn: "/auth/signin",
  },
})

And I throw the error, I am redirected to /auth/undefined/.

Moreover, when other kind of errors are thrown, I am redirected to my /auth/signin?error=ErrorType page WITH the error search param indicating what happened.

How to reproduce

  1. Clone and install the repository in the reproduction URL
  2. Start the server
  3. Click on the "Sign in" button
  4. Enter an email and click on "Sign in"
  5. See how you are redirected to /auth/undefined/.
  6. Optionally, you can go to /auth.ts, remove the custom pages configuration and repeat steps 3-5 to see how you are redirected to /api/auth/error?error=Configuration

Expected behavior

I would expect:

  1. Consistency in how we should handle errors, whether we are using custom pages or not
  2. To be able to gracefully handle errors when using a custom sign in page, instead of being redirected to /auth/undefined/ (being the /auth/signin?error=ErrorType approach my preferred one as I don't have to create a whole new page just to show an error and a button that would redirect me again to the sign in page)
@peguerosdc peguerosdc added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels May 25, 2024
@andresgutgon
Copy link
Contributor

andresgutgon commented May 25, 2024

Thanks for opening! 👏
I made a PR fixing this issue. Let's see if it goes in the right direction

andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 25, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 26, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 26, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 26, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 26, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
andresgutgon added a commit to andresgutgon/next-auth that referenced this issue May 26, 2024
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008
@roberte777
Copy link
Contributor

I am working on an application using a credentials provider. When I throw an error in the authorize method, I see similar behavior.

              onClick={() =>
                signIn("signin", {
                  username,
                  password,
                  redirect: false,
                }).then((res) => {
                  if (res?.ok) {
                    void router.push("/dashboard");
                  } else {
                    if (res?.error) {
                      setSignInError(
                        res.error || "There was an error signing in",
                      );
                      setPassword("");
                    }
                  }
                })
              }

This is the javascript code I am calling. However, when the promise returns after I throw an error for invalid credentials, this is the object I get:

{
    error: "Configuration"
    ok: true
    status: 200
    url: null
}

This is the error I am throwing:

      authorize: async (credentials) => {
        if (!credentials) {
          throw new Error("Invalid credentials");
        }
        const creds = await db.credentials.findFirst({
          where: {
            username: credentials.username as string,
          },
        });
        if (!creds) {
          throw new Error("Invalid credentials");
        }

I would expect the "ok" field to be false and the "error" field to be the error I threw.

@andresgutgon
Copy link
Contributor

As far as I understand what signIn method does is:

  1. Redirect to the ok or error page when redirect: true (default)
  2. Return the URL when redirect: false. Your case.

I think you should check in your case error prop to be present
https://next-auth.js.org/getting-started/client#using-the-redirect-false-option

@DanielDerma
Copy link

Same error when i deploy this project: https://github.com/vercel/nextjs-postgres-auth-starter
in localhost works very well, but deployed throw me the same error

ThangHuuVu added a commit that referenced this issue Jun 1, 2024
…rows an error (#11010)

* Fix NextAuth redirecting to /undefined when signIn method throws an
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
#11008

* Move action test to tests folder

* Remove test-adapter and add reference to docs

* Defend from undefined responseUrl

* Fix linter

* chore(test): simplify tests

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
@roberte777
Copy link
Contributor

roberte777 commented Jun 1, 2024

As far as I understand what signIn method does is:

  1. Redirect to the ok or error page when redirect: true (default)

  2. Return the URL when redirect: false. Your case.

I think you should check in your case error prop to be present

https://next-auth.js.org/getting-started/client#using-the-redirect-false-option

How do you figure it returns the URL only? As per the docs you linked, this is the return type:

{
  /**
   * Will be different error codes,
   * depending on the type of error.
   */
  error: string | undefined
  /**
   * HTTP status code,
   * hints the kind of error that happened.
   */
  status: number
  /**
   * `true` if the signin was successful
   */
  ok: boolean
  /**
   * `null` if there was an error,
   * otherwise the url the user
   * should have been redirected to.
   */
  url: string | null
}

This hasn't changed as far as I'm aware from previous version. The "ok" field on the return object should be false and the error should be the error message thrown in the authorize method on the credentials provider.

In my example, error was not the correct string and "ok" was true even though an error was thrown.

hillac pushed a commit to hillac/next-auth that referenced this issue Jun 19, 2024
…rows an error (nextauthjs#11010)

* Fix NextAuth redirecting to /undefined when signIn method throws an
error
@auth/core `Auth` function can return an internalResponse or a Standard
Response. Internal response has a `redirect` attribute. The problem is
that the logic inside `Auth` method when there is an error is returning
a Standard web Response which doesn't have `redirect` attribute but we
can get redirecting url by using `headers.get('Origin')`.

I think this fix this issue:
nextauthjs#11008

* Move action test to tests folder

* Remove test-adapter and add reference to docs

* Defend from undefined responseUrl

* Fix linter

* chore(test): simplify tests

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants