StatPro Revolution Web API


Authorization using OAuth2


Native applications

Native applications run on an end user's computer desktop or mobile device. As with Server-Side Web apps, the user is prompted at runtime to grant access, and the OAuth 2.0 Authorization Code flow is used to provide a Native application with an access token and refresh token. A Native application, however, typically uses an embedded browser control to prompt the user for access since the application itself doesn't run in a browser. Native applications are not considered to be confidential with respect to the code that talks to the OAuth2 Server.


Workflow

The following subsections detail how a registered Native application gets an access token from the OAuth2 Server, and then uses that access token to request user data from the Web API.

The steps are:-

  1. Client application issues an authorization request
  2. Client application receives an authorization response
  3. Client application swaps an Authorization Code for an access token and refresh token
  4. Client application issues requests to the Web API using an access token
  5. Client application gets a new access token from a refresh token

For steps 1 and 2, a firm understanding of section '4.1. Authorization Code Grant' of RFC 6749 is required.

For step 3, a firm understanding of section '5. Issuing an Access Token' of RFC 6749 is required.

For step 5, a firm understanding of section '6. Refreshing an Access Token' of RFC 6749 is required.

You may also find the book "Getting Started with OAuth 2.0" by Ryan Boyd to be useful.


Step 1. Client application issues an authorization request

Issue a GET authorization request to the Authorization endpoint (https://revapiaccess.statpro.com/OAuth2/Authorization), according to the rules of section '4.1.1. Authorization Request' of RFC 6749.

Native applications are by definition not browser-based, but they must still use a web browser to talk to the OAuth2 Server. See Step 1a. Native application uses system or embedded browser below for guidance.

The query strings that are added to the Authorization endpoint's URI:-

The response_type query string value MUST be "code" (without the quotes).

The client_id query string value MUST be set to the application's registered public identifier. The identifier must be case-correct (i.e. it is treated case sensitively).

The redirect_uri query string value MUST be set to the application's registered redirect URI which, for Native applications, is always "urn:ietf:wg:oauth:2.0:oob" (without the quotes). The redirect URI must be case-correct (i.e. it is treated case sensitively).

The scope query string value MUST be set to "RevolutionWebApi" (without the quotes).

The state query string value is REQUIRED. The specified state value should be retained, and later used to verify the authorization response (whether successful or in error). See RFC 6749 for more details.

All query string values MUST be correctly encoded (i.e. URL encoding).


Example:-

GET https://revapiaccess.statpro.com/OAuth2/Authorization?response_type=code&client_id=s6BhdRkqt3&scope=RevolutionWebApi&state=xyz&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob HTTP/1.1


Step 1a. Native application uses system or embedded browser

The end user (aka resource owner) is always prompted to grant or deny access by the OAuth2 Server for an authorization request. Because the OAuth2 Server is a website, a web browser must always be used. For Server-Side Web applications the web browser in question is simply the browser that the user is currently using to view and interact with the web app. A native application, on the other hand, must do more work.

A native application has two choices:-

  1. Use a web browser application (e.g. the system web browser).
  2. Embed a Web Browser control in one of its forms (the terminology here differs from platform to platform).

Both approaches have their strengths and weaknesses. Using a separate application is less programmatic, and the user experience is more disjointed. On the other hand, a proper web browser application has strong security indicators. Embedding a Web Browser control is more programmatic, allowing the user experience to be made more streamlined. On the downside, it doesn't have strong security indicators, and it has its own, separate cookie store (e.g. separate from the system browser). The book "Getting Started with OAuth 2.0" by Ryan Boyd discusses both approaches in more detail (see chapter 6).

Using a web browser application (typically the system web browser)

Get the URI of the Authorization endpoint and add the correct query strings, as described in Step 1. Cause the browser to navigate to this address using the standard technique(s) for your platform. Assuming that the native application is unable to programmatically detect when the browser loads the Success or Failed page (and is unable to read information from the page), then the user should end up looking at one of the following two pages:-

Page 1.  Authorization Success

Page 1. Authorization Success


Page 2.  Authorization Failed

Page 2. Authorization Failed


As the Authorization Success page shows, the user is instructed to copy the code (an Authorization Code) to the Clipboard, and then paste it into the native application. The native application will need to provide a user interface for receiving this code.

Embedding a Web Browser control in one of the application's forms

Using Windows Forms terminology, the application embeds the Web Browser control in one of its forms, displays the form, directs the web control to the correct URI (see above), and then monitors when the web control has finished loading (e.g. via the DocumentCompleted event) either the Success page (https://revapiaccess.statpro.com/OAuth2/AuthCodeRequestSuccess) or the Failed page (https://revapiaccess.statpro.com/OAuth2/AuthCodeRequestFailed).

After detecting the redirect to either the Success or the Failed page, the idea is to programmatically read the required data (primarily the Authorization Code from the Success page), and then close the form as quickly as possible.

On the Success page the title will be:-

Success code=<authorization code> state=<client-specified state string>

The authorization code and the state string will also be specified as the values of query strings code and state of the redirected-to URL.

On the Failed page the title will be:-

Failed error=<error code> error_description="<error description>" state=<client-specified state string>

Note that the error code will not contain spaces. The error description may contain spaces. The state may contain spaces, but it is recommended that the client application specifies a state string that doesn't include spaces in the first place.

The error code, error description and the state string will also be specified as the values of query strings error, error_description and state of the redirected-to URL.

(Refer to section '4.1.2.1. Error Response' of RFC 6749 for a list of possible error codes.)


Step 2. Client application receives an authorization response

If the authorization request is valid, and if the end user (aka resource owner) grants access, the OAuth2 Server redirects to its Authorization Success page according to the rules of section '4.1.2. Authorization Response' of RFC 6749.

The native application SHOULD validate the value of the state query string to mitigate against a cross-site request forgery attack, as described in section '10.12. Cross-Site Request Forgery' of RFC 6749.

The native application SHOULD use the issued Authorization Code to get an access token (and refresh token) as soon as possible, because it has a short lifetime (approximately three minutes, but this figure may change).

If the authorization request is invalid, or if the end user denied access, the OAuth2 Server MAY redirect to its Authorization Failed page according to the rules of section '4.1.2.1. Error Response' of RFC 6749. (A redirect will not occur for certain types of error in the authorization request, or if the user simply closes the browser.) Currently the OAuth2 Server provides the optional error_description value, but not the optional error_uri value.


Step 3. Client application swaps an Authorization Code for an access token and refresh token

Armed with an authorization code obtained via the steps above, the client application is then expected to make a POST request to the OAuth2 Server's Token endpoint (https://revapiaccess.statpro.com/OAuth2/Token) to obtain an access token and refresh token. It (currently) has approximately three minutes in which to do so, before the authorization code expires.

The rules of this request are described in section '4.1.3. Access Token Request' of RFC 6749.

The OAuth2 Server REQUIRES that the client identifies itself via HTTP Basic Authentication for this request. E.g. include this request header:-

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

where the base64-encoded string is an encoding of:-

clientId + ":" + clientSecret

Notes:-

  1. The client identifier is NOT included in the entity body of the request.
  2. The client identifier is the application's public identifier, and is specified when registering the application.
  3. The client secret is provided to the application's administrator after the application has been successfully registered.
  4. In the context of a Native Application, the client secret is not a secret. Nevertheless, a native application should endeavour to keep its client secret as confidential as it can. The situation you are trying to avoid is that of a rogue application impersonating your application, by using its client id and secret. The fact that the resource owner (aka end user) is presented with the name of the application that is requesting authorization helps to mitigate this attack.

Example:-

POST https://revapiaccess.statpro.com/OAuth2/Token HTTP/1.1
Host: revapiaccess.statpro.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob


The response to the access token request is described by sections '4.1.4. Access Token Response', '5.1. Successful Response' and '5.2. Error Response' of RFC 6749.

For a successful response:-

  • it is guaranteed that the access token is base64-encoded; this has implications when requesting resources from the Web API;
  • the OAuth2 Server will always include a refresh token;
  • the refresh token may currently be a GUID, but this is an implementation detail and is subject to change;
  • the lifetime of the access token is currently set at 3600 seconds (an hour), but this is an implementation detail and is subject to change;
  • the token type is currently set to be "Bearer";
  • the server will always indicate the scope of the issued access token (i.e. what Resource Servers are accessible); this is a space-delimited list, although currently it will only be set to "RevolutionWebApi";
  • the server always augments the JSON in the entity body with the user's external identifier (which uniquely identifies the user within the Revolution system) and the user's display name, using members user_id and user_name respectively. See below for an example.

For an error response:-

  • error_uri is not currently set;
  • if an internal server error occurred, the response status is 500 and the error code is set to "server_error" (a non-standard error code in the context of this response).

Example of a successful response:-

{
    "access_token": "<base64-encoded access token>",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "RevolutionWebApi",
    "refresh_token": "3c5a821e-795e-44f7-abf4-ec0c0eb9bd30",
    "user_id": "4289ee5d82e3d8fb48ce4048e82344bc44ced59122a34db287c2457379aeb3e9",
    "user_name": "A Person"
}


Step 4. Client application issues requests to the Web API using an access token

Armed with the base64-encoded access token via the preceding step, the client app issues a request to the Revolution Web API (described elsewhere).

For each and every request to the Web API, add an Authorization header in this format:-

Authorization: Bearer <accessToken>

The access token must not be base64-encoded by the client application, because it is already base64-encoded.

The OAuth 2.0 Bearer Token Usage specification identifies three different methods of providing a bearer access token. The StatPro Revolution Web API supports only one - the Authorization header (aka Authorization Request Header Field) method.

A successful response should result in the requested resource representation being returned.

An unsuccessful response is described in section '3. The WWW-Authenticate Response Header Field' of RFC 6750. See sub-section '3.1. Error Codes' for how the Web API indicates that an access token is invalid or has expired. Example:-

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="StatPro Revolution Web API", error="invalid_token", error_description="The access token is invalid."

Note that a client application can use the date/time of receiving an access token combined with the indicated lifetime of the access token to predict (roughly) when it will expire, rather than waiting for the Web API to tell it so. (A well-behaved client application will only ask the OAuth2 Server for another access token when the current one has expired, or when expiry is imminent - e.g. within the next minute.)


Step 5. Client application gets a new access token from a refresh token

If an access token is used successfully (say for an hour), but then the Web API suddenly responds with a 401 status and an error of "invalid_token", for example:-

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="StatPro Revolution Web API", error="invalid_token", error_description="The access token is invalid."

then the access token has expired. In this case the client application can request another using the previously-issued refresh token. The end user is not prompted or alerted during this process. The client application requests a new access token by making a POST request to the OAuth2 Server's Token endpoint (https://revapiaccess.statpro.com/OAuth2/Token).

The rules of this request are described in section '6. Refreshing an Access Token' of RFC 6749.

Note that the OAuth2 Server requires that the client application identifies itself via HTTP Basic Authentication for this request, as in Step 3. For example, include the request header:-

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

where the base64-encoded string is an encoding of:-

clientId + ":" + clientSecret

Note that the scope form parameter is not used by the OAuth2 Server, and so shouldn't be specified.

The response from this request (whether successful or unsuccessful) is the same as for Step 3.

A client application may persist refresh tokens between application sessions, but this is discouraged.

Note that a refresh token, like an access token, is tied to a specific user. If an access token and a refresh token have been obtained for user A, then they mustn't be used for user B. The safest way to deal with this is to forget/drop the current access token and refresh token when the application is closed, and/or when the current user logs out.

Using a refresh token to get a new access token may fail because:-

  • the OAuth2 Server's transient cache of refresh tokens and/or underlying authorizations has been cleared;
  • the underlying authorization's lifetime of 31 days (this figure is subject to change) expired;
  • the user explicitly revoked the underlying 'interactive' authorization on the StatPro Revolution API Authorization Management website;
  • a new version of the Terms of Use for the Revolution Web API has been published, which the user has not yet accepted;
  • the user's right to use the Revolution Web API has been revoked by an administrator.

If unable to get a new access token from a refresh token, the client application wishing to access user data from the Web API has no option but to begin the workflow cycle again at Step 1.


Tenancy selection and tenancy information

Native applications can allow users to select which of their tenancies is used for any one interactive session. They can also get information about the tenancy that an access token targets. These advanced topics are covered on the Tenancy selection page.


Last updated: December 2016


To Top