Using Cognito with PhoneGap/Cordova - Part 2


Facebook Sign in with OpenFB

back to Part 1
Code for tutorial is at Github Gist



 has created a excellent lightweight library for Facebook integration with Cordova/PhoneGap. Download it fromhttps://github.com/ccoenraets/OpenFB .
After you have downloaded OpenFB, create a template PhoneGap Build application and put logoutcallback.html and oauthcallback.html in the root folder withindex.html.
Create a folder called js and put openfb.js in it.
In order to improve the way OpenFB works with PhoneGap/Cordova we need to make a couple of changes. OpenFB uses the deviceready event to identify whether the app is using PhoneGap/Cordova. For reliability I prefer to pass this directly to OpenFB on initialisation. Also the address bar is not used when the inappbrowser is opened. This means if anything goes wrong the user is presented with a blank white screen.
Open in your editor openfb.js and add a cordova parameter to the init function:


    /**
     * Initialize the OpenFB module. You must use this function and initialize the module with an appId before you can
     * use any other function.
     * @param params - init paramters
     *  appId: The id of the Facebook app,
     *  tokenStore: The store used to save the Facebook token. Optional. If not provided, we use sessionStorage.
     */
    function init(params) {
        if (params.appId) {
            fbAppId = params.appId;
            if (params.cordova!=null){
                runningInCordova = params.cordova;
            }
        } else {
            throw 'appId parameter not set in init()';
        }

        if (params.tokenStore) {
            tokenStore = params.tokenStore;
        }
    }

Also change all window.open calls to 'location=yes';


Now open your config.xml file and add the inappbrowser plugin.



    AWS Cognito Example App

    
        Example app using AWS Cognito 
    

    
        Paul Coady
    

    
    

Now lets create a simple index.html page with our login buttons and status output. This will load Jquery and the AWS Javascript SDK.

  
    AWS Cognito App
    
     
  
  
        
        
        

Next create a file app.js in the js folder. Create a self-invoking anonymous function to contain our code.
(function($){


 
})(jQuery); 
Add variables in app.js:
AWS_ACCOUNT_ID - This is your AWS account number.
COGNITO_IDENTITY_POOL_ID - You can get this from your Cognito dashboard by selecting Edit Identity Pool
IAM_ROLE_ARN - This is the IAM role created when you created your Cognito pool. You can get this from the the main Services menu - IAM - Roles - then select the role for your identity pool.
FACEBOOK_APP_ID - From the facebook app page.
var AWS_ACCOUNT_ID = 'XXXXXXXX';
var AWS_REGION = 'us-east-1';
var COGNITO_IDENTITY_POOL_ID = 'us-east-1:XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXX';
var COGNITO_IDENTITY_ID, COGNITO_SYNC_TOKEN, AWS_TEMP_CREDENTIALS; 
var cognitosync;
var IAM_ROLE_ARN = 'arn:aws:iam::XXXXXXXXX:role/Cognito_CognitoBrowserExampleAuth_DefaultRole';
var COGNITO_SYNC_COUNT;
var COGNITO_DATASET_NAME = 'TEST_DATASET';
var FACEBOOK_APP_ID = 'XXXXXXXXXXXXXX';
var FACEBOOK_TOKEN;
var FACEBOOK_USER = {
  id: '',
  first_name: '',
  gender: '',
  last_name: '',
  link: '',
  locale: '',
  name: '',
  timezone: 0,
  updated_time: '',
  verified: false 
};
var userLoggedIn = false;

var message = 'AWS Cognito Example App Loaded_____';
var errorMessage = '';

Now add some code for our button events and clearing our status areas.
function clearConsole(){
    message = "";
    $('#appConsole').html(message);
    errorMessage = "";
    $('#errorConsole').html(errorMessage);    
}

// Login button
$('#btnLogin').on('click', function (event) {
    login();
});

// Login button
$('#btnLogout').on('click', function (event) {
    logout();
});
Now lets add our call to OpenFB.init and functions for handling login, logout, revoke permissions (not used here) and getting user info. I won't go into much detail here as this is explained on the OpenFB Github. There is a call to a function getCognitoID() in the callback of getInfo() below, please comment this out for now as we will be building this later.
openFB.init({
    appId:FACEBOOK_APP_ID, 
    cordova:true
});

function login() {
    clearConsole();        
    openFB.login(
        function(response) {
            if(response.status === 'connected') {
                FACEBOOK_TOKEN = response.authResponse.token;
                message += "Connected to Facebook_____";
                $('#appConsole').text(message);
                getInfo();
            } else {
                errorMessage += 'Facebook login failed: ' + response.error + "_____";
                $('#errorConsole').text(errorMessage);
            }
        }, {scope: 'email,read_stream,publish_stream'});
}

function getInfo() {
    openFB.api({
        path: '/me',
        success: function(data) {            
            message += "Logged in with Facebook as " + data.name+"_____";
            $('#appConsole').text(message);
            getCognitoID();
        },
        error: errorHandler});
}

function logout() {
    openFB.logout(
        function() {
            message += "Logged out of Facebook_____";
            $('#appConsole').text(message);
        },
        errorHandler);
}

function revoke() {
    openFB.revokePermissions(
        function() {
            message += "Permissions revoked_____";
            $('#appConsole').text(message);                
        },
        errorHandler);
}

function errorHandler(error) {
    errorMessage += error.message;
    $('#errorConsole').text(errorMessage);
}

Now you can build and run your app. You should be able to login to Facebook.


Now that we have our Facebook session token we will use this in the next page to get our Cognito ID credentials.

Get CognitoID Credentials

Now it's time to pass our Facebook token over to Cognito. Prior to version v2.0.14 of the AWS Javascript SDK this was a difficult process involving calls to IAM and STS. A new object CognitoIdentityCredentials has greatly simplified the CognitoID credentials process by removing the need to create STS tokens and temporary IAM credentials yourself.
We are going to create a new function to get our CognitoID credentials. Open app.js in your editor and add a call to the new function getCognitoID() in the success callback of our getInfo page.
function getInfo() {
    openFB.api({
        path: '/me',
        success: function(data) {            
            message += "Logged in with Facebook as " + data.name+"_____";
            $('#appConsole').text(message);
            getCognitoID();
        },
        error: errorHandler});
}
Now lets create the function. There is a call to a function getCognitoSynToken() in the callback of AWS.config.credentials.get() below, please comment this out for now as we will be building this later.

function getCognitoID(){
  // The parameters required to intialize the Cognito Credentials object.
  var params = {
    AccountId: AWS_ACCOUNT_ID, // required
    RoleArn: IAM_ROLE_ARN,  // required
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID, // required
    Logins: {
      'graph.facebook.com': FACEBOOK_TOKEN
    }  
  };   
  // set the Amazon Cognito region
  AWS.config.region = AWS_REGION;
  // initialize the Credentials object with our parameters
  AWS.config.credentials = new AWS.CognitoIdentityCredentials(params);

  // We can set the get method of the Credentials object to retrieve
  // the unique identifier for the end user (identityId) once the provider
  // has refreshed itself
  AWS.config.credentials.get(function(err) {
    if (err){ // an error occurred
        errorMessage += "credentials.get: " + err, err.stack + "_____";
        $('#errorConsole').text(errorMessage);
        errorMessage += "AWS.config.credentials: " + JSON.stringify(AWS.config.credentials) + "_____";
        $('#errorConsole').text(errorMessage);
    }
    else{
      AWS_TEMP_CREDENTIALS = AWS.config.credentials;
      COGNITO_IDENTITY_ID = AWS.config.credentials.identityId;
      message += "Cognito Identity Id: " + COGNITO_IDENTITY_ID + "_____";
      $('#appConsole').text(message);  
      getCognitoSynToken();     
    }
  });
}

Now you can build and run your app. You should be able to login to Facebook and get your user Cognito ID.
Now that we have our Cognito ID credentials we can use this in the next page to get our CognitoSync Session Token.

Get CognitoSync Session Token

Now that we have our CognitoID credentials we can use these to access CognitoSync. First we need to use our new temporary credentials to create a CognitoSync session token.
We are going to create a new function to get our CognitoSync session token. Open app.js in your editor and add a call to the new function getCognitoSynToken() in the callback of getCognitoID().
function getCognitoID(){
  // The parameters required to intialize the Cognito Credentials object.
  var params = {
    AccountId: AWS_ACCOUNT_ID, // required
    RoleArn: IAM_ROLE_ARN,  // required
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID, // required
    Logins: {
      'graph.facebook.com': FACEBOOK_TOKEN
    }  
  };   
  // set the Amazon Cognito region
  AWS.config.region = AWS_REGION;
  // initialize the Credentials object with our parameters
  AWS.config.credentials = new AWS.CognitoIdentityCredentials(params);

  // We can set the get method of the Credentials object to retrieve
  // the unique identifier for the end user (identityId) once the provider
  // has refreshed itself
  AWS.config.credentials.get(function(err) {
    if (err){ // an error occurred
        errorMessage += "credentials.get: " + err, err.stack + "_____";
        $('#errorConsole').text(errorMessage);
        errorMessage += "AWS.config.credentials: " + JSON.stringify(AWS.config.credentials) + "_____";
        $('#errorConsole').text(errorMessage);
    }
    else{
      AWS_TEMP_CREDENTIALS = AWS.config.credentials;
      COGNITO_IDENTITY_ID = AWS.config.credentials.identityId;
      message += "Cognito Identity Id: " + COGNITO_IDENTITY_ID + "_____";
      $('#appConsole').text(message);  
      getCognitoSynToken();     
    }
  });
}
In order to get the token we must make a call to listRecords. If our dataset doesn't exist (as is the case now) it will be created automatically. We also get the sync count for the dataset which is needed later to add or change dataset records. There is a call to a function addRecord() in the callback of cognitosync.listRecords() below, please comment this out for now as we will be building this later.

function getCognitoSynToken(){
  // Other AWS SDKs will automatically use the Cognito Credentials provider
  // configured in the JavaScript SDK.
  cognitosync = new AWS.CognitoSync();
  cognitosync.listRecords({
    DatasetName: COGNITO_DATASET_NAME, // required
    IdentityId: COGNITO_IDENTITY_ID,  // required
    IdentityPoolId: COGNITO_IDENTITY_POOL_ID  // required
  }, function(err, data) {
    if (err){
      errorMessage += "listRecords: " + err, err.stack + "_____";
      $('#errorConsole').text(errorMessage); // an error occurred       
    }
    else {
      COGNITO_SYNC_TOKEN = data.SyncSessionToken;
      COGNITO_SYNC_COUNT = data.DatasetSyncCount;
      message += "listRecords: " + JSON.stringify(data) + "_____"; 
      message += "DatasetSyncCount: " + COGNITO_SYNC_COUNT + "_____";      
      $('#appConsole').text(message);       // successful response
      addRecord();         
    }
  });
}

Now you can build and run your app. You should be able to login to Facebook, create a dataset and list the records.
Now that we have our CognitoSync Session Token we can use this in the next part 3 to access the CognitoSync database and add records to the dataset.
Paul Coady CEO BackSpace Technology LLC

Providing the best value AWS certification courses and exam engines.

3 comments:

  1. Hi,
    I'm having a hard time with the login function. The inappbrowser is opening and facebook is letting me allow the app to publish etc.. but it end up by writting : Success and a securtiy warning about how dangerous is to manipulate the url.
    The problem is that the inappbrowser is never closing and I guess that the code is still waiting. Have you experienced the same issue ?
    In any case, thanks for the great tutorial, its well explicated and easy to follow.

    ReplyDelete
  2. Hi Buddy,
    I wrote this tutorial a long time ago. There are a number of better supported options for Facebook login that you can use eg https://github.com/Wizcorp/phonegap-facebook-plugin
    The process is the same, you just pass the Facebook token to Cognito as before.
    Hope this helps!

    ReplyDelete