Our API allows your application to access and submit information on behalf of our customers. To make sure this is permitted we need the customer to authorise your application, and we use OAuth 2.0 to do this.

OAuth 2.0 is a protocol that lets us grant your application access to a customer’s account without you needing their password. It uses the customer’s preferred web browser (which it is assumed they trust) to login and confirm that they will grant access to your application. Your application then gets an access token (a long random string) that it can use to authenticate the requests it makes.

Bear in mind that the authorisation granted to your application extends to all the admin accounts that the customer can access: you should associate the tokens you receive with the user of your application, not with a specific payroll or admin account.

This guide covers the details of our implementation of OAuth 2.0, but as it is a widely used open standard there are many other sources of information on the protocol and how to implement it in any particular programming environment. OAuth 2.0 Simplified is a good starting point that is linked to by the OAuth 2.0 site.

It’s also worth checking whether there are client libraries that you can use on your platform to help with the implementation. A good client library may perform some of the following steps for you so you don’t need to implement everything yourself.

Before you start

Our OAuth 2.0 implementation supports the Authorization Code Grant Flow (‘flow’ is the OAuth term for the sequence of interactions between your application, the web browser, and the authorisation server). To initiate the flow you need the following pieces of information:

  • The authorisation server URLs to start the authorisation flow and to retrieve access tokens.
  • Your client credentials.
  • A user account that you will use to login.
  • A redirect URL.

We cover finding the authorisation server URLs in the next section of this guide.

Your client credentials have two parts: a client id and a client secret. You can find your client id on your Developer Hub Dashboard. The client secret is a secret value that we will have given to you when your login was created. We treat the client secret like a password, and store only a hash of the secret rather than the secret itself. This means we cannot show you the client secret if you lose it: you will be able to create a new client secret if necessary though.

While developing your software you will be using our sandbox environment and you should use your Developer Hub login details to authenticate. In the production environment the customer will use their existing employer Online Services login details here.

At the end of the authorisation flow the user’s web browser will be redirected back to a URI that you can control. You’ll need to choose a value which is suitable for the environment in which your application runs. For example, for web-based applications the redirect URI would be a specific URL in your web application.

It is important that we restrict the set of redirect URIs associated with each client id: it would be insecure if anyone could initiate the authorisation flow using your client id and a redirect URI that they controlled. You can configure the acceptable redirect URIs for your client id in your Developer Hub Dashboard.

Finding the authorisation server URLs

Our authorisation flow is started by directing the web browser to navigate to the ‘authorization’ end point https://sbconnect.peoplespartnership.co.uk/connect/authorize. You’ll also need to pass some additional parameters with that URL, but we’ll cover that shortly. Later in the flow you’ll request an access token from the authorisation server at the ‘token’ end point https://sbconnect.peoplespartnership.co.uk/connect/token.

Our production environment has different URLs for these two end points so you should make these values something that you can change easily, depending on whether your software is being used in a development or production setting.

You can also find all the necessary URLs dynamically using the OpenID Connect Discovery protocol. Using this approach your application only needs to know the hostname of the authorisation server. Your application makes a request to https://{authorisation server hostname}/.well-known/openid-configuration and it gets back a JSON document that includes all the URLs that the authorisation supports. For example:

GET /.well-known/openid-configuration HTTP/1.1
Host: sbconnect.peoplespartnership.co.uk

To which the response would be:

{
  "issuer": "https://sbconnect.peoplespartnership.co.uk",
  "authorization_endpoint": "https://sbconnect.peoplespartnership.co.uk/connect/authorize",
  "token_endpoint": "https://sbconnect.peoplespartnership.co.uk/connect/token",
  "revocation_endpoint": "https://sbconnect.peoplespartnership.co.uk/connect/revocation",
  [...]
}

(Other fields removed, and JSON formatted.)

With this response your application can configure its OAuth client, using the value of authorization_endpoint to initiate the authorisation flow and the value of token_endpoint to request the access token. We recommend that you use this approach as it reduces the amount of information about our service that is embedded within your application.

Starting the authorisation flow

To start the authorisation flow your application should cause a customer’s web browser to go to the ‘authorization’ end point given above. You’ll also need to include the following URL parameters:

  • response_type: The value code, to indicate the authorization code grant is being used.
  • client_id: The client id value from your Developer Hub Dashboard.
  • redirect_uri: The redirect URI value that you’ve decided on. You need to make sure the value you pass is an exact match with one of the values you have registered through the Developer Hub Dashboard.
  • scope: This is a list of permissions that your application is requesting. To use the Payroll Integration API, use the value openid profile read write offline_access here.
  • state: This is used to protect against Cross-Site Request Forgery attacks that attempt to trick your application into using an authorisation code that was not requested. You should provide an unguessable random value for this parameter, and then verify that same value is returned along with the authorisation code you receive at your redirect_uri.

Putting this together, you start the authorisation flow by navigating to a URL something like this:

https://sbconnect.peoplespartnership.co.uk/connect/authorize?
  response_type=code&
  client_id=myClient-idFr-omDe-velo-perHub123456&
  redirect_uri=http://localhost:54231/return&
  scope=openid+profile+read+write+offline_access&
  state=randomStringOfCharactersEachTime

(Line breaks added for clarity, and you should use your own values for client_id, redirect_uri and state.)

The authorisation server will then authenticate the customer and return an authorisation code to the redirect_uri that you provided.

Being given an authorisation code

After authenticating the customer the authorisation server will give your application an authorisation code by redirecting the customer’s browser to your redirect_uri.
The full URL will look something like this:

http://localhost:54231/return?
  code=longRandomStringOfHexadecimalDigits&
  state=randomStringOfCharactersEachTime

(Line breaks added for clarity.)

The state value that you are given will be the same value you provided to the ‘authorize’ URL. You should ignore any requests to your redirect_uri that don’t have a state parameter, or where the state parameter does not match an authorisation flow you have recently started.

If the state value is valid you can proceed to use the authorisation code in the code parameter to get an access token.

Getting an access token

You get an access token by making an HTTP POST request to the authorisation server’s ‘token’ end point. The ‘token’ end point can be used in a number of ways to request access tokens; at this point in the flow you’ll use the authorisation code you just received to request an access token. Do this by passing the following parameters as the form-encoded request body (that is, using the application/x-www-form-urlencoded content type):

  • grant_type: This should be authorization_code to indicate that you are using an authorisation code.
  • code: The authorisation code received at the redirect URI in the previous step.
  • client_id: The client id value from your Developer Hub Dashboard.
  • client_secret: Your client secret to go with the client id.
  • redirect_uri: The redirect URI value that you used when starting the authorisation flow.

The HTTP request should look something like this:

POST /connect/token HTTP/1.1
Host: sbconnect.peoplespartnership.co.uk
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=longRandomStringOfHexadecimalDigits&
client_id=myClient-idFr-omDe-velo-perHub123456&
client_secret=myClientSecret&
redirect_uri=http://localhost:54231/return

(Line breaks added for clarity and form-encoding removed.)

A successful response to this request will be a JSON document containing the following fields:

  • token_type: The value “Bearer”, indicating that this is an OAuth 2.0 Bearer Token.
  • access_token: The access token itself. This value should be presented along with any API request to prove that the request is authorised.
  • expires_in: The number of seconds that the access_token can be used for, measured from the time when the response is generated.
  • refresh_token: The refresh token can be used to request a new access token when the existing access token has expired, as described below.

For example:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
 "access_token": "SlAV32hkKG",
 "token_type": "Bearer",
 "refresh_token": "8xLOxBtZp8",
 "expires_in": 3600
}

If the request parameters are invalid for some reason an error will be returned. For example:

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
 "error": "invalid_request"
}

Making API requests

Once the authorisation flow has been completed your application should have an access token that can be used to make API requests, and a refresh token to generate a new access token when required. Your application must store these tokens securely, as they can be used by anyone who possesses them to make API requests.

To make an authenticated API request, include an Authorization header with the value Bearer {access_token}. For example:

GET /api/v2/accounts/855969 HTTP/1.1
Host: api-sandbox.peoplespartnership.co.uk
Authorization: Bearer SlAV32hkKG

Logging out

We recommend that your application provides a method for the customer to ‘log out’ of The People’s Pension Payroll Integration API. Implementing this involves two steps:

  1. Request that the authorisation server revokes the access token and refresh token that your application currently has.
  2. Remove the access token and refresh token from your application’s secure storage.

To revoke a token, send an HTTP request to the authorisation server’s ‘revocation’ end point. The URL of this end point is included in the OpenID Connnect Provider Configuration Information in the revocation_endpoint field (see “Starting the authorisation flow” above). The request should pass the following parameters as the form-encoded request body:

  • token_type_hint: Either access_token or refresh_token, as appropriate.
  • token: The value of the token being revoked.

For example:

POST /connect/revocation HTTP/1.1
Host: sbconnect.peoplespartnership.co.uk
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=8xLOxBtZp8&token_type_hint=refresh_token

A successful revocation will result in a response with a 200 status code. A detailed description of token revocation can be found in the OAuth 2.0 Token Revocation specification.

Refreshing the access token

Access tokens are only valid for a restricted period of time. This is a security measure and means that if an attacker were to obtain a single access token they have only a limited time window to make use of it. You can calculate the expiry time of the access token: it is expires_in seconds from the time when the access token was created.

Once the access token has expired you can use the refresh token to request a new access token. This action also ‘uses up’ the refresh token, so a new refresh token is also generated at the same time.

To request a new access token using a refresh token, make an HTTP request to the ‘token’ end point with the following parameters:

  • grant_type: In this instance this should be refresh_token to indicate that you are using a refresh token to request the access token.
  • refresh_token: The refresh token received with the existing access token.
  • client_id: The client id value from your Developer Hub Dashboard.
  • client_secret: Your client secret to go with the client id.
  • scope: The set of permissions that your client is requesting. As above, this should be the value openid profile read write offline_access.

The HTTP request should look something like this:

POST /connect/token HTTP/1.1
Host: sbconnect.peoplespartnership.co.uk
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&
refresh_token=8xLOxBtZp8&
client_id=myClient-idFr-omDe-velo-perHub123456&
client_secret=myClientSecret&
scope=openid+profile+read+write+offline_access

(Line breaks added for clarity and form-encoding removed.)

The format of the response is the same as when the authorisation code was used to request an access token.