Skip to content

Commit 3533b32

Browse files
author
renkelvin
authored
Create handleRecaptchaFlow helper method (#7666)
1 parent b592298 commit 3533b32

File tree

5 files changed

+75
-140
lines changed

5 files changed

+75
-140
lines changed

.changeset/lucky-dragons-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@firebase/auth': patch
3+
---
4+
5+
Create handleRecaptchaFlow helper method

packages/auth/src/core/credentials/email.ts

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { IdTokenResponse } from '../../model/id_token';
3131
import { AuthErrorCode } from '../errors';
3232
import { _fail } from '../util/assert';
3333
import { AuthCredential } from './auth_credential';
34-
import { injectRecaptchaFields } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
34+
import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
3535
import { RecaptchaActionName, RecaptchaClientType } from '../../api';
3636
/**
3737
* Interface that represents the credentials returned by {@link EmailAuthProvider} for
@@ -123,32 +123,12 @@ export class EmailAuthCredential extends AuthCredential {
123123
password: this._password,
124124
clientType: RecaptchaClientType.WEB
125125
};
126-
if (auth._getRecaptchaConfig()?.emailPasswordEnabled) {
127-
const requestWithRecaptcha = await injectRecaptchaFields(
128-
auth,
129-
request,
130-
RecaptchaActionName.SIGN_IN_WITH_PASSWORD
131-
);
132-
return signInWithPassword(auth, requestWithRecaptcha);
133-
} else {
134-
return signInWithPassword(auth, request).catch(async error => {
135-
if (
136-
error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`
137-
) {
138-
console.log(
139-
'Sign-in with email address and password is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.'
140-
);
141-
const requestWithRecaptcha = await injectRecaptchaFields(
142-
auth,
143-
request,
144-
RecaptchaActionName.SIGN_IN_WITH_PASSWORD
145-
);
146-
return signInWithPassword(auth, requestWithRecaptcha);
147-
} else {
148-
return Promise.reject(error);
149-
}
150-
});
151-
}
126+
return handleRecaptchaFlow(
127+
auth,
128+
request,
129+
RecaptchaActionName.SIGN_IN_WITH_PASSWORD,
130+
signInWithPassword
131+
);
152132
case SignInMethod.EMAIL_LINK:
153133
return signInWithEmailLink(auth, {
154134
email: this._email,

packages/auth/src/core/strategies/email_and_password.ts

Lines changed: 15 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { _castAuth } from '../auth/auth_impl';
3636
import { AuthErrorCode } from '../errors';
3737
import { getModularInstance } from '@firebase/util';
3838
import { OperationType } from '../../model/enums';
39-
import { injectRecaptchaFields } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
39+
import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
4040
import { IdTokenResponse } from '../../model/id_token';
4141
import { RecaptchaActionName, RecaptchaClientType } from '../../api';
4242

@@ -103,61 +103,15 @@ export async function sendPasswordResetEmail(
103103
email,
104104
clientType: RecaptchaClientType.WEB
105105
};
106-
if (authInternal._getRecaptchaConfig()?.emailPasswordEnabled) {
107-
const requestWithRecaptcha = await injectRecaptchaFields(
108-
authInternal,
109-
request,
110-
RecaptchaActionName.GET_OOB_CODE,
111-
true
112-
);
113-
if (actionCodeSettings) {
114-
_setActionCodeSettingsOnRequest(
115-
authInternal,
116-
requestWithRecaptcha,
117-
actionCodeSettings
118-
);
119-
}
120-
await authentication.sendPasswordResetEmail(
121-
authInternal,
122-
requestWithRecaptcha
123-
);
124-
} else {
125-
if (actionCodeSettings) {
126-
_setActionCodeSettingsOnRequest(
127-
authInternal,
128-
request,
129-
actionCodeSettings
130-
);
131-
}
132-
await authentication
133-
.sendPasswordResetEmail(authInternal, request)
134-
.catch(async error => {
135-
if (error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`) {
136-
console.log(
137-
'Password resets are protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the password reset flow.'
138-
);
139-
const requestWithRecaptcha = await injectRecaptchaFields(
140-
authInternal,
141-
request,
142-
RecaptchaActionName.GET_OOB_CODE,
143-
true
144-
);
145-
if (actionCodeSettings) {
146-
_setActionCodeSettingsOnRequest(
147-
authInternal,
148-
requestWithRecaptcha,
149-
actionCodeSettings
150-
);
151-
}
152-
await authentication.sendPasswordResetEmail(
153-
authInternal,
154-
requestWithRecaptcha
155-
);
156-
} else {
157-
return Promise.reject(error);
158-
}
159-
});
106+
if (actionCodeSettings) {
107+
_setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
160108
}
109+
await handleRecaptchaFlow(
110+
authInternal,
111+
request,
112+
RecaptchaActionName.GET_OOB_CODE,
113+
authentication.sendPasswordResetEmail
114+
);
161115
}
162116

163117
/**
@@ -318,32 +272,12 @@ export async function createUserWithEmailAndPassword(
318272
password,
319273
clientType: RecaptchaClientType.WEB
320274
};
321-
let signUpResponse: Promise<IdTokenResponse>;
322-
if (authInternal._getRecaptchaConfig()?.emailPasswordEnabled) {
323-
const requestWithRecaptcha = await injectRecaptchaFields(
324-
authInternal,
325-
request,
326-
RecaptchaActionName.SIGN_UP_PASSWORD
327-
);
328-
signUpResponse = signUp(authInternal, requestWithRecaptcha);
329-
} else {
330-
signUpResponse = signUp(authInternal, request).catch(async error => {
331-
if (error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`) {
332-
console.log(
333-
'Sign-up is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-up flow.'
334-
);
335-
const requestWithRecaptcha = await injectRecaptchaFields(
336-
authInternal,
337-
request,
338-
RecaptchaActionName.SIGN_UP_PASSWORD
339-
);
340-
return signUp(authInternal, requestWithRecaptcha);
341-
}
342-
343-
throw error;
344-
});
345-
}
346-
275+
const signUpResponse: Promise<IdTokenResponse> = handleRecaptchaFlow(
276+
authInternal,
277+
request,
278+
RecaptchaActionName.SIGN_UP_PASSWORD,
279+
signUp
280+
);
347281
const response = await signUpResponse.catch(error => {
348282
if (
349283
error.code === `auth/${AuthErrorCode.PASSWORD_DOES_NOT_MEET_REQUIREMENTS}`

packages/auth/src/core/strategies/email_link.ts

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { AuthErrorCode } from '../errors';
3232
import { _assert } from '../util/assert';
3333
import { getModularInstance } from '@firebase/util';
3434
import { _castAuth } from '../auth/auth_impl';
35-
import { injectRecaptchaFields } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
35+
import { handleRecaptchaFlow } from '../../platform_browser/recaptcha/recaptcha_enterprise_verifier';
3636
import { RecaptchaActionName, RecaptchaClientType } from '../../api';
3737

3838
/**
@@ -101,37 +101,13 @@ export async function sendSignInLinkToEmail(
101101
);
102102
}
103103
}
104-
if (authInternal._getRecaptchaConfig()?.emailPasswordEnabled) {
105-
const requestWithRecaptcha = await injectRecaptchaFields(
106-
authInternal,
107-
request,
108-
RecaptchaActionName.GET_OOB_CODE,
109-
true
110-
);
111-
setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
112-
await api.sendSignInLinkToEmail(authInternal, requestWithRecaptcha);
113-
} else {
114-
setActionCodeSettings(request, actionCodeSettings);
115-
await api
116-
.sendSignInLinkToEmail(authInternal, request)
117-
.catch(async error => {
118-
if (error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`) {
119-
console.log(
120-
'Email link sign-in is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.'
121-
);
122-
const requestWithRecaptcha = await injectRecaptchaFields(
123-
authInternal,
124-
request,
125-
RecaptchaActionName.GET_OOB_CODE,
126-
true
127-
);
128-
setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
129-
await api.sendSignInLinkToEmail(authInternal, requestWithRecaptcha);
130-
} else {
131-
return Promise.reject(error);
132-
}
133-
});
134-
}
104+
setActionCodeSettings(request, actionCodeSettings);
105+
await handleRecaptchaFlow(
106+
authInternal,
107+
request,
108+
RecaptchaActionName.GET_OOB_CODE,
109+
api.sendSignInLinkToEmail
110+
);
135111
}
136112

137113
/**

packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { Auth } from '../../model/public_types';
2828
import { AuthInternal } from '../../model/auth';
2929
import { _castAuth } from '../../core/auth/auth_impl';
3030
import * as jsHelpers from '../load_js';
31+
import { AuthErrorCode } from '../../core/errors';
3132

3233
const RECAPTCHA_ENTERPRISE_URL =
3334
'https://www.google.com/recaptcha/enterprise.js?render=';
@@ -175,6 +176,45 @@ export async function injectRecaptchaFields<T>(
175176
return newRequest;
176177
}
177178

179+
type ActionMethod<TRequest, TResponse> = (
180+
auth: Auth,
181+
request: TRequest
182+
) => Promise<TResponse>;
183+
184+
export async function handleRecaptchaFlow<TRequest, TResponse>(
185+
authInstance: AuthInternal,
186+
request: TRequest,
187+
actionName: RecaptchaActionName,
188+
actionMethod: ActionMethod<TRequest, TResponse>
189+
): Promise<TResponse> {
190+
if (authInstance._getRecaptchaConfig()?.emailPasswordEnabled) {
191+
const requestWithRecaptcha = await injectRecaptchaFields(
192+
authInstance,
193+
request,
194+
actionName,
195+
actionName === RecaptchaActionName.GET_OOB_CODE
196+
);
197+
return actionMethod(authInstance, requestWithRecaptcha);
198+
} else {
199+
return actionMethod(authInstance, request).catch(async error => {
200+
if (error.code === `auth/${AuthErrorCode.MISSING_RECAPTCHA_TOKEN}`) {
201+
console.log(
202+
`${actionName} is protected by reCAPTCHA Enterprise for this project. Automatically triggering the reCAPTCHA flow and restarting the flow.`
203+
);
204+
const requestWithRecaptcha = await injectRecaptchaFields(
205+
authInstance,
206+
request,
207+
actionName,
208+
actionName === RecaptchaActionName.GET_OOB_CODE
209+
);
210+
return actionMethod(authInstance, requestWithRecaptcha);
211+
} else {
212+
return Promise.reject(error);
213+
}
214+
});
215+
}
216+
}
217+
178218
export async function _initializeRecaptchaConfig(auth: Auth): Promise<void> {
179219
const authInternal = _castAuth(auth);
180220

0 commit comments

Comments
 (0)