firebase-js-sdk
firebase-js-sdk copied to clipboard
Firebase web 9 Auth incompatible with Capacitor 3
- Operating System version: ios 14.5
- Browser version: Capacitor
- Firebase SDK version: 9 beta 2
- Firebase Product: auth
[REQUIRED] Describe the problem
When getting the auth with getAuth(firebaseApp);
The app crash and the only issue I see in safari dev console is :
TypeError: undefined is not an object (evaluating 'gapi.iframes.getContext')
Relevant Code:
import { getAuth, onAuthStateChanged, signInAnonymously } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { initializeApp } from "firebase/app"
var firebaseConfig = {
apiKey: "***",
authDomain: "***",
databaseURL: "***",
projectId: "***",
storageBucket: "***",
messagingSenderId: "****",
appId: "***"
};
const firebaseApp = initializeApp(firebaseConfig);
export const user = new Promise((resolve, reject) => {
try {
const auth = getAuth(firebaseApp);
const removeListener = onAuthStateChanged(auth, user => {
// Check for user status
if (!user) {
signInAnonymously(auth);
return
}
console.log('user', user); // Will log the user object.
removeListener();
resolve(user);
});
} catch (err) {
console.error('reject', err);
reject(err)
}
})
user()
Hi @riderx -- we don't explicitly support Capacitor, nor is it on our roadmap at this time. With that said, you're running into this issue because the default getAuth()
function assumes you're in a browser context and automatically includes pieces you need to perform social login (i.e. signInWithPopup
and signInWithRedirect
). Instead, I'd suggest trying to initialize auth manually, which allows you to specifically choose your dependencies. For example:
const auth = initializeAuth(app, {
persistence: browserLocalPersistence, // This uses localStorage
});
Here is the reference docs: https://firebase.google.com/docs/reference/js/v9/auth#initializeauth
I'm not sure whether or not this will work with Capacitor, but it should at least get you past the error you linked.
@sam-gc i don't need social auth so for sure it will helps ! i got the same issue of https://github.com/firebase/firebase-js-sdk/issues/5020 now
[Log] onscript loading complete (user-script:2, line 262)
[Error] Preflight response is not successful
[Error] Fetch API cannot load https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=AIzaSyA38ipaW0j7sY34I3DiHL3AykwNNJ94aGA due to access control checks.
[Error] Failed to load resource: Preflight response is not successful (accounts:signUp, line 0)
[Warning] Ignoring Event: localhost (user-script:2, line 262)
[Error] Unhandled Promise Rejection: FirebaseError: Firebase: Error (auth/network-request-failed).
dispatchException (4.9789fcb5.chunk.js:2:798381)
(anonymous function) (4.9789fcb5.chunk.js:2:794609)
r (4.9789fcb5.chunk.js:2:188)
u (4.9789fcb5.chunk.js:2:428)
promiseReactionJob
What I don't get is I have 2 apps in store (Captime and Mimesis) on google play store and apple who worked well until few days ago, now none of them work :/
@sam-gc i'm still unable to use firebase 9 in my apps, do you if it will be fixed, and when ?
I have to know if I need to switch from firebase to something else for my mobile apps
@riderx what did you end up doing? Looks like I'll need to ditch firebase as well
I have tried both firebase 8 & 9 now. The issue exists with Capacitor 3 and iOS 14, I have not tested other versions or on Android. I don't know the root cause yet, I am sure that in the worse case you could use your own api/server and do the firebase authentication there. I truly hope it is not something related to the WebKit.
@jayordway let's hope this gets resolved :/ I'm sure there's a lot of people stuck on this. Thank you for your insight.
FIXED! Here's the solution: https://harryherskowitz.com/2021/08/23/firebase-capacitor.html
@roldyclark thanks a lot, i will try to upgrade to v9 so :)
This worked for me, but it is work elaborating that I was not able to get it to work with angularfire. I had to revert to using firebase 9 directly.
init() {
const app = initializeApp(environment.firebase);
if (Capacitor.isNativePlatform) {
initializeAuth(app, {
persistence: indexedDBLocalPersistence
});
}
this.firestore = getFirestore(app);
}
The reason I did this is because I could not find a reliable way to set the persistence properly with "indexedDBLocalPersistence" when using angularFire. It may be possible though, I will attempt once more and report back.
Ever since I started using Capacitor 3.x with Firebase 9.x compat build I cannot launch Capacitor anymore with the same error as the OP.
@sam-gc With the compat build however there is no concept of const auth = initializeAuth(app, ...
because it's the compat syntax.
Does anyone know how I can solve this issue without having to convert to the modular syntax? The reason is that some plugins I use do not yet support the modular syntax.
For the folks using v9 modular, I would also suggest trying to import getAuth
from firebase/auth/cordova
. This will also avoid the browserPopupRedirectResolver
dependency.
@mesqueeb, I will investigate. The compat layer should select the correct dependency at runtime.
@sam-gc Thank you very much. I spent all day yesterday upgrading all dependencies to V9 Modular syntax, and now my app launches. However, now I'm getting this error on Capacitor:
Failed to load resource: the server responded with a status of 404 (Not Found)
The error has to do with Firestore not being able to connect in my Capacitor app. It thinks it has no connection, but my phone definitely has internet connection.
The web version in the browser loads normally.
PS: I already use modular Firestore SDK syntax as well
Potential causes:
- Maybe some Capacitor setting that prevents internet connection? But the Capacitor
browser
plugin works fine. - Maybe some Firebase SDK issue?
Should I open a new issue for this?
See attached a screenshot of some error logs:
I definitely checked internet connection both on wifi and 4G and the phone is connected properly to the internet. The capacitor in-app browser also works. Just Firestore won't connect.
@sam-gc Update: It works when I instantiate firestore like so:
const firestore =
platform === 'web'
? getFirestore(firebaseApp)
: initializeFirestore(firebaseApp, { experimentalForceLongPolling: true })
Do you think we always will need to "ForceLongPolling" for Capacitor apps? And are there any downsides of doing this?
[[ PS: Let me know if I need to move these comments into a new issue ]]
FIXED! Here's the solution: https://harryherskowitz.com/2021/08/23/firebase-capacitor.html
I was facing an internal uncatchable auth-network-error on iOS but not on Android. This fixed it.
I am using Capacitor 3 as well.
@mesqueeb, yes please create a separate issue for the Firestore issue you're experiencing.
I will move all my apps to supabase, firebase is driving me crazy for a too long time
Fixed here: https://stackoverflow.com/a/69793220/12624390
Any solutions for non-modular syntax? I'm using AngularFire and I have the same problem (iOS only, Android works fine)
me too. AngularFire doesn't work with Capacitor on iOS :(
The real problem: firebase-js-sdk on mobile iOS assumes google API (gapi) exists on the window, even when it isn't used.
I found a work around: Mock window.gapi before using firebase auth login:
window['gapi'] = {
load: (name: string) => Promise.resolve(),
iframes: {
getContext: () => {
return {
iframe: {
contentWindow: {
postMessage: (message: any) => {
console.log("gapi iframe message:", message);
}
}
}
}
}
}
} as any;
Reposting: https://github.com/firebase/firebase-js-sdk/issues/5020#issuecomment-1116237515
It looks like the issue is Firebase incorrectly detecting the environment (see @alistairheath's comment here).
There's a check in the auth/compat
library here which checks for the URL scheme "ionic://"
, which was used by older versions of Capacitor (it's now "capacitor://"
) and if you set it back to "ionic://"
(see the config option iosScheme
) it seems to work again and doesn't attempt to load the gapi libraries.
TL;DR, in capacitor.config
set server: { iosScheme: "ionic" }
This entry contains multiple issues, including one fixed. Filed an umbrella bug to track.
Thanks @wmadden even i have left Firebase for Supabase who is more reactive. i made a fix from your comment as PR : https://github.com/firebase/firebase-js-sdk/pull/6236
in capacitor.config set server: { iosScheme: "ionic" }
The Pr is merged ! It will come soon in production !
Seeing as this issue is still open, I wanted to confirm I'm doing this correctly still, and I noticed others have recently reported recently as well: https://github.com/firebase/firebase-js-sdk/issues/6504
On the latest version of firebase (9.9.2) I did not have to change the iosScheme to "ionic" - looks like that issue was already resolved.
I got it working with this per @jayordway 's suggestion (this is the only thing I changed to get the native iOS build working as web was working fine).
Create a new function to get firebase auth
let auth: Auth;
export function getFirebaseAuth() {
if (auth) return auth;
if (Capacitor.isNativePlatform()) {
auth = initializeAuth(getApp(), { persistence: indexedDBLocalPersistence });
} else {
auth = getAuth();
}
return auth;
}
Then anywhere I would normally call getAuth() I use the new function:
e.g. when Initializing firebase
export function initFirebase() {
initializeApp(environment.firebaseConfig);
initializeFirestore(getApp(), { ignoreUndefinedProperties: true });
getFirebaseAuth().onAuthStateChanged(user => {
if (user) {
signIn(user);
} else {
signOut();
}
});
}
Yes the key is the persistence
you must do it only on native
I am running Vue 3, Pinia, Firebase 9, Cap 4, can get registering all good, signing in all good with email and google using some plugins. But ANYTHING I do to try and either getDoc() or setDoc() it just doesn't seem to work but works totally fine on web.
I am using the fixes above and still nothing, anyone else had this - driving me mad?
Thanks!
Seeing as this issue is still open, I wanted to confirm I'm doing this correctly still, and I noticed others have recently reported recently as well: #6504
On the latest version of firebase (9.9.2) I did not have to change the iosScheme to "ionic" - looks like that issue was already resolved.
I got it working with this per @jayordway 's suggestion (this is the only thing I changed to get the native iOS build working as web was working fine).
Create a new function to get firebase auth
let auth: Auth; export function getFirebaseAuth() { if (auth) return auth; if (Capacitor.isNativePlatform()) { auth = initializeAuth(getApp(), { persistence: indexedDBLocalPersistence }); } else { auth = getAuth(); } return auth; }
Then anywhere I would normally call getAuth() I use the new function:
e.g. when Initializing firebase
export function initFirebase() { initializeApp(environment.firebaseConfig); initializeFirestore(getApp(), { ignoreUndefinedProperties: true }); getFirebaseAuth().onAuthStateChanged(user => { if (user) { signIn(user); } else { signOut(); } }); }
![image](https://user-images.githubusercontent.com/105666140/186507543-aa623ca7-72b9-411f-8ffc-96fee131cbd5.png)
For Ionic 6 this is valid. Resolves the cors issue even without the mentioned scheme change for CapacitorConfig, or backend change to http native
When I use the
if (Capacitor.isNativePlatform()) { auth = initializeAuth(getApp(), { persistence: indexedDBLocalPersistence }); } else { auth = getAuth(); } return auth;
The auth on Capacitor looks totally different compared to web, in fact it has hardly any data so I am not able to get the currentUser etc.
If you log your auth on web vs capacitor are they the same?