Platform-level support for Authorization in Cloud Service with OAuth 2
On March 11th 2014 I have presented a paper entitled “Platform-level support for Authorization in Cloud Service with OAuth 2” at the Intercloud 2014 workshop co-located with IEEE International Conference on Cloud Engineering (IC2E) in Boston. This paper describes a result of the joint collaboration with Anderson Santana de Oliveira, Gabriel Serme and Yann Lehmann, who are the paper co-authors.
Sharing data in the cloud
In the world of cloud services we constantly link, share and exchange our information between the services. I would like my contact list, calendar, photos or other personal information that I store in one of the services to be available for the other service which I use. For example, I allow the sports app to access my calendar in order to automatically add the reminders about the coming games. Or when I am requesting on-line an insurance and the insurance company website would like to access my bank statements from the online banking application.
The question arises how to do it without giving my banking service credentials to the insurance company? Disclosing my password may lead to loosing the control over my information stored inside the banking service, not to mention that we cannot limit which actions the insurance service will be able to perform once it has the access to my account. In principle, it could make some money transfers or request a very detailed information related to my transactions, while it only needs my balance history for the past 3 months.
The problem is solved by the OAuth protocol. OAuth allows sharing the resources without a need to disclose the credentials. OAuth also enables limiting the duration for which resources are shared and the actions allowed to be performed on the resources.
How is it possible?
OAuth 2 protocol flows
OAuth defines a general flow in which the Client application willing to access my protected resources stored on the other service requests first my (so the Resource Owner) authorization. If the Resource Owner permits the Client to access the resource the Client will receive an Authorization Grant which it presents to the Authorization Server. The Authorization Server exchanges the Authorization Grant for an Access Token and now the Client can use this token to access the resources stored on the Resource Server.
The Access Token can have a certain validity period associated with it, which will limit the time for how long Client can use it to access the resource without requesting a new token. It can also have associated scope which can limit a set of possible actions to be performed on a resource or a set of resources to which the access is given.
OAuth defines multiple flows that are concrete instantiation of this conceptual flow. The one widely used for the services on the web is called the OAuth Authorization Code flow. This variation of the general flow introduces a notion of the User Agent, typically a web browser operated by a User, who is the Resource Owner. We can also observe that the Resource and Authorization Servers are typically owned by the same entity which we can treat as the OAuth Server.
Upon a user request the OAuth Client will first redirect the web browser to the Authorization Server (here represented by the more general OAuth Server). The OAuth Server will authenticate the Resource Owner and now he will be able to decide whether to grant the authorization to access the resource or not.
In the case when the user permits the access the Authorization Server will redirect the web browser back to the Client web site, with the URI including now the Authorization Code. With that Authorization Code the OAuth Client can request the Access Token from the OAuth Server and hence obtain the access to the resource.
Looking at our example of the insurance web site and the banking service, the Authorization Server and the Resource Server are both operated by the bank, so we just depict them as a single Banking Service. Now the Insurance Service which I would like to give the access to my bank account balance history redirects me to the Banking Service, which first requires me to authenticate and after I log in it will ask me for the permission to grant the Insurance Service the access to my bank account balance information.
The whole set up of the protocol requires setting up the Authorization Server controlling the access to the Resource Server, issuing the Authorization Code and the Access Tokens as well as verifying them once they are received from the OAuth Client application. On the OAuth Client side for each resource request it requires validating whether the Client is already in possession of the valid access token and if this is not the case, requesting it from the OAuth Server.
Implementing this functionality can be tedious and error prone. There exist libraries providing the functionality of the Authorization Server. However they provide only the building blocks for the protocol implementation without directly orchestrating the protocol flow. Developers willing to implement it on their own will need to be very careful about the consequences of the potential errors in their custom implementation.
Could we simplify the integration of the OAuth protocol?
How about a simple OAuthize button that could turn any web application into the OAuth Server and add the necessary Access Token management to the Client application?
Why not let all this complex error-prone operations to be handled by the cloud platform provider?
Avoiding OAuth boilerplate with the help of interceptors
In our implementation we have designed a set of interceptors for handling all of the OAuth protocol flow operations transparently from both the Server and the Client. Interceptor is simply a filter that processes the incoming or outgoing message inspecting the headers and the content as well as possibly modifying it.
Analyzing the OAuth Authorization Code flow we have established that the interceptors functionality will need to cover both request and response handling of Client and Server messages.
On the OAuth Client side we need an interceptor for the outgoing messages (the Client requests): it needs to attach the Access Token to the request, first checking its validity. Otherwise if there is no valid Access Token it will initiate the OAuth flow, redirecting the user to the Authorization Server. For the incoming messages (the Client responses) the interceptor needs to retrieve the Authorization Code if the incoming message is part of the OAuth flow. Then using this code it can obtain the Access Token and repeat the initial request to the Resource Server now already including with it the Access Token.
On the OAuth Server side the interceptor needs to provide the following functionality for the outgoing messages (the Server requests): it checks the validity of the Access Token and based on that it either provides the access to the resource or not. For the incoming messages (the Server responses) it performs one of the following actions:
- Validates the request parameters.
- Authenticates the user.
- In case of the Access Token request it performs the OAuth Client authentication and the Authorization Code validation.
We have encapsulated this functionality in a form of four handlers for the incoming and outgoing messages:
- OAuth Client Request Handler
- OAuth Client Response Handler
- OAuth Server Request Handler
- OAuth Server Response Handler
To have a better understanding of the handlers functionality let’s now take a closer look at how the OAuth Client Response Handler acts upon the incoming message.
This handler takes care of retrieving Authorization Code from the Client’s Redirect URI. Once the code is obtained, it issues a request to the Authorization Server, supplying client authentication credentials and the Authorization Code. After the Authorization Server response containing the Access Token it will persist the token for any further Client requests for the same scope. The last action for this handler is to reissue the original query for the resource, supplying now valid Access Token.
The OAuth flow management is delegated to these message interceptors. From the Client and Server perspective no modifications in the application source code are required. Thanks to that we avoid mixing the security related functionality with the business logic of the application. Tedious steps required to integrate the OAuth protocol are now being encapsulated inside the handlers. So when Client requests a remote resource it looks like a simple Client-Server request.
OAuthize: Eclipse extension for integrating the OAuth interceptors
We have also created an extension for Eclipse IDE that integrates automatically the handlers with existing web applications. The handlers together with all of the necessary libraries are added via simple OAuthize wizard that will enable further customization, e.g. configure the Access Token scopes and the mappings between the scopes and the resources. For the OAuth Server it will guide the process of selecting which resources are protected via the protocol.
When the project is deployed on Platform-as-a-Service all of the necessary dependencies are supplied by the platform. Developers do not need to worry anymore about which library for OAuth support they will need to use. Also they are no longer concerned by the Access Token management. For the applications acting as a Resource Server they no longer need to take care of validating the Authorization Codes and the Access Tokens as all of the checks are implemented in the handlers.
We have provided a simple solution to integrate the standard security protocol for the resource access authorization. Thanks to the OAuth Client- and Server-side Handlers developers are able to incorporate OAuth functionality into their services, without a need to look for the specific libraries supporting the protocol on both sides. Interceptors encapsulate all necessary functionality and can be easily integrated with the services thanks to the intuitive wizard for Eclipse IDE.