remix-auth
remix-auth copied to clipboard
Pass custom error data
This is more of an idea than a finalized PR - I'm not sure if this approach is the best one, and supporting it fully would require changes to the other community Strategies.
I have been trying to get custom data passed through when throwing an error inside an authentication call (same as this discussion).
Usually in these situations, I create a custom error class where I can add data to an error message:
export class FancyError extends Error {
constructor(message, data) {
super(message);
this.data = data;
}
}
throw new FancyError('Uh oh', {moreData:'yes'})
try{
throw
} catch(error) {
console.log(error.message) // Uh oh
console.log(error.data) // {moreData:'yes'}
}
The problem is that remix-auth
and at least remix-auth-form
pass errors around by calling new AuthorizationError(error.message)
instead of passing through the original error object. This strips away any custom functionality.
This PR adds a simple errors[]
list to the AuthorizationError
class, and allows passing an errors list into authenticate.failure
.
To actually make use of this, you'd have to throw new AuthorizationError(message,errors)
inside your authentication call, and update your strategy to pass error.errors
as the final parameter of failure
.
Here's remix-auth-form
with that enabled:
export class FormStrategy extends Strategy {
name = 'form';
async authenticate(request, sessionStorage, options) {
let form = await request.formData();
let user;
try {
user = await this.verify({ form, context: options.context });
} catch (error) {
let message = error.message;
return await this.failure(
message,
request,
sessionStorage,
options,
error.errors,
);
}
return this.success(user, request, sessionStorage, options);
}
}
And how I'd use it in the app:
authenticator.use(
new FormStrategy(async ({ form }) => {
const api = new Api();
let email = form.get('email');
let password = form.get('password');
try {
return await api.login(email, password);
} catch (error) {
// this assumes my api is sending in error.data.errors - you could set any list of strings as the second argument
throw new AuthorizationError(error.message, error.data?.errors);
}
}),
'user-pass'
);
Forgot to mention, but the errors
object is completely optional in failure
and AuthorizationError
- so there'd be no breaking changes.
If this was accepted, I'd be happy to file PRs with the strategies listed in the discussion 👍🏼
This was added in v3.4.0