Skip to content

fix(auth,app-check): Fix Auth/AppCheck ReCAPTCHA Enterprise conflict#9991

Draft
hsubox76 wants to merge 7 commits into
mainfrom
ch-appcheck-fix2
Draft

fix(auth,app-check): Fix Auth/AppCheck ReCAPTCHA Enterprise conflict#9991
hsubox76 wants to merge 7 commits into
mainfrom
ch-appcheck-fix2

Conversation

@hsubox76
Copy link
Copy Markdown
Contributor

@hsubox76 hsubox76 commented May 21, 2026

Fixes #9405

App Check and Auth (when using phone number verification) do not work when both are using ReCAPTCHA Enterprise in the same app. It causes an Auth error.

This bug was caused by two issues, one in Auth and one in App Check.

Auth

The Auth SDK was detecting (with isEnterprise()) if a window.grecaptcha.enterprise object existed on the page, and if so, did not download the ReCAPTCHA Enterprise (abbreviated RCE from here on out) script, assuming it was ready to use. Unfortunately, this check passes if it sees the ReCAPTCHA Enterprise instance downloaded by App Check (or any other source), which is not sufficient for Auth. In order for RCE to work the way Auth is set up to use it, Auth needs to initiate its own script download with the "render" param set to the user's RCE sitekey.

Auth needs to know when this script is ready (it has both finished downloading, AND has initialized) before it can call grecaptcha.execute(), or there will be an error (as in the issue linked above). It turns out that grecaptcha.ready() is not reliable when more than one RCE script is being loaded on the page, as it fires when any script is ready, even though the one you are calling execute on may not be ready. script.onload on the script tag used to download the script also isn't reliable, as there is a small delay between the download of the script and when it finishes its initialization on the page.

The one event that does seem reliable is a callback which must be placed on the global window namespace, and its name passed to the onload url param of the recaptcha script download url (not to be confused with script.onload on the script tag).

To track this, I have added a new static property: RecaptchaEnterpriseVerifier.scriptInjectionDeferred, a deferred object (a promise that can be resolved from outside). This deferred object is resolved when window.onFirebaseAuthREInstanceReady() (the new callback we create and pass to the onload url param) is called. Calls to retrieveRecaptchaToken() (which calls execute()) now await the resolution of this promise.

Auth tests

Auth tests needed to be changed as almost all of them now call loadJS, which won't work in a test environment. loadJS has been stubbed in all relevant tests, and the stub calls window.onFirebaseAuthREInstanceReady() to ensure the deferred is resolved and the code can continue.

Also fixed an async test that was incorrect and did not await its result, causing a race condition with the next test.

App Check

App Check does not include the sitekey in the url for downloading the RCE script, as part of its design to allow multiple sitekeys. Instead, it manually renders a widget. When you do this, you are supposed to set a render=explicit param on the url, which we didn't. It still worked by itself, but caused this clash with Auth.

When both of these changes are made, Auth and App Check both work together.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 21, 2026

🦋 Changeset detected

Latest commit: 1f9ee8d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@firebase/app-check Patch
@firebase/auth Patch
@firebase/app-check-compat Patch
firebase Patch
@firebase/auth-compat Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses a conflict between Auth and App Check when both utilize ReCAPTCHA Enterprise by ensuring the script is loaded with the render=explicit parameter in App Check and tracking the injection state in Auth. The reviewer identified a performance regression where the injection flag was defined as an instance property rather than a static one, leading to redundant script loads across multiple verifier instances. Feedback was also provided to ensure this static state is properly reset between tests to maintain isolation.

Comment thread packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts Outdated
Comment thread packages/auth/src/platform_browser/recaptcha/recaptcha_enterprise_verifier.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Invalid site key or not loaded in api.js when firebase initializeAppCheck with ReCaptchaEnterpriseProvider

1 participant