Your question
I wonder is there any ability to specify custom error message rather than ?error=CredentialsSignin while making request to external service in authorize method or in events / callbacks.
This issue is slightly connected to #330 but I'm okay with redirect and my question is more about custom errors.
What are you trying to do
My app has an external service for authorization using user credentials. I am using same code as in documenation credentials#example
authorize: async (credentials) => {
// Add logic here to look up the user from the credentials supplied
const result = async sendRequest(credentials);
// my code returns user or custom error object
if (result && !result.error) {
// Any object returned will be saved in `user` property of the JWT
return Promise.resolve(user)
} else {
// If you return null or false then the credentials will be rejected
return Promise.resolve(null)
}
}
I expect some kind of this code to return a custom error code, but it doesn't
return Promise.reject(result.error.code);
I am using custom page config to show errors on the same page after redirect (#330):
pages: {
signin: '/auth/signin',
signout: '/auth/signout',
error: '/auth/signin', // Error code passed in query string as ?error=
verifyRequest: '/auth/verify-request', // (used for check email message)
newUser: null // If set, new users will be directed here on first sign in
},
Why I find this important
Any external backend service might return any type of errors, from 400 to 500 and I want to show different errors on this page according to type of response, but now with return Promise.resolve(null) i can get only this code ?error=CredentialsSignin so when page reloads I do not know what exact error was before.
For example, 'Server is not available', 'Your credentials is not correct', 'Your account is suspended, contact your manager' is three different errors that must process three different UX for users, you can't label them with the same message.
I could not find any resolution for this in documentation so I am asking for your help. There is no callback for error and neither
return Promise.resolve(null) neither return Promise.reject('message') does fire 'error' event in my case.
@yournatalita Thank you for writing this up! It is an issue that has come up in tickets before but wasn't written up anywhere.
I completely agree with this approach and this is exactly how it should work - and I don't seen why this can't be done in a way that is fully backwards compatible with the current approach, so it doesn't need to be a breaking change.
I'lll see what I can do!
Considerations: We might want to consider supporting similar behaviour in the signIn() callback.
Any chance this issue will go to production in v3 or earlier?
@yournatalita Thanks for asking! I think it will be part of v3 yes!
Supporting calling Promise.Reject() with either a string (which should be a URL to redirect to) or an Error object (which will trigger a redirect to /{path}error?error=${error}) is how I'm thinking of supporting this.
i.e. That is either can be used - both Promise.Reject('/signin?error=auth_failed) or Promise.Reject(new Error('auth_failed')) would be valid syntax.
Note: I think the existing behaviour of returning Promise.resolve(false) would also still work, for backwards compatibility.
@yournatalita Happy to say this is resolved with the new callbacks in version 3.0!
The old behaviour (returning Promise.resolve() with false or null) still works, but you can now reject promises with Error messages Promise.reject(new Error('an error message') or a URL Promise.reject('/url/to/redirect/to').
This also applies to the authorize() callback on the Credentials Provider.
The default error handling on the built in pages is now improved too.
Most helpful comment
@yournatalita Happy to say this is resolved with the new callbacks in version 3.0!
The old behaviour (returning
Promise.resolve()with false or null) still works, but you can now reject promises with Error messagesPromise.reject(new Error('an error message')or a URLPromise.reject('/url/to/redirect/to').This also applies to the
authorize()callback on the Credentials Provider.The default error handling on the built in pages is now improved too.