packages/fxa-content-server/app/scripts/lib/auth-errors.js (610 lines of code) (raw):
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// provides functions to work with errors returned by the auth server.
import _ from 'underscore';
import Errors from './errors';
import Logger from './logger';
var logger = new Logger();
const t = (msg) => msg;
var UNEXPECTED_ERROR_MESSAGE = t('Unexpected error');
var EXPIRED_VERIFICATION_ERROR_MESSAGE = t(
'The link you clicked to verify your email is expired.'
);
var THROTTLED_ERROR_MESSAGE = t(
"You've tried too many times. Try again later."
);
// L10N Note: '%(retryAfterLocalized)s' becomes:
// 'in 10 minutes' / 'in a minute' or
// 'через 15 минут' / 'через 3 минуты' / 'через минуту'
var THROTTLED_LOCALIZED_ERROR_MESSAGE = t(
"You've tried too many times. Try again %(retryAfterLocalized)s."
);
var ERRORS = {
UNEXPECTED_ERROR: {
errno: 999,
message: UNEXPECTED_ERROR_MESSAGE,
},
INVALID_TOKEN: {
errno: 110,
message: t('Invalid token'),
},
INVALID_TIMESTAMP: {
errno: 111,
message: t('Invalid timestamp in request signature'),
},
INVALID_NONCE: {
errno: 115,
message: t('Invalid nonce in request signature'),
},
ACCOUNT_ALREADY_EXISTS: {
errno: 101,
message: t('Account already exists'),
},
UNKNOWN_ACCOUNT: {
errno: 102,
message: t('Unknown account'),
},
INCORRECT_EMAIL_CASE: {
errno: 120,
message: t('Incorrect email case'),
},
INCORRECT_PASSWORD: {
errno: 103,
message: t('Incorrect password'),
},
UNVERIFIED_ACCOUNT: {
errno: 104,
message: t('Unverified account'),
},
INVALID_VERIFICATION_CODE: {
errno: 105,
message: t('Invalid verification code'),
},
INVALID_JSON: {
errno: 106,
message: t('Invalid JSON in request body'),
},
INVALID_PARAMETER: {
errno: 107,
message: t('Invalid parameter: %(param)s'),
},
MISSING_PARAMETER: {
errno: 108,
message: t('Missing parameter: %(param)s'),
},
INVALID_REQUEST_SIGNATURE: {
errno: 109,
message: t('Invalid request signature'),
},
MISSING_CONTENT_LENGTH_HEADER: {
errno: 112,
message: t('Missing content-length header'),
},
REQUEST_TOO_LARGE: {
errno: 113,
message: t('Request body too large'),
},
THROTTLED: {
errno: 114,
message: THROTTLED_ERROR_MESSAGE,
},
/*
ACCOUNT_LOCKED: {
errno: 121,
message: t('Your account has been locked for security reasons')
},
ACCOUNT_NOT_LOCKED: {
errno: 122,
message: UNEXPECTED_ERROR_MESSAGE
},
*/
REQUEST_BLOCKED: {
errno: 125,
message: t('The request was blocked for security reasons'),
},
ACCOUNT_RESET: {
errno: 126,
message: t('Your account has been locked for security reasons'),
},
INCORRECT_UNBLOCK_CODE: {
errno: 127,
message: t('Invalid authorization code'),
},
INVALID_PHONE_NUMBER: {
errno: 129,
message: t('Invalid phone number'),
},
INVALID_PHONE_REGION: {
errno: 130,
message: t('Cannot send to this country'),
},
SMS_ID_INVALID: {
errno: 131,
// should not be user facing, not wrapped in t
message: 'SMS ID invalid',
},
SMS_REJECTED: {
errno: 132,
message: t('Could not send a message to this number'),
},
EMAIL_SENT_COMPLAINT: {
errno: 133,
message: t('Your email was just returned'),
},
EMAIL_HARD_BOUNCE: {
errno: 134,
message: t('Your email was just returned. Mistyped email?'),
},
EMAIL_SOFT_BOUNCE: {
errno: 135,
message: t('Unable to deliver email'),
},
EMAIL_EXISTS: {
errno: 136,
message: t('This email was already verified by another user'),
},
UNVERIFIED_SESSION: {
errno: 138,
message: t('Unverified session'),
},
EMAIL_PRIMARY_EXISTS: {
errno: 139,
message: t('Secondary email must be different than your account email'),
},
EMAIL_VERIFIED_PRIMARY_EXISTS: {
errno: 140,
message: t('Account already exists'),
},
MAX_SECONDARY_EMAILS_REACHED: {
errno: 188,
message: t('You have reached the maximum allowed secondary emails'),
},
ACCOUNT_OWNS_EMAIL: {
errno: 189,
message: t('This email already exists on your account'),
},
UNVERIFIED_PRIMARY_EMAIL_NEWLY_CREATED: {
errno: 141,
message: t('Account already exists'),
},
LOGIN_WITH_SECONDARY_EMAIL: {
errno: 142,
message: t('Primary account email required for sign-in'),
},
VERIFIED_SECONDARY_EMAIL_EXISTS: {
errno: 144,
message: t('Address in use by another account'),
},
RESET_PASSWORD_WITH_SECONDARY_EMAIL: {
errno: 145,
message: t('Primary account email required for reset'),
},
INVALID_SIGNIN_CODE: {
errno: 146,
message: t('Invalid signin code'),
},
CHANGE_EMAIL_TO_UNVERIFIED_EMAIL: {
errno: 147,
message: t('Can not change primary email to an unverified email'),
},
CHANGE_EMAIL_TO_UNOWNED_EMAIL: {
errno: 148,
message: t(
'Can not change primary email to an email that does not belong to this account'
),
},
LOGIN_WITH_INVALID_EMAIL: {
errno: 149,
message: t('This email can not currently be used to login'),
},
RESEND_EMAIL_CODE_TO_UNOWNED_EMAIL: {
errno: 150,
message: t(
'Can not change primary email to an email that does not belong to this account'
),
},
FAILED_TO_SEND_EMAIL: {
errno: 151,
message: t('Failed to send email'),
},
INVALID_OTP_CODE: {
errno: 152,
message: t('Valid code required'),
},
EXPIRED_TOKEN_VERIFICATION_CODE: {
errno: 153,
message: t('This verification code has expired'),
},
TOTP_TOKEN_EXISTS: {
errno: 154,
message: t('A TOTP token already exists for this account'),
},
TOTP_TOKEN_NOT_FOUND: {
errno: 155,
message: t('TOTP token not found'),
},
RECOVERY_CODE_NOT_FOUND: {
errno: 156,
message: t('Backup authentication code not found'),
},
DEVICE_COMMAND_UNAVAILABLE: {
errno: 157,
message: t('Unavailable device command'),
},
RECOVERY_KEY_NOT_FOUND: {
errno: 158,
message: t('Account recovery key not found'),
},
INVALID_RECOVERY_KEY: {
errno: 159,
message: t('Invalid account recovery key'),
},
TOTP_REQUIRED: {
errno: 160,
message: t(
'This request requires two step authentication enabled on your account.'
),
},
REDIS_CONFLICT: {
errno: 165,
message: t('Failed due to a conflicting request, please try again.'),
},
INSUFFICIENT_ACR_VALUES: {
errno: 170,
message: t(
'This request requires two step authentication enabled on your account.'
),
},
UNKNOWN_SUBSCRIPTION_CUSTOMER: {
errno: 176,
message: t('Unknown customer for subscription.'),
},
UNKNOWN_SUBSCRIPTION: {
errno: 177,
message: t('Unknown subscription.'),
},
UNKNOWN_SUBSCRIPTION_PLAN: {
errno: 178,
message: t('Unknown plan for subscription.'),
},
REJECTED_SUBSCRIPTION_PAYMENT_TOKEN: {
errno: 179,
message: t('Invalid payment token for subscription.'),
},
SUBSCRIPTION_ALREADY_CANCELLED: {
errno: 180,
message: t('Subscription has already been cancelled'),
},
REJECTED_CUSTOMER_UPDATE: {
errno: 181,
message: t('Update was rejected, please try again'),
},
INVALID_EXPIRED_OTP_CODE: {
errno: 183,
message: t('Invalid or expired confirmation code'),
},
SERVER_BUSY: {
errno: 201,
message: t('Server busy, try again soon'),
},
FEATURE_NOT_ENABLED: {
errno: 202,
message: t('Feature not enabled'),
},
BACKEND_SERVICE_FAILURE: {
errno: 203,
message: t('System unavailable, try again soon'),
},
DISABLED_CLIENT_ID: {
errno: 204,
message: t('System unavailable, try again soon'),
},
ENDPOINT_NOT_SUPPORTED: {
errno: 116,
message: t('This endpoint is no longer supported'),
},
UNABLE_TO_LOGIN_NO_PASSWORD_SET: {
errno: 210,
message: t(
'Complete account setup, please <a href="/reset_password">reset password</a> to continue.'
),
},
SERVICE_UNAVAILABLE: {
errno: 998,
message: t('System unavailable, try again soon'),
},
USER_CANCELED_LOGIN: {
errno: 1001,
message: t('Login attempt cancelled'),
},
SESSION_EXPIRED: {
errno: 1002,
message: t('Session expired. Sign in to continue.'),
},
COOKIES_STILL_DISABLED: {
errno: 1003,
message: t('Cookies are still disabled'),
},
PASSWORDS_DO_NOT_MATCH: {
errno: 1004,
message: t('Passwords do not match'),
},
WORKING: {
errno: 1005,
message: t('Working…'),
},
COULD_NOT_GET_PP: {
errno: 1006,
message: t('Could not get Privacy Notice'),
},
COULD_NOT_GET_TOS: {
errno: 1007,
message: t('Could not get Terms of Service'),
},
PASSWORDS_MUST_BE_DIFFERENT: {
errno: 1008,
message: t('Your new password must be different'),
},
PASSWORD_TOO_SHORT: {
errno: 1009,
message: t('Must be at least 8 characters'),
},
PASSWORD_REQUIRED: {
errno: 1010,
message: t('Valid password required'),
},
EMAIL_REQUIRED: {
errno: 1011,
message: t('Valid email required'),
},
/*
Removed in issue #3137
YEAR_OF_BIRTH_REQUIRED: {
errno: 1012,
message: t('Year of birth required')
},
*/
UNUSABLE_IMAGE: {
errno: 1013,
message: t('A usable image was not found'),
},
NO_CAMERA: {
errno: 1014,
message: t('Could not initialize camera'),
},
URL_REQUIRED: {
errno: 1015,
message: t('Valid URL required'),
},
/*
Removed in issue #3137
BIRTHDAY_REQUIRED: {
errno: 1016,
message: t('Valid birthday required')
},
*/
DESKTOP_CHANNEL_TIMEOUT: {
errno: 1017,
message: UNEXPECTED_ERROR_MESSAGE,
},
SIGNUP_EMAIL_BOUNCE: {
errno: 1018,
message: t('Your confirmation email was just returned. Mistyped email?'),
},
DIFFERENT_EMAIL_REQUIRED: {
errno: 1019,
message: t('Valid email required'),
},
DIFFERENT_EMAIL_REQUIRED_FIREFOX_DOMAIN: {
errno: 1020,
message: t(
'Enter a valid email address. firefox.com does not offer email.'
),
},
CHANNEL_TIMEOUT: {
errno: 1021,
message: UNEXPECTED_ERROR_MESSAGE,
},
ILLEGAL_IFRAME_PARENT: {
errno: 1022,
message: t(
'Mozilla accounts can only be placed into an IFRAME on approved sites'
),
},
INVALID_EMAIL: {
errno: 1023,
message: t('Valid email required'),
},
/*
Removed in issue #3040
FORCE_AUTH_EMAIL_REQUIRED: {
errno: 1024,
message: t('/force_auth requires an email')
},
*/
EXPIRED_VERIFICATION_LINK: {
errno: 1025,
message: EXPIRED_VERIFICATION_ERROR_MESSAGE,
},
DAMAGED_VERIFICATION_LINK: {
errno: 1026,
message: t('Verification link damaged'),
},
UNEXPECTED_POSTMESSAGE_ORIGIN: {
errno: 1027,
message: UNEXPECTED_ERROR_MESSAGE,
},
INVALID_IMAGE_SIZE: {
errno: 1028,
message: t('The image dimensions must be at least 100x100px'),
},
IOS_SIGNUP_DISABLED: {
errno: 1029,
message: t('Signup is coming soon to Firefox for iOS'),
},
/*
Removed in issue #2950
SIGNUP_DISABLED_BY_RELIER: {
errno: 1030,
message: t('Signup has been disabled')
},
*/
AGE_REQUIRED: {
errno: 1031,
message: t('You must enter your age to sign up'),
},
INVALID_AGE: {
errno: 1032,
message: t('You must enter a valid age to sign up'),
},
/*
Removed in #4927
NO_GRAVATAR_FOUND: {
errno: 1032,
message: t('No Gravatar found')
},
*/
INVALID_CAMERA_DIMENSIONS: {
errno: 1033,
message: UNEXPECTED_ERROR_MESSAGE,
},
DELETED_ACCOUNT: {
errno: 1034,
message: t('Account no longer exists.'),
},
INVALID_RESUME_TOKEN_PROPERTY: {
errno: 1035,
message: t('Invalid property in resume token: %(property)s'),
},
MISSING_RESUME_TOKEN_PROPERTY: {
errno: 1036,
message: t('Missing property in resume token: %(property)s'),
},
INVALID_DATA_ATTRIBUTE: {
errno: 1037,
message: t('Invalid data attribute: %(property)s'),
},
MISSING_DATA_ATTRIBUTE: {
errno: 1038,
message: t('Missing data attribute: %(property)s'),
},
POLLING_FAILED: {
// this error is not visible to the user
errno: 1039,
message: t('Server busy, try again soon'),
},
UNKNOWN_ACCOUNT_VERIFICATION: {
errno: 1040,
message: EXPIRED_VERIFICATION_ERROR_MESSAGE,
},
REUSED_SIGNIN_VERIFICATION_CODE: {
errno: 1041,
message: t(
'That confirmation link was already used, and can only be used once.'
),
},
INPUT_REQUIRED: {
errno: 1042,
message: t('This is a required field'),
},
UNBLOCK_CODE_REQUIRED: {
errno: 1043,
message: t('Authorization code required'),
},
INVALID_UNBLOCK_CODE: {
errno: 1044,
message: t('Invalid authorization code'),
},
DAMAGED_REJECT_UNBLOCK_LINK: {
errno: 1045,
message: t('Link damaged'),
},
// logged when view.unsafeTranslate called with a string that
// contains a variable without an `escaped` prefix
UNSAFE_INTERPOLATION_VARIABLE_NAME: {
errno: 1046,
// not user facing, only used for logging, not wrapped in `t`
message: 'String variable name does not have escape prefix: %(string)s',
},
// logged when view.translate called with a string that contains
// HTML.
HTML_WILL_BE_ESCAPED: {
errno: 1047,
// not user facing, only used for logging, not wrapped in `t`
message: 'HTML will be escaped: %(string)s',
},
CANNOT_CHANGE_INPUT_TYPE: {
errno: 1048,
// not user facing, only used for logging, not wrapped in `t`
message: 'Cannot change input type: %(type)s',
},
PHONE_NUMBER_REQUIRED: {
errno: 1049,
message: t('Phone number required'),
},
ACCOUNT_HAS_NO_UID: {
errno: 1050,
// not user facing, only used for logging. Logged whenever
// an attempt is made to write an account w/o a uid
// to localStorage.
message: 'Account has no uid',
},
INVALID_WEB_CHANNEL: {
errno: 1051,
message:
'Browser not configured to accept WebChannel messages from this domain',
},
REUSED_PRIMARY_EMAIL_VERIFICATION_CODE: {
errno: 1052,
message: t(
'That confirmation link was already used, and can only be used once.'
),
},
TOTP_CODE_REQUIRED: {
errno: 1053,
message: t('Two-step authentication code required'),
},
INVALID_TOTP_CODE: {
errno: 1054,
message: t('Invalid two-step authentication code'),
},
RECOVERY_CODE_REQUIRED: {
errno: 1055,
message: t('Backup authentication code required'),
},
INVALID_RECOVERY_CODE: {
errno: 1056,
message: t('Invalid backup authentication code'),
},
PASSWORD_SAME_AS_EMAIL: {
errno: 1057,
message: 'Password must not be your email address', // only used for logging, no need for translation
},
PASSWORD_TOO_COMMON: {
errno: 1058,
message: 'Password is too common', // only used for logging, no need for translation
},
RECOVERY_KEY_REQUIRED: {
errno: 1059,
message: t('Account recovery key required'),
},
OTP_CODE_REQUIRED: {
errno: 1060,
message: t('Please enter verification code'),
},
/*
Removed in https://github.com/mozilla/fxa/pull/1242
TOTP_PAIRING_NOT_SUPPORTED: {
errno: 1061,
message: t('Accounts with two-step authentication do not support pairing at this time')
},
*/
INVALID_REDIRECT_TO: {
errno: 1062,
message: t('Invalid redirect'),
},
/*
Removed in https://github.com/mozilla/fxa/pull/2658
COULD_NOT_GET_SUBPLAT_TOS: {
errno: 1063,
message: t('Could not get Subscription Platform Terms of Service'),
},
*/
INVALID_EMAIL_DOMAIN: {
errno: 1064,
message: t('Mistyped email? %(domain)s does not offer email.'),
},
IMAGE_TOO_LARGE: {
errno: 1065,
message: t('The image file size is too large to be uploaded.'),
},
EMAIL_MASK_NEW_ACCOUNT: {
errno: 1066,
message: t('Email masks can’t be used to create an account.'),
},
};
export default _.extend({}, Errors, {
ERRORS: ERRORS,
NAMESPACE: 'auth',
/**
* Fetch the interpolation context out of the server error.
*
* @param {Error} err
* @returns {Object}
*/
toInterpolationContext(err) {
// For data returned by backend, see
// https://github.com/mozilla/fxa/blob/main/packages/fxa-auth-server/lib/error.js
try {
if (this.is(err, 'INVALID_PARAMETER')) {
return {
param: err.param || err.validation.keys,
};
} else if (this.is(err, 'MISSING_PARAMETER')) {
return {
param: err.param,
};
} else if (this.is(err, 'INVALID_RESUME_TOKEN_PROPERTY')) {
return {
property: err.property,
};
} else if (this.is(err, 'MISSING_RESUME_TOKEN_PROPERTY')) {
return {
property: err.property,
};
} else if (this.is(err, 'INVALID_DATA_ATTRIBUTE')) {
return {
property: err.property,
};
} else if (this.is(err, 'MISSING_DATA_ATTRIBUTE')) {
return {
property: err.property,
};
} else if (this.is(err, 'UNSAFE_INTERPOLATION_VARIABLE_NAME')) {
return {
string: err.string,
};
} else if (this.is(err, 'HTML_WILL_BE_ESCAPED')) {
return {
string: err.string,
};
} else if (this.is(err, 'CANNOT_CHANGE_INPUT_TYPE')) {
return {
type: err.type,
};
} else if (this.is(err, 'THROTTLED')) {
if (err.retryAfterLocalized) {
// enhance the throttled message if localized retryAfter data is available
err.message = THROTTLED_LOCALIZED_ERROR_MESSAGE;
}
return {
retryAfterLocalized: err.retryAfterLocalized,
};
} else if (this.is(err, 'INVALID_EMAIL_DOMAIN')) {
return {
domain: err.domain,
};
}
} catch (e) {
// handle invalid/unexpected data from the backend.
logger.error('Error in errors.js->toInterpolationContext: %s', String(e));
}
return {};
},
});
export const legacyL10nStrings = [
t('Firefox Accounts can only be placed into an IFRAME on approved sites'),
];