Search code examples
javascriptfirebasefirebase-authenticationphonegap

Firebase auth, phonegap build and the deviceready event


I would like to generate an android app from my vanilla Js code with a firebase realtime database via Phonegap online build and everything works fine except the firebase facebook/Google auth.

When I tap on the facebook login img I get the well-known location.protocol error. With Google auth the error message is "no universal links plugin installed".

The firebase docs (https://firebase.google.com/docs/auth/web/cordova#handle_the_sign-in_flow_with_the_firebase_sdk) says that "Firebase Auth depends on deviceReady event in order to determine correctly the current Cordova environment. Ensure the Firebase App instance is initialized after that event is triggered."

What does it mean exactly? Calling the firebase.InitalizeApp() function after deviceready event? Unfortunatelly, my app needs the firebase app from the beginning of the code. (The deviceready event fires, the admob plugin starts after deviceready event and it works fine.) Could anyone show me a working example of a deveiceready event-firebase app start? :)

//google auth code:
function googleAuth() {

    var provider = new firebase.auth.GoogleAuthProvider();
    provider.addScope('https://www.googleapis.com/auth/contacts.readonly');

    //firebase.auth().signInWithPopup(provider).then(function (result) {
        firebase.auth().signInWithRedirect(provider).then(function() {
            return firebase.auth().getRedirectResult();
        // This gives you a Google Access Token. You can use it to access the Google API.
        var token = result.credential.accessToken;
        // The signed-in user info.
        var user = result.user;
        // ...
    }).catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        alert(errorMessage);
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
        // ...
    });

    firebase.auth().getRedirectResult().then(function (result) {
        if (result.credential) {
            // This gives you a Google Access Token. You can use it to access the Google API.
            var token = result.credential.accessToken;
            // ...
        }
        // The signed-in user info.
        var user = result.user;
    }).catch(function (error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // The email of the user's account used.
        var email = error.email;
        // The firebase.auth.AuthCredential type that was used.
        var credential = error.credential;
        // ...
        return;
    });
}

//face auth code
function faceAuth() {

    if (!firebase.auth().currentUser) {
        // [START createprovider]
        var provider = new firebase.auth.FacebookAuthProvider();
        // [END createprovider]
        // [START addscopes]
        //provider.addScope('user_likes');
        // [END addscopes]
        // [START signin]
        //firebase.auth().signInWithRedirect(provider).then(function (result) {
        firebase.auth().signInWithPopup(provider).then(function (result) {
            // This gives you a Facebook Access Token. You can use it to access the Facebook API.
            var token = result.credential.accessToken;
            // The signed-in user info.
            var user = result.user;
            // [START_EXCLUDE]
            //document.getElementById('quickstart-oauthtoken').textContent = token;
            // [END_EXCLUDE]
        }).catch(function (error) {
            // Handle Errors here.
            var errorCode = error.code;
            var errorMessage = error.message;
            alert(errorMessage);
            // The email of the user's account used.
            var email = error.email;
            // The firebase.auth.AuthCredential type that was used.
            var credential = error.credential;
            // [START_EXCLUDE]
            if (errorCode === 'auth/account-exists-with-different-credential') {
                //alert('You have already signed up with a different auth provider for that email.');
                // If you are using multiple auth providers on your app you should handle linking
                // the user's accounts here.
            } else {
                console.error(error);
            }
            // [END_EXCLUDE]
        });
        // [END signin]
    } else {
        // [START signout]
        firebase.auth().signOut();
        // [END signout]
    }


Solution

  • After adding firebase to the project on device ready event use the following code

    var firebaseConfig = {
            apiKey: "***********8",
            authDomain: "*********.firebaseapp.com",
            databaseURL: "https://*********.firebaseio.com",
            projectId: "*********8",
            storageBucket: "",
            messagingSenderId: "000000000000",
            appId: "1:0000000000:web:a0a0a0a0a0a0a0a0"
          };
          // Initialize Firebase
          if(!firebase.apps.length){
            firebase.initializeApp(firebaseConfig);
          }
    

    This how firebase is initailized. Put the above code in device ready or not depends how firebase is access in app.

    Please follow the instructions here Firebase Auth for Cordova then come here if universal-links tag does not copy data to manifest file on android.

    I am using PhoneGap Build. The problem is Universal-links tag is not copied to AndroidManifest.xml. So the solution is

    1. Install cordova-universal-links-plugin-fix
    2. If you want to keep universal-links tag in config.xml keep it. But also add this to config.xml

    In widget tag on top add

    xmlns:android="http://schemas.android.com/apk/res/android"
    

    The add following code anywhere in config.xml I prefer before plugins or beside unvirsal-links tag

    <config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
        <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:host="****-***.firebaseapp.com" android:pathPrefix="/__/auth/callback" android:scheme="https" />
        </intent-filter>
    </config-file>
    

    Now when app is build either with phonegapbuild or local cordova CLI, it copies the universal-links data which was supposed to be in manifest file. When app runs and firebase.auth().getRedirectResult() is called it will not give any error which was something like

    auth/cancelled by user. The redirect was cancelled by user before finalizing

    User building app using cordova CLI please after running cordova build android make sure you have the above intent-filter tag under activity tag in the manifest file.