Skip to content

Commit 873fb89

Browse files
committed
Make ApplicationVerifier params optional in Phone APIs
1 parent 56f904c commit 873fb89

File tree

8 files changed

+93
-20
lines changed

8 files changed

+93
-20
lines changed

common/api-review/auth.api.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ export function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean;
445445
export function linkWithCredential(user: User, credential: AuthCredential): Promise<UserCredential>;
446446

447447
// @public
448-
export function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
448+
export function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
449449

450450
// @public
451451
export function linkWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise<UserCredential>;
@@ -625,7 +625,7 @@ export class PhoneAuthProvider {
625625
static readonly PHONE_SIGN_IN_METHOD: 'phone';
626626
static readonly PROVIDER_ID: 'phone';
627627
readonly providerId: "phone";
628-
verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier: ApplicationVerifier): Promise<string>;
628+
verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier?: ApplicationVerifier): Promise<string>;
629629
}
630630

631631
// @public
@@ -692,7 +692,7 @@ export interface ReactNativeAsyncStorage {
692692
export function reauthenticateWithCredential(user: User, credential: AuthCredential): Promise<UserCredential>;
693693

694694
// @public
695-
export function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
695+
export function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
696696

697697
// @public
698698
export function reauthenticateWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise<UserCredential>;
@@ -778,7 +778,7 @@ export function signInWithEmailAndPassword(auth: Auth, email: string, password:
778778
export function signInWithEmailLink(auth: Auth, email: string, emailLink?: string): Promise<UserCredential>;
779779

780780
// @public
781-
export function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
781+
export function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
782782

783783
// @public
784784
export function signInWithPopup(auth: Auth, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise<UserCredential>;

docs-devsite/auth.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,7 @@ This method does not work in a Node.js environment or with [Auth](./auth.auth.md
930930
<b>Signature:</b>
931931

932932
```typescript
933-
export declare function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
933+
export declare function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
934934
```
935935

936936
#### Parameters
@@ -1304,7 +1304,7 @@ This method does not work in a Node.js environment.
13041304
<b>Signature:</b>
13051305

13061306
```typescript
1307-
export declare function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
1307+
export declare function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
13081308
```
13091309

13101310
#### Parameters
@@ -1457,7 +1457,7 @@ This method does not work in a Node.js environment or on any [User](./auth.user.
14571457
<b>Signature:</b>
14581458

14591459
```typescript
1460-
export declare function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier: ApplicationVerifier): Promise<ConfirmationResult>;
1460+
export declare function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise<ConfirmationResult>;
14611461
```
14621462

14631463
#### Parameters

docs-devsite/auth.phoneauthprovider.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ Starts a phone number authentication flow by sending a verification code to the
203203
<b>Signature:</b>
204204

205205
```typescript
206-
verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier: ApplicationVerifier): Promise<string>;
206+
verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier?: ApplicationVerifier): Promise<string>;
207207
```
208208

209209
#### Parameters

packages/auth/src/api/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const enum RecaptchaActionName {
8989
SIGN_UP_PASSWORD = 'signUpPassword',
9090
SEND_VERIFICATION_CODE = 'sendVerificationCode',
9191
MFA_SMS_ENROLLMENT = 'mfaSmsEnrollment',
92-
MFA_SMS_SIGNIN = 'mfaSmsSignin'
92+
MFA_SMS_SIGNIN = 'mfaSmsSignIn'
9393
}
9494

9595
export const enum EnforcementState {

packages/auth/src/platform_browser/providers/phone.test.ts

+43
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,49 @@ describe('platform_browser/providers/phone', () => {
104104
});
105105
});
106106

107+
it('calls the server without appVerifier when recaptcha enterprise is enabled', async () => {
108+
const recaptchaConfigResponseEnforce = {
109+
recaptchaKey: 'foo/bar/to/site-key',
110+
recaptchaEnforcementState: [
111+
{
112+
provider: RecaptchaAuthProvider.PHONE_PROVIDER,
113+
enforcementState: EnforcementState.ENFORCE
114+
}
115+
]
116+
};
117+
const recaptcha = new MockGreCAPTCHATopLevel();
118+
if (typeof window === 'undefined') {
119+
return;
120+
}
121+
window.grecaptcha = recaptcha;
122+
sinon
123+
.stub(recaptcha.enterprise, 'execute')
124+
.returns(Promise.resolve('enterprise-token'));
125+
126+
mockEndpointWithParams(
127+
Endpoint.GET_RECAPTCHA_CONFIG,
128+
{
129+
clientType: RecaptchaClientType.WEB,
130+
version: RecaptchaVersion.ENTERPRISE
131+
},
132+
recaptchaConfigResponseEnforce
133+
);
134+
135+
const route = mockEndpoint(Endpoint.SEND_VERIFICATION_CODE, {
136+
sessionInfo: 'verification-id'
137+
});
138+
139+
const provider = new PhoneAuthProvider(auth);
140+
const result = await provider.verifyPhoneNumber('+15105550000');
141+
expect(result).to.eq('verification-id');
142+
expect(route.calls[0].request).to.eql({
143+
phoneNumber: '+15105550000',
144+
captchaResponse: 'enterprise-token',
145+
clientType: RecaptchaClientType.WEB,
146+
recaptchaVersion: RecaptchaVersion.ENTERPRISE
147+
});
148+
});
149+
107150
it('calls the server when recaptcha enterprise is enabled', async () => {
108151
const recaptchaConfigResponseEnforce = {
109152
recaptchaKey: 'foo/bar/to/site-key',

packages/auth/src/platform_browser/providers/phone.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export class PhoneAuthProvider {
104104
*/
105105
verifyPhoneNumber(
106106
phoneOptions: PhoneInfoOptions | string,
107-
applicationVerifier: ApplicationVerifier
107+
applicationVerifier?: ApplicationVerifier
108108
): Promise<string> {
109109
return _verifyPhoneNumber(
110110
this.auth,

packages/auth/src/platform_browser/strategies/phone.test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,21 @@ describe('platform_browser/strategies/phone', () => {
181181
});
182182
});
183183

184+
it('calls verify phone number without a v2 RecaptchaVerifier when recaptcha enterprise is enabled', async () => {
185+
if (typeof window === 'undefined') {
186+
return;
187+
}
188+
mockRecaptchaEnterpriseEnablement(EnforcementState.ENFORCE);
189+
await signInWithPhoneNumber(auth, '+15105550000');
190+
191+
expect(sendCodeEndpoint.calls[0].request).to.eql({
192+
phoneNumber: '+15105550000',
193+
captchaResponse: RECAPTCHA_ENTERPRISE_TOKEN,
194+
clientType: RecaptchaClientType.WEB,
195+
recaptchaVersion: RecaptchaVersion.ENTERPRISE
196+
});
197+
});
198+
184199
context('ConfirmationResult', () => {
185200
it('result contains verification id baked in', async () => {
186201
if (typeof window === 'undefined') {
@@ -504,6 +519,21 @@ describe('platform_browser/strategies/phone', () => {
504519
});
505520
});
506521

522+
it('works without v2 RecaptchaVerifier when recaptcha enterprise is enabled', async () => {
523+
if (typeof window === 'undefined') {
524+
return;
525+
}
526+
mockRecaptchaEnterpriseEnablement(EnforcementState.ENFORCE);
527+
const sessionInfo = await _verifyPhoneNumber(auth, 'number');
528+
expect(sessionInfo).to.eq('session-info');
529+
expect(sendCodeEndpoint.calls[0].request).to.eql({
530+
phoneNumber: 'number',
531+
captchaResponse: RECAPTCHA_ENTERPRISE_TOKEN,
532+
clientType: RecaptchaClientType.WEB,
533+
recaptchaVersion: RecaptchaVersion.ENTERPRISE
534+
});
535+
});
536+
507537
it('calls fallback to recaptcha v2 flow when receiving MISSING_RECAPTCHA_TOKEN error in recaptcha enterprise audit mode', async () => {
508538
if (typeof window === 'undefined') {
509539
return;

packages/auth/src/platform_browser/strategies/phone.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class ConfirmationResultImpl implements ConfirmationResult {
129129
export async function signInWithPhoneNumber(
130130
auth: Auth,
131131
phoneNumber: string,
132-
appVerifier: ApplicationVerifier
132+
appVerifier?: ApplicationVerifier
133133
): Promise<ConfirmationResult> {
134134
if (_isFirebaseServerApp(auth.app)) {
135135
return Promise.reject(
@@ -162,7 +162,7 @@ export async function signInWithPhoneNumber(
162162
export async function linkWithPhoneNumber(
163163
user: User,
164164
phoneNumber: string,
165-
appVerifier: ApplicationVerifier
165+
appVerifier?: ApplicationVerifier
166166
): Promise<ConfirmationResult> {
167167
const userInternal = getModularInstance(user) as UserInternal;
168168
await _assertLinkedStatus(false, userInternal, ProviderId.PHONE);
@@ -194,7 +194,7 @@ export async function linkWithPhoneNumber(
194194
export async function reauthenticateWithPhoneNumber(
195195
user: User,
196196
phoneNumber: string,
197-
appVerifier: ApplicationVerifier
197+
appVerifier?: ApplicationVerifier
198198
): Promise<ConfirmationResult> {
199199
const userInternal = getModularInstance(user) as UserInternal;
200200
if (_isFirebaseServerApp(userInternal.auth.app)) {
@@ -224,7 +224,7 @@ type PhoneApiCaller<TRequest, TResponse> = (
224224
export async function _verifyPhoneNumber(
225225
auth: AuthInternal,
226226
options: PhoneInfoOptions | string,
227-
verifier: ApplicationVerifierInternal
227+
verifier?: ApplicationVerifierInternal
228228
): Promise<string> {
229229
if (!auth._getRecaptchaConfig()) {
230230
const enterpriseVerifier = new RecaptchaEnterpriseVerifier(auth);
@@ -274,7 +274,7 @@ export async function _verifyPhoneNumber(
274274
request.phoneEnrollmentInfo.captchaResponse === FAKE_TOKEN
275275
) {
276276
_assert(
277-
verifier.type === RECAPTCHA_VERIFIER_TYPE,
277+
verifier?.type === RECAPTCHA_VERIFIER_TYPE,
278278
authInstance,
279279
AuthErrorCode.ARGUMENT_ERROR
280280
);
@@ -329,14 +329,14 @@ export async function _verifyPhoneNumber(
329329
authInstance: AuthInternal,
330330
request: StartPhoneMfaSignInRequest
331331
) => {
332-
// If reCAPTCHA Enterprise token is empty or "NO_RECAPTCHA", fetch v2 token and inject into request.
332+
// If reCAPTCHA Enterprise token is empty or "NO_RECAPTCHA", fetch reCAPTCHA v2 token and inject into request.
333333
if (
334334
!request.phoneSignInInfo.captchaResponse ||
335335
request.phoneSignInInfo.captchaResponse.length === 0 ||
336336
request.phoneSignInInfo.captchaResponse === FAKE_TOKEN
337337
) {
338338
_assert(
339-
verifier.type === RECAPTCHA_VERIFIER_TYPE,
339+
verifier?.type === RECAPTCHA_VERIFIER_TYPE,
340340
authInstance,
341341
AuthErrorCode.ARGUMENT_ERROR
342342
);
@@ -380,14 +380,14 @@ export async function _verifyPhoneNumber(
380380
authInstance: AuthInternal,
381381
request: SendPhoneVerificationCodeRequest
382382
) => {
383-
// If reCAPTCHA Enterprise token is empty or "NO_RECAPTCHA", fetch v2 token and inject into request.
383+
// If reCAPTCHA Enterprise token is empty or "NO_RECAPTCHA", fetch reCAPTCHA v2 token and inject into request.
384384
if (
385385
!request.captchaResponse ||
386386
request.captchaResponse.length === 0 ||
387387
request.captchaResponse === FAKE_TOKEN
388388
) {
389389
_assert(
390-
verifier.type === RECAPTCHA_VERIFIER_TYPE,
390+
verifier?.type === RECAPTCHA_VERIFIER_TYPE,
391391
authInstance,
392392
AuthErrorCode.ARGUMENT_ERROR
393393
);
@@ -421,7 +421,7 @@ export async function _verifyPhoneNumber(
421421
return response.sessionInfo;
422422
}
423423
} finally {
424-
verifier._reset();
424+
verifier?._reset();
425425
}
426426
}
427427

0 commit comments

Comments
 (0)