Skip to content

Adds backend multi-factor auth related errors and their client mappings. #752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/auth/user-import-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export function convertMultiFactorInfoToServerFormat(multiFactorInfo: SecondFact
} else {
// Unsupported second factor.
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_ENROLLED_FACTORS,
AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR,
`Unsupported second factor "${JSON.stringify(multiFactorInfo)}" provided.`);
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/utils/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ export class AuthClientErrorCode {
code: 'missing-display-name',
message: 'The resource being created or edited is missing a valid display name.',
};
public static MISSING_EMAIL = {
code: 'missing-email',
message: 'The email is required for the specified action. For example, a multi-factor user ' +
'requires a verified email.',
};
public static MISSING_IOS_BUNDLE_ID = {
code: 'missing-ios-bundle-id',
message: 'The request is missing an iOS Bundle ID.',
Expand Down Expand Up @@ -624,6 +629,14 @@ export class AuthClientErrorCode {
code: 'quota-exceeded',
message: 'The project quota for the specified operation has been exceeded.',
};
public static SECOND_FACTOR_LIMIT_EXCEEDED = {
code: 'second-factor-limit-exceeded',
message: 'The maximum number of allowed second factors on a user has been exceeded.',
};
public static SECOND_FACTOR_UID_ALREADY_EXISTS = {
code: 'second-factor-uid-already-exists',
message: 'The specified second factor "uid" already exists.',
};
public static SESSION_COOKIE_EXPIRED = {
code: 'session-cookie-expired',
message: 'The Firebase session cookie is expired.',
Expand All @@ -645,10 +658,23 @@ export class AuthClientErrorCode {
message: 'The domain of the continue URL is not whitelisted. Whitelist the domain in the ' +
'Firebase console.',
};
public static UNSUPPORTED_FIRST_FACTOR = {
code: 'unsupported-first-factor',
message: 'A multi-factor user requires a supported first factor.',
};
public static UNSUPPORTED_SECOND_FACTOR = {
code: 'unsupported-second-factor',
message: 'The request specified an unsupported type of second factor.',
};
public static UNSUPPORTED_TENANT_OPERATION = {
code: 'unsupported-tenant-operation',
message: 'This operation is not supported in a multi-tenant context.',
};
public static UNVERIFIED_EMAIL = {
code: 'unverified-email',
message: 'A verified email is required for the specified action. For example, a multi-factor user ' +
'requires a verified email.',
};
public static USER_NOT_FOUND = {
code: 'user-not-found',
message: 'There is no user record corresponding to the provided identifier.',
Expand Down Expand Up @@ -811,6 +837,8 @@ const AUTH_SERVER_TO_CLIENT_CODE: ServerToClientCode = {
DUPLICATE_EMAIL: 'EMAIL_ALREADY_EXISTS',
// uploadAccount provides a localId that already exists.
DUPLICATE_LOCAL_ID: 'UID_ALREADY_EXISTS',
// Request specified a multi-factor enrollment ID that already exists.
DUPLICATE_MFA_ENROLLMENT_ID: 'SECOND_FACTOR_UID_ALREADY_EXISTS',
// setAccountInfo email already exists.
EMAIL_EXISTS: 'EMAIL_ALREADY_EXISTS',
// Reserved claim name.
Expand Down Expand Up @@ -849,6 +877,9 @@ const AUTH_SERVER_TO_CLIENT_CODE: ServerToClientCode = {
MISSING_CONFIG_ID: 'MISSING_PROVIDER_ID',
// Missing tenant display name: This can be thrown on CreateTenant and UpdateTenant.
MISSING_DISPLAY_NAME: 'MISSING_DISPLAY_NAME',
// Email is required for the specified action. For example a multi-factor user requires
// a verified email.
MISSING_EMAIL: 'MISSING_EMAIL',
// Missing iOS bundle ID.
MISSING_IOS_BUNDLE_ID: 'MISSING_IOS_BUNDLE_ID',
// Missing OIDC issuer.
Expand All @@ -873,6 +904,8 @@ const AUTH_SERVER_TO_CLIENT_CODE: ServerToClientCode = {
PROJECT_NOT_FOUND: 'PROJECT_NOT_FOUND',
// In multi-tenancy context: project creation quota exceeded.
QUOTA_EXCEEDED: 'QUOTA_EXCEEDED',
// Currently only 5 second factors can be set on the same user.
SECOND_FACTOR_LIMIT_EXCEEDED: 'SECOND_FACTOR_LIMIT_EXCEEDED',
// Tenant not found.
TENANT_NOT_FOUND: 'TENANT_NOT_FOUND',
// Tenant ID mismatch.
Expand All @@ -881,8 +914,15 @@ const AUTH_SERVER_TO_CLIENT_CODE: ServerToClientCode = {
TOKEN_EXPIRED: 'ID_TOKEN_EXPIRED',
// Continue URL provided in ActionCodeSettings has a domain that is not whitelisted.
UNAUTHORIZED_DOMAIN: 'UNAUTHORIZED_DOMAIN',
// A multi-factor user requires a supported first factor.
UNSUPPORTED_FIRST_FACTOR: 'UNSUPPORTED_FIRST_FACTOR',
// The request specified an unsupported type of second factor.
UNSUPPORTED_SECOND_FACTOR: 'UNSUPPORTED_SECOND_FACTOR',
// Operation is not supported in a multi-tenant context.
UNSUPPORTED_TENANT_OPERATION: 'UNSUPPORTED_TENANT_OPERATION',
// A verified email is required for the specified action. For example a multi-factor user
// requires a verified email.
UNVERIFIED_EMAIL: 'UNVERIFIED_EMAIL',
// User on which action is to be performed is not found.
USER_NOT_FOUND: 'USER_NOT_FOUND',
// Password provided is too weak.
Expand Down
8 changes: 4 additions & 4 deletions test/integration/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,16 @@ describe('admin.auth', () => {
// Confirm expected email.
expect(userRecord.email).to.equal(newUserData.email);
// Confirm second factors added to user.
expect(userRecord.multiFactor.enrolledFactors.length).to.equal(2);
expect(userRecord.multiFactor!.enrolledFactors.length).to.equal(2);
// Confirm first enrolled second factor.
const firstMultiFactor = userRecord.multiFactor.enrolledFactors[0];
const firstMultiFactor = userRecord.multiFactor!.enrolledFactors[0];
expect(firstMultiFactor.uid).not.to.be.undefined;
expect(firstMultiFactor.enrollmentTime).not.to.be.undefined;
expect(firstMultiFactor.phoneNumber).to.equal(enrolledFactors[0].phoneNumber);
expect(firstMultiFactor.displayName).to.equal(enrolledFactors[0].displayName);
expect(firstMultiFactor.factorId).to.equal(enrolledFactors[0].factorId);
// Confirm second enrolled second factor.
const secondMultiFactor = userRecord.multiFactor.enrolledFactors[1];
const secondMultiFactor = userRecord.multiFactor!.enrolledFactors[1];
expect(secondMultiFactor.uid).not.to.be.undefined;
expect(secondMultiFactor.enrollmentTime).not.to.be.undefined;
expect(secondMultiFactor.phoneNumber).to.equal(enrolledFactors[1].phoneNumber);
Expand Down Expand Up @@ -413,7 +413,7 @@ describe('admin.auth', () => {
});
})
.then((userRecord) => {
expect(userRecord.multiFactor.enrolledFactors.length).to.equal(1);
expect(userRecord.multiFactor!.enrolledFactors.length).to.equal(1);
const actualUserRecord: {[key: string]: any} = userRecord.toJSON();
expect(actualUserRecord.multiFactor.enrolledFactors[0]).to.deep.equal(enrolledFactors[0]);
// Remove all second factors.
Expand Down
6 changes: 3 additions & 3 deletions test/unit/auth/auth-api-request.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,7 +1530,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => {
{
index: 22,
error: new FirebaseAuthError(
AuthClientErrorCode.INVALID_ENROLLED_FACTORS,
AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR,
`Unsupported second factor "${JSON.stringify(testUsers[22].multiFactor.enrolledFactors[0])}" provided.`,
),
},
Expand Down Expand Up @@ -2032,7 +2032,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => {
{
name: 'invalid second factor type',
error: new FirebaseAuthError(
AuthClientErrorCode.INVALID_ENROLLED_FACTORS,
AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR,
`Unsupported second factor "${JSON.stringify(unsupportedSecondFactor)}" provided.`),
secondFactor: unsupportedSecondFactor,
},
Expand Down Expand Up @@ -2512,7 +2512,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => {
{
name: 'invalid second factor type',
error: new FirebaseAuthError(
AuthClientErrorCode.INVALID_ENROLLED_FACTORS,
AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR,
`Unsupported second factor "${JSON.stringify(unsupportedSecondFactor)}" provided.`),
secondFactor: unsupportedSecondFactor,
},
Expand Down
2 changes: 1 addition & 1 deletion test/unit/auth/user-import-builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ describe('UserImportBuilder', () => {
{
index: 9,
error: new FirebaseAuthError(
AuthClientErrorCode.INVALID_ENROLLED_FACTORS,
AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR,
`Unsupported second factor "${JSON.stringify(testUsers[9].multiFactor!.enrolledFactors[0])}" provided.`),
},
],
Expand Down