Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

Introduction

Eric Woods and Matthew Marum are implementing support for an OAuth 2.0 Service Provider in Apache Shindig.  This article provides an overview of the implementation including high level design, supported flows, common How-Tos, and future considerations.

The OAuth 2.0 specification is here: http://tools.ietf.org/html/draft-ietf-oauth-v2-20

Note that the implementation is still evolving, so consider this design document to be a draft.

High Level Design

Image Removed

All OAuth 2.0 requests are received by the OAuth2Servlet.  Per the spec, there are two OAuth 2.0 related endpoints: /oauth/authorize and /oauth/token.  The request is quickly delegated to either the OAuth2AuthorizationHandler or the OAuth2TokenHandler accordingly.

The first thing either handler does is normalize the incoming OAuth 2.0 request using the OAuth2NormalizedRequest class.  This class is designed to receive the incoming HttpServletRequest and normalize all OAuth 2.0-related fields.  For example, a pre-registered client may authenticate using Basic Authentication or by including "client_secret" as a URL parameter.  These permutations make it difficult to process an incoming request consistently.  OAuth2NormalizedRequest will make the client secret accessible by getClientSecret() regardless of authentication method, thus "normalizing" the method that was used to authenticate, pass a token, pass a grant type, etc.

After normalization, the request is processed.  We have two distinct layers to process OAuth requests: OAuth2Service and OAuth2DataService.  The OAuth2Service handles all OAuth processing and enforcement as defined by the OAuth 2.0 specification.  For example, the OAuth2Service handles client authentication and request validation for an authorization code, access token, refresh token, or resource.  The OAuth2Service also handles generation of authorization codes, access tokens, and refresh tokens.

The second layer, OAuth2DataService, represents the data store to manage authorization codes, access tokens, refresh tokens, and association with a pre-registered client.  For example, the OAuth2DataService manages registering/unregistering the various OAuth 2.0 codes/tokens, retrieving a client by ID, and retrieving a code/token by value.

We provide "poor-man" implementations of the two service interfaces; the OAuth2ServiceImpl uses in-memory data structures, and the OAuth2DataServiceImpl uses canonical.json.

OAuth 2.0 Flow Support

How-Tos

How to Register a Client

Clients are pre-registered in canonicaldb.json.  Client registration, authorization codes, access tokens, and refresh tokens are keyed by client.  Here's the current structure (subject to change):

Code Block

 // Registry of OAuth 2.0 clients with Shindig's service provider.
 "oauth2" : {
     "advancedOpenSocialClient" : {
         "registration" : {
             "id" : "advancedOpenSocialClient",
             "secret": "advancedOpenSocialClient_secret",
             "title": "Most Advanced OpenSocial Client Ever!",
             "redirectUri" : "http://localhost:8080/oauthclients/OpenSocialClient",
             "type" : "confidential",
             "flow" : "authentication_code"
         },
         "authorizationCodes" : {
             "advancedClient_authcode_1" : {
                 // Authentication code has been consumed since associatedSignature exists
                 "redirectUri" : "http://localhost:8080/oauthclients/OpenSocialClient",
                 "associatedSignature" : "advancedClientOS_accesstoken_1"
             },
             "advancedClient_authcode_2" : {
                 "redirectUri" : "http://localhost:8080/oauthclients/OpenSocialClient"
             }
         },
         "accessTokens" : {
             "advancedClient_accesstoken_1" : {
                 "redirectUri" : "http://localhost:8080/oauthclients/OpenSocialClient"
             }
         }
     },
    "testClient" : {
         "registration" : {
             "id" : "testClient",
             "redirectUri" : "http://localhost:8080/oauthclients/OpenSocialClient",
             "type" : "public"
         }
     }
 }

Clients can only be registered with a single flow at a given time.  Some flows have restrictions.  For example, Client Credentials flow requires a confidential client.

How to Add a Custom Grant Validator

Per the OAuth 2.0 specification, grant types are extensible beyond the 4 pre-defined types (authorization_code, client_credentials, refresh_token, and password).  To accommodate, validation of new grant types, grant handlers are registered with the OAuth2Service.  The appropriate grant handler is identified by its registered "grant_type" and invoked within OAuth2Service.validateRequestForAccessToken(...) to validate requests.

TODO: where and how are grant handlers registered?

How to Enable/Disable OAuth 2.0 Security

You can add OAuth2 support to protect your Social APIs by using an AuthenticationHandlerProvider that provides the OAuth2AuthenticationHandler.  The OAuth2AuthenticationHandler ensures that requests for protected resources (the Social REST APIs) include valid access tokens.

You can disable the OAuth2 access token and authorization endpoints by removing mappings for the OAuth2Servlet in the Shindig web.xml

If your AuthenticationHandlerProvider doesn't return the OAuth2AuthenticationHandler, access tokens will not be checked when clients access protected resources (the Social REST APIs).

Future Considerations

Currently, the entire OAuth 2.0 implementation is located in a single package within Shindig's social-api module.  We need to determine the most appropriate way to integrate this package into shindig.  We could integrate this package into social-api following the existing patterns, or it may even be broken out as an entirely new module within Shindig.  To be determined...

Additionally, client registration is currently facilitated by modifying canonicaldb.json.  We could expose client registration services via a REST API and provide a UI for clients to register themselves.This documentation lives on the Apache Shindig wiki: https://cwiki.apache.org/confluence/display/SHINDIG/OAuth+2.0+Service+Provider+Implementation+in+Apache+Shindig