Skip to content

Instantly share code, notes, and snippets.

@lbrenman
Last active November 9, 2016 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lbrenman/f9ae6ecaaf62a9959c3b86870b47353d to your computer and use it in GitHub Desktop.
Save lbrenman/f9ae6ecaaf62a9959c3b86870b47353d to your computer and use it in GitHub Desktop.
Setting up OAuth on API GW and Consuming OAuth secured APIs in Titanium

API GW OAUth Notes

For this workflow, I am using the API Manager Reference VM 7.5.1

OAUth Background

For the purpose of this workflow, here is what you need to know about the OAuth flow:

  • Client app needs to request an token (access and refresh) from an OAuth server using the OAuth Client ID and Secret and user login credentials
  • Then the client requests to the data APIs must pass the (access) token in the header of each requests
  • Once the (access) token expires (401 error), use the refresh token to get a new access token

Setting up OAuth in the API GW

  • You should have a published Arrow Builder app and associated Swagger for virtualizing in the API GW

  • Instead of API Key auth on your virtualized API, use OAuth and accept defaults

  • Create a new client app and enable OAuth to get a Client ID and Secret

    Client ID: 2dbf6d79-90f4-4c4d-8c16-60a1f0296daf
    Secret Key: c5230981-a818-4272-8232-ee500e5a5d45

Client Access to APIs

The client app needs to get an access token (and refresh token) as follows:

  • Use the following user to make a POST to the OAuth server at :8089/api/oauth/token

    username: regadmin
    password: changeme
  • and the following body parameters:

    client_id
    client_secret
    grant_type
    username
    password
  • for example, via curl, using:

    curl -X POST -H "Cache-Control: no-cache" -H "Postman-Token: 270e15b9-2549-ab49-f925-789bb3579e29" -H "Content-Type: application/x-www-form-urlencoded" -d 'client_id=2dbf6d79-90f4-4c4d-8c16-60a1f0296daf&client_secret=c5230981-a818-4272-8232-ee500e5a5d45&grant_type=password&username=regadmin&password=changeme' "https://10.156.68.169:8089/api/oauth/token"
  • Or using POSTMAN:

  • Sample response is shown below

    {
      "access_token": "rpn9dErdbNrX4MhMV38jBFiDVg2kgnJ3JtJbMuahh94rzTyZ5M4sqS",
      "token_type": "Bearer",
      "expires_in": 3599,
      "refresh_token": "Qm063yhdqN12qZDNfoda4Ua4YFFsM7imH3K73hmLSdziab",
      "scope": "resource.WRITE resource.READ"
    }

Now, the client can access the data API's by passing in the access token in a header:

Authorization: Bearer <access_token>

Here is a sample curl command:

curl -X GET -H "Authorization: Bearer rpn9dErdbNrX4MhMV38jBFiDVg2kgnJ3JtJbMuahh94rzTyZ5M4sqS" -H "Cache-Control: no-cache" -H "Postman-Token: 9bfce815-9566-2e1f-4987-6c95924c6fcc" "https://10.156.68.169:8065/api/account"

and in POSTMAN:

and the API response:

{
  "success": true,
  "request-id": "d77f7380-851d-4030-804d-14c078a95e03",
  "key": "accounts",
  "accounts": [
    {
      "id": "001i000000PscewAAB",
      "Name": "GenePoint",
      "Type": "Customer - Channel",
      "Phone": "(650) 867-3450"
    },
    {
      "id": "001i000000PscexAAB",
      "Name": "United Oil & Gas, UK",
      "Type": "Customer - Direct",
      "Phone": "+44 191 4956203"
    },
    ...
    {
      "id": "001i000000Pscf6AAB",
      "Name": "United Oil & Gas Corp.",
      "Type": "Customer - Direct",
      "Phone": "(212) 842-5500"
    }
  ]
}

Titanium Sample Code

POSTMAN provides a javascript XHR code snipet we can use as a starting point for our Titanium code to get a token.

Here is the Titanium code to request a token from the API GW OAuth server:

var access_token, refresh_token;

var data = "client_id=2dbf6d79-90f4-4c4d-8c16-60a1f0296daf&client_secret=c5230981-a818-4272-8232-ee500e5a5d45&grant_type=password&username=regadmin&password=changeme";

  var xhr = Ti.Network.createHTTPClient({
      onload: function onLoad() {
          Ti.API.debug("Loaded: " + this.status + ": " + this.responseText);
          var response = JSON.parse(this.responseText);
          access_token = response.access_token;
          // Ti.API.debug("access_token = "+response.access_token);
          // Ti.API.debug("refresh_token = "+response.refresh_token);
          refresh_token = response.refresh_token;
      },
      onerror: function onError() {
          Ti.API.debug("Errored: " + this.status + ": " + this.responseText);
          alert("Error reaching OAuth Token Server. Please try again later.");
      }
  });

  xhr.open("POST","https://10.156.68.169:8089/api/oauth/token");
  xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
  xhr.send(data);

Here is the Titanium code to call an API and pass the token in the header:

var xhr = Ti.Network.createHTTPClient({
    onload: function onLoad() {
        Ti.API.debug("Loaded: " + this.status + ": " + this.responseText);
        var response = JSON.parse(this.responseText);
    },
    onerror: function onError() {
        Ti.API.debug("Errored: " + this.status + ": " + this.responseText);
        alert("Error reaching API Server. Please try again later.");
    }
});

xhr.open("GET","https://10.156.68.169:8065/api/account");
xhr.setRequestHeader("Authorization", "Bearer "+access_token);
xhr.send();

Now you need to add the code to deal with expired tokens, etc...

At some point the access_token will expire and you will get a 401 reply. You can try the refresh_token against the same /api/oauth/token API and if the refresh_token was not also expired, you will get a new access_token AND refresh_token

For example, assume the tokens are retrieved via login as follows:

POST /api/oauth/token HTTP/1.1
Host: 192.168.1.65:8089
Cache-Control: no-cache
Postman-Token: e18029ba-ad95-9ac9-5759-fec86fb1bbc4
Content-Type: application/x-www-form-urlencoded

client_id=96528e9d-6cda-4c54-8a5c-32b12cc0c1c4&client_secret=f6e977b6-4fd9-4807-a26f-e18e08192485&grant_type=password&username=regadmin&password=changeme

With the following reply:

{
  "access_token": "ezhy3ADmqTJZYRogM3naeP3Vj7RkcdrWRdi5waUW0FpXCpStIWEbUl",
  "token_type": "Bearer",
  "expires_in": 3599,
  "refresh_token": "OaspjV9Ej6UbIXlc38Z6XSc4rUAlPH6iKlkneQdqhsyADD",
  "scope": "resource.WRITE resource.READ"
}

To get a new access token make the following call:

POST /api/oauth/token HTTP/1.1
Host: 192.168.1.65:8089
Cache-Control: no-cache
Postman-Token: bf841851-58be-3d09-03e3-90f4f222a489
Content-Type: application/x-www-form-urlencoded

client_id=96528e9d-6cda-4c54-8a5c-32b12cc0c1c4&client_secret=f6e977b6-4fd9-4807-a26f-e18e08192485&grant_type=refresh_token&refresh_token=OaspjV9Ej6UbIXlc38Z6XSc4rUAlPH6iKlkneQdqhsyADD

With the following reply:

{
  "access_token": "omo4g5icRQoL2K7VZBcLQjrZajl6ie5c9kMLewPs8IHQzi1q1rO500",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "6NRRaPz6UR8P9Fi32G2K9or684bbwsGzpWpw09bsRo7r3y",
  "scope": "resource.WRITE resource.READ"
}

Refer to this blog post for a full, proper Alloy implementation of the mobile app to perform OAuth Authentication, including using the refresh token to retrieve new access tokens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment