firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.42k stars 1.43k forks source link

reCAPTCHA incompatible with restricted API keys #12256

Open johnfrancmartin opened 5 months ago

johnfrancmartin commented 5 months ago

Description

Best practices dictate restricting the Firebase API key to the bundle IDs of your iOS app, but doing so prevents reCAPTCHA from working due to the browser not passing the bundle identifier (which is logical and seems intentional as the browser shouldn't spoof the iOS app).

The documentation seems to indicate we should be allowlisting the HTTP referrer:

Phone auth on iOS uses silent push notifications for client app verification. If that fails, it falls back to reCAPTCHA. This reCAPTCHA flow requires your API Key to be unrestricted or allowlisted for "${PROJECT_NAME}.firebaseapp.com".

But GCP doesn't enable allowlisting both HTTP referrers and iOS apps?

Is there no way to use a follow best practice in restricting our API key, while also supporting reCAPTCHA?

Reproducing the issue

No response

Firebase SDK Version

10.9

Xcode Version

15.2

Installation Method

Swift Package Manager

Firebase Product(s)

Authentication

Targeted Platforms

iOS

Relevant Log Output

No response

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet
```json Replace this line with the contents of your Package.resolved. ```

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
```yml Replace this line with the contents of your Podfile.lock! ```
google-oss-bot commented 5 months ago

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

rizafran commented 5 months ago

Hi @johnfrancmartin, per checking, it looks like API key restrictions must be removed in order for the reCAPTCHA to work. See #7653 for more info.

johnfrancmartin commented 5 months ago

Hi @johnfrancmartin, per checking, it looks like API key restrictions must be removed in order for the reCAPTCHA to work. See #7653 for more info.

Hm, feels a little silly, no? Could we add support for passing an alternate API key to authentication? Or is the presumption that AppCheck + unrestricted API key is the preferred solution?

weixifan commented 5 months ago

This is a great topic to cover, with some important nuances, so thank you for bringing this to my attention.

There are two kinds of API Key restrictions, and you can see both categories in the Google Cloud Console page for your API key:

  1. Application restrictions. These are a speed bump meant for filtering out simple unsophisticated attacks, such as the reported package name on Android or the reported Bundle ID on iOS; however, they are not meant to protect against the kinds of abuse that App Check is designed to protect against. If you plan on using Firebase App Check with a device and/or app attestation provider to provide such protection—such as reCAPTCHA, Play Integrity, and Apple's App Attest or DeviceCheck DCDevice tokens—we recommend not using application restrictions, as they not only give a false sense of security, but can also potentially interfere with the handshakes that are performed.
  2. API restrictions. This is very confusingly named, as it is awfully close to the overall term "API Key restrictions". These restrict which API surface your API key can access. These are strongly recommended, whether you use App Check or not. If your API key is exfiltrated, you can limit the damage it can cause by limiting the API surface it has access to. We recommend that you set it to include only the APIs this app needs to function, such as the Firebase backends your app uses (don't forget the Firebase App Check API itself, if your app uses App Check).

Of course, before adding any restriction to your API key, test it first. For example, you can test the development version of your app with a different test API key. This avoids breaking your existing users if your restrictions accidentally block legitimate traffic.

To @johnfrancmartin's point, yes, it would be more correct to use a separate API key to call attestation providers since they are at a lower level in the stack. After all, attestation providers are meant to be callable by anyone wishing to prove their validity, so it is incorrect to protect those calls with application restrictions in the first place. On the other hand, application restrictions aren't designed to be secure against nontrivial attacks, and should not be used if your requirements demand protection against them. Thus, the much simpler way of thinking about this problem is to use device and/or app attestation providers to protect your backend interactions from abuse, and limit the APIs your API key can call.

paulb777 commented 5 months ago

Thanks for the detailed explanation @weixifan! Are there any follow up actions or should the issue be considered resolved and closed?