Taking some REST (part 3)Published on: Author: Milco Numan Category: Oracle
INVOKING THE SERVICES USING OAUTH
Finally I have arrived at the part where I can show you how to consume the fruits of this labor, viz. invoking some OAuth 2.0 secured APIs (resources).
In the first part, I discussed some of the basics and setup required to obtain client credentials (clientId and client secret). The second part focused on developing some OAuth 2.0 utility services, in order to:
- redeem the authorization code into a set of tokens (access and refresh tokens)
- store and retrieve the tokens from the in-memory cache using the SOA Suite Coherence adapter
- refresh a token
- composite service to obtain an active token, i.e. retrieve the token from the cache and refresh it using the refresh token if it has exceeded its lifetime
The API I have selected for the POC is the Google Task API. Like all Google APIs, this API is quite welldocumented. If you’re accustomed to SOAP Web Services, you mostly have interface definitions available as a WSDL document, but in the case of REST APIs this is not quite so straight forward. Furthermore, this API is using a combination of features for passing payload and parameters, like JSON and URL-encoded parameters, as well of what is modeled as “template” parameters in SOA Suite’s REST implementation (these are the tasklist infix parameters in URLs like /users/@me/tasklist/tasks).
For the POC I have selected the following operations to expose a SOAP services:
REST Service Data structures
Before defining the REST Business Services, you should have a schema definition where the data structures that are exchanged with the API are defined. Although it is possible to define them “on the fly”, another advantage of being prepared is that you can consolidate your data structures in a single schema.
The implementation of the service in Service Bus is quite simple with respect to the components required:
As you can see from the diagram, this project also has a single proxy as the external interface and uses both a REST Business Service as a conduit to Google’s Task API and interaction with the OAuth 2.0 proxy service for retrieving the required access token.
REST Business Service
The REST business service is the abstraction of the actual logic, in essence it contains the metadata that specifies how to invoke the actual service and which payloads and parameters are expected:
As you can see from the above definition, three different resource paths are used to create five different operations; if you check the Google API documentation for the Tasks API you can see that there are much more operations that I have not considered for this Proof of Concept.
As you can see from the definition, the GetTasks request uses the HTTP GET method (so there is no payload), where the parameters are passed as part of the URL. One parameter, the task list for which we want to retrieve the tasks, is part of the URL path whereas the others are passed as actual parameters (name-value pairs) on the URL like:
The response for this operation is defined as JSON, being modeled as the “ListOfTasks” element:
Now the good thing about the SOA Suite REST adapter is that it will transparently translate the JSON structures, URL-encoded parameters and the like from and to the schema message specified!
All other operations being m.m. equal to this setup, there is just one that is slightly different, the request message for the InsertTasks operation:
InsertTasks Request Mapping
For mapping the InsertTasks request, we require both a template parameter for the pointing to the correct task list as well as a JSON body for the POST carrying the task to be created. Now, the payload body does not (and to conform to Google’s definition cannot) contain the task list identification, so in Service Bus this has to be passed as a property. In the definition above, I have defined the task list template parameter to be represented by a “TaskList” property. At runtime, a user-metadata element needs to be defined in the $outbound, with @name=”TaskList” and @value equal to the identification of the task list where the task is to be inserted.
The service pipeline consists of a few simple stages: the first stage will capture the inbound request for later use, the second stage will implement a service callout to retrieve the required access token from the cache:
Implementation of the service pipeline
The routing node shown on the bottom of the screen will do the “heavy” work of routing to the correct service operation, transforming between the inbound SOAP data structures and the outbound representation of the REST data structures (that will be shielded from us by the REST adapter):
Routing Table for the business services
In the routing table, there is also a “default” path if the case has not been matched: in this case, an exception will be triggered and result in a SOAP Fault being thrown to the caller.
To prove that we are authorized to access the resource (API) on behalf of the user, an access token should be presented as an HTTP header; in Service Bus, a Transport Header action is used to manipulate the headers:
Proving your authorization
The access token needs to be passed as an “Authorization” HTTP header whose value is made up of a prefix “Bearer” and the actual access token’s value (separated by a single space).
The property metadata is provided as the request’s outbound metadata; for this purpose, insert a new user-metadata element into the $outbound message context variable, where the name attribute represents the property name and the value attribute is.. well, it’s value:
Testing … Testing
As explained in the second part of the series, the interactive part for consenting into access from the client application cannot be performed as a service, but should be performed by a (Web) application. For this, I will now simply use the browser, requesting the URL https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=<your-client-id-inserted-here>&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/tasks
Approving the access
This will ask you to log into to the site (in this case, Google) and approve or reject the client application’s request for access with the scope(s) mentioned in the request (“Uw taken beheren”). After approving the request, an authorization code is returned to the browser:
With this authorization code, service invocations can start. First, the authorization code needs to be redeemed for tokens. Only the access token will be returned to the caller, but both the access token and the refresh token are stored in the in-memory cache:
Redeeming the authorization code
Getting an access token:
This operation shows retrieving the access token. After it expires (or when the RefreshToken operation is invoked), the refresh token is used from the cached token to obtain a fresh token:
Refreshing the access token
From the example shown above, you should see that the access token’s value has changed from the previous examples, as the token has been refreshed!
The following pictures represent the invocations of the SOAP service operations from SoapUI.
Accessing your task lists
Retrieving a single task list
Creating a new task list
Creating a task in the newly created task list
Retrieving all tasks from a task list
Finally, here is the representation of the task list in your Google Mail:
I hope that this will convince you that Service Bus is very well suited to access any OAuth secured API. Actually, with some small utility services, the Service Bus makes a very good fit for an “outbound” API Management platform, enabling you to invoke a wealth of OAuth secured REST services using a simple SOAP interface. Because REST may be a protocol that is being used more and more for providing access to resources for mobile platforms, but there is also an enormous installed bases of enterprise service platforms that are implemented using the SOAP protocol that may also need to access these REST resources. Again, Service Bus proves to be an indispensable part of the service infrastructure you’ll (almost) certainly need!
You can find the sample code for this project in my GitHub repository SBGoogleRESTAPI.