Using OAuth2 Authentication

To use web services that require OAuth 2.0 authentication, you need to obtain an access token using one of three functions provided by the Intel® XDK. Some web services included with the Intel XDK need OAuth 2.0 authentication, such as those provided by Foursquare*, Instagram*, and Twitter*. Which functions you need to use depends on how the service will be authenticated. There are three different types of OAuth 2.0 authentication and thus three Intel XDK functions (in the helper class).

To use web services that require OAuth 2.0 authentication, you need to obtain an access token using one of three functions provided by the Intel® XDK. Some web services included with the Intel XDK need OAuth 2.0 authentication, such as those provided by Foursquare*, Instagram*, and Twitter*. Which functions you need to use depends on how the service will be authenticated. There are three different types of OAuth 2.0 authentication and thus three Intel XDK functions (in the helper class).

Parameters

Regardless of which authentication function you use, you use several parameters to obtain the service token:

 var url = {
   codeUrl: 'http://www.example.com/auth',
   tokenUrl: 'http://www.example.com/token'
 }

The url object lets the corresponding authentication function know which url(s) to call. These urls will be provided by the service, and certain services require only one url (codeUrl).

 
 var urlParams = {
   code: {
     client_id: credentials.apiKey,
     redirect_uri: params.redirect_uri,
     response_type: params.response_type
   },
   token: {
     client_secret: credentials.apiSecret,
     grant_type: 'authorization_code'
   }
 }

The urlParams object has two parts:

  • The code portion for use in both client-side and server-side OAuth authentication.
  • The token portion for use in client-side OAuth.

The code portion of urlParams has three variables that must be included:

client_id
Usually referred to as the API key given by the site, the client_id must be included to link the OAuth call to your application. Most times, this will be a part of your credentials object as the apiKey, although you can pass it as a parameter if you want.
redirect_uri
The redirect_uri is set within the app settings on the website of the service you're trying to use. To create a data binding within the Services tab, the redirect_uri must be set to the following:
'http://localhost:58889/http-services/api-explorer/iodocs/oauth2Callback'

Once you have obtained the access token and are using the data binding within your application, this redirect_uri can be changed to whatever url is best, although it will continue working with the localhost url you set it to originally. Make sure that the redirect_uri in your app and within your app settings are the same, otherwise the authentication will not work.
response_type
When using server-side authentication, set this to 'code'. When using client-side authentication, set this to 'token'. It is not used with client credential authentication.

The token portion of urlParams is only used with client-side authentication and there's only one variable and one constant:

client_secret
Whereas client_id is the API key for your application, client_secret is the API secret of that same application. Again, this is usually passed as a part of the credentials object, but you can access it however you like. For security purposes, do not hard code your application secret within the .js file for your service.
grant_type
Is always set to 'authorization_code' so there's no need to change it or pass it as a parameter.
There are multiple kinds of OAuth 2.0 authentication and different functions for each:

Server-Side - Uses Authorization Code

To use server-side authentication, call the oauth2AuthCode function:
 . . .
 helpers.oauth2AuthCode(url, urlParams)
 .then(function(token) {
   return token;
 })
 .fail(function(err){
    return err;
 });
  • If the parameters were filled in correctly, this function returns a promise with your access token.
  • Otherwise, it returns an error thrown by the service.

To use this function, set the response_type variable in urlParams.code to 'code'.

Client-Side - Uses Implicit Authentication

To use client-side authentication, call the oauth2Implicit function:
. . .
 helpers.oauth2Implicit(url.codeUrl, urlParams.code)
 .then(function(token) {
   return token;
 })
 .fail(function(err){
   return err;
 }); 

Unlike server-side authentication, implicit authentication only requires the code portion of the parameters, meaning you can omit the token portion. To use this call, the response_type variable in urlParams.code should be 'token'.

Client Credentials

Client credentials authentication is not used as frequently as server- or client-side OAuth. It also behaves differently than the other two methods.
 . . .
 helpers.oauth2CC(url, params, header)
 .then(function(token) {
   return token;
 })
 .fail(function(err){
   return err;
 }); 

The url to be passed is provided by the service like the other authentication methods, but only a single url is needed for client credentials. Usually, client credentials has a slightly different set of parameters that need to be passed, so whatever object that you pass will be the parameters that are passed in the POST call. On top of the url and params, a header string must be passed for use in the 'Authorization' header passed with the POST call.

If any of the calls require parameters not defined within urlParams, include them inside the urlParams.code portion and they will be passed in the query string along with other parameters.

Once you have gotten the access token back from the service, it is recommended that you store the token in local storage or some other way so you won't need to repeatedly call your authentication function each time you want to use a function that requires authentication. An example of these authentication methods will be given when you create a new service, along with a way to store the token in local storage.

OAuth 2.0 Example Template Code

 /* OAuth Functions */
      exports.methodA1Authenticate = function(params) {
        // var implicitUrl = 'https://www.exampleurl.com/auth?';
        var url = {
          codeUrl: 'https://www.exampleurl.com/auth?',
          tokenUrl: 'https://www.exampleurl.com/access_token?'
        };

        //parameters will vary from service to service
        /* var = implicitParams {
          client_id: credentials.apiKey,
          redirect_uri: params.redirect_uri,
          response_type: params.response_type
        } */
        var urlParams = {
          code: {
            client_id: credentials.apiKey,
            redirect_uri: params.redirect_uri,
            response_type: params.response_type
          },
          token: {
            client_secret: credentials.apiSecret,
            grant_type: 'authorization_code'
          }
        };

        //helper oauth functions return access token. check to see if service uses authentication code or implicit oauth
        //return helpers.oauth2Implicit(implicitUrl, implicitParams)
        return helpers.oauth2AuthCode(url, urlParams)
        .then(function(token){
          var db = window.localStorage;
          //'service_access_token' should be unique to each service so that multiple authenticated services can be used
          db.setItem('service_access_token', token);
          return token;
        })
        .fail(function(err){
          console.log(err);
        });
      };

      exports.authenticatedMethodA1 = function(params){
        var token = window.localStorage.getItem('service_access_token')
        if (!token) return 'Need access token before making call';

        var urlParams = $.extend({access_token: token}, params);
        var completeUrl = 'https://api.example.com/call?' +  $.param(urlParams);
        return $.ajax({
          url: completeUrl,
          type: 'GET',
          dataType: 'json'})
        .then(function(response){
          return response;
        })
        .fail(function(err){
          return err.responseText;
        });
      };

Resources

For more complete information about compiler optimizations, see our Optimization Notice.