next-auth
                                
                                
                                
                                    next-auth copied to clipboard
                            
                            
                            
                        feat: customizable `authorize()` error
This introduces a way to throw custom errors in the authorize() callback of the Credentials provider.
Any generic or sensitive server error will continue to return error=Configuration (full error is logged on the server), but for custom ones thrown from authorize() that extend CredentialsSignin, we will let the error propagate. Example:
import { CredentialsSignin } from "@auth/core/errors" // import is specific to your framework
class CustomError extends CredentialsSignin {
  code = "custom"
}
// ...
authorize() {
  // ...
  throw new CustomError()
}
Then, based on your framework, one of the following will happen:
client-side (fetch to the sign-in endpoint):
- get redirected to the signin page as such 
/signin?error=CredentialsSignin&code=custom - if 
redirect: falsewas set onsignIn, it returns the error and code properties. 
server-side handled form actions:
CustomErroris thrown that you would need to handle in a catch block.
Notes:
- The name 
CredentialsSigninwas chosen to be backwards compatible with NextAuth.js v4 https://github.com/nextauthjs/next-auth/blob/2072750c017c3d2a7f7374dd683055b79d331319/packages/next-auth/src/core/routes/callback.ts#L336 - I also renamed 
AuthorizedCallbackErrorto AccessDenied for the same reason https://github.com/nextauthjs/next-auth/blob/2072750c017c3d2a7f7374dd683055b79d331319/packages/next-auth/src/core/routes/callback.ts#L99 - Support for framework integrations like 
next-authwill be added in a separate PR 
Related: #9099 (see https://github.com/nextauthjs/next-auth/issues/9099#issuecomment-1913754338). This PR won't close that issue yet, a next-auth PR will be opened after this gets merged
The latest updates on your projects. Learn more about Vercel for Git ↗︎
| Name | Status | Preview | Comments | Updated (UTC) | 
|---|---|---|---|---|
| auth-docs | ✅ Ready (Inspect) | Visit Preview | 💬 Add feedback | Mar 2, 2024 4:21am | 
2 Ignored Deployments
| Name | Status | Preview | Comments | Updated (UTC) | 
|---|---|---|---|---|
| next-auth-docs | ⬜️ Ignored (Inspect) | Visit Preview | Mar 2, 2024 4:21am | |
| nextra-docs | ⬜️ Ignored (Inspect) | Visit Preview | Mar 2, 2024 4:21am | 
Codecov Report
Attention: Patch coverage is 86.99187% with 16 lines in your changes are missing coverage. Please review.
Project coverage is 41.68%. Comparing base (
34b8995) to head (b361d08). Report is 53 commits behind head on main.
:exclamation: Current head b361d08 differs from pull request most recent head 1fa5116. Consider uploading reports for the commit 1fa5116 to get more accurate results
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9871      +/-   ##
==========================================
- Coverage   42.56%   41.68%   -0.88%     
==========================================
  Files         173      158      -15     
  Lines       27752    25406    -2346     
  Branches     1194     1040     -154     
==========================================
- Hits        11813    10591    -1222     
+ Misses      15939    14815    -1124     
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.
Any updates/plans on when this will be merged?
@ndom91 we will enable it again in my pr #100017 as I remember Balazs got some issues with the tests when he added the restart mock function
Hi! Any updates/ETA on this? I am testing our migration to beta v5 and want to display custom error messages on signin flow from backend directly on the page without redirection.
How do I use this in next.js? I don't install the @auth/core package and couldn't find it in any section of the CredentialsSignin library
@MrOxMasTer do you mean how do you use this new feature? Or next-auth in general?
For next-auth in general, first of all, you do not need to install @auth/core any more. That's why you won't find it anywhere.
A straightforward setup description can be found here: https://authjs.dev/guides/upgrade-to-v5#configuration
You can also check out our Next.js example app here: https://github.com/nextauthjs/next-auth-example
@MrOxMasTer do you mean how do you use this new feature? Or
next-authin general?
How do I use this feature in next.js, which I am currently on pull request. I couldn't find this class anywhere. How do I use this new feature? Where do I import CredentialsSignin from. The latest version where this feature was added is installed
@MrOxMasTer you'd be surprised where people ask what :joy:
Anyway, sorry about that! So yeah the CredentialsSignin error class seems to only be exported from @auth/core/errors at the moment, which is not ideal as you're not supposed to install that package explicitly (it won't hurt if you do, but we're trying to avoid that additional complexity).
I've opened a PR reexporting it in the framework packages here: https://github.com/nextauthjs/next-auth/pull/10200
It also updates the docs example updated in this PR to show throwing the new custom error
I've opened a PR reexporting it in the framework packages here: #10200
It also updates the docs example updated in this PR to show throwing the new custom error
Thank you, I pray for you 🛐🛐🛐
@MrOxMasTer the changes have been merged to main. You can now import CredentialsSignin from next-auth, for example.
Hi, I tried the CustomError solution suggested by @balazsorban44
export class CustomError extends CredentialsSignin {
  code = "custom";
}
However, my custom error message will always be appended with an additional string of " .Read more at https://errors.authjs.dev#credentialssignin", which I don't want to be sent to client.
Below is the screenshot of what my CustomError instance looks like in debugger (my custom error message is just "Login failed"):
Upon inspecting the source code, it seems the string is appended in the constructor of AuthError class, as shown in below link:
https://github.com/nextauthjs/next-auth/blob/239dfcf71fb3267272e2d972f9551f6f8aea0105/packages/core/src/errors.ts#L75-L76
Currently I have to workaround it by adding a constructor to my CustomError class to overwrite the unwanted appended string:
export class CustomError extends CredentialsSignin {
  code = "custom";
  constructor(message?: any, errorOptions?: any) {
    super(message, errorOptions);
    this.message = message;
  }
}
Is there any elegant way to solve it? Thanks in advance.
I think you shouldn't depend on error.code not error.message
@balazsorban44 this has broken the redirection for me. Instead of /<my-signin-page>?error=CredentialsSignin this now redirects to /api/auth/<my-signin-page>?error=CredentialsSignin&code=<code> which returns "Bad Request"
My config:
{
    pages: {
        signIn: '/<my-signin-page>',
        error: '/<my-signin-page>', // Error code passed in query string as ?error=
    },
    ...
    basePath: "/api/auth",
}
on build 13 of the beta this works as expected. I don't see any relevant changes in the regexp matching so am curious why this stopped working.
@balazsorban44 this has broken the redirection for me. Instead of
/<my-signin-page>?error=CredentialsSigninthis now redirects to/api/auth/<my-signin-page>?error=CredentialsSignin&code=<code>which returns "Bad Request"My config:
{ pages: { signIn: '/<my-signin-page>', error: '/<my-signin-page>', // Error code passed in query string as ?error= }, ... basePath: "/api/auth", }on build 13 of the beta this works as expected. I don't see any relevant changes in the regexp matching so am curious why this stopped working.
Because of basePath: "/api/auth"
@balazsorban44 this has broken the redirection for me. Instead of
/<my-signin-page>?error=CredentialsSigninthis now redirects to/api/auth/<my-signin-page>?error=CredentialsSignin&code=<code>which returns "Bad Request" My config:{ pages: { signIn: '/<my-signin-page>', error: '/<my-signin-page>', // Error code passed in query string as ?error= }, ... basePath: "/api/auth", }on build 13 of the beta this works as expected. I don't see any relevant changes in the regexp matching so am curious why this stopped working.
Because of
basePath: "/api/auth"
Both with basePath not set and  basePath: "/" it's giving the same behaviour.
@ccyen8358 hmm interesting, so I can't htink of any other way to solve it currently. Other than adding an additional custom error class designed to be extended from for this use-case :thinking: I've put up a quick prototype PR of that here to hopefully get some discussion going there :pray:
@sjoukedv hmm interesting, do you have an AUTH_URL env var set as well? If so, what to? iirc there shouldn't be any changes related to that that shipped recently, as we're working on soemthing very similar (regarding basePath) here as we speak.
@ndom91
@sjoukedv hmm interesting, do you have an
AUTH_URLenv var set as well? If so, what to? iirc there shouldn't be any changes related to that that shipped recently, as we're working on soemthing very similar (regardingbasePath) here as we speak.
// path next.config.js
/** @type {import("next").NextConfig} */
module.exports = {
    env: {
        AUTH_URL: `${process.env.VERCEL_URL || 'http://localhost:3000'}/api/auth`,
        NEXTAUTH_URL: `${process.env.VERCEL_URL || 'http://localhost:3000'}/api/auth`,
        AUTH_SECRET: `${process.env.AUTH_SECRET || 'somestring'}`,
    },
    // ...
// path auth.ts
export const config = {
    // ...
    basePath: "/api/auth",
    trustHost: true
} satisfies NextAuthConfig
export const { handlers, auth, signIn, signOut } = NextAuth(config)
With e.g. VERCEL_URL=http://127.0.0.1:3000
@sjoukedv hmm okay so we auto detect the basePath based on VERCEL_URL (among other things), so if that's available even in dev too, like you've set it yourself there, then you don't need a lot of this actually.
Can you try removing auth_url and nextauth_url env vars and basePath config?
@sjoukedv hmm okay so we auto detect the basePath based on VERCEL_URL (among other things), so if that's available even in dev too, like you've set it yourself there, then you don't need a lot of this actually.
Can you try removing auth_url and nextauth_url env vars and basePath config?
@ndom91 That redirects me to api/auth/<custom-page>?error=CredentialsSignin&code=<my-custom-error>.
Looks like the page becomes relative to /api/auth instead of the root
    pages: {
        signIn: '/<custom-page>',
        error: '/<custom-page>', // Error code passed in query string as ?error=
    },
If I remove the leading slash frompages.error I get redirected to api/auth<custom-page>?error=CredentialsSignin&code=<my-custom-error> no / after auth. Is the URL properly parsed to be an absolute path instead of relative to /api/auth?
I have also verified the authorized callback is not the issue by always returning true.
@sjoukedv hmm okay so we auto detect the basePath based on VERCEL_URL (among other things), so if that's available even in dev too, like you've set it yourself there, then you don't need a lot of this actually. Can you try removing auth_url and nextauth_url env vars and basePath config?
@ndom91 That redirects me to
api/auth/<custom-page>?error=CredentialsSignin&code=<my-custom-error>.Looks like the page becomes relative to
/api/authinstead of the rootpages: { signIn: '/<custom-page>', error: '/<custom-page>', // Error code passed in query string as ?error= },If I remove the leading slash from
pages.errorI get redirected toapi/auth<custom-page>?error=CredentialsSignin&code=<my-custom-error>no/afterauth. Is the URL properly parsed to be an absolute path instead of relative to/api/auth?I have also verified the
authorizedcallback is not the issue by always returning true.
I think I'm running into a similar issue here.
This is what I currently have for my pages setting
pages: {
  signIn: `/auth`,
  error: `/auth/error`,
},
Both signIn and error are custom pages.
When user gets redirected to error the resulting redirect redirects to /api/auth/auth/error instead of /auth/error. This started to happened after I upgraded from [email protected] to [email protected]
I believe it would be a good idea to make pages route options an absolute url.
I've tried adding a custom error but we're using the signIn function from packages/next-auth/src/react.tsx Source and here the code isn't available in the response.
Is it possible to have it added to the response?
I believe it should just be adding the following:
  const error = new URL(data.url).searchParams.get("error")
+ const code = new URL(data.url).searchParams.get("code")
  if (res.ok) {
    await __NEXTAUTH._getSession({ event: "storage" })
  }
  return {
    error,
+   code,
    status: res.status,
    ok: res.ok,
    url: error ? null : data.url,
  } as any
                                    
                                    
                                    
                                
@CyanFlare @sjoukedv I think both of these are due to an issue we had with AUTH_URL/basePath. This shuold be fixed in main I believe, unfortunately we haven't cut a release yet though. If you're up for testing it in main we'd love some more feedback!
next-auth@beta-16 / next.js 14.1.4. A strange error occurs when imorting a classnext-auth@beta-16 / next.js 14.1.4. A strange error occurs when imorting a class
https://github.com/nextauthjs/next-auth/assets/59291123/41a1d677-9122-49f4-bf10-514ed44666c8
@MrOxMasTer Hmm so it's working "as expected" with AuthError, but when yuo extend it from CredentialsSignin you get this odd next/fonts error, did I understand that correctly?
@MrOxMasTer Hmm so it's working "as expected" with
AuthError, but when yuo extend it fromCredentialsSigninyou get this odd next/fonts error, did I understand that correctly?
yes
With beta16 this is working for me now (with Next.js 14.2.0-canary.48)
import { CredentialsSignin } from "@auth/core/errors" 
class InvalidLoginError extends CredentialsSignin {
    code = 'Invalid identifier or password'
}
export const config = {
    providers: [
        CredentialsProvider({
            ....
            async authorize(credentials) {
               throw new InvalidLoginError()
            }
        })
    ]
                                    
                                    
                                    
                                
With
beta16this is working for me now (with Next.js 14.2.0-canary.48)
Look where I'm importing the class from. It was moved to the main library to avoid downloading "@auth/core", but it doesn't work. But I can say that you have made a good point, that at least some implementation of the class works
@MrOxMasTer Was just trying something with this again in beta.16 and wanted to report that the above did work for me with import { CredentialsSignin } from 'next-auth', but with AuthError it cuased the FE to redirect to a configuration error, while the BE still did log my custom error message / code.
I can't view your video anymore, but it cause anything else weird to happen with [email protected]
I've tried adding a custom error but we're using the
signInfunction frompackages/next-auth/src/react.tsxSource and here thecodeisn't available in the response.Is it possible to have it added to the response?
I believe it should just be adding the following:
const error = new URL(data.url).searchParams.get("error") + const code = new URL(data.url).searchParams.get("code") if (res.ok) { await __NEXTAUTH._getSession({ event: "storage" }) } return { error, + code, status: res.status, ok: res.ok, url: error ? null : data.url, } as any
We implemented the login page based on the intercepting logic so we can not enable the redirection. As redirection will move out of the intercepted modal. I want to stick in the same modal. Is it possible to attach the code when redirection is disabled
i also need the above change