Sun Java Solaris Communities My SDN Account Join SDN

Article

Securing REST Web Services With OAuth

By Malla Simhachalam, with contributions from Rick Palkovic, August 2009  

In this article, you explore an example REST application that uses the open-source protocol OAuth to address security issues.

Contents
 
Background

Web services based on REST (REpresentational State Transfer) architecture have become popular across many enterprises, especially those engaged in Web 2.0. REST web services are comparatively easy to develop. They are based on standard HTTP operations such as GET, POST, PUT, and DELETE, and their response format is free form, depending on the application — you can use XML, JSON, or another format.

As REST web services gain in popularity, security issues become increasingly important. You can use transport-level security (TLS/SSL) for secure peer-to-peer authentication, but these techniques are inadequate when requests for authentication are based on user consent or delegation (allowing sites to authenticate on behalf of the user).

One way to address REST security issues is with the open-source protocol OAuth. As described on the OAuth website, OAuth is "an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications." OAuth incorporates common principles employed by several proprietary frameworks, including Google AuthSub, AOL OpenAuth, Yahoo BBAuth, Upcoming API, Flickr API, and Amazon Web Services API.

The OAuth protocol enables a website or application (known as a service consumer) to access protected resources from a web service (known as a service provider) through an API. The API does not require users to disclose their service provider credentials to consumers.

Not requiring users to provide their credentials directly can be a business advantage. For example, a photo print company may need access to a customer's private photos that have been posted to a photo hosting service. Using the OAuth protocol, the print company can access the photos without requiring that customers reveal their hosting service login credentials.

Using OAuth With Java Technology

For use with Java technology, OAuth requires the following components:

  • Project Jersey – Project Jersey is Sun's open source implementation of the JAX-RS specification (JSR 311 API) for REST web services. Through extensions, Jersey supports OAuth.

  • OpenSSO – OpenSSO, Sun's open-source implementation of identity access management for the enterprise, supports OAuth Token Service through extensions.

Requirements for service consumers – Consumers that use Jersey and JSR 311 API for REST web service clients require the following components for OAuth security:

  • Jersey OAuth Client Filter – Adds required security elements automatically to outbound client requests.

  • Jersey OAuth Signature Library – An API that is used by the client filter.

Requirements for service providers – Providers of Jersey-based REST web services require the following components for OAuth security:

  • Jersey OAuth Signature Library – API that is used by filters and other components to validate inbound requests.

  • OpenSSO OAuth Filter – Service provider component that supplies validation for authentication and authorization.

  • OpenSSO Server – Server that provides authentication and authorization services.

  • Token Service – An OpenSSO extension that issues tokens for OAuth.
Architecture

The following architecture diagram is a high-level overview of REST-based web service consumer and provider deployment.

REST-Based Web Service Deployment Architecture
Figure 1. REST-Based Web Service Deployment Architecture
 

The architecture is based on the OAuth component model for REST web services. Service provider components include the web service host and OAuth token service components. To facilitate authentication and authorization, these components are typically either co-hosted or co-located in the same domain.

The OAuth Client Filter intercepts outbound REST web service calls for Jersey clients and provides security as needed. Similarly, the OpenSSO OAuth filter intercepts inbound web service requests and validates OAuth access tokens. OpenSSO is the user authentication and authorization authority that exposes these interfaces not only for the browser, but for REST web service clients through identity services. As a result, clients can obtain user authentication and authorization through any of the interfaces.

OAuth Token Service generates access and request tokens. It also manages consumer secret key registrations. Currently, it is an independently deployable web archive (war file) that uses its own repository rather than the OpenSSO repository.

Deploying the Example Application

This section demonstrates REST web service security by explaining a simple example. The example requires the software components listed below:

This article assumes that you have some familiarity with the open-source components listed above, and that you can install and configure them with information obtained from their download sites.

The example is a simple Stock Quote application that was built using JAX-RS (JSR 311). The compressed example file restsample.zip contains the required jar files for compile, build, and deployment. The example uses JSR 311 API and the implementation from Project Jersey.

The following instructions describe the steps to install, configure, deploy, and run the example application.

Downloading and Installing

Begin by downloading and installing the necessary software.

  1. Install and configure GlassFish v2.

    Download and install GlassFish v2. The installation is straightforward, following instructions from the GlassFish website.

    This example assumes that you have installed GlassFish on localhost, port 8080. Any change in the host and port will require code changes in the example application. GlassFish v2 requires JDK 1.6 or above as the Java environment.

  2. Install and configure OpenSSO.

    Download and install OpenSSO. Express build 7 is recommended.

    OpenSSO is a simple web archive (opensso.war) that you can install from the GlassFish admin console. The installation of OpenSSO is self-explanatory and follows the instructions available from the OpenSSO website.

    After you have installed OpenSSO, configure it through your web browser interface by entering the URL http://localhost:8080/opensso. See Sun documentation for configuration instructions.

  3. Download and uncompress restsample.zip, the example application.

    The restsample.zip file contains the web archive TokenService.war, an SQL script for setting up TokenService, the Java classes and sources for StockClient and StockService, libraries of jar files, and configuration files.

Deploying and Configuring OAuth Token Service

Next, deploy and configure the TokenService.war file.

At this writing, the OAuth Token Service uses the Java DB (Derby), and requires several steps of configuration before it is ready to run. In the following steps, <glassfish_directory> represents the GlassFish installation directory, and <examples_directory> represents the directory in which you have stored the files from restsample.zip.

  1. First, ensure that the DERBY_HOME environment variable is set correctly by issuing the following command in a command shell:

    export DERBY_HOME=<glassfish_directory>/javadb

  2. Restart GlassFish and Derby with the following commands:

    <glassfish_directory>/bin/asadmin stop-domain
    <glassfish_directory>/bin/asadmin start-database
    <glassfish_directory>/bin/asadmin start-domain

  3. Create the OAuth Token Service database tables using the Derby ij utility. Before running ij for the first time, you may need to set its executable flag. Use the following commands. Note that ij> is the ij program prompt, and that some command lines may appear as wrapped in this article. Enter each command on a single line.

    chmod a+x <glassfish_directory>/javadb/bin/ij
    <glassfish_directory>/javadb/bin/ij
    ij version 10.2
    ij> connect 'jdbc:derby://localhost:1527/TokenServiceDB;create=true;user=username;password=password';
    ij> run '<examples_directory>/dbsetup.sql';
    ij> quit;

  4. Create a JDBC connection pool and resource with the following steps.

    1. In your web browser, log in to the GlassFish admin console with the following URL:
      http://localhost:4848/

      Use the default username admin and the default password adminadmin.

    2. In the GlassFish admin console, open the Resources entry in the list on the left, then open JDBC. Click Connection Pools, then New.

    3. Edit the text fields to read as follows:

      Name: TokenServicePool
      Resource Type: javax.sql.DataSource
      Database Vendor: Derby

    4. Click Next, then Additional Properties. Enter the following values:

      DatabaseName: TokenServiceDB
      Password: password
      User: username

    5. Click Finish.

    6. Click JDBC Resources in the left pane, then click New on the right. Enter the following values:

      JNDI Name: TokenServiceDB
      Pool Name: TokenServicePool

    7. Click OK.

  5. Deploy the TokenService.war file from <examples_directory>/TokenService.war using the GlassFish admin console.

Building and Deploying the Example Application
  1. Build the StockService web service with the following command:

    cd <examples_directory>/StockService; ant

    This command compiles the StockService web service and creates a StockServiceREST.war file in the directory <examples_directory>/StockService/dist/

  2. From the GlassFish admin console, deploy the StockServiceREST.war file.

  3. Build and deploy the StockClient example.

    1. Change to the StockClient directory and type the ant command, as follows:

      cd <examples_directory>/StockClient; ant

      This command compiles StockClient and creates a StockClientREST.war file in the directory <examples_directory>/StockClient/dist/.

    2. In the GlassFish admin console, deploy the StockClientREST.war file.


Running the Example Application

When you run the example application, the StockClient example code first registers the StockClient with the TokenService by means of its Token Secret. Consumer registration with the Token Service is done through programmatic interfaces in the example. Consumer registration can alternatively be done through Token Service UI interfaces, but at this writing that approach is not mature.

The application finishes the OAuth Protocol sequence actions to obtain the OAuth token. It uses the OAuth token to make a request to the StockService. Upon successful validation of the OAuth Token, the StockService responds in XML format.

Run the StockClient example with the following steps:

  1. In your web browser, enter the following URL to access the StockClient example:

    http://localhost:8080/StockClientREST/

    stockclient1
    Figure 2. Running the Example Application
     


  2. Click GetQuote to display the user authorization page.

    stockclient2
    Figure 3. User Authorization Page
     
  3. Click Authorize to display the StockSample XML response message.

    response
    Figure 4. XML Response Message
     
Analyzing HTTP Sequence Data

This section describes the HTTP protocol sequence data for the example application. To view the data, you can use an HTTP protocol analyzer or enable the GlassFish access log with protocol headers.

  1. Accessing the stock client example at http://localhost:8080/StockClientREST/ results in the following HTTP data:

    GET /StockClientREST/ HTTP/1.1 200

  2. Accessing the stock resource results in a 401 return and a message indicating that the service must authorize the client:
    GET /StockServiceREST/resources/stock?quote=JAVA HTTP/1.1" 401
    
    HTTP/1.x 401 Unauthorized
    X-Powered-By: Servlet/2.5Server: 
    Sun Java System Application Server 9.1_02WWW-Authenticate: 
    OAuth realm="http://www.sample.com/"
    

  3. The stock client requests the Request Token from the OAuth Token Service to authorize against the stock service, and obtains the oauth token:
    POST /TokenService/resources/oauth/v1/get_request_token HTTP/1.1" 201 157"OAuth 
    oauth_signature ="%2BJfoxyJ6H5S2k4bwIZg0vaTovfI%3D",
    oauth_nonce="09b10c5b-f815-4807-b92c-f6a8dcaef583", 
    oauth_signature_method="HMAC-SHA1",
    oauth_consumer_key="http%3A%2F%2Flocalhost%3A8080%2FTokenService%2Fresources%2Foauth%2Fv1%2Fconsumer%2FStockClient",
    oauth_timestamp="1247685651"
    
     

  4. The stock client redirects to the request for user authorization with a callback URL. In this example, it uses the default user name demo and password changeit).
    GET /TokenService/authenticate.jsp?username=demo&password=changeit&
    url=http://localhost:8080/opensso/identity&
    oauth_token=http://localhost:8080/TokenService/resources/oauth/v1/rtoken/829ace0720034eb5be4c79f2e022b720&
    oauth_callback=http%3A%2F%2Flocalhost%3A8080%2FStockClientREST%2FGetQuote%3Fcallback%3Dtrue%26symbol%3DJAVA
    HTTP/1.1" 20
    
     

  5. After the authentication is successful, the stock client asks for the access token with the following request token:
    POST /TokenService/resources/oauth/v1/get_access_token HTTP/1.1" 201 157
    "OAuth oauth_signature="Gp4KDgza0BmsRux9CPWyGYpxU9E%3D",
    oauth_nonce="6162a0e0-c734-42ee-a258-735762c3e7cd", 
    oauth_signature_method="HMAC-SHA1",
    oauth_consumer_key="http%3A%2F%2Flocalhost%3A8080%2FTokenService%2Fresources%2Foauth%2Fv1%2Fconsumer%2FStockClient",
    oauth_token="http%3A%2F%2Flocalhost%3A8080%2FTokenService%2Fresources%2Foauth%2Fv1%2Frtoken%2F829ace0720034eb5be4c79f2e022b720",
    oauth_timestamp="1247685806"
    
     

  6. The Token service issues the access token upon validation.

  7. The stock client accesses the resource, this time with an authorization header with the following access token:
    GET /StockServiceREST/resources/stock?quote=JAVA HTTP/1.1" 200 308 "OAuth
    oauth_signature="eJJRqklwbB1scH24CGeIyWVL0LY%3D",
    oauth_nonce="124efaf3-6770-4ebe-bad2-dd28bc380210",
    oauth_signature_method="HMAC-SHA1",
    oauth_consumer_key="http%3A%2F%2Flocalhost%3A8080%2FTokenService%2Fresources%2Foauth%2Fv1%2Fconsumer%2FStockClient",
    oauth_token="http%3A%2F%2Flocalhost%3A8080%2FTokenService%2Fresources%2Foauth%2Fv1%2Fatoken%2F0778f2002a33444d91f45a50fb3c3c77",
    oauth_timestamp="1247685806"
    
     

  8. Upon successful validation of the access token, the stock service renders the request.
Conclusion

In this article, you explored an example REST application that used the open-source protocol OAuth to address security issues. The OAuth protocol enables a service consumer to access protected resources from a web service provider through an API. The API gives service consumers access to services without requiring that users disclose their service provider credentials.

Resources
Rate This Article
 
Comments
Do you have comments about this article? We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of replies - your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.
Malla Simhachalam Malla Simhachalam is a member of the Access Manager engineering team. He joined Sun in 2000 and focuses on building identity management and identity Web services. Before joining Sun, Malla developed Web single sign-on and real-time systems solutions for CMC India's R&D Center. He holds an M.S. degree from the Indian Institute of Technology, Delhi.
 
Rick Palkovic Rick Palkovic is a staff writer for Sun Developer Network. He has written about the Solaris OS and Java technologies for longer than he likes to admit, composing everything from man pages to technical white papers.