Search code examples
cordovacross-domainfacebook-javascript-sdkhybrid-mobile-app

Cordova hybrid iframe app integrate facebook login


I'm building one Web application and two hybrid Cordova applications (iOS and android) which relies on web application, i.e. Cordova app calls iframe web application and it works well.

Now, I'm stuck on Facebook login API.

FB login API is implemented and works well on Web app, but on e.g. android Cordova app, because it isn't a web app, it doesn't have a domain, hence it doesn't have any page to return to within the "site" and FB API doesn't work.

Correct me if I'm wrong!

I find this plugin: https://github.com/jeduan/cordova-plugin-facebook4 with which we can use Facebook SDK in Cordova projects.

Now, if I implement this plugin, I will need to send fb.id, fb.name and fb.email from Cordova app to my Web app and I will have a cross-domain problem then.

What to do now? Can this be done using FB login API in Web application or by using Cordova plugin and what to do with cross-domain problem?


Solution

  • Finally manage to solve the problem by:

    • using openfb micro-library (https://github.com/ccoenraets/OpenFB) in cordova project
    • to use openfb in cordova, cordova-plugin-inappbrowser plugin needed
    • after openfb login in cordova we need to use postMessage (https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) to communicate between cordova app (parent) and iframe (child) and send fb login data (for me: id, name, email).
    • in web application (iframe) need to check wheather cordova is loaded or not, and show/hide javascript fb api login buttons, status, etc.

    So let's go step-by-step:

    1. installing cordova-plugin-inappbrowser:


    2. installing openfb in cordova:

    • go to https://github.com/ccoenraets/OpenFB and pull the resources
    • copy openfb.js somewhere in your cordova www folder and link in your index page
    • copy logoutcallback.html and oauthcallback.html to cordova project www folder (root)
    • there in the openfb index.html file is a < script >. I used that script to write my own login/logout etc. methods.
    • once you call openFB.login() and response status == "connected" you can call:

    openFB.api({
            path: '/me',
            params: { fields: "name, email" },
            success: function(data) {
                fb_data.id = data.id; // used to save my fb id
                fb_data.name = data.name; // used to save my fb name
                fb_data.email = data.email; // used to save my fb email
                // select iframe content window and post cross-domain message with fb_data
                $("iframe")[0].contentWindow.postMessage(fb_data, "*");
            },
            error: errorHandler
        });

    • so we log to fb using openfb and once logged in we send cross-domain message with login data

    1. receiving cross-domain message in iframe (child) from cordova app (parent):

      • below is a receive cross-domain message handler which checks incoming cross-domain messages from cordova (parent) wheather cordova is loaded and also as well as facebook login data.

    window.addEventListener("message", receiveMessage, false);
    
            function receiveMessage(event) {
    
                var origin = event.origin || event.originalEvent.origin; // For Chrome, the origin property is in the event.originalEvent object.
    
                switch (event.data) {
                    case "cordova-not-loaded":
                        cordova_is_loaded = "no";
                        break;
                    case "cordova-is-loaded":
                        cordova_is_loaded = "yes";
                        break;
                    default:
                        if (origin == "file://") {
                            fb_data = event.data; // get facebook login data
                        }
                }
    
            }


    1. Check wheather cordova is loaded in iframe app (child)

      • send cross-domain message to cordova app (parent) to check if cordova is loaded
      • parent will send another message with requested data.
      • then create interval that listens for requested data and once recieved -> if cordova is loaded then hide all javascript login api elements on page
        (because we use javascript facebook api as a login method for web app, and if that app is used as an iframe in cordova app, then use openfb)

    function handleCordovaLoaded() {
    
            window.parent.postMessage("is-cordova-loaded", "*");
            var interval = setInterval(function() {
                if(typeof cordova_is_loaded != "undefined") {
                    clearInterval(interval);
                    // hide all parts of javascript social plugin if cordova is loaded
                    if(cordova_is_loaded == "yes") {
                        $(".all-your-facebook-elements-in-app").hide(); // hide all your javascript fb api login buttons, statuses etc.
                    }
                }
            }, 100);
    
        }


    1. receiving cross-domain message in cordova app (parent) from iframe (child)

      • as mentioned in step 4., we need to detect "is-cordova-loaded" cross-domain message from iframe (child) to cordova (parent)
      • after receiving that message send the answer back to iframe (child).

    window.addEventListener("message", receiveMessage, false);
    
        function receiveMessage(event)
        {
            var origin = event.origin || event.originalEvent.origin; // For Chrome, the origin property is in the event.originalEvent object.
            switch(event.data) {
                case "is-cordova-loaded":
                    var cordova_loaded = typeof cordova == 'undefined' ? "cordova-not-loaded" : "cordova-is-loaded";
                    $("iframe")[0].contentWindow.postMessage(cordova_loaded, "*"); // get iframe content window and send cross-domain message with cordova_loaded status
                    break;
            }
        }


    • One more thing that I didn't mentioned is checking if we are logged in web app (child). If we are not logged then check if cordova is loaded and if it is loaded then send cross-domain message that will trigger fb-login popup in cordova app.

    I hope this will help someone with the same problems.
    I will be glad to help, so please ask if anything is unclear.

    :: cheers ::

    Josip