9 JavaScript Applications

If you develop JavaScript-based mobile apps, you can use the client SDK that Oracle Mobile Cloud Service (MCS) provides for JavaScript. This SDK simplifies authentication with MCS and provides JavaScript wrapper classes for MCS platform APIs.

This SDK is primarily geared toward browser-based apps but can also be used for hybrid frameworks. If you develop Cordova-based apps, use the Cordova SDK. See Cordova Applications.

Getting the SDK for JavaScript

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

Contents of the JavaScript SDK Bundle

The JavaScript 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 Sync Express library.

  • 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 Sync Express library.

  • oracle_mobile_cloud_config.js - The MCS configuration file. In this file, you insert environment and authentication details for the mobile backends that your app will access.

  • \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 JavaScript App

  1. If you haven’t already done so, unzip the JavaScript 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 backend details in oracle_mobile_cloud_config.js.

Configuring SDK Properties for JavaScript

To use the SDK in a JavaScript app, you need to add the oracle_mobile_cloud_config.js configuration file to the app and fill it in with environment details for your mobile backend. In turn, 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.

You 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"
        },
      }
    }
  }
};

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.

  • 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 in MCS.

  • 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.

  • 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, or tokenAuth. The contents of the object depend on the type of authentication.

HTTP Basic

For HTTP Basic, you need to nest an basicAuth object within the authorization object and fill in the HTTP Basic credentials provided by the mobile backend. The resulting authorization property might look something like this:

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

OAuth Consumer

For OAuth, you need to nest an oAuth 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": {
  "oAuth": {
    "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",
  }
}

Loading a Mobile Backend's Configuration into a JavaScript App

For any calls to MCS APIs using the JavaScript 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 transactions between your application and its associated mobile backend, including calls to platform APIs and any custom APIs you have defined.

Using mobileBackendManager.setConfig, you specify a configuration that is defined 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 establish the mobile backend and retrieve data from the oracle_mobile_cloud_config.js file.

mcs.mobileBackendManager.platform = new mcs.BrowserPlatform();
mcs.mobileBackendManager.setConfig(mcs_config);

this.backend = mcs.mobileBackendManager.getMobileBackend("YOUR_BACKEND_NAME");

Authenticating and Logging In Using the SDK for JavaScript

Here are some examples of how to use the Authorization class of the JavaScript SDK in your code.

OAuth and HTTP Basic

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

function initializeMCS(){
  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 a user name and password.

function login(username, password){
  var deferred = $q.defer();
  mcsBackend.Authorization.authenticate(username, password, success, failed);

  return deferred.promise;

  function success(response,data){
    deferred.resolve();
    logAnalyticsEvent();
  }

  function failed(statusCode,data){
    deferred.reject();
  }
}

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, see Third-Party SAML and JWT Tokens.

Note:

Third-party token exchange requires the pako JavaScript library, so make sure to add it to your app. Pako is distributed with the SDK in the \pako subdirectory.

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

function initializeMCS(){
  mcs.mobileBackendManager.platform = new mcs.JSPlatform();
  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.

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

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 JavaScript

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 class in the JavaScript SDK is the mcs.mobileBackendManager. An instance of mcs.mobileBackendManager manages one or moremobileBackend 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).

It retrieves the information it needs about each mobile backend (such as the mobile backend name and authentication information) from the app’s oracle_mobile_cloud_config.js file.

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){
    //create new Storage object and set its name and payload
    var obj = new mcs.StorageObject(collection);
    obj.setDisplayName("JSFile.txt");
    obj.loadPayload("Hello World from Oracle Mobile Cloud Service Javascript SDK", "text/plain");

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

function getCollection(){
  var deferred = $q.defer();

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

  return deferred.promise;

  function onGetCollectionSuccess(collection){
    deferred.resolve(collection);
  }

  function onGetCollectionFailed(statusCode, headers, data){
    deferred.reject(statusCode);
  }
}

function postObject(collection, obj){
  var deferred = $q.defer();

  //post an object to the collection
  collection.postObject(obj, onPostObjectSuccess, onPostObjectFailed);

  return deferred.promise;

  function onPostObjectSuccess(object){
    deferred.resolve(object);
  }

  function onPostObjectFailed(statusCode, headers, data){
    deferred.reject(statusCode);
  }
}

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

Avoiding Unsafe Header Errors

When you have JavaScript web apps that call the Storage APIs, you need to set the Security_ExposeHeaders policy to allow headers returned by these APIs to be accessed by the browser. For example, setting the value of that policy to the following would allow you to use all Storage API endpoints:

*.*.Security_ExposeHeaders=Oracle-Mobile-Created-By,Oracle-Mobile-Created-On,Oracle-Mobile-Modified-By,Oracle-Mobile-Modified-On,Accept-Encoding,Oracle-Mobile-Name,ETag

For instructions on setting policies, see Environment Policies.

Calling Custom APIs Using the SDK for JavaScript

The SDK provides the CustomCode class to simplify the calling of custom APIs in MCS. You can use this class to 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 make a call to a custom API endpoint, you could use something like this:

mcs.mobileBackendManager.setConfig(mcs_config);
backend = mcs.mobileBackendManager.getMobileBackend("JSBackend");
.....
  
backend.CustomCode.invokeCustomCodeJSONRequest("TaskApi1/tasks/100" , "GET" , null, function(statusCode, data){
  mcs._Logger.log(mcs.LOG_LEVEL.INFO, statusCode);
  //The statusCode parameter returns the status code from the HTTP REST Call.
  mcs._Logger.log(mcs.LOG_LEVEL.INFO, data);
  //The data parameter is the HTTP payload from the server, if available, or an error message.
    Example:
      statusCode: 200,
      data: {}
      //Depends on the response format defined in the API.
}, 
function(statusCode, data){
  mcs._Logger.log(mcs.LOG_LEVEL.INFO, statusCode);
  //The statusCode parameter returns the status code from the HTTP REST Call.
  mcs._Logger.log(mcs.LOG_LEVEL.INFO, data);
  //The data parameter is the HTTP payload from the server, if available, or an error message. 
    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 JSApi2 in Mobile Backend JSBackend(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/JSApi2/tasks" }
        //Depends on the response format defined in the API.
  });