Skip to content

User Authentication

Accessing Platform 6 products as a user requires an access token granted using OAuth 2.0. This guide explains in detail how user authentication works in P6.

Overview

One of the main goals of OAuth is allowing a client application (a client in OAuth2 terms) to authenticate a user to REST API providers (the resource providers) without having to capture the user’s credentials.

The client should never store the credentials of the user, only the access token and the refresh token - if available - delivered following the OAuth dance.

The access token has a short time to live (in minutes), and the refresh token can be used by the client to get a new access token delivered for the user. The refresh token has a much longer time to live (in days). If it also expires, the whole dance should be restarted from the start.

In summary, the dance is as follows:

Initial authorization grant:

  • The client calls the authorize endpoint on the login server using its credentials (client_id, client_secret and redirect_uri).
  • The login server replies with a 302 redirecting to a login page.
  • The client displays the login page to the user.
  • The user enters their credentials (username and password) on the login page and submits them to the login server.
  • The login server replies with an authorization code, and the login form redirects to the client redirect_uri, passing the authorization code as a parameter.
  • The client calls the login server’s token endpoint using the authorization code to retrieve the user access token and refresh token (if any).

Refresh token grant:

  • The client calls the token endpoint on the login server passing the refresh token and grant_type of refresh_token as parameters.
  • The login server replies with a new access token.

OAuth2 stakeholders

Login server

The login server is the only server delivering access and refresh tokens.

The server is found at login.amalto.io. The IP address may change, but the server name is fixed.

The login server listens to HTTP requests on its 443 port only.

Client

A client consumes services provided by resource providers on behalf of the user.

A client is identified to the login server by a triplet:

  • client ID (client_id)
  • secret (client_secret)
  • redirect URI (redirect_uri)

The redirect URI is part of the authentication and is validated by the login server. It is also the URI redirected to by the login page with the authorization code passed as a query parameter called code.

User

The user is the final consumer of the services.

A user authorizes a client to consume services on resource providers (e.g. to call their REST APIs) on its behalf. The access token holds this authorization; the refresh token provides the possibility to the client to get a new access token without having the user re-enter her/his credentials.

A user is identified to the login server by a username and a password.

Resource provider

A resource provider (basically a P6 instance) exposes its services for the client’s consumption.

Resource providers expose a REST API.

When a client issues a REST call to a resource provider, it is expected to provide an HTTP Authorization header, starting with the word Bearer, followed by a space and followed by an access token:

Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpPU0UifQ.eyJpc3MiOiAiaHR0cDovL2FtYWx0by5jb20iLCA...

The access token will be validated by the resource provider. If it is absent or invalid, the resource provider will return a 401.

Authorization is associated to the access token in the form of scopes. When the client calls a service on the resource provider, the latter verifies that the user identified by the access token has the appropriate scopes to authorize the request to complete. When that is not the case, the resource provider will reply with a 403.

Resource providers support CORS and can answer Cross-Origin requests.

Initial authorization grant in detail

1 - Authorize endpoint call

The client calls the authorize endpoint on the login server using its credentials (client_id, client_secret and redirect_uri).

This is an HTTP GET call to https://login.amalto.io/oauth2/authorize passing client credentials as query parameters in addition to a query parameter called response_type with the value set to code.

Example using curl

curl -v "https://login.amalto.io/oauth2/authorize?client_id=myClientId&client_secret=myClientSecret&redirect_uri=http://localhost:8080/receiveAuthCode&response_type=code"

The login server will reply with a 302 and the location header will contain the URL of the login page.

< HTTP/1.1 302 Found
< Date: Tue, 23 Jun 2015 08:51:10 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Allow-Headers: origin, authorization, content-type, accept
< Location: https://login.amalto.io/p6auth?code=3c870b0b43ce6675077d39cd24fdaad3&realm=b2&cctx=%2F
< Content-Length: 0

In case of an error, the location will be that of the redirect URI augmented with two query parameters:

  • error: which provides an error code
  • error_description: a human-readable description of the error
< HTTP/1.1 302 Found
< Date: Wed, 24 Jun 2015 13:19:15 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Allow-Headers: origin, authorization, content-type, accept
< Location: http://localhost:8080/receiveAuthCode?error_description=Client+authentication+failed+%28e.g.+unknown+client%2C+no+client+authentication+included%2C+or+unsupported+response+type%29.&realm=b2&error=unauthorized_client
< Content-Length: 0

2 - User login

The client should display the page indicated in the location header above by calling the full URL including the query parameters.

The user should then enter its credentials (username and password) and hit the submit button. When doing so, the login page will issue a POST to the login server.

Using curl the POST would be something like:

curl -d "uname=myusername&pw=mypassword&code=3c870b0b43ce6675077d39cd24fdaad3&realm=b2" https://login.amalto.io/oauth2/authorize-cont

The login server will reply with a 200 and will pass a JSON containing the authorization code and optionally, the redirect_uri:

{
    "code": "aze4a57edf5h",
    "redirect_uri": "http://localhost:8080/receiveAuthCode"
}

The login page will then call the client redirect URI, passing the code as a query parameter; using curl:

curl "http://localhost:8080/receiveAuthCode?code=aze4a57edf5h"

3 - Retrieving the access token and refresh token

Once the client is called on its redirect URI, it should recover the authorization code passed as the code query parameter and issue a call to the login server to get access to the tokens.

The call is FORM POST call to the token endpoint where the client passes:

  • its 3 credentials,
  • the authorization code in the code parameter,
  • a grant_type parameter with value fixed to authorization_code

Using curl:

curl -d "client_id=myClientId&client_secret=myClientSecret&redirect_uri=http://localhost:8080/receiveAuthCode&code=aze4a57edf5h&grant_type=authorization_code" https://login.amalto.io/oauth2/token

The server will respond with a 200 and a JSON:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpPU0UifQ.eyJpc3MiOiAiaHR0cDovL2FtYWx0by5jb20iLCAic3ViIjogInByb3h5dGVzdHMiLCAiYXVkIjogWyJw...",
    "refresh_token": "iOiAiaHR0cDovL2FtYWx0by5jb20iLCAic3ViIjogI",
    "scope": "demo:counters:summary p6auth:user:write",
    "expires_in": 600
}

The only mandatory field is access_token. Other fields may not be provided by the login server.

scope is a space-separated list of the authorizations granted to this access token.

expires_in is the time to live in seconds of the access token. After that period, the refresh_token should be used to recover a new access token. From now on, on all calls to the resource providers REST API, the client should insert an Authorization header of typeBearer in its HTTP requests, i.e.

GET https://proxy.amalto.com/apis/v2/counters/summary?baseUrl=https://demo.platform6.com/p6
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpPU0UifQ.eyJpc3MiOiAiaHR0cDovL2FtYWx0by5jb20iLCAic3ViIjogInByb3h5dGVzdHMiLCAiYXVkIjogWyJw...
Host: proxy.amalto.com

Refresh token grant

When the access token expires, a new request to a resource provider will return a 401.

When a refresh token is available, the client should use the refresh token to get a new access token then replay the original request to the resource provider using the new access token.

The client should keep this process transparent to the user.

To refresh a token, the client issues a FORM POST request to the login server token endpoint passing:

  • its 3 credentials,
  • the refresh token in the refresh_token parameter,
  • a grant_type parameter with value fixed to refresh_token

A curl request would look like:

curl -d "client_id=myClientId&client_secret=myClientSecret&redirect_uri=http://localhost:8080/receiveAuthCode&refresh_token=iOiAiaHR0cDovL2FtYWx0by5jb20iLCAic3ViIjogI&grant_type=refresh_token" https://login.amalto.io/oauth2/token

Note

Although the redirect_uri is never called, it is considered an authentication parameter and must be valid.

The server will respond with a 200 and a JSON:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpPU0UifQ.eyJpc3MiOiAiaHR0cDovL2FtYWx0by5jb20iLCAic3ViIjogInByb3h5dGVzdHMiLCAiYXVkIjogWyJw...",
    "expires_in": 600
}

The only mandatory field is access_token. Other fields may not be provided by the login server.

expires_in is the time to live in seconds of the access token. After that period, the refresh_token should be used once again to recover a new access token.