OpenMRS OAuth2 module - for Client Developers
OAuth2 Protocol Flow
OpenMRS OAuth2 module strictly adheres to the OAuth2 specifications which are enforced by Spring Security and Spring Security OAuth2 projects. For a quick overview of the Oauth2 protocol flow, you can utilize the following resources :
Step 1 : Client Registration
If you wish to write external application that want to access OAuth2 protected resources from the OpenMRS installation, you will have to register your external application with the OAuth2 module running on the OpenMRS instance.
You will need to contact the administrator of OpenMRS installation to give you credentials to login as a client developer.
After logging into the OpenMRS instance, go-to your Admin page and click Manage Registered Clients under the OAuth2 module label.
This will display a list of clients registered by you. You can click on any of the clients in the list to see their details (client-id and client-secret).
To register a new client, Click "Register new Client" on top of the list. This will re-direct you to the client registration form.
Note : Currently all users are client developers as no particular OpenMRS role has been created for client develoeprs, therefore any login generic credentials should do for now.
The UI is being modified currently and screenshots will be up soon. The mid-term presentation talks in much details about the Client Registration Process with the old UI :
Talk Post : https://talk.openmrs.org/t/gsoc-2015-oauth2-support-for-web-services-apis-midterm-presentation/2284
After the client registration process you will receive an auto-generated client-id and client-secret which will be required during the remaining steps
Step 2 : Obtaining Access Token
1. Authorization Code Grant Type
Protocol Flow
The OAuth2 specification states the following workflow.
Fig : Authorization Code Flow
Here, as usual, the client is the external application. The authorization server is the OAuth2 module. The user agent is the browser being used by the resource owner( end-user).
A) The client initiates the flow by directing the browser to the authorization endpoint i.e to the OAuth2 module’s authorization controller in the omod layer. The client specifies its client identifier, requested scope, local state and a redirection URI in the request
B) The OAuth2 module will authenticate the end-user (via browser/user-agent). The OAuth2 module will then ask the end-user if he/she authorizes the client to act on their behalf.
C) Assuming the access is granted to the client, the OAuth2 module generates a authentication code and stores it in the database. It then redirects to the redirection URI it received in Part A after appending the authorization code and the local state request parameters.
D) The client sends a request to obtain an access token from the OAuth2 module and includes the authorization code received in the step C. The client should include the redirection URI used to obtain authorization code for verification. The OAuth2 module will first authenticate the client based on the strategy discussed in the Client Authentication section above.
E) The Oauth2 module authenticates the client, validates the authorization code, and ensures that the redirection URI of step D matches step C. If valid, the OAuth2 module will generate an access token and/ or a refresh token
Authorization Request
Authorization Endpoint : GET /ws/oauth/authorize
Request Structure :
Parameter | Required | Description |
response_type | REQUIRED | Value = “code” |
client_id | REQUIRED | Obtained during Client Registration |
redirect_uri | REQUIRED | The redirection endpoint provided during Client Registration |
scope | OPTIONAL | The scope of the request (Read/Write) |
state | RECOMMENDED | To be used by client to maintain state between request and callback. |
Demo Authorization Request :
Authorization Response
The OAuth2 module redirects the user to the refirectionURI specified during client registration and appends the following parameters in the response's query string :
Parameter | Required | Description |
code | REQUIRED | The authorization code generated by OAuth2 module.Expires in 10 minutes. Therefore make sure you send an access token request within this time frame |
state | REQUIRED | If the state parameter is present in the request, it is appended. |
Demo Authorization Response :
Access Token Request
Access Token Endpoint : GET /ws/oauth/token
Request Structure
Parameter | Required | Description |
grant_type | REQUIRED | Value = “authorization_code” |
code | REQUIRED | The authorization code received from OAuth2 module |
redirect_uri | REQUIRED | If the “redirect_uri” parameter was included in the authorization request, their value must be identitcal |
client_id | REQUIRED | The client_ID given to client during Client Registration process |
Demo Token Request
Access Token Response
The response to the access token request is a JSON object containing the access token plus some more information.
Property | Value |
---|---|
access_token | the access_token issued by the OAuth2 module |
token_type | bearer. OAuth2 module uses bearer tokens. So any request that 'bears' this token will be allowed to access the protected resource |
expires_in | number of seconds after which token will become invalid |
refresh_token | use this to get a fresh access token when the current access token has expired. (see the section on refresh token for details) |
Demo Access Token Response :
OAuth2 Access Token Response body (JSON)
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
}
Implicit Grant Type
Protocol Flow
Fig : Implicit Grant Flow
A) The client sends a request to the authorization endpoint of the OAuth2 module. The client includes its client identifier, requested scope, local state and redirection URI.
B) The OAuth2 module authenticates the user (resource owner) and establishes whether the end-usergrants or denies client’s access request.
C) Assuming access is granted, OAuth2 module generates a token , and includes it in the URI fragment of the redirection URI specified in Step A.
D,E,F) The user-agent retains the fragment information locally and processes the response to extract the access token
G) The user-agent(browser) passes the access token to the client.
Authorization Request
Authorization Endpoint : GET /ws/oauth2/authorize
Request Parameter Structure
Parameter | Required | Description |
response_type | REQUIRED | Value = “token” |
client_id | REQUIRED | Obtained during Client Registration |
redirect_uri | OPTIONAL | The redirection endpoint registered by the client |
scope | OPTIONAL | The scope of the request (see Client Registration) |
state | RECOMMENDED | To be used by client to maintain state between request and callback. |
Demo Authorization Request
Access Token Response
When the client gets authorized by the end-user, the OAuth2 module will generate an access token and include the following parameters to the fragment component of the redirection URI
Parameter | Required | Description |
access_type | REQUIRED | The access token issued by the OAuth2 module |
token_type | REQUIRED | "bearer" |
expires_in | RECOMMENDED | The lifetime in seconds of access token. |
scope | OPTIONAL | The scope of the request (Read/Write) |
state | RECOMMENDED | To be used by client to maintain state between request and callback. |
NOTE : As per specification, the OAuth2 module will not generate a refresh token for implicit grant type.
Demo Access Token Response:
Resource Owner Password Credentials Grant Type
Protocol Flow
This grant type is suitable when the resource owner (patient/doctor/ OpenMRS user etc) has a trust relationship with the client. As per specification, this grant type should be allowed only when other grant types are not available
Fig : Resource Owner Password Credential Flow
A) The end-user/resource owner provides the client with its username and password for the OpenMRS installation.
B) The client requests an access token OAuth2 module running on the OpenMRS installation through its token endpoint. The OAuth2 module authenticates the client as well.
C) The OAuth2 module authenticates the client and validates the end-user’s credentials, and if valid, it issues an access token.
Access Token Request
Token Endpoint : POST /ws/oauth2/token
Request Parameter Structure
The client needs to add the following parameters to the request made to the token endpoint.
Parameter | Required | Description |
grant_type | REQUIRED | Value = “password” |
username | REQUIRED | The end-user’s username |
password | REQUIRED | The end-user’s password |
scope | OPTIONAL | The scope requested by the client |
Demo Access Token Request:
Access Token Response
The response is a JSON object similar to the one shown in Authorization Code Grant Type's access token response.
Client Credentials Grant Type
Protocol Flow
The client can request access token using only client credentials to request access to OpenMRS modules and resources for which the client has permissions.
Fig : Client credentials flow
A) The client authenticates with the OAuth2 module and requests an access token from the token endpoint.
B) If the client authentication succeeds, OAuth2 module will generate a token and send it to client.
Access Token Request
Token Endpoint: POST /ws/oauth2/token
Parameter | Required | Desciption |
grant_type | REQUIRED | Value = “client_credentials” |
scope | OPTIONAL | The scope requested by the token |
Access Token Response
If the access token request is valid and authorized, the OAuth2 module will issue the access token and redirect to the redirection uri specified during client registration. The HTTP response to the client is exactly similar to those in Authorization Code grant type and Resource Owner Password Credentials grant type.
Step 3 : Retrieving Protected Resources
If you try to access the OAuth2 protected resources without an access token, an 401 Unauthorized response code will be returned.
After obtaining an access token, it can be used to access the protected resources by including the access token in the Authorization Header or as an request parameter while requesting the protected resource.
The OAuth2 module will intercept this request and validate the token and allow access to the protected resource if the token passes validation
Sample Request
Or
http://localhost:8080/openmrs/ws/fhir/Location/8d6c993e-c2cc-11de-8d13-0010c6dffd0f&
Request Header | Value |
---|---|
Authorization | Bearer fc49c67e-6932-4846-a4f9-e9a23822da1f |
Refreshing Tokens
Once the validity period of access tokens is over, you will have to generate a new access token by using any of the above mentioned grant types or you can swap the expired access token with a new one by using the refresh token that was issued along with the access token.
You need to make a request to the Token Endpoint and include the refresh_token as the request parameter
URI : GET /ws/oauth/token
Request Parameters
Parameter | Required | Description |
---|---|---|
grant_type | REQUIRED | "refresh_token" |
access_token | REQUIRED | the access token that has expired |
refresh_token | REQUIRED | the refresh_token that was issued along with the access token |
Demo Request
http://localhost:8080/openmrs/ws/oauth/token&grant_type=refresh_token&access_token=2YotnFZFEjr1zCsicMWpAA&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
Demo Response
The response will include a JSON object containing the new access token, token type, expiry time and refresh token as shown in the Access Token Reponse for Authorization Code Grant Type.