X

Best Practices from Oracle Development's A‑Team

Implementing OAuth 2 with Oracle Access Manager OAuth Services (Part IV)

Introduction

This post is part IV of a series of posts about OAM's OAuth implementation.

Other posts can be found here:

Part I - explains the proposed architecture and how to enable and configure OAM OAuth Services.

Part II - describes a Business to Business use-case (2-legged flow);

Part III  - deals with the Customer to Business use-case (3-legged flow), when the client code is running in the application server;

Part IV - describes the Customer to Business use-case (3-legged flow), when the client application runs on the browser, embedded as Javascript code;

Part V  - provides the source code and additional information for the use case implementation.

This post will present the C2B use-case where the Client Application is a Javascript code, running on the browser.

Oracle recommends that customers install the latest bundle patch available for their specific IdM release. Bundle Patches might include important patches for OAuth implementation. You can find information about Bundle Patch History and Releases in the Support document "OAM Bundle Patch Release History (Doc ID 736372.1)". Please visit My Oracle Support (https://support.oracle.com) and search for Doc ID 736372.1.

Before You Proceed...

Read this if you're using OAM R2PS3 (11.1.2.3)

This post was written based on OAM R2PS2 release. Even though most things are still the same on R2PS3 release, there are some subtle differences from one release to the other.
In OAM R2PS3, you need to deploy a webgate in front of your OAM servers in order to use the OAuth 3-legged flow.
The webgate is required to protect the OAuth consent page, otherwise you will get an error when trying to follow the 3-legged OAuth flow.
Review the documentation on how to install a supported webserver and deploy webgate here.

Deploy and register a webserver/webgate and configure the following resources in your application domain:

/ms_oauth/oauth2/oammsui/** - Excluded
/oam/** - Excluded
/ms_oauth/img/* - Excluded
/ms_oauth/style/* - Excluded
/ms_oauth/oauth2/endpoints/** - Excluded
/ms_oauth/oauth2/ui/** - Protected

In your webserver create a new conf file with the following directives

<Location /oam>
SetHandler weblogic-handler
WLProxySSL ON
WLProxySSLPassThrough ON
WLCookieName OAM_JSESSIONID
WebLogicCluster server1:port1, server2:port2
</Location>

<Location /ms_oauth>
SetHandler weblogic-handler
WLProxySSL ON
WLProxySSLPassThrough ON
WLCookieName OAM_JSESSIONID
WebLogicCluster server1:port1, server2:port2
</Location>

Use Case

This is a variation of the C2B use-case presented before; in this case, the client application resides in the browser itself, embedded as javascript code.

All the API calls are made directly from the browser to the OAuth server, but this presents two problems:

 

  • First, the client credentials would be exposed, hardcoded in the javascript code, when making calls with AJAX, just like this:
    $.ajax({     type: "POST",     url: "https://oxygen.mycompany.com:14101/ms_oauth/oauth2/endpoints/oauthservice/tokens",     data: {         "code":code,         "grant_type":"authorization_code"     },     dataType: "text",     headers: {         "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",         "Authorization": "Basic d2h5c29jdXJpb3VzOnlvdWFza21l"     },     success: function(data){         //handle token     },     error: function(data){         //handle error     } });

Note that the client credentials appears in a Base64 encoded format: d2h5c29jdXJpb3VzOnlvdWFza21l, which can be easily decoded and visible to anyone accessing this web page.

 

  • Second, the AJAX call most probably would run into Cross-Domain issues. This is very likely to happen because we're hosting our application in a web server domain different than the domain where the OAuth server is running. Although there are ways to prevent this, like changing the response headers from the OAuth server, sometimes it will just not be possible.

To avoid this situation, we are going to implement a ‘proxy’ application or 'relay endpoint', that will make the actual calls to the OAuth Server, thus preserving the client credentials and bypassing cross-domains restrictions imposed to AJAX calls in the web browser.

Use Case Flow

The following picture shows the flow between the different components

C2B - Javascript

1. The webpage that contains the javascript code is loaded in a browser. The embedded javascript code checks if there is an authorization code in the URL parameters.

2. If it does not find the Authorization Code, it makes a redirection to the OAuth Server Authorization URL. If the user has already been authenticated with OAM, the OAuth Server will not ask him to authenticate again, in this case the flow would proceed to step 5.

//Gets the Authorization Code var code = getURLParameter("code"); //Not Authorized if(typeof code == 'undefined') {     //Redirecting to Authorization URL     location.href = "https://oxygen.mycompany.com:14101/ms_oauth/oauth2/endpoints/oauthservice/authorize?response_type=code&client_id=browserClient&redirect_uri=https://oxygen.mycompany.com:7502/ClientWebApp/index.html&scope=Customer.Info%20UserProfile.me&state=getauthz";     ...

3. OAuth server replies with the OAM Login Page.

4. User logs in with its credentials.

5. OAuth Server checks if the user needs to give consent for the client application to access his resources.

6. OAuth Server replies with the consent page.

7. User gives consent for the client application to access his resources.

8. OAuth Server returns the Authorization Code back to the redirect_uri as an URL parameter.

9. The javascript code embedded in the webpage extracts the Authorization Code from the URL parameter and makes a call to the Relay Endpoint requesting an Access Token, passing the Authorization Code.

} else {     //Gets an Access Token passing Authorization Code using Proxy Application     $.ajax({         type: "POST",         url: "https://oxygen.mycompany.com:7502/ClientWebApp/rest/tokens",         data: {'code':code},         dataType: "text",         success: function(token){         ...

10. The Relay Endpoint makes a call to the OAuth Server requesting an Access Token, passing the Authorization Code. Since the code is running server-side, there is no cross-domain access controls imposed by browsers.

11. The OAuth Server checks the Authorization Code, checks if the grant type is enabled for this client and if its credentials are correct before issuing the Access Token.

12. OAuth Server replies with the Access Token back to the Relay Endpoint

13. The Relay Endpoint replies with the Access Token back to the Javascript code embedded in the webpage.

14. The Javascript code embedded in the webpage makes a REST call to the Resource Server passing the Access Code.

//Gets the Customer Information passing the Access Token $.ajax({     type: "POST",     url: "https://oxygen.mycompany.com:7502/ResourceService/rest/customer",     data: {         "code":accessToken     },     dataType: "text",     headers: {         "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"     },     success: function(data){         //Handles Data returned from the server     },     error: function(data){         //Handles error message     } });

15. The Resource Server requests a token validation with the OAuth Server

16. The OAuth Server validates the token and sends the response to the Resource Server

15. The Resource Server sends back application data to the javascript code embedded in the webpage.

C2B Use Case Implementation

To implement the C2B use case, a HTML page is used as the Client Application.

The Relay Endpoint is written in an annotated plain Java class using Jersey to expose it as a RESTful webservice.

The Resource Service is implemented in a plain Java class using the Jersey framework to expose the Customer Service as a RESTful webservice.

The Resource Server also implements a Servlet Filter, that intercepts all incoming requests to validate the incoming Access Token before giving access to the REST Endpoint.

The relevant classes/files for this use case are:

  • index.html
  • TokenProxyService.java
  • UserProfileProxyService.java
  • CustomerService.java
  • OAuthTokenValidationFilter.java
  • OAuthTokenValidator.java

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha

Recent Content