Managing OAuth 2.0 Applications

Overview

Client applications that send OAuth requests to the API Gateway’s Authorization Server must be registered with the Authorization Server. This chapter describes the registry used to store these client applications, and how to manage them using a REST API-based HTML interface. This topic also includes details on the relational database schema, and SSL commands used for the example client applications.

[Note] Note

This topic assumes that you have already performed the steps described in Setting up API Gateway OAuth 2.0. These include enabling the OAuth endpoints, importing sample applications, and migrating existing client applications.

Managing Registered Client Applications

Every client application that sends OAuth requests to the API Gateway's OAuth Authorization Server must be registered with the Client Application Registry. The API Gateway provides the Client Application Registry Web-based HTML interface for managing registered client applications. If you have the API Management Solution Pack installed, the Client Application Registry is available in the API Portal web-based interface. The API Gateway also provides the Client Application Registry REST API to enable you to manage registered clients on the command line.

Accessing the Client Application Registry Web Interface

You can access the Client Application Registry Web interface at the following URL:

https://localhost:8089

The default username/password is admin/changeme. Alternatively, if you have installed the API Management Solution Pack, enter apiadmin@localhost/changeme.

You can select a client registration entry to update its details. For example, you can can configure API keys, OAuth credentials, and protected resources:

REST API HTML Interface

By default, the Client Application Registry is backed by an embedded Apache Cassandra database.

Running the Sample Client Applications

The API Gateway includes sample Jython client applications for all supported OAuth flows in the following directory your API Gateway installation:

INSTALL_DIR/samples/scripts/oauth

To run a sample script, open a UNIX shell or DOS command prompt in the following directory:

INSTALL_DIR/samples/scripts

Windows

For example, run the following command:

> run.bat oauth\implicit_grant.py

Linux/Solaris

For example, run the following command:

> sh run.sh oauth/implicit_grant.py

Managing Access Tokens and Authorization Codes

The API Gateway can store generated authorization codes and access tokens in its caches, in an embedded database, or in a relational database. The Authorization Server issues tokens to clients on behalf of a Resource Owner to use when authenticating subsequent API calls to the Resource Server. These issued tokens must be persisted so that subsequent client requests to the Authorization Server can be validated.

The following screen shows the OAuth stores in the Policy Studio:

REST API HTML Interface

The Authorization Server can cache authorization codes and access tokens depending on the OAuth flow. The steps for adding an authorization code cache are similar to adding an access token cache.

The Authorization Server offers the following persistent storage options for access tokens and authorization codes:

  • API Gateway cache (default)

  • Relational Database Management System (RDBMS)

  • Embedded Apache Cassandra database

The following screen shows these options in the Policy Studio:

Add OAuth Token Store

The Purge expired tokens every 60 secs setting enables you to configure the time in seconds that a background process polls the cache or database looking for expired access/refresh tokens or authorization codes.

Storing in a cache

Perform the following steps:

  1. Right-click Access Token Stores in the Policy Studio tree, and select Add Access Token Store.

  2. In dialog that enables you to choose the persistence type, select Store in a cache, and select the browse button to display the cache configuration dialog.

  3. Add a new cache (for example, OAuth Access Token Cache). For more details, see the API Gateway User Guide.

Storing in a relational database

Perform the following steps:

  1. Right-click Access Token Stores in the Policy Studio tree, and select Add Access Token Store.

  2. In the dialog that enables you to choose the persistence type, select Store in a database, and select the browse button to display a database configuration dialog.

  3. Complete the database configuration details. The following example uses a MySQL instance named oauth_db. For more details, see the API Gateway User Guide.

Database Connection

[Note] Note

On first use of the database for caching access tokens, the following tables are created automatically: oauth_access_token and oauth_refresh_token. A table named oauth_authz_code is created for caching authorization codes.

For more details, see the section called “Relational Database-Backed Client Application Registry”.

Storing in Cassandra

Perform the following steps:

  1. Right-click Access Token Stores in the Policy Studio tree, and select Add Access Token Store.

  2. This displays the dialog that enables you to choose the persistence type. Select Store in Cassandra.

  3. You can configure Read and Write consistency levels for the Cassandra database. These control how up-to-date and synchronized a row of data is on all of its replicas. The default Read setting of ONE means that the database returns a response from the closest replica. The default Write setting of ANY means that a write must be written to at least one replica node. For more details, see http://www.datastax.com/docs/0.8/dml/data_consistency.

Querying OAuth 2.0 Message Attributes

Most of the OAuth 2.0 policy filters in the API Gateway generate message attributes that can be queried further using API Gateway selector syntax. The message attributes generated by the OAuth filters are as follows:

  • accesstoken

  • accesstoken.authn

  • authzcode

  • authentication.subject.id

  • oauth.client.details

accesstoken methods

The following methods are available to call on the accesstoken message attribute:

${accesstoken.getValue()}
${accesstoken.getExpiration()}
${accesstoken.getExpiresIn()}
${accesstoken.isExpired()}
${accesstoken.getTokenType()}
${accesstoken.getRefreshToken()}
${accesstoken.getOAuth2RefreshToken().getValue()}
${accesstoken.getOAuth2RefreshToken().getExpiration()}
${accesstoken.getOAuth2RefreshToken().getExpiresIn()}
${accesstoken.getOAuth2RefreshToken().hasExpired()}
${accesstoken.hasRefresh()}
${accesstoken.getScope()}
${accesstoken.getAdditionalInformation()}

The following example shows output from querying each of the accesstoken methods:

so0HlJYASrnXqn2fL2VWgiunaLfSBhWv6W7JMbmOa131HoQzZB1rNJ
Fri Oct 05 17:16:54 IST 2012
3599
false
Bearer
xif9oNHi83N4ETQLQxmSGoqfu9dKcRcFmBkxTkbc6yHDfK
xif9oNHi83N4ETQLQxmSGoqfu9dKcRcFmBkxTkbc6yHDfK
Sat Oct 06 04:16:54 IST 2012
43199
false
true
https://localhost:8090/auth/userinfo.email
{department=engineering}

accesstoken.authn methods

The following methods are available to call on the accesstoken.authn message attribute:

${accesstoken.authn.getUserAuthentication()}
${accesstoken.authn.getAuthorizationRequest().getScope()}
${accesstoken.authn.getAuthorizationRequest().getClientId()}
${accesstoken.authn.getAuthorizationRequest().getState()}
${accesstoken.authn.getAuthorizationRequest().getRedirectUri()}
${accesstoken.authn.getAuthorizationRequest().getParameters()}

The following example shows output from querying each of the accesstoken.authn methods:

admin
[https://localhost:8090/auth/userinfo.email]
SampleConfidentialApp
343dqak32ksla
https://localhost/oauth_callback
{client_secret=6808d4b6-ef09-4b0d-8f28-3b05da9c48ec, 
  scope=https://localhost:8090/auth/userinfo.email, grant_type=authorization_code, 
  redirect_uri=https://localhost/oauth_callback, state=null, 
  code=FOT4nudbglQouujRl8oH3EOMzaOlQP, client_id=SampleConfidentialApp}

authzcode methods

The following methods are available to call on the authzcode message attribute:

${authzcode.getCode()}
${authzcode.getState()}
${authzcode.getApplicationName()}
${authzcode.getExpiration()}
${authzcode.getExpiresIn()}
${authzcode.getRedirectURI()}
${authzcode.getScopes()}
${authzcode.getUserIdentity()}
${authzcode.getAdditionalInformation()}

The following example shows output from querying each of the authzcode methods:

F8aHby7zctNRknmWlp3voe61H20Md1
sds12dsd3343ddsd
SampleConfidentialApp
Fri Oct 05 15:47:39 IST 2012
599 (expiry in secs)
https://localhost/oauth_callback
[https://localhost:8090/auth/userinfo.email]
admin
{costunit=hr}

oauth.client.details methods

The following methods are available to call on the oauth.client.details message attribute:

${authzcode.getCode()}
${authzcode.getState()}
${authzcode.getApplicationName()}
${authzcode.getExpiration()}
${authzcode.getExpiresIn()}
${authzcode.getRedirectURI()}
${authzcode.getScopes()}
${authzcode.getUserIdentity()}

The following example shows output from querying each of the oauth.client.details methods:

F8aHby7zctNRknmWlp3voe61H20Md1
sds12dsd3343ddsd
SampleConfidentialApp
Fri Oct 05 15:47:39 IST 2012
599 (expiry in secs)
https://localhost/oauth_callback
[https://localhost:8090/auth/userinfo.email]
admin

Example of querying message attribute

If you add additional access token parameters to the OAuth 2.0 Access Token Info  filter, you can return a lot of additional information about the token. For example:

{  
   "audience" : "SampleConfidentialApp",
   "user_id" : "admin",
   "scope" : "https://localhost:8090/auth/userinfo.email",
   "expires_in" : 3567,
   "Access Token Expiry Date" : "Wed Aug 15 11:19:19 IST 2012",
   "Authentication parameters" : "{username=admin, 
    client_secret=6808d4b6-ef09-4b0d-8f28-3b05da9c48ec, 
    scope=https://localhost:8090/auth/userinfo.email, grant_type=password, 
    redirect_uri=null, state=null, client_id=SampleConfidentialApp, 
    password=changeme}",
   "Access Token Type:" : "Bearer"

You also have the added flexibility to add extra name/value pair settings to access tokens upon generation.The OAuth 2.0 access token generation filters provide an option to store additional parameters for an access token. For example, if you add the name/value pair Department/Engineering to the Client Credentials filter:

Adding Additional OAuth 2.0 Access Token Parameters

You can then update the Access Token Info filter to add a name/value pair using a selector to get the following value:

Department/${accesstoken.getAdditionalInformation().get("Department")}

For example:

Retrieving Parameters from OAuth 2.0 Access Token

Then the JSON response is as follows:

{
  "audience" : "SampleConfidentialApp",
  "user_id" : "SampleConfidentialApp",
  "scope" : "https://localhost:8090/auth/userinfo.email",
  "expires_in" : 3583,
  "Access Token Type:" : "Bearer",
  "Authentication parameters" : 
  "{client_secret=6808d4b6-ef09-4b0d-8f28-3b05da9c48ec, 
    scope=https://localhost:8090/auth/userinfo.email, grant_type=client_credentials, 
    redirect_uri=null, state=null, client_id=SampleConfidentialApp}",
  "Department" : "Engineering",
  "Access Token Expiry Date" : "Wed Aug 15 12:10:57 IST 2012"

You can also use API Gateway selector syntax when storing additional information with the token. For more details on selectors, see the API Gateway User Guide.

OAuth scope attributes

In addition, the following message attributes are used by the OAuth filters to manage OAuth scopes. The scopes are stored as a set of strings (for example, https://localhost:8090/auth/user.photos https://localhost:8090/auth/userinfo.email):

  • scopes.in.token

    Stores the OAuth scopes that have been sent in to the Authorization Server when requesting the access token.

  • scopes.for.token

    Stores the OAuth scopes that have been granted for the access token request.

  • scopes.required

    Used by the Validate Access Token filter only. If there is a failure accessing an OAuth resource due to incorrect scopes in the access token, an insufficent_scope exception is sent back in the WWW-Authenticate header. When Get scopes by calling a policy is set, the configured policy can set the scopes.required message attribute. This enables the OAuth Resource Server to properly interact with client applications and provide useful error response messages. For example:

    WWW-Authenticate  Bearer realm="DefaultRealm",error="insufficient_scope",
       error_description="scope(s) associated with access token are not valid 
       to access this resource", scope="Scopes must match All of these scopes:
       https://localhost:8090/auth/user.photos https://localhost:8090/auth/userinfo.email"

Relational Database-Backed Client Application Registry

By default, the Oracle Client Application Registry Key Property Store (KPS) is backed by an Apache Cassandra database. The Oracle Client Application Registry KPS can also be backed by a relational database such as Oracle, MySQL, DB2, or Microsoft MySQL Server. For more details, see the Key Property Store User Guide, available from Oracle Support.

OAuth relational database schemas

For example, the OAuth relational database schemas displayed by example mysql commands are as follows:

oauth_access_token schema

The following shows the result from the show columns from auth_access_token; command:

    +---------------+--------------+------+-----+---------+-------+
    | Field         | Type         | Null | Key | Default | Extra |
    +---------------+--------------+------+-----+---------+-------+
    | id            | varchar(2    | NO   | PRI | NULL    |       |
    | auth_request  | blob         | NO   |     | NULL    |       |
    | client_id     | varchar(255  | NO   |     | NULL    |       |
    | expiry_ti     | datetime     | NO   |     | NULL    |       |
    | token         | blob         | NO   |     | NULL    |       |
    | refresh_token | varchar(2    | YES  |     | NULL    |       |
    | user_auth     | varchar(255  | NO   |     | NULL    |       |
    | user_name     | varchar(255  | NO   |     | NULL    |       |
    +---------------+--------------+------+-----+---------+-------+

oauth_refresh_token schema

The following shows the result from the show columns from oauth_refresh_token; command:

    +--------------+--------------+------+-----+---------+-------+
    | Field        | Type         | Null | Key | Default | Extra |
    +--------------+--------------+------+-----+---------+-------+
    | token_id     | varchar(255) | NO   | PRI | NULL    |       |
    | auth_request | blob         | NO   |     | NULL    |       |
    | expiry_time  | datetime     | NO   |     | NUL     |       |
    | token        | blob         | NO   |     | NULL    |       |
    | user_name    | varchar(255) | NO   |     | NULL    |       |
    +--------------+--------------+------+-----+---------+-------+

oauth_refresh_token schema

The following shows the result from the show columns from oauth_refresh_token; command:

    +---------------+--------------+------+-----+---------+-------+
    | Field         | Type         | Null | Key | Default | Extra |
    +---------------+--------------+------+-----+---------+-------+
    | id            | varchar(255) | NO   | PRI | NULL    |       |
    | authorization | blob         | NO   |     | NULL    |       |
    | expiry_time   | datetime     | NO   |     | NULL    |       |
    +---------------+--------------+------+-----+---------+-------+

Generating a Certificate and Private Key for a Client Application

The following example openssl command shows generating a client application certificate and private key:

$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mykey.pem 
-out mycert.pem
Generating a 1024 bit RSA private key
...................................................................
...........++++++
.....++++++
writing new private key to 'mykey.pem'
-----
You are about to be asked to enter information that will be incorporated 
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank. 
For some fields there will be a default value.
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:MA
Locality Name (eg, city) []:Newton
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Oracle
Organizational Unit Name (eg, section) []:API Gateway
Common Name (eg, YOUR name) []:SampleConfidentialApp
Email Address []:support@widgits.com