How to get firebase App Check working with cloud firestore in a web app - firebase

I try to get App Check working in my vue.js pwa. Using the latest firebase sdk and by following steps here https://firebase.google.com/docs/app-check/web/recaptcha-provider
My api key (https://console.cloud.google.com/apis/credentials/key..) is not limited to any API restrictions. I did add some Application Restrictions on https tho including my project domains.
Everything works fine till i activate appCheck with recaptcha v3 and i get following console errors:
FirebaseError: [code=unknown]: Fetching auth token failed: AppCheck: Fetch server returned an HTTP error status. HTTP status: 403. (appCheck/fetch-status-error)
Further more the app can't get any firebase data or auth. I tried in several browsers and without any vpn stuff.
In my already installed pwa the App Check error occurs but connection to firebase still works..
Without App Check activated it both works without an issue. Also with an App Check debug token the whole thing just works. I don't understand why it breaks firebase connection even if i haven't enabled enforcement.
I appreciate any tips on how to solve this.

I found the problem i accidently left self.FIREBASE_APPCHECK_DEBUG_TOKEN = true; in my production code.
Remove this line or only use when in development envirement solved the whole problem
if (location.hostname === "localhost") {
self.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
}
I didn't expect this line to impact browsers where i haven't registered a debug token to fail with the regular appCheck but of course it doesn't make sense to use it in production anyways.

Based on your question, you want to enable Firebase App Check for Firestore with Web Application. Currently, Firestore App Check does not support it.
As per this Documentation:
Cloud Firestore support is currently available only for Android and iOS clients. If your project has a web app, don't enable Cloud Firestore enforcement until web client support is available.

I'll leave an answer for people who have problems with the setup. For the more detailed answer, you can check this question.
In short, you need to do a few steps.
Set up a firebase.
Go to how to set up app check.
Register reCAPTCHA here and add the secret_key to the Firebase console, and the site_key to your web code.
Initialize the Firebase in your code based on how to set up app check docs.
Get your debug_key and add it to your firebase console and code.
Finally, the code should look something like this:
Don't forget to save your key to a .env file or firebase.js or somewhere where you won't upload it to git.
if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
window.FIREBASE_APPCHECK_DEBUG_TOKEN = 'your_debug_token';
}
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider('your_site_key_from_register'),
// Optional argument. If true, the SDK automatically refreshes App Check
// tokens as needed.
isTokenAutoRefreshEnabled: true
});

Related

FirebaseAuthentication Plugin not updating local FireBase.Auth JS with signed in user

Background
I have an almost finished webapp already working with the following stack
Firebase
React/TypeScript
Context
I'm adding Capacitor to my WebApp so I have a native app where I can send push notifications, and have presence in App Store, Google Play Store. The application already works on its web version, so there is no rule (Real Time Database, FireStore, etc) problem, no credentials problems at all on its web version, all well tested.
Problem
I've added Authentication to my application via Firebase Authentication, which works well, and I have also connected the Native iOS version to it, as it's described in the documentation
Auth flows works fine, User/Password & Google sign up are working fine and actually triggering the methods like onIdTokenChange and OnAuthStateChange from the official Firebase Auth library, in both cases, iOS and WebApp, and also the OnAuthStateChange from the Capacitor plugin (in both clients too).
The problem is that the Firebase JS library remains somehow in a unauthenticated state, where any call to FireStore, Database, or Storage, ends up in "Permissions Denied" error (Only on iOS). Once the Token ID has changed, I can see that currentUser is NULL, and the "signed in user" is not propagating to the Firebase official library from the Capacitor Plugin.
Once I have connected the Capacitor Firebase Authentication plugin, I was expecting that the Firebase official JS library was going to be updated, I've also used Firebase Authentication with IndexedDB local persistence as follows (when being in Native) as follows:
export const Authentication = Capacitor.isNativePlatform() ? initializeAuth(FirebaseApp, {
persistence: indexedDBLocalPersistence
}) : getAuth(FirebaseApp);

Unable to call Firebase function from React.js application

I have a React.js application powered by a number of Firebase functions and real time database standing behind them. It has been working without any issue for the past 2-3 months and now I am getting a warning on the functions logs which says that:
#firebase/database: FIREBASE WARNING: {"code":"app/invalid-credential","message":"Credential implementation provided to initializeApp() via the \"credential\" property failed to fetch a valid Google OAuth2 access token with the following error: \"Failed to parse access token response: Error: Server responded with status 404.\"."}
The way I initialize firebase from my React.js application looks like this:
I have double-checked everything standing behind process.env and it seems to be as expected. The website written in React.js in hosted under the Firebase hosting.
And this is how Firebase functions connect to Admin SDK:
I am not sure what would be the issue here. Nothing has changes in the code base from our side. Not sure if Firebase changed something internally that we need to consider.
What solved the issue for me was to go to the google cloud console (where Firebase functions are also available). Then I opened one of the failing cloud functions and I navigated to
My_Function_Name/Edit/RUNTIME, BUILD AND CONNECTIONS SETTINGS/RUNTIME SERVICE ACCOUNT/
And then I noticed there that for all of my functions it was selected App Engine Default Service Account instead of Firebase Admin SDK. I never explicitly set the runtime to this option. So, when I brought it back to Firebase Admin SDK the error was gone I was able to use the application once again.

No auth information for emulated local Cloud function

I have the following setup: Vue Webapp with Hosting, Cloud Functions and Firestore.
When deploying the app to the Google Cloud, everything works. When i emulate the functions and hosting using firebase emulators:start --only functions,hosting, I can use the hosted app and cloud functions, but the authentication information from context.auth is undefined.
This works in the cloud but not in the emulator. Any ideas or solutions?
Note: I also set the admin credentials as described in the Docs.
Edit: I have a colleague that runs the emulator on windows successfully including authentication info, but I can't find any differences in the setup?!
export default class AuthGuard {
private readonly authentication: object;
public constructor(context: any) {
this.authentication = context.auth;
}
public isAuthenticated(): boolean {
console.log('this.authentication', this.authentication ); // this in undefined
if (this.authentication === undefined) {
throw new functions.https.HttpsError(
'unauthenticated',
'The request requires user authentication',
);
}
return true;
}
[Firebaser here] This is a bug in the emulators and it was fixed in version 7.16.2:
https://github.com/firebase/firebase-tools/releases/tag/v7.16.2
To update, just re-install the Firebase CLI at the latest version.
As mentioned in the official documentation Set up admin credentials in Emulator, this is an optional setting that you need to configure, in case you want to test your authentication as well.
To set up the authentication, please, follow the below steps.
Open the Service Accounts pane of the Google Cloud Console.
Make sure that App Engine default service account is selected, and use the options menu at right to select Create key.
When prompted, select JSON for the key type, and click Create.
Set your Google default credentials to point to the downloaded key:
As per the documentation indicates, this should be good for testing, since now it will be using the Admin SDK for tests. One of the examples mentioned is calling the function admin.auth().getUserByEmail(email).
Besides that, in this other below case - now from a Github issue - you can get more examples and information on how to use authentication in local emulator.
Add firebase authentication emulator to emulator suite
I would like to add as well, that as per the official documentation indicates, the Local Emulator is in Beta. So, it might be worth it to contact the Firebase support team directly, via their free support.
Let me know if the information helped you!

Firebase Phone Auth is not working in flutter app neither in iOS simulator nor in a real device

I have been trying and searching various methods to make Firebase Phone Auth to work in my flutter application. (There is an open issue talking about conflicts between Firebase Cloud Messaging & Firebase Phone Auth, but I am unsure if my issue is related to that. I do use Firebase Cloud Messaging which works perfectly fine.).
In iOS simulator, whenever I call FirebaseAuth.instance.verifyPhoneNumber, my app opens a web page for reCAPTCHA workflow, and returns back to the app. Then I see the error logs like below in verificationFailed callback. (It is expected to follow reCAPTCHA flow for iOS Simulator according to Firebase Phone Auth Doc)
flutter: Instance of 'AuthException'
flutter: {"error":{"code":403,"message":"Requests from this ios client application <empty> are blocked.","errors":[{"message":"Requests from this ios client application <empty> are blocked.","domain":"global","reason":"forbidden"}],"status":"PERMISSION_DENIED"}}
It is suspicious that error message is using <empty> as my application name, instead of my real app name (or default firebase app name which is __FIRAPP_DEFAULT), but I am unsure why that is happening.
In real iOS device, whenever I call FirebaseAuth.instance.verifyPhoneNumber, the app invokes verificationFailed callback again and I get the error with verifyPhoneNumberError as code and Token mismatch as error message. This is happening in both debug build as well as in release build.
I am using following SDK & library versions.
Flutter SDK = 1.12.13+hotfix.5
firebase_core = 0.4.3
firebase_auth = 0.15.4
firebase_messaging = 6.0.9
Has anyone been able to get Firebase Auth Phone auth working in iOS? I am stuck in this limbo state because I cannot seem to search any info online related to this. I have setup iOS APN, GoogleService-info.plist, Google Cloud Credentials multiple times so far with no luck. (Given that Firebase Cloud Messaging works perfectly fine, I doubt it is an issue with credentials or APN setup.)
Answering my own question since I figured out the root cause.
In Google Cloud Project that is connected to Firebase, I was able to find a set of API Keys that were created by Firebase.
https://console.cloud.google.com/apis/credentials
For each App you define and create in Firebase, a new API key will be auto-created in the API key section. In my case, there was one for 'iOS key (auto created by Firebase)' and another for 'Android key (auto created by Firebase)'.
Well, by default, they do not impose any restrictions and you see a yellow triangle next to the key. So I added restrictions to those keys so that they can only be useable in my app. This is done by setting Application restrictions with corresponding bundle id for iOS and another app id for Android within each API key detail page.
This restriction was actually the reason that Phone Auth has not been working in my apps. Once I reverted the change back to None, I no longer encountered Token mismatch or AuthException.
Ideally, I should restrict these API keys to my app only, but it seems like my Flutter app is unable to prove its identity/appId/bundleId to google services, and Google had been rejecting requests from my App. This must be why I was seeing Requests from this ios client application <empty> are blocked. error message.
For now, everything is working because there is no restriction, but I will need to figure out why my app and its id association is not working as expected sooner than later, so that I can add restriction back.

Using Firebase Phone number Auth with react-native

With the newly released Firebase Phone number Auth, I was wondering if it is possible to use it using the firebase JS SDK within react native. If so how?
We (react-native-firebase team) are actually working on this at the moment, see this issue: https://github.com/invertase/react-native-firebase/issues/119
Edit: this is now live and available in v3.0.0 onwards :)
Unfortunately, phone authentication does not work out of the box with react-native.
Currently, what you can do is the following:
Prerequisite, Firebase Phone auth for web depends on an app verifier interface:
https://firebase.google.com/docs/reference/js/firebase.auth.ApplicationVerifier
You can provide your own implementation for with the verify() method resolving with a reCAPTCHA token. Here is how you can do it:
User initiates phone number sign-in in your app.
You will need to open a chrome custom tab or SFSafariViewController
and redirect to a website you own which you whitelisted. You then render a firebase.auth.RecaptchaVerifier instance. You ask the user to solve the reCAPTCHA. You may also use an invisible reCAPTCHA which may not require any challenge to be presented to a user.
You then pass the reCAPTCHA response token back to your app using FDL (Firebase Dynamic Links). This guarantees that only your app can open it.
You will then provide your own implementation of the ApplicationVerifier interface which on verify() returns a promise that resolves with the reCAPTCHA token. You can now call signInWithPhoneNumber successfully in your react native app.
It requires some work but it is possible. Feel free to file a request for dedicated react native support in the Firebase Google Group forum.
You can check this example of using firebase phone auth in react-native
react-native-firebase-phone-auth
For better user experience refer to this repo https://github.com/boudlal/react-native-firebase-phone-auth and i would suggest making some changes so that the user doesn't have to complete any challenges or click i am not a robot
In Captcha.html file change the size to invisible so that token is generated in the background
var captcha = new firebase.auth.RecaptchaVerifier("captcha", {
size: "normal",
callback: function (token) {
callback(token);
},
"expired-callback": function () {
callback("");
},
});
The Captcha.html will be needed to be deployed to a server and is called via url in
react-native-webview
Style and remove unwanted text also make webview transparent by simply
style={{backgroundColor:'transparent'}}
Copy firebase config corresponding to your firebase project in the project and Captcha.html

Resources