8 Cordova Applications

If you develop hybrid apps based on the Apache Cordova framework, you can use the client SDK that Oracle Mobile Cloud Service (MCS) provides for Cordova. This SDK simplifies authentication with MCS and provides Cordova wrapper classes for MCS platform APIs as well as libraries for Data Offline and Sync and Sync Express.

If you are new to Cordova itself and still need to set it up on your system, you can follow the Getting Started with JET Hybrid Apps tutorial for an end-to-end look at creating a Cordova app and connecting it with a mobile backend.

Note:

This SDK supports Cordova apps for the iOS and Android platforms. Apps for Microsoft Windows are not supported.

Getting the SDK for Cordova

To get the MCS client SDK for Cordova, go to the Oracle Technology Network’s MCS download page.

Contents of the Cordova SDK Bundle

The Cordova SDK contains the following items:

  • jsdocs.zip — The compiled documentation for the library.

  • mcs.js — The uncompressed version of the SDK. This version contains code comments and is best used as you are developing and debugging your app.

  • mcs.sync.js — The uncompressed version of the SDK Data Offline and Sync and Sync Express libraries.

  • mcs.min.js — The compressed version of the SDK. Use this version when you deploy the completed app.

  • mcs.sync.min.js — The compressed version of the SDK Data Offline and Sync and Sync Express libraries.

  • oracle_mobile_cloud_config.js — An MCS configuration file, in which you can insert environment and authentication details for the mobile backends that your app will access.

  • oracle_mobile_js_sdk_cookies_cordova_plugin[VERSION].zip — A Cordova plugin that’s necessary if you are developing Cordova apps that authenticate with MCS via SSO.

  • \pako — This folder includes the pako JavaScript library, which is required to use SSO with a third-party token.

  • mcs-tools.zip - The MCS Custom Code Test Tools, a set of command line tools for debugging custom APIs that you have associated with your app's mobile backend. Detailed instructions are located in the README file included in the zip.

Adding the SDK to a Cordova App

  1. If you haven’t already done so, unzip the Cordova SDK zip.
  2. Copy mcs.min.js and oracle_mobile_cloud_config.js into the directory where you keep your JavaScript libraries.
  3. Fill in your mobile backend details in oracle_mobile_cloud_config.js. See Configuring SDK Properties for Cordova.
  4. If you will be using SSO or Facebook authentication in your apps, add the Cordova inappbrowser to your project:
    cordova plugin add cordova-plugin-inappbrowser -save
  5. If you will be using SSO in your apps, install the oracle_mobile_js_sdk_cookies_cordova_plugin plugin:
    1. Unzip oracle_mobile_js_sdk_cookies_cordova_plugin[VERSION].zip.
    2. At the command line, type:
      cordova plugin add <PLUGIN_FOLDER>

      where <PLUGIN_FOLDER> is the path to the unpacked plugin.

  6. Load mcs.min.js in your app using RequireJS or a HTML script tag.

    Note:

    In addition to mcs.min.js, if your app uses Sync Express, mcs.sync.min.js must be fetched and executed as the first script in the main page of your app, before any other script, including RequireJS. For detailed instructions on adding Sync Express to your app, see Building Apps that Work Offline Using Sync Express.

Configuring SDK Properties for Cordova

To use the SDK in a Cordova app, add the oracle_mobile_cloud_config.js configuration file to the app and fill it in with environment details for your mobile backend. The SDK classes draw on this file for the details needed to access the mobile backend and use them to construct HTTP headers for REST calls made to APIs.

Note:

If any of your apps will be browser-based, you need to manage cross-origin resource sharing (CORS) for access to MCS APIs. See Securing Browser-Based Apps Against Cross-Site Request Forgery Attacks.

Package the configuration file in the same folder as the mcs.min.js file.

The following example shows the structure of a generic oracle_mobile_cloud_config.js file:

var mcs_config = {
  "logLevel": mcs.LOG_LEVEL.INFO,
  "logHTTP": true,
  "mobileBackends": {
    "YOUR_BACKEND_NAME": {
      "default": true,
      "baseUrl": "YOUR_BACKEND_BASE_URL",
      "applicationKey": "YOUR_BACKEND_APPLICATION_KEY",
      "authorization": {
        "basicAuth": {
          "backendId": "YOUR_BACKEND_ID",
          "anonymousToken": "YOUR_BACKEND_ANONYMOUS_TOKEN"
        },
        "oAuth": {
          "clientId": "YOUR_CLIENT_ID",
          "clientSecret": "YOUR_ClIENT_SECRET",
          "tokenEndpoint": "YOUR_TOKEN_ENDPOINT"
        },
        "facebookAuth":{
          "facebookAppId": "YOUR_FACEBOOK_APP_ID",
          "backendId": "YOUR_BACKEND_ID",
          "anonymousToken": "YOUR_BACKEND_ANONYMOUS_TOKEN"
        },
        "ssoAuth":{
          "clientId": "YOUR_CLIENT_ID",
          "clientSecret": "YOUR_CLIENT_SECRET",
          "tokenEndpoint": "YOUR_TOKEN_ENDPOINT"
        },
        "tokenAuth":{
          "backendId": "YOUR_BACKEND_ID"
        }
      }
    }
  },
  "syncExpress": {
    "handler": "OracleRestHandler",
    "policies": [
      {
        "path": '/mobile/custom/firstApi/tasks/:id(\\d+)?',
      },
      {
        "path": '/mobile/custom/secondApi/tasks/:id(\\d+)?',
      }
    ]
  }
};

Here’s a list of the file’s elements. The values that you need to fill in for a given mobile backend can be found on the Settings and Clients pages for that mobile backend. For details on sync elements, see Building Apps that Work Offline Using Sync Express.

  • logLevel — Determines how much SDK logging is displayed in the app’s console. The default value is mcs.LOG_LEVEL.INFO (where only important events are logged). Other possible values are mcs.LOG_LEVEL.ERROR (only errors are logged) and mcs.LOG_LEVEL.VERBOSE.

  • logHTTP — When set to true, enables additional logging capability that includes the complete HTTP headers and body in requests and responses to MCS.

  • mobileBackends — The config file’s root element, containing a JSON object for each mobile backend.

  • baseUrl — The URL your app uses to connect to its mobile backend.

  • applicationKey — The application key, which is a unique string assigned to your app when you register it as a client in MCS. See Registering an App as a Client in MCS.

  • authorization — JSON object containing the authentication details for connecting your app to MCS. In turn, it must contain one or more objects of type basicAuth, oAuth, ssoAuth, tokenAuth or facebookAuth. The contents of the object depend on the type of authentication.

OAuth Consumer

For OAuth, nest an oAuth object within the authorization object and fill in the OAuth credentials provided by the mobile backend.
  • clientID — The unique client identifier assigned to all apps when they’re first created in your mobile backend.

  • clientSecret — The unique secret string assigned to all apps they’re first created in your mobile backend.

  • tokenEndpoint — The URL of the OAuth server your app goes to, to get its authentication token.

The resulting authorization property might look something like this:

"authorization": {
  "oAuth": {
    "clientID": "b20a34b4-e646-44dc-a787-3a8715f4bb46",
    "clientSecret": "chIkehuDPYsaosPEMyE2",
    "tokenEndpoint": "http://abc09xyz.oracle.com:14100/oam/oauth2/tokens",
  }
}

HTTP Basic

For HTTP Basic, nest a basicAuth object within the authorization object and fill in the HTTP Basic credentials provided by the mobile backend.
  • backendId — The unique identifier assigned to a specific mobile backend.

  • anonymousToken — A unique string that allows your app to access APIs that don’t require login. In this scenario, the anonymous key is passed to MCS instead of an encoded user name and password combination.

The resulting authorization property might look something like this:

"authorization": {
  "basicAuth": {
    "backendId": "3b113ad5-07dc-4143-8b6a-a2ef62a175c1",
    "anonymousToken": "UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOnZrZWJxUmwuamEwbTdu"
  }
}

SSO

For SSO, nest an ssoAuth object within the authorization object and fill in the OAuth credentials provided by the mobile backend. The resulting authorization property might look something like this:

"authorization": {
  "ssoAuth": {
    "clientID": "b20a34b4-e646-44dc-a787-3a8715f4bb46",
    "clientSecret": "chIkehuDPYsaosPEMyE2",
    "tokenEndpoint": "http://abc09xyz.oracle.com:14100/oam/oauth2/tokens",
  }
}

SSO with a Third-Party Token

For SSO with a third-party token, nest a tokenAuth object within the authorization object and fill in credentials, depending on how you have the token issuer integrated with MCS.

If you are using JWT tokens and have integrated the token issuer by registering a configuration via a policy in MCS, you need to include the mobile backend ID and the OAuth credentials for the backend. The resulting authorization property might look something like this:
"authorization": {
  "tokenAuth": {
    "backendId": "3b113ad5-07dc-4143-8b6a-a2ef62a175c1",
    "clientId": "b20a34b4-e646-44dc-a787-3a8715f4bb46",
    "clientSecret": "chIkehuDPYsaosPEMyE2"  }
}
If you have integrated the IdP token issuer by uploading certificates into MCS you just nest the mobile backend ID. The resulting authorization property might look something like this:
"authorization": {
  "tokenAuth": {
    "backendId": "3b113ad5-07dc-4143-8b6a-a2ef62a175c1",
  }
}

Facebook

For Facebook login, nest a facebookAuth object within the authorization object, fill in the HTTP Basic credentials provided by the mobile backend, and add the facebookAppId. The resulting authorization property might look something like this:

"authorization": {
  "basicAuth": {
    "backendId": "3b113ad5-07dc-4143-8b6a-a2ef62a175c1",
    "anonymousToken": "UFJJTUVfREVDRVBUSUNPTl9NT0JJTEVfQU5PTllNT1VTX0FQUElEOnZrZWJxUmwuamEwbTdu",
    "facebookAppId": "123456789012"
  }
}

Loading a Mobile Backend's Configuration in a Cordova App

For any calls to MCS APIs using the Cordova SDK to successfully complete, you need to have the mobile backend’s configuration loaded. You do this using the mobileBackendManager and mobileBackend objects.

The root object in the SDK is the mcs.mobileBackendManager. The mcs.mobileBackendManager object manages one or more mobileBackend objects. A mobileBackend object is used to manage connectivity, authentication, and other interactions between your application and its associated mobile backend, including calls to platform APIs and any custom APIs you have defined.

Use mobileBackendManager.setConfig to specify a configuration, defined in a local JavaScript object or in the app’s oracle_mobile_cloud_config.js file. This configuration includes info such as the mobile backend name and version, base URL, and authentication details.

Here’s some code you can insert into the app class to retrieve data from the oracle_mobile_cloud_config.js file:

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
  mcs.mobileBackendManager.setConfig(mcs_config);
  backend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");
  if(backend != null){
    backend.setAuthenticationType("oAuth");
  }
}

Authenticating and Logging In Using the SDK for Cordova

Here are some examples of using the Cordova SDK’s Authorization class.

OAuth and HTTP Basic

Get the mobile backend and set the authentication type to oAuth (or basicAuth).

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
  mcs.mobileBackendManager.setConfig(mcs_config);
  mcsBackend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");
  if(mcsBackend != null){
    mcsBackend.setAuthenticationType("oAuth");
  }
}

Then add a function that calls Authorization.authenticate and pass it the MCS mobile backend and a user name and password.

function login(username, password){
  return mcsBackend
    .authorization
    .authenticate(username, password)
    .then(succeed)
    .catch(failed);

  function succeed(response){
    logAnalyticsEvent();
    console.log(response.statusCode + " with message: " + response.data);
    return response;
  }

  function failed(response){
    console.log(response.statusCode + " with message: " + response.data);
    return response;
  }
}

SSO

Get the mobile backend and set the authentication type to ssoAuth.

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
  mcs.mobileBackendManager.setConfig(mcs_config);
  mcsBackend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");
  if (mcsBackend != null) {
    mcsBackend.setAuthenticationType("ssoAuth");
  }
},

Then add a function that calls Authorization.authenticate.

function ssoLogin() {
  mcsBackend.authorization.authenticate().then(
    function (response) {
      console.log(response.statusCode + " with message: " + response.data);
    }).catch(
    function (response) {
      console.log(response.statusCode + " with message: " + response.data);
    });
}

SSO with a Third-Party Token

To use SSO with a third-party token, first your app needs to get a token from the third-party token issuer. The way you can obtain the token varies by issuer. For detailed information on obtaining third-party tokens and configuring identity providers in MCS, seeThird-Party SAML and JWT Tokens.

Get the mobile backend and set the authentication type to tokenAuth.

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
  mcs.mobileBackendManager.setConfig(mcs_config);
  mcsBackend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");
  if (mcsBackend != null) {
    mcsBackend.setAuthenticationType("tokenAuth");
  }
},

Then pass the token you got from the third-party token issuer to a function that calls Authorization.authenticate.

function ssoLoginToken() {
  mcsBackend.Authorization.authenticate(thirdPartyToken).then(
    function() {
      console.log("MCS authenticate() worked");
     }
   ).catch(
     function() {
       console.log("MCS authenticate() FAILED");
     });
}

Facebook

Get the mobile backend and set the authentication type to facebookAuth.

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
  mcs.mobileBackendManager.setConfig(mcs_config);
  mcsBackend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");
  if (mcsBackend != null) {
    mcsBackend.setAuthenticationType("facebookAuth");
},

Then add a function that calls Authorization.authenticate.

function facebookLogin() {
  mcsBackend.authorization.authenticate().then(
    function (response) {
      console.log(response.statusCode + " with message: " + response.data);
    }).catch(
    function (response) {
      console.log(response.statusCode + " with message: " + response.data);
    });
}

Setting Up a Cordova App for FCM or GCM Notifications

If you want to use Firebase Cloud Messaging (FCM) or Google Cloud Messaging (GCM) in a Cordova app, follow the instructions below.

For more information on using notifications in MCS, see Notifications.

FCM

These steps configure a Cordova app to use Firebase Cloud Messaging (FCM).
  1. Create a project in Firebase. Record the Server Key and Sender ID (Project Number), and download the google-service.json file. For details on setting up a Firebase project, see Set Up a Firebase Cloud Messaging Client App on Android on Google’s developer site.

  2. Create a client for your mobile app and configure notifications profile(s) by entering the credentials you got in step 1. See Client Management.

  3. Copy the google-service.json file you downloaded in step 1 to the root of your project, typically app/.

  4. Add following lines to the application config.xml in the platform tag for Android:
    • cordova-android 7.0 or above:
      <platform name="android">
      	<resource-file src="google-services.json" target="app/google-services.json" />
      </platform>
    • cordova-android 6.x or earlier:
      <platform name="android">
      	<resource-file src="google-services.json" target="google-services.json" />
      </platform>
  5. Add the phonegap-plugin-push Cordova plugin to your application.
    cordova plugin add phonegap-plugin-push
  6. From the application code, after the device ready event, register the device.
    const push = PushNotification.init({
            android: { }
          });
    
          push.on('registration', (data) => {
            backend.notifications.registerForNotifications(data.registrationId, appId, appVersion, 'FCM');
          });
    
          push.on('notification', (data) => {
            // data.message,
            // data.title,
            // data.count,
            // data.sound,
            // data.image,
            // data.additionalData
           console.log(data);
          });
    
          push.on('error', (e) => {
            console.error(e.message);
          });
          function success(data) {
            console.log('Registered successfully');
          }
  7. For next steps and more information, see Setting Up Android Notifications and Sending Notifications to and from Your App.

GCM

These steps configure a Cordova app to use Google Cloud Messaging (GCM).

Note:

Google Cloud Messaging (GCM) is being phased out, so new apps should be configured with FCM.
  1. Open your project in Google console and record the API Key and Sender ID (Project Number).

  2. Create a client for your mobile app and configure notifications profile(s) by entering the credentials you got in step 1. See Client Management.

  3. Add the phonegap-plugin-push Cordova plugin to your application.
    cordova plugin add phonegap-plugin-push@v1.9.0 --variable SENDER_ID="SENDER_ID_FROM_FIRST_STEP"
  4. From the application code, after the device ready event, register the device.
    const push = PushNotification.init({
            android: {
                senderID: "SENDER_ID_FROM_FIRST_STEP"
            }
          });
    
          push.on('registration', (data) => {
            backend.notifications.registerForNotifications(data.registrationId, appId, appVersion, 'GCM');
          });
    
          push.on('notification', (data) => {
            // data.message,
            // data.title,
            // data.count,
            // data.sound,
            // data.image,
            // data.additionalData
           console.log(data);
          });
    
          push.on('error', (e) => {
            console.error(e.message);
          });
          function success(data) {
            console.log('Registered successfully');
          }
  5. For next steps and more information, see Setting Up Android Notifications and Sending Notifications to and from Your App.

Securing Browser-Based Apps Against Cross-Site Request Forgery Attacks

If any of your apps will be browser-based, you need to manage cross-origin resource sharing (CORS) for access to MCS APIs to protect against Cross-Site Request Forgery (CSRF) attacks. Do this by setting the Security_AllowOrigin environment to either disallow (the default value) or to a comma-separated whitelist of trusted URLs from which cross-site requests can be made. For more information and details on how to use the wildcard character (*), see Securing Cross-Site Requests to MCS APIs.

Note:

For convenience, during the development of a browser-based application or during testing of a hybrid application running in the browser, you can set Security_AllowOrigin to http://localhost:[port], but be sure to update the value in production.

Calling Platform APIs Using the SDK for Cordova

Once you include the SDK libraries in your application, and adjust configuration settings, you’re ready to use the SDK classes in your apps.

The root object in the Cordova SDK is the mcs.mobileBackendManager. An instance of mcs.mobileBackendManager manages one or more mobileBackend objects. A mobileBackend object is used to manage connectivity, authentication, and other transactions between your application and its associated mobile backend, including calls to platform APIs and any custom APIs you have defined. In turn, a mobileBackend instance manages instances of ServiceProxy. These instances correspond to platform services in MCS (for example, Analytics, Notifications, Offline Data, and so on).

Here’s an example of how you could use these classes to get a Storage collection in the mobile backend, create a storage object (in this case, a text file), and then upload that object to the collection. The code here manages calls to the Storage API, including the constructing of the HTTP headers with the mobile backend credentials necessary to access the API:

var backend;
var collection_id = 'YOUR_STORAGE_COLLECTION_NAME';

function uploadTextFile() {

  return getCollection()
    .then(success);

  function success(collection){
    var obj = new mcs.StorageObject(collection);
    obj.setDisplayName("JSFile.txt");
    obj.loadPayload("Hello World from Oracle Mobile Cloud Service Cordova SDK", "text/plain");

    return postObject(collection, obj).then(function(object){
      return readObject(collection, object.id);
    });
  }
}

function getCollection(){
  //return a storage collection with the name assigned to the collection_id variable.
  return backend
    .storage
    .getCollection(collection_id, null)
    .then(onGetCollectionSuccess)
    .catch(onGetCollectionFailed);

  function onGetCollectionSuccess(collection){
    console.log('onGetCollectionSuccess:', collection);
    return collection;
  }

  function onGetCollectionFailed(response){
    console.log('onGetCollectionFailed:', response);
    return response.statusCode;
  }
}

function postObject(collection, obj){
  return collection
    .postObject(obj)
    .then(onPostObjectSuccess)
    .catch(onPostObjectFailed);
  
  function onPostObjectSuccess(object){
    console.log('onPostObjectSuccess:', object);
    return object;
  }

  function onPostObjectFailed(response){
    console.log('onPostObjectFailed:', response);
    return response.statusCode;
  }
}

For more information on the individual platform APIs, see Platform APIs.

Calling Custom APIs Using the SDK for Cordova

The SDK provides the CustomCode class to simplify the calling of custom APIs in MCS. You can call a REST method (GET, PUT, POST, or DELETE) on an endpoint where the request payload is JSON or empty and the response payload is JSON or empty.

To call a custom API endpoint, you could use something like this:

mcs.mobileBackendManager.platform = new mcs.CordovaPlatform();
mcs.mobileBackendManager.setConfig(mcs_config);
backend = mcs.mobileBackendManager.getMobileBackend("CordovaJSBackend");
.....

backend.CustomCode.invokeCustomCodeJSONRequest("TaskApi1/tasks/100" , "GET" , null).then(function(response){
    //The response parameter returns the status code and HTTP payload from the HTTP REST Call.
    console.log(response);
    // Example: { statusCode: 200, data: {} }
    //Depends on the response format defined in the API.
  }).catch(function(response){
  //The response parameter returns the status code and HTTP payload, if available, or an error message, from the HTTP REST Call.
  console.log(response);
  /*
    Example:
      { statusCode: 404,
        data: {
      "type":"http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1",
        "status":404,"title":"API not found",
        "detail":"We cannot find the API cordovaJSApi2 in Mobile Backend CordovaJSBackend(1.0). Check that this Mobile Backend is associated with the API.",
        "o:ecid":"005Bojjhp2j2FSHLIug8yf00052t000Jao, 0:2", "o:errorCode":"MOBILE-57926", "o:errorPath":"/mobile/custom/cordovaJSApi2/tasks" } }
   */
  //Depends on the response format defined in the API.
  });