Single Sign On

Single Sign On

Introduction

We provide an Open ID Connect compliant authentication service to facilitate single-sign-on across your custom applications, the merchant and administration portal (BIP) and the developer portal.

This guide runs through each of the API calls required to integrate the service. After integrating, users can log in into your application using their credentials as defined in the BIP. Additionally, they will also be directly logged into the BIP or some other PAY.ON application in case you redirect them to specific endpoints for each application (i.e. single sign on).

This solution follows the OAuth2 authorization code workflow (https://tools.ietf.org/html/rfc6749#page-8) and in order to successfully integrate your application you will need credentials named throughout this tutorial as client id and client secret. If you do not have one for your application, ask your account manager on how to obtain one.

An example implementation of the Authentication Service in Java can be found on GitHub.

Login workflow

Overview

The goal of the login workflow is to allow a user previously configured at the PAY.ON platform to log in into an integrated application with their credentials. This is accomplished in the following steps:

  1. Your application redirects the user browser to the authentication endpoint (/v1/authenticate).
  2. The user inserts his credentials and logs in.
  3. The browser is redirected back to your application according to the redirect url that you defined during the first call.
  4. Your application requests and receives an access token (/v1/tokens).
  5. Your application uses the access token to query information about the user (/v1/users).
  6. Your application receives information about the user and logs him in according to your rules.

The following sequence diagram details a login workflow. Details on how to implement your application to follow this workflow is further explained in the tutorial following.

Redirecting the user to authenticate

Whenever a user needs to be authenticated into an application, it should start a Login Workflow. In order to do that, your application only needs to redirect the user to the authentication endpoint (GET - /v1/authenticate) passing a few parameters in the request string such as the client id of the application (client_id), the URL to redirect the user back to your application after a successful workflow (redirect_url) and some other mandatory parameters (scope=openid, response_type=code)

Request

Parameter Mandatory Format Comment
client_id mandatory AN OAuth client ID - described on BIP as attribute of an OAUTH_APP user
redirect_uri mandatory AN The URL to redirect the user back after a successful authentication. This URL needs to be previously handled as a url encoding algorithm before sent.
scope mandatory AN The scope for currently accessing data. Currently it is mandatory the value "openid"
response_type mandatory AN The type of OAuth2 workflow to execute. Currently it is mandatory the value "code"
state optional AN

An optional parameter to prevent Cross Site Request Forgery (CSRF) following the OAuth2 specification.

This same value sent by the redirect to the authentication server will be returned back to the client application.

For more information: http://www.twobotechnologies.com/blog/2014/02/importance-of-state-in-oauth2.html

prompt optional AN

Determines if the authentication server should or should interact with the user requesting authentication details whenever the user is not yet logged in.

if: [1. prompt=none; and 2. user is not logged in the authentication server] then the server will redirect the user back to the url defined by "redirect_url" with an additional response parameter error=login_required in the query string.

Response

Redirection to the login form for the user to authenticate using his credentials.

Example

curl "https://yourapp.com/login" -v
* About to connect() to localhost port 3000 (#0)
* Trying 127.0.0.1... connected
* Connected to an-external-app.com (127.0.0.1) port 80 (#0)
> GET /login HTTP/1.1
> User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.15 libssh2/1.2.6
> Host: an-external-app
> Accept: */*
 
HTTP/1.1 302 Moved Temporarily
X-Powered-By: Express
Location: https://test.oppwa.com/authentication/v1/authenticate?client_id=da39a3ee5e6b4b0d3255bfef95601890afd80709&redirect_uri=https://an-external-app.com/enter&scope=openid&response_type=code&state=someState
Vary: Accept
Content-Type: text/plain; charset=utf-8

Requesting an access token

After the Authentication Manager has successfully authenticated the user, it will redirect the browser back to your application - more specifically to the url your application provided with the redirect_url parameter. With the redirect your application shall receive a parameter code in the query string. When the user is back to your application, you should request an access token in order to perform further calls to query user information. This can be done by performing a server-to-server call to the Token endpoint (POST - /v1/tokens), passing the value of the code parameter received in conjunction with the same request_uri sent on the first redirect, the client id and client secret for your application and some mandatory parameters (grant_type=authorization_code, scope=openid).

Request

HTTP Header Mandatory Format Comment
Authorization mandatory AN

This header follows the HTTP Basic authentication scheme (http://tools.ietf.org/html/rfc1945#page-48).

In order to create a valid value, you need to encode the string "{yourClientId}:{yourClientSecret}" in base 64

and append the result to the string "Basic {yourBase64String}".

In summary: "Basic " + base64.encode(clientId + ':' + clientSecret)

Parameter Mandatory Format Comment
code mandatory AN One time use code passed by authentication
grant_type mandatory AN Type of grant associated with the token request. Currently we only accept: 'authorization_code'
redirect_uri mandatory AN Redirect url provided on the first redirect
scope mandatory AN Scope of the token. Currently we only accept: 'openid'

Response

Attribute Format Comment

access_token

AN256

The access_token that allows further calls from an application in behalf on an user

expires_in N Amount of time until the expiration of the access token (in seconds)
token_type AN

The type of token defined on the OAuth2 specification that was sent.

Currently this value will be only 'bearer'. Check https://tools.ietf.org/html/rfc6750 for more details

scope AN Currently this value will only be 'openid'

Example

curl "https://test.oppwa.com/authentication/v1/tokens" --header "Authorization: Basic ZGEzOWEzZWU1ZTZiNGIwZDMyNTViZmVmOTU2MDE4OTBhZmQ4MDcwOTpheENSR0VlMg==" -d "code=V5YL7D" -d "grant_type=authorization_code" -d "redirect_uri=http://an-external-app.com/enter" -d "scope=openid"
{
    "access_token":"9fa4ebf2-7f08-44fc-a713-b24f0bc7ebd3",
    "token_type":"bearer",
    "expires_in":43199,
    "scope":"openid"
}

Requesting user information

After the Authentication Manager has successfully authenticated the user and your application acquired an access_token, this token can be used to query user information at the users endpoint (GET - /v1/users). 

Request

HTTP Header Mandatory Format Comment
Authorization (Header) mandatory AN256

This header follows the Bearer token specification (http://self-issued.info/docs/draft-ietf-oauth-v2-bearer.html)

A valid value is: "bearer " + access_token

Response

Parameter Format Comment
sub

AN32

[a-zA-Z0-9]{32}

An unique identifiable key of the subject in compliance to OpenID Connect specification (http://openid.net/specs/openid-connect-core-1_0.html#UserInfo).

Currently its value is the same as "id".

id

AN32

[a-zA-Z0-9]{32}

The id of the contact on the system
name AN35 Name of the contact
preferred_username AN256 Username of the contact
email AN128 E-mail of the contact
attached_to ARRAY

List of strings related to each level that the user is attached to. Each level is represented as:

Root: "/"

Psp: "/pspName"

Division: "/pspName/divisionName"

Merchant: "/pspName/divisionName/merchantName"

Channel: "/pspName/divisionName/merchantName/channelName"

role AN256

Can be one of:

  • Account Access
  • Accounting Global
  • Administrator
  • Analysis
  • Callcentre
  • Callcentre Restricted
  • Operator

Example

curl "https://test.oppwa.com/authentication/v1/users" --header "Authorization: bearer 9fa4ebf2-7f08-44fc-a713-b24f0bc7ebd3"
{
    "sub": "12345678901234567890123456789012",
    "id": "12345678901234567890123456789012",  
    "name": "John Doe",
    "preferred_username": "john.doe@mymerchant.com",
    "email": "john@doe.com",
    "attached_to": [ '/myPsp', '/myPsp/division1', '/yourPsp/division1/merchant1/channel2', '/myPsp/division2', '/myPsp/division1/merchant1']
}

Logout workflow

Overview

The goal of the logout workflow is to safely log out the user in your application and also make sure that other applications are aware that the user has logged out. A correct logout workflow should consist on.

  1. The user desires to log out from your application (by clicking on a "Logout" link for example).
  2. Your application logs his user session out from your own session
  3. Your application redirects the browser to the logout endpoint (/v1/logout) passing the url from your application to redirect the user back after a logout (post_logout_redirect_uri).
  4. The Authentication Manager logs the user out and redirects the user back to your application.

Calling the logout endpoint

When an user wants to logout in your application, your application should first clear the user local session in the local server, and then redirect the browser to the logout endpoint (GET /v1/logout). Your application should add the parameter post_logout_redirect_uri indicating to which url should the user be redirected in your application after logout. We recommend that your application sets this value as the initial url in your application on that the user starts the Login Workflow.

Request

Parameter Mandatory Format Comment
post_logout_redirect_uri mandatory AN256

The url to redirect the user back after a successful logout. This url needs to be previously handled as a url encoding algorithm before sent.

Response

Redirection to the post_logout_redirect_uri.

Example

curl "https://test.oppwa.com/authentication/v1/logout?post_logout_redirect_uri=http://yourapp.com/login" -v
> GET /authentication/v1/logout?post_logout_redirect_uri=http://yourapp.com/login HTTP/1.1
> User-Agent: curl/7.21.0 (x86_64-pc-linux-gnu) libcurl/7.21.0 OpenSSL/0.9.8o zlib/1.2.3.4 libidn/1.15 libssh2/1.2.6
> Host: test.oppwa.com
> Accept: */*
>
< HTTP/1.1 302 Found
< Location: http://yourapp.com/login
< Vary: Accept-Encoding

Session tracking workflow

Overview

The session tracking workflow allows your application to check if the user is still remotely logged in - which means it still has a valid session in the Authentication Manager and has still not logged out of any of the applications that use it. Whenever a user logs out, your application will receive a notification and can act upon it. After performing any specific action, your application should start a new Login Workflow in case the user wants to log in again.

  1. The user logs into your application using the Login Workflow.
  2. The user clicks on a link to another application, for example BIP.
  3. The user clicks "Logout" activating the Logout workflow on that application.
  4. The user accesses some internal page in your application. The Session Tracker Javascript Snippet notifies your application that the session has changed.
  5. Your application removes the user session locally and start a new Login Workflow.

Listening to a logout event

It is possible to be notified about changes in the remote session of the user (on the Authentication Manager) by pasting a JavaScript Snippet into each of your application's pages, allowing your application to take actions to remove the user session from your local server and start a new Login Workflow. The following JavaScript code should be added to each page of your application that needs to logout if the user log out on a remote session.

NOTE: you will need to uncomment one of the function calls (check or poll) to complete the script.

Example

<script type="text/javascript">
(function(w, d, o, u, r, a, m)  {
    w[r] = w[r] ||
        function() {
            (w[r].q = w[r].q || []).push(arguments);
    };
    a = d.createElement(o),
    m = d.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = u;
    m.parentNode.insertBefore(a, m);
})(window, document, 'script', 'https://test.oppwa.com/authentication/v1/sessionTracker/oasm.js', '_OASM');
 
//put your client id instead of {your_client_id}
_OASM('client_id', '{your_client_id}');

//perform checking using either
//_OASM('check', 'logged_in');
//or
//_OASM('poll', {state:'logged_in', interval: 10000});
 
//callback for whenever the session status is different than expected
_OASM('on_change', function(){
    //remove user session locally
    //start a new Login Workflow
});
</script>

Checking if the user is still logged in

After pasting the example above into your page, your application can then perform individual checks if the user has logged out remotely ('check') or program a polling mechanism ('poll') that can keeps checking according to an interval if the user has logged out. Your application will be notified on the function defined by OASM('on_change') in case the remote login status of the user is not as expected ('logged_in').

Individual check

_OASM('check', 'logged_in');

Polling

//interval: the time interval (in milliseconds) in which your application should check if the user has logged out.
_OASM('poll', {state:'logged_in', interval: 10000});