-
Notifications
You must be signed in to change notification settings - Fork 10
OAuth2 WebADE Developer Guide
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.
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.
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:
- 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.
- 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.
- 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
- 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.
- 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.
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.
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.
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.
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:
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
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.
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:
- Developers must be registered for access to the Ministry Git repository (Stash)
- Developers must be registered to user the Ministry Jenkins
- Developers must have obtained a valid IRS acronym for the application under development
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:
- The application (client) configuration file is created as ‘app.json’; an example is available here
- 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
- 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
- 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.
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.
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.
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.
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.
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.
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.
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"
}
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.
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:
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"
}
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:
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
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: Bearer <access token>
GET .../phonebook-api/v1/ HTTP/1.1
Authorization: Bearer 205f3bfd-1abe-4f07-8edc-bf5dc8930574
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:
- https://projects.spring.io/spring-security/
- http://projects.spring.io/spring-security-oauth/
- http://projects.spring.io/spring-social/
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. |
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:
- Implicit Grant Type: Insert a record into the SERVICE_CLIENT_GRANT_TYPE table with ‘implicit’ as the grant type.
- Client Credentials Grant Type: Insert a record into the SERVICE_CLIENT_GRANT_TYPE table with the ‘client_credentials’ as the grant type.
- 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. |
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. |
Return Home
- Home
- Common Services
- Authentication
- Authorization
- Data Persistence
- Developer Resources
- Observability
- Operations
- Research
- Testing
- Acronyms and Terms