mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 22:27:26 +01:00
add InvalidCredentialsError with language-agnostic code (#15472)
* add InvalidCredentialsError with language-agnostic code and update backend & web logout logic * error.code in API error responses Updated the error handler to serialize responseErr.code as the JSON error field, falling back to responseErr.name when no code is set. * fix(lint): whitespace and missing def * fix(lint): missed one * add InvalidCredentialsError case for bad token Add test verifying that auth middleware throws InvalidCredentialsError with code "invalid_credentials" and correct translated message when the API token is invalid. * fix(test): user fields implicitly required --------- Co-authored-by: Kalista Payne <sabrecat@gmail.com>
This commit is contained in:
@@ -60,5 +60,20 @@ describe('auth middleware', () => {
|
||||
return done();
|
||||
});
|
||||
});
|
||||
|
||||
it('errors with InvalidCredentialsError and code when token is wrong', done => {
|
||||
const authWithHeaders = authWithHeadersFactory({ userFieldsToExclude: [] });
|
||||
|
||||
req.headers['x-api-user'] = user._id;
|
||||
req.headers['x-api-key'] = 'totally-wrong-token';
|
||||
|
||||
authWithHeaders(req, res, err => {
|
||||
expect(err).to.exist;
|
||||
expect(err.name).to.equal('InvalidCredentialsError');
|
||||
expect(err.code).to.equal('invalid_credentials');
|
||||
expect(err.message).to.equal(res.t('invalidCredentials'));
|
||||
return done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -223,11 +223,10 @@ export default {
|
||||
|
||||
const errorData = error.response.data;
|
||||
const errorMessage = errorData.message || errorData;
|
||||
const errorCode = errorData.error;
|
||||
|
||||
// Check for conditions to reset the user auth
|
||||
// TODO use a specific error like NotificationNotFound instead of checking for the string
|
||||
const invalidUserMessage = [this.$t('invalidCredentials'), 'Missing authentication headers.'];
|
||||
if (invalidUserMessage.indexOf(errorMessage) !== -1) {
|
||||
// If 'invalid_credentials' signaled, force logout
|
||||
if (error.response.status === 401 && errorCode === 'invalid_credentials') {
|
||||
this.$store.dispatch('auth:logout', { redirectToLogin: true });
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -117,3 +117,27 @@ export class InternalServerError extends CustomError {
|
||||
this.message = customMessage || 'An unexpected error occurred.';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @apiDefine InvalidCredentials
|
||||
* @apiError InvalidCredentials The user’s credentials are no longer valid.
|
||||
*
|
||||
* @apiNote
|
||||
* The 'invalid_credentials' error code is language-agnostic:
|
||||
* clients should use this code (regardless of locale or translated message)
|
||||
* to unambiguously trigger a user logout.
|
||||
*
|
||||
* @apiErrorExample Error-Response:
|
||||
* HTTP/1.1 401 Unauthorized
|
||||
* {
|
||||
* "error": "invalid_credentials",
|
||||
* "message": "There is no account that uses those credentials."
|
||||
* }
|
||||
*/
|
||||
export class InvalidCredentialsError extends NotAuthorized {
|
||||
constructor (message) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
this.code = 'invalid_credentials';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import moment from 'moment';
|
||||
import nconf from 'nconf';
|
||||
import url from 'url';
|
||||
import {
|
||||
InvalidCredentialsError,
|
||||
NotAuthorized,
|
||||
} from '../libs/errors';
|
||||
import {
|
||||
@@ -81,7 +82,7 @@ export function authWithHeaders (options = {}) {
|
||||
.exec()
|
||||
.then(user => {
|
||||
if (!user || apiToken !== user.apiToken) {
|
||||
throw new NotAuthorized(res.t('invalidCredentials'));
|
||||
throw new InvalidCredentialsError(res.t('invalidCredentials'));
|
||||
}
|
||||
|
||||
if (user.auth.blocked) {
|
||||
|
||||
@@ -82,7 +82,7 @@ export default function errorHandler (err, req, res, next) { // eslint-disable-l
|
||||
|
||||
const jsonRes = {
|
||||
success: false,
|
||||
error: responseErr.name,
|
||||
error: responseErr.code || responseErr.name,
|
||||
message: responseErr.message,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user