OAuth2 WebADE Developer Guide - bcgov/common-service-showcase GitHub Wiki

Open Authorization Standard (OAuth)

OAuth (Open Authorization) is an open standard for implementing token-based authorizations. OAuth 2.0 refers to the second version of the “Open Authorization” standard, published in 2010 and described in RFC 6749. OAuth 2.0 is used to grant access to Web resources without the need to provide usernames and passwords over the Internet. OAuth may be used with desktop, Web and mobile applications.
There are a number of documents describing OAuth available on-line. Unfortunately, there is a lack of consistency in the descriptions and terminology used in many of these documents. It is important to note that when dealing with OAuth2, the terms “application”, “client” and “user” have meanings that may differ from conventional usage:

  • Application: aka “the Client” makes resource requests on behalf of the resource owner
  • Authorization Server: responsible for issuing OAuth2 access tokens after the client authenticates;
  • Resource Owner: aka “the User”; an entity capable of granting access to a protected resource; when the resource owner is a person, it is referred to as an end-user;
  • Resource Server: hosts the API; grants access to the API when a valid access token is presented.

NRM Implementation of OAuth 2.0

The Natural Resource Ministries (NRM) has implemented an OAuth2 API service that utilizes the repository of authorizations maintained within WebADE. WebADE is a custom authorization service developed for the Province of BC and is shared collectively by a number of ministries including the NRM.
The key to understanding how OAuth works is understanding the authorization flow. The authorization flow is the process by which a client obtains an OAuth2 access token. The OAuth2 standard specifies five pre-defined authorization flows. In OAuth2 terminology, these authorization flows are refereed to as “Grant Types.” The five grant types defined for OAuth2 are:

  • Authorization Code Grant
  • Implicit Grant
    Resource Owner Credentials Grant
  • Client Credentials Grant
  • Refresh Token Grant

The Resource Owner Credential Grant is never used by NRM applications as it does not support authentication using the SiteMinder Common Log-on Page (CLP).
Industry best practices have recently changed regarding use of the Implicit Grant Type. Use of the Authorization Code Grant with PKCE (proof key for code exchange) is recommend instead of the implicit Grant Type due to security concerns. However, the custom OAuth2 service used by the NRM does not currently support the Authorization Code Grant with the PKCE option. NRM applications are to continue to use the implicit Grant type for mobile and JavaScript-based applications.

Logical Infrastructure Figure 1- WebADE-OAuth2 Infrastructure for the NRM

The physical infrastructure for the centralized OAuth2 server deployed by the NRM is shown in Figure 1. The salient features of this implementation are listed below:

  1. WebADE authorizations are stored in a relational database schema. The WebADE schema is a collection of database tables used to store WebADE configurations and authorizations.
  2. ADaM (Authority Delegation & Management) is a graphical user interface for managing WebADE authorizations. Changes made through the ADaM interface will affect both WebADE authorizations and OAuth2 scopes for applications that use either WebADE or OAuth2 security.
  3. The OAuth2 API implements most of the OAuth2 specification. However, the older WebADE-OAuth2 Service is still used to host the Authorize endpoint. The access token returned by the OAuth2 API contains scopes. The structure of the scopes is in the form of
application_acronym.action

For example, a scope for the FTA application would look like:

FTA.UPDATE_CUT_PERMIT
  1. The WebADE-REST API provides an endpoint that can be used to register an application to use the NRM OAuth services. The registration process is described later in this document.
  2. WebADE-OAuth2 authorization services are provided through the OAuth2 API which is published and secured via the WSO2 API Gateway. The OAuth2 API is a custom extension to WebADE utilizing the repository of authorizations maintained by WebADE. The WebADE-OAuth service implements most of the OAuth2 specification as described in RFC 6749. When valid credentials are presented, the OAuth2 API returns an OAuth access token

Note: Before connecting to WebADE, and before requesting an OAuth access token via the OAuth2 API, the “Client” must be registeredin WebADE. Within the BC Government computing environment, authentication services are provided by CA SiteMinder. OAuth2 is not an authentication protocol.

API Management

APIs for the NRM common services are managed using the open source WSO2 API Manager. The WSO2 API Manager is an open source product that is used to version, publish and secure APIs that were built using Rest Web service technology. The WSO2 API Manager also provides the capability to monitor API usage and to dynamically throttle API traffic.

API Endpoints

Endpoints for the production version of NRM common services may be found at: https://api.nrs.gov.bc.ca. Non-production (test) API endpoints are located at: https://t1api.nrs.gov.bc.ca. All of the common service APIs require an access token to be included as part of the header request in order to invoke the API.

API Versioning

NRM common services are versioned. API versioning follows the pattern:

/ API Endpoint / API name / API version /

The API version is specified as v1, v2 etc which is included in the URL. The WSO2 API Manager also supports a URL for APIs that does not include a version number. The URL without the version normally references the most recent version of the API. This URL can be used as a permanent, immutable reference to the API. This feature can be particularly useful when specifying HATEOS links.

API Store

The API Store lists published APIs. Potential consumers can browse the API Store to discover available APIs. The API Store also provides information regarding API end-points which is available through the “API Console” tab. Detailed documentation for the API is available through the “Documentation” tab.
Most developers will find the “API Console” tab of the API Store to be extremely useful. Both the high-level design and low-level capabilities of the API can be easily determined from the “API Console” tab. The “Expand Operations” option provides information regarding response messages. The “Try it out” button within “Expand Operations” provides developers with properly structured.

Note: The Production API Store is currently implemented in read-only mode. As of January 2019, the common services APIs include:

  1. Client Management
  2. Document Generation
  3. Document Management
  4. Common Messaging
  5. Common WebMapping

WebADE-OAuth Configuration

The WebADE-OAuth2 service implemented by the NRM uses WebADE as the repository of authorizations. The work required to configure WebADE to support OAuth2 security for an application is intended to be minimal. When applications are designed to protect their resources using OAuth2, the application (client) must be registered in WebADE

Registering the Application (Client) in WebADE

There are two approaches available for registering the application (client) in WebADE. One approach is to pass a JSON file containing the application (client) configuration data to the WebADE API for registration in WebADE. The alternate approach is to insert the application (client) configuration data directly into the WebADE database tables using database scripts. A sample of the database scripts used to register a client in WebADE are provided at the end of this document. The recommended approach for development teams is to use the WebADE API to register the application.
Note: When the application (client) has been registered in WebADE using database scripts, a JSON configuration file can be generated by querying the WebADE-API for the target application.

Registering an Application (Client) using the WebADE API

Figure 2 depicts the process used to register an OAuth2 application (client) using the WebADE-REST API. This approach requires that certain prerequisites be complete before attempting to register the application (client). These prerequisites include:

  1. Developers must be registered for access to the Ministry Git repository (Stash)
  2. Developers must be registered to user the Ministry Jenkins
  3. Developers must have obtained a valid IRS acronym for the application under development

Registration
Figure 2 – Application (Client) Registration using the WebADE API

Once these prerequisites have been met, a configuration file for the application can be created. The configuration file is in JSON format and must be named app.json where ‘app’ is the application acronym registered in IRS. A Jenkins job should be configured to submit the configuration file to the WebADE API.
This process is depicted in Figure 2 is as follows:

  1. The application (client) configuration file is created as ‘app.json’; an example is available here
  2. A Jenkins job is configured to submit the configuration file to the WebADE API; the production version of the WebADEAPI may be found at: https://api.nrs.gov.bc.ca/webade-api/v1
  3. When the Jenkins job runs, configuration information is passed to the WebADE API which results in database tables in the WebADE database schema being populated with rows that contain the control information for the Service Client
  4. The Service Client configuration information can be updated by modifying the ‘app.json’ file and re-running the Jenkins job or manually using the ADaM graphical user interface.
    Note: If the application has been previously registered in WebADE using database script method, a fully populated app.json file can be generated from a query of the WebADE-REST API. This mechanism is provided for development team that registered the application for OAuth using database scripts to easily switch to using the app.json configuration file method.

Registering OAuth2 Grant Types in WebADE

When the resource owner is a person, they are referred to as an end-user. To access a resource on behalf of an end-user, the application (client) must obtain an access token. Access can be implemented using the Authorization Code Grant Type or the Implicit Grant Type. The architecture of the client application will dictate which grant type (authorization flow) must be used to obtain the access token.

Configuring an Authorization Code Grant Type

The Authorization Code Grant Type is the most common of the OAuth 2.0 grant types. It is used by web apps and native apps to get an access token.

Configuring an Implicit Grant Type (Flow)

The Implicit grant type can be used by public applications (clients) where the access token is returned immediately without the need for an the authorization code exchange.

Configuring the Client Credentials Grant Type (Flow)

The Client Credentials grant type is used by applications (clients) to obtain an access token outside of the context of a user. This grant type is typically used by applications (clients) to access resources about themselves rather than to access a user's resources. This provides secure access outside the context of a user request.

Configuring User Roles and OAuth Scopes in WebADE

In addition to registering a application (client) in WebADE, and specifying the OAuth Grant Type, we must also specify OAuth2 scopes. OAuth2 scopes are used to control the degree of access that is granted by an access token. In the WebADE-OAuth API, the combination of application acronym and WebADE “actions” are used as the building blocks for formulating OAuth2 scopes. For applications protected by WebADE, roles and actions can be specified using the ADaM interface to authorize groups and users for operations within the application itself. Thus for many applications, two levels of authorizations are required. The first level to permit access to the application API. The second level of authorization to permit use of the underlying application. Therefore, multiple scopes may be required for use of a WebADE protected application. Multiple scopes can be specified using the wildcard syntax app.* to request all available scopes for an application. While all available scopes can be requested, only authorized scopes will be returned in the access token.

Examples for Developers

In order to use an NRM API protected by OAuth2, we need to first obtain an access token by calling the /token endpoint of the authorization server. The type of token request and the desired scopes for the token are specified as query parameters. The client credentials (client_id, client_secret) are validated using Basic Authentication. A successful response from the authorization server will return a JSON formatted body with details describing the token. The ‘access_token’ property is the token string that must be sent to the resource server via the HTTP authorization header.

Example - Client Credentials Token Request

https://t1auth.nrs.gov.bc.ca/pub/webade-oauth2/oauth/token?grant_type=client_credentials&scope=NRS_COMMON_PHONEBOOK.
HTTP/1.1*
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8

{
"access_token":"4385be59-9906-429f-8fed-bed18f684258",
"token_type":"bearer",
"expires_in":43199,
"scope":"NRS_COMMON_PHONEBOOK.VIEWER NRS_COMMON_PHONEBOOK.UPDATER",
"jti":"3a754da2-ece7-4e54-95ef-cabc6d390507"
}

Example - Obtaining an Authorization Code Token

In order to obtain an Authorization Code token, the requesting application must have some ability to navigate and display web content similar to a web application being accessed via a web browser. Before we call the /token endpoint we must first call the /authorize endpoint of the authorization server to get an authorization code. The request parameters must include the type of response expected, the application (client) name, the desired scopes for the token, and the redirect URL where the authorization code will be returned.

https://t1auth.nrs.gov.bc.ca/pub/webade-oauth2/oauth/authorize?client_id=NRS_STAFF_PORTAL&scope=NRS_COMMON_PHONEBOOK.*&redirect_uri=http%3A%2F%2Fwww.redirecturi.com&response_type=code HTTP/1.1

If the application (client) requests a scope for which the application has not been authorized, the return value will include a request parameter error code. If the application (client) has been authorized for at least a subset of the requested scopes, then the request will be redirected to the provided URL with a request parameter code.

HTTP/1.1 302 Moved Temporarily Location: http://www.redirecturi.com?code=wEPbvy

Once an authorization code has been obtained, a call can be made to the /token endpoint of the authorization server. The type of token request, the desired scopes for the token, the redirect URL and the authorization code are specified as query parameters. The application (client) credentials are provided using BASIC Authentication. A successful response will return a JSON formatted body with details describing the token. The ‘access_token’ property is the token string that must be sent to the resource server via the Authorization header in order to be granted access to the API. For example:

https://t1auth.nrs.gov.bc.ca/pub/webade-oauth2/oauth/token?grant_type=authorization_code&code=wEPbvy&scope=NRS_COMMON_PHONEBOOK.*&redirect_uri=http%3A%2F%2Fwww.redirecturi.com HTTP/1.1 Authorization: Basic Q0NTQzpwYXNzd29yZA==

HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8

{
"access_token":"d603a449-3916-41e3-962e-8ecc202f60a2",
"token_type":"bearer",
"refresh_token":"7cb8bf10-7be1-4ca1-9c1c-02dbce849983",
"expires_in":43199,
"scope":"NRS_COMMON_PHONEBOOK.VIEWER NRS_COMMON_PHONEBOOK.UPDATER",
"jti":"c108f701-83cd-42cc-900e-d1b162e94a79"
}  

Example - Obtaining an Implicit Token

To obtain an Implicit token, the requesting application must have some ability to navigate and display web content like a web application being accessed via a web browser. Instead of calling the /token endpoint which requires the Service Client credentials, we redirect the user to the /authorize endpoint of the authorization server to obtain the token. When redirecting we include as request parameters, the type of response expected, the application (client) name, the desired scopes for the token, and the URL where the authorization code will be returned. For example:

https://t1auth.nrs.gov.bc.ca/pub/webade-oauth2/oauth/authorize?client_id=NRS_STAFF_PORTAL&scope=NRS_COMMON_PHONEBOOK.*&redirect_uri=http%3A%2F%2Fwww.redirecturi.com&response_type=token%20HTTP/1.1

Once an authorization code has been obtained, a call can be made to the /token endpoint of the authorization server. The type of token request, the desired scopes for the token, the redirect URL and the authorization code are specified as query parameters. The application (client) credentials are provided using BASIC Authentication. A successful response will return a JSON formatted body with details describing the token. The ‘access_token’ property is the token string that must be sent to the resource server via the Authorization header in order to be granted access to the API

HTTP/1.1 302 Moved Temporarily Location: https://www.redirecturi.com#access_token=6d6690e9-0c90-456e-a454-79dd9c656e38&token_type=bearer&expires_in=2591999&scope=NRS_COMMON_PHONEBOOK.*&jti=808b594c-2f12-4db4-a09d-59736989a751

Example - Using a Security Token to call an OAUTH protected resource

Regardless of how the security token is obtained the token can be used to authorize any requests to the OAuth protected resource server for as long as the token is valid. The ‘expires_in’ parameter of the token request indicates how long the token will be valid. A valid token is provided to the resource server with each request as part of the Authorization header.

Authorization Header Format

Authorization: Bearer <access token>

Example OAuth Protected Resource Request

GET .../phonebook-api/v1/ HTTP/1.1
Authorization: Bearer 205f3bfd-1abe-4f07-8edc-bf5dc8930574

Example - Using Spring to Simplify use of OAUTH2 in Java Applications

Using OAuth security can be complex if you have to implement all of the flow logic yourself. Fortunately, the Spring project provides Java libraries that implement all of the OAuth grant types (flow logic) and simplify access to OAuth protected resources. Attached is a Java class that shows how to implement API access using the OAuth Client Credentials Grant Type. This grant type (flow) is used to access an OAuth protected API using the Spring support classes. The Authorization Code Grant and Implicit Grants are more complex and require a bit more code to implement. However, Spring provides support libraries and code examples for both.
For additional information concerning Spring security, please see:

Using WebADE Database Scripts

Registering the Application (Client) using a database script

An Application (client) can also be registered by inserting rows directly into the WebADE SERVICE_CLIENT database table using a database script. You can insert a record into the SERVICE_CLIENT table to register the application as either a client application or as a resource server.

INSERT INTO SERVICE_CLIENT (SERVICE_CLIENT_ID,USER_GUID,ACCOUNT_NAME, SECRET,APPLICATION_ACRONYM,ACCESS_TOKEN_VALIDITY, REFRESH_TOKEN_VALIDITY,ADDITIONAL_INFORMATION,
REVISION_COUNT,CREATED_BY,CREATED_DATE, UPDATED_BY,UPDATED_DATE)
VALUES (service_client_seq.nextval,SYS_GUID(),'APP NAME','s0QYqlr8’,null,null,null,'{"autoapprove":"true"}',1,'NRS_AS v1.0.0', SYSDATE,'NRS_AS v1.0.0',SYSDATE);

Table 1 - Column descriptions for SERVICE_CLIENT database table

Column Name Description
service_client_id This is the PK of the table. Use the service_client_seq sequence.
user_guid This is a unique GUID for the service client. Use the SYS_GUID function.
account_name This is a unique name for the service client.
secret This is the service client’s password. This will be encrypted on first use.
application_acronym If the client app is secured by webade then provide the application acronym.
access_token_validity The duration in seconds that an OAUTH2 access token issued to this client will be valid. Null for default.
refresh_token_validity This duration in seconds that an OAUTH2 refresh issued to this client will be valid. Null for default.
additional_information Json formatted text. Use {"autoapprove":"true"}
revision_count The number of updates that have been applied to this record. Use 1.
created_by The name of the user that was responsible for the inserting of this record.
created_date Use SYSDATE.
updated_by The name of the user that was responsible for the inserting of this record.
updated_date Use SYSDATE.

Registering an OAuth2 Grant Type using a database script

To implement this grant type, we must insert a record into the SERVICE_CLIENT_GRANT_TYPE table, specifying the grant type. OAuth2 Grant Type supported by WebADE include:

  1. Implicit Grant Type: Insert a record into the SERVICE_CLIENT_GRANT_TYPE table with ‘implicit’ as the grant type.
  2. Client Credentials Grant Type: Insert a record into the SERVICE_CLIENT_GRANT_TYPE table with the ‘client_credentials’ as the grant type.
  3. Refresh Tokens: Insert a record into the SERVICE_CLIENT_GRANT_TYPE table with either the ‘refresh_token’ grant type. Note: Refresh Tokens are not available with Implicit Grants.
INSERT INTO SERVICE_CLIENT_GRANT_TYPE (SERVICE_CLIENT_GRANT_TYPE_ID,SERVICE_CLIENT_ID,GRANT_TYPE, REVISION_COUNT,CREATED_BY,CREATED_DATE,
UPDATED_BY,UPDATED_DATE)
VALUES (service_client_grant_type_seq.nextval, service_client_seq.currval,'client_credentials',1, 'NRS_AS v1.0.0',SYSDATE,'NRS_AS v1.0.0',SYSDATE);

Table 2- Column descriptions for SERVICE_CLIENT_GRANT_TYPE database table

Column Name Description
service_client_grant_type_id This is the PK of the table. Use the service_client_grant_type_seq sequence.
service_client_id This is the FK of the SERVICE_CLIENT table.
grant_type Use ‘client_credentials’, ‘authorization_code’, ‘implicit’, or ‘refresh_token’.
revision_count The number of updates that have been applied to this record. Use 1.
created_by The name of the user that was responsible for the inserting of this record.
created_date Use SYSDATE.
updated_by The name of the user that was responsible for the inserting of this record.
updated_date Use SYSDATE.

Registering the Client Action Link using a database script

For each application (client) that is permitted to request an OAuth2 access token, we need to insert a record in the SERVICE_CLIENT_ACTION_LNK database table. We can also create a so called ‘wild card’ record by only specifying the application acronym which will allow the application to obtain a token for any security scope belonging to the resource server.

INSERT INTO SERVICE_CLIENT_ACTION_LNK (SERVICE_CLIENT_ACTION_LNK_ID,SERVICE_CLIENT_ID,ACTION_NAME, APPLICATION_ACRONYM,REVISION_COUNT,CREATED_BY, CREATED_DATE,UPDATED_BY,UPDATED_DATE)
VALUES (service_client_action_lnk_seq.nextval,service_client_seq.currval,null, 'NRS_AS',1,'NRS_AS v1.0.0',SYSDATE,'NRS_AS v1.0.0',SYSDATE);

Table 3 - Column Descriptions for SERVICE_CLIENT_ACTION_LNK database table

Column Name Description
service_client_action_lnk_id This is the PK of the table. Use the service_client_action_lnk_seq sequence.
service_client_id This is the FK of the SERVICE_CLIENT table.
action_name The name of the action or null to indicate all actions.
application_acronym The acronym of the resource server application.
revision_count The number of updates that have been applied to this record. Use 1.
created_by The name of the user that was responsible for the inserting of this record.
created_date Use SYSDATE.
updated_by The name of the user that was responsible for the inserting of this record.
updated_date Use SYSDATE.