Skip to content

Commit 7fa04b5

Browse files
author
renkelvin
authored
Merge f8bc16b into c51f120
2 parents c51f120 + f8bc16b commit 7fa04b5

File tree

19 files changed

+538
-272
lines changed

19 files changed

+538
-272
lines changed

common/api-review/auth.api.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,14 @@ export const AuthErrorCodes: {
227227
readonly WEAK_PASSWORD: "auth/weak-password";
228228
readonly WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported";
229229
readonly ALREADY_INITIALIZED: "auth/already-initialized";
230-
readonly RECAPTCHA_CHECK_FAILED: "auth/recaptcha-check-failed";
231230
readonly RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled";
231+
readonly MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token";
232+
readonly INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token";
233+
readonly INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action";
234+
readonly MISSING_CLIENT_TYPE: "auth/missing-client-type";
235+
readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version";
236+
readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version";
237+
readonly INVALID_REQ_TYPE: "auth/invalid-req-type";
232238
};
233239

234240
// @public
@@ -666,11 +672,6 @@ export function reauthenticateWithPopup(user: User, provider: AuthProvider, reso
666672
// @public
667673
export function reauthenticateWithRedirect(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise<never>;
668674

669-
// @public (undocumented)
670-
export interface RecaptchaConfig {
671-
emailPasswordEnabled: boolean;
672-
}
673-
674675
// @public
675676
export interface RecaptchaParameters {
676677
// (undocumented)

docs-devsite/auth.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ Firebase Authentication
132132
| [PhoneSingleFactorInfoOptions](./auth.phonesinglefactorinfooptions.md#phonesinglefactorinfooptions_interface) | Options used for single-factor sign-in. |
133133
| [PopupRedirectResolver](./auth.popupredirectresolver.md#popupredirectresolver_interface) | A resolver used for handling DOM specific operations like [signInWithPopup()](./auth.md#signinwithpopup) or [signInWithRedirect()](./auth.md#signinwithredirect)<!-- -->. |
134134
| [ReactNativeAsyncStorage](./auth.reactnativeasyncstorage.md#reactnativeasyncstorage_interface) | Interface for a supplied <code>AsyncStorage</code>. |
135-
| [RecaptchaConfig](./auth.recaptchaconfig.md#recaptchaconfig_interface) | |
136135
| [RecaptchaParameters](./auth.recaptchaparameters.md#recaptchaparameters_interface) | Interface representing reCAPTCHA parameters.<!-- -->See the \[reCAPTCHA docs\](https://developers.google.com/recaptcha/docs/display\#render\_param) for the list of accepted parameters. All parameters are accepted except for <code>sitekey</code>: Firebase Auth provisions a reCAPTCHA for each project and will configure the site key upon rendering.<!-- -->For an invisible reCAPTCHA, set the <code>size</code> key to <code>invisible</code>. |
137136
| [TotpMultiFactorAssertion](./auth.totpmultifactorassertion.md#totpmultifactorassertion_interface) | The class for asserting ownership of a TOTP second factor. Provided by [TotpMultiFactorGenerator.assertionForEnrollment()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforenrollment) and [TotpMultiFactorGenerator.assertionForSignIn()](./auth.totpmultifactorgenerator.md#totpmultifactorgeneratorassertionforsignin)<!-- -->. |
138137
| [TotpMultiFactorInfo](./auth.totpmultifactorinfo.md#totpmultifactorinfo_interface) | The subclass of the [MultiFactorInfo](./auth.multifactorinfo.md#multifactorinfo_interface) interface for TOTP second factors. The <code>factorId</code> of this second factor is [FactorId](./auth.md#factorid)<!-- -->.TOTP. |
@@ -1827,8 +1826,14 @@ AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY: {
18271826
readonly WEAK_PASSWORD: "auth/weak-password";
18281827
readonly WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported";
18291828
readonly ALREADY_INITIALIZED: "auth/already-initialized";
1830-
readonly RECAPTCHA_CHECK_FAILED: "auth/recaptcha-check-failed";
18311829
readonly RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled";
1830+
readonly MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token";
1831+
readonly INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token";
1832+
readonly INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action";
1833+
readonly MISSING_CLIENT_TYPE: "auth/missing-client-type";
1834+
readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version";
1835+
readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version";
1836+
readonly INVALID_REQ_TYPE: "auth/invalid-req-type";
18321837
}
18331838
```
18341839

docs-devsite/auth.recaptchaconfig.md

Lines changed: 0 additions & 34 deletions
This file was deleted.

packages/auth/src/api/authentication/recaptcha.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
_performApiRequest,
2424
_addTidIfNecessary
2525
} from '../index';
26-
import { Auth, RecaptchaConfig } from '../../model/public_types';
26+
import { Auth } from '../../model/public_types';
2727

2828
interface GetRecaptchaParamResponse {
2929
recaptchaSiteKey?: string;
@@ -47,9 +47,14 @@ interface GetRecaptchaConfigRequest {
4747
version?: RecaptchaVersion;
4848
}
4949

50-
interface GetRecaptchaConfigResponse {
51-
recaptchaKey?: string;
52-
recaptchaConfig?: RecaptchaConfig;
50+
interface RecaptchaEnforcementState {
51+
provider: string;
52+
enforcementState: string;
53+
}
54+
55+
export interface GetRecaptchaConfigResponse {
56+
recaptchaKey: string;
57+
recaptchaEnforcementState: RecaptchaEnforcementState[];
5358
}
5459

5560
export async function getRecaptchaConfig(

packages/auth/src/api/errors.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,14 @@ export const enum ServerError {
9191
USER_DISABLED = 'USER_DISABLED',
9292
USER_NOT_FOUND = 'USER_NOT_FOUND',
9393
WEAK_PASSWORD = 'WEAK_PASSWORD',
94-
INVALID_RECAPTCHA_SCORE = 'invalid-recaptcha-score',
94+
RECAPTCHA_NOT_ENABLED = 'recaptcha-not-enabled',
9595
MISSING_RECAPTCHA_TOKEN = 'missing-recaptcha-token',
9696
INVALID_RECAPTCHA_TOKEN = 'invalid-recaptcha-token',
97-
INVALID_RECAPTCHA_ACTION = 'invalide-recaptcha-action',
98-
INVALID_RECAPTCHA_ENFORCEMENT_STATE = 'invalid-recaptcha-enforcement-state',
99-
RECAPTCHA_NOT_ENABLED = 'recaptcha-not-enabled',
97+
INVALID_RECAPTCHA_ACTION = 'invalid-recaptcha-action',
10098
MISSING_CLIENT_TYPE = 'missing-client-type',
10199
MISSING_RECAPTCHA_VERSION = 'missing-recaptcha-version',
102-
INVALID_REQ_TYPE = 'invalid-req-type',
103-
INVALID_RECAPTCHA_VERSION = 'invalid-recaptcha-version'
100+
INVALID_RECAPTCHA_VERSION = 'invalid-recaptcha-version',
101+
INVALID_REQ_TYPE = 'invalid-req-type'
104102
}
105103

106104
/**
@@ -216,15 +214,15 @@ export const SERVER_ERROR_MAP: Partial<ServerErrorMap<ServerError>> = {
216214
[ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE]: AuthErrorCode.INTERNAL_ERROR,
217215

218216
// Recaptcha related errors.
219-
[ServerError.INVALID_RECAPTCHA_SCORE]: AuthErrorCode.RECAPTCHA_CHECK_FAILED,
220217
[ServerError.RECAPTCHA_NOT_ENABLED]: AuthErrorCode.RECAPTCHA_NOT_ENABLED,
221-
[ServerError.MISSING_RECAPTCHA_TOKEN]: AuthErrorCode.INTERNAL_ERROR,
222-
[ServerError.INVALID_RECAPTCHA_TOKEN]: AuthErrorCode.INTERNAL_ERROR,
223-
[ServerError.INVALID_RECAPTCHA_ACTION]: AuthErrorCode.INTERNAL_ERROR,
224-
[ServerError.INVALID_RECAPTCHA_ENFORCEMENT_STATE]:
225-
AuthErrorCode.INTERNAL_ERROR,
226-
[ServerError.MISSING_CLIENT_TYPE]: AuthErrorCode.INTERNAL_ERROR,
227-
[ServerError.MISSING_RECAPTCHA_VERSION]: AuthErrorCode.INTERNAL_ERROR,
228-
[ServerError.INVALID_REQ_TYPE]: AuthErrorCode.INTERNAL_ERROR,
229-
[ServerError.INVALID_RECAPTCHA_VERSION]: AuthErrorCode.INTERNAL_ERROR
218+
[ServerError.MISSING_RECAPTCHA_TOKEN]: AuthErrorCode.MISSING_RECAPTCHA_TOKEN,
219+
[ServerError.INVALID_RECAPTCHA_TOKEN]: AuthErrorCode.INVALID_RECAPTCHA_TOKEN,
220+
[ServerError.INVALID_RECAPTCHA_ACTION]:
221+
AuthErrorCode.INVALID_RECAPTCHA_ACTION,
222+
[ServerError.MISSING_CLIENT_TYPE]: AuthErrorCode.MISSING_CLIENT_TYPE,
223+
[ServerError.MISSING_RECAPTCHA_VERSION]:
224+
AuthErrorCode.MISSING_RECAPTCHA_VERSION,
225+
[ServerError.INVALID_RECAPTCHA_VERSION]:
226+
AuthErrorCode.INVALID_RECAPTCHA_VERSION,
227+
[ServerError.INVALID_REQ_TYPE]: AuthErrorCode.INVALID_REQ_TYPE
230228
};

packages/auth/src/core/auth/auth_impl.test.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -661,9 +661,27 @@ describe('core/auth/auth_impl', () => {
661661
});
662662
});
663663

664-
context('recaptchaConfig', () => {
665-
const configAgent = { emailPasswordEnabled: true };
666-
const configTenant = { emailPasswordEnabled: false };
664+
context('recaptchaEnforcementState', () => {
665+
const recaptchaConfigResponseEnforce = {
666+
recaptchaKey: 'foo/bar/to/site-key',
667+
recaptchaEnforcementState: [
668+
{ provider: 'EMAIL_PASSWORD_PROVIDER', enforcementState: 'ENFORCE' }
669+
]
670+
};
671+
const recaptchaConfigResponseOff = {
672+
recaptchaKey: 'foo/bar/to/site-key',
673+
recaptchaEnforcementState: [
674+
{ provider: 'EMAIL_PASSWORD_PROVIDER', enforcementState: 'OFF' }
675+
]
676+
};
677+
const cachedRecaptchaConfigEnforce = {
678+
emailPasswordEnabled: true,
679+
siteKey: 'site-key'
680+
};
681+
const cachedRecaptchaConfigOFF = {
682+
emailPasswordEnabled: false,
683+
siteKey: 'site-key'
684+
};
667685

668686
beforeEach(async () => {
669687
mockFetch.setUp();
@@ -682,14 +700,11 @@ describe('core/auth/auth_impl', () => {
682700
clientType: RecaptchaClientType.WEB,
683701
version: RecaptchaVersion.ENTERPRISE
684702
},
685-
{
686-
recaptchaKey: 'site-key',
687-
recaptchaConfig: configAgent
688-
}
703+
recaptchaConfigResponseEnforce
689704
);
690705
await auth.initializeRecaptchaConfig();
691706

692-
expect(auth._getRecaptchaConfig()).to.eql(configAgent);
707+
expect(auth._getRecaptchaConfig()).to.eql(cachedRecaptchaConfigEnforce);
693708
});
694709

695710
it('recaptcha config should be set for tenant if tenant id is not null.', async () => {
@@ -702,14 +717,11 @@ describe('core/auth/auth_impl', () => {
702717
version: RecaptchaVersion.ENTERPRISE,
703718
tenantId: 'tenant-id'
704719
},
705-
{
706-
recaptchaKey: 'site-key',
707-
recaptchaConfig: configTenant
708-
}
720+
recaptchaConfigResponseOff
709721
);
710722
await auth.initializeRecaptchaConfig();
711723

712-
expect(auth._getRecaptchaConfig()).to.eql(configTenant);
724+
expect(auth._getRecaptchaConfig()).to.eql(cachedRecaptchaConfigOFF);
713725
});
714726

715727
it('recaptcha config should dynamically switch if tenant id switches.', async () => {
@@ -721,10 +733,7 @@ describe('core/auth/auth_impl', () => {
721733
clientType: RecaptchaClientType.WEB,
722734
version: RecaptchaVersion.ENTERPRISE
723735
},
724-
{
725-
recaptchaKey: 'site-key',
726-
recaptchaConfig: configAgent
727-
}
736+
recaptchaConfigResponseEnforce
728737
);
729738
await auth.initializeRecaptchaConfig();
730739
auth.tenantId = 'tenant-id';
@@ -735,17 +744,14 @@ describe('core/auth/auth_impl', () => {
735744
version: RecaptchaVersion.ENTERPRISE,
736745
tenantId: 'tenant-id'
737746
},
738-
{
739-
recaptchaKey: 'site-key',
740-
recaptchaConfig: configTenant
741-
}
747+
recaptchaConfigResponseOff
742748
);
743749
await auth.initializeRecaptchaConfig();
744750

745751
auth.tenantId = null;
746-
expect(auth._getRecaptchaConfig()).to.eql(configAgent);
752+
expect(auth._getRecaptchaConfig()).to.eql(cachedRecaptchaConfigEnforce);
747753
auth.tenantId = 'tenant-id';
748-
expect(auth._getRecaptchaConfig()).to.eql(configTenant);
754+
expect(auth._getRecaptchaConfig()).to.eql(cachedRecaptchaConfigOFF);
749755
});
750756
});
751757
});

packages/auth/src/core/auth/auth_impl.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import {
2222
AuthErrorMap,
2323
AuthSettings,
2424
EmulatorConfig,
25-
RecaptchaConfig,
2625
NextOrObserver,
2726
Persistence,
2827
PopupRedirectResolver,
@@ -65,6 +64,7 @@ import { HttpHeader, RecaptchaClientType, RecaptchaVersion } from '../../api';
6564
import { getRecaptchaConfig } from '../../api/authentication/recaptcha';
6665
import { RecaptchaEnterpriseVerifier } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
6766
import { AuthMiddlewareQueue } from './middleware';
67+
import { RecaptchaConfig } from '../../platform_browser/recaptcha/recaptcha';
6868

6969
interface AsyncAction {
7070
(): Promise<void>;
@@ -397,16 +397,14 @@ export class AuthImpl implements AuthInternal, _FirebaseService {
397397
clientType: RecaptchaClientType.WEB,
398398
version: RecaptchaVersion.ENTERPRISE
399399
});
400-
// TODO(chuanr): Confirm the response format when backend is ready
401-
if (response.recaptchaConfig === undefined) {
402-
throw new Error('recaptchaConfig undefined');
403-
}
404-
const config = response.recaptchaConfig;
405-
if (this.tenantId) {
406-
this._tenantRecaptchaConfigs[this.tenantId] = config;
407-
} else {
400+
401+
const config = new RecaptchaConfig(response);
402+
if (this.tenantId == null) {
408403
this._agentRecaptchaConfig = config;
404+
} else {
405+
this._tenantRecaptchaConfigs[this.tenantId] = config;
409406
}
407+
410408
if (config.emailPasswordEnabled) {
411409
const verifier = new RecaptchaEnterpriseVerifier(this);
412410
void verifier.verify();

0 commit comments

Comments
 (0)