Strong Customer Authentication

❗️

This section applies only to Regulated partners.

Strong Customer Authentication Flow

Strong Customer Authentication is done by Shine within Shine's own applications (mobile or web). The flow is the same for all actions.

Below we'll try to initiate a bank transfer of 234€ on behalf of a user (USER_ID) to a recipient (BANK_TRANSFER_RECIPIENT_ID).

1. Create an Action Request

First, we have to create an Action Request that describes the action that we want to make on the user's behalf. Here we want to make a bank transfer so the action will have bank:transfers:create as value.
The payload parameter is the payload that we will send in the end to the Create a transfer endpoint once the Strong Customer Authentication flow has been completed.

See Create an action request

const {data: actionRequest } = axios.post('/v2/authentication/oauth2/action_request', {
 action: 'bank:transfers:create',
 client_id: 'your_client_id',
 client_secret: 'your_client_secret',
 uid: 'USER_ID',
 payload: {
 amount: 234,
 bankTransferRecipientId: 'BANK_TRANSFER_RECIPIENT_ID',
 uid: 'USER_ID'
 }
})

console.log(actionRequest)
{
 "data": {
 "authenticationActionRequestId": "ACTION_REQUEST_ID",
 "clientId": "your_client_id",
 "action": "bank:transfers:create",
 "payload": {
 "amount": 234,
 "bankTransferRecipientId": "BANK_TRANSFER_RECIPIENT_ID",
 "uid": "USER_ID"
 },
 "uid": "USER_ID",
 "status": "PENDING",
 "updatedAt": "2019-11-28T17:08:17.455967000Z",
 "createdAt": "2019-11-28T17:08:17.455967000Z",
 "expiresAt": "2019-11-28T17:09:17.437000000Z"
 },
 "metadata": {}
}

Action request expires after three minutes.

2. Prompt the user to confirm this Action Request

Upon creating this Action Request, the user will receive a notification sent by Shine inviting them to confirm this action request.
As notifications are not guaranteed to be received by the user, you should display a message to the user asking them to confirm this bank transfer in Shine mobile or web application if no notification has been received after X seconds.

3. Wait for Action Request confirmation

Once the Action Request created, we poll (with a reasonable poll interval) the Poll an action request endpoint to know when action has been confirmed or rejected by the user.

const {data: actionRequest } = axios.get(`/v2/authentication/oauth2/action_request/${authenticationActionRequestId}/poll`, {
 params: {
 client_id: 'your_client_id',
 		 client_secret: 'your_client_secret',
 }
})

console.log(actionRequest)
{
 "data": {
 "authenticationActionRequestId": "ACTION_REQUEST_ID",
 "clientId": "your_client_id",
 "action": "bank:transfers:create",
 "payload": {
 "amount": 234,
 "bankTransferRecipientId": "BANK_TRANSFER_RECIPIENT_ID",
 "uid": "USER_ID"
 },
 "uid": "USER_ID",
 "status": "CONFIRMED",
 "token": "SHORT_LIVED_TOKEN",
 "updatedAt": "2019-11-28T17:08:17.455967000Z",
 "createdAt": "2019-11-28T17:08:17.455967000Z",
 "expiresAt": "2019-11-28T17:09:17.437000000Z"
 },
 "metadata": {}
}

We need to handle 3 cases:

  • The action request has been confirmed (status = CONFIRMED): A token field will be returned in the action request. This short lived token, that expires after one minute, will be used in the next request.
  • The action request has been rejected (status = REJECTED): The user has rejected the request within Shine's application.
  • The action request has expired: After one minute, the action requests expire and can't be confirmed anymore. To check if an action request has expired, you have to use the expiresAt field. It may happens if the user can't confirm the action within Shine quickly enough. In this case, you can create a new action request.

In any case, you should stop polling once the action request has reached one the previous states. No more updates will be done.

4. Trigger the action

Once the Action Request confirmed and the short-lived token retrieved, we can call the Create a transfer endpoint and initiate the bank transfer.
The short-lived token must be passed as header alongside the access_token.

axios.post('/v3/bank/transfers', {
 amount: 234,
 bankTransferRecipientId: 'BANK_TRANSFER_RECIPIENT_ID',
 uid: 'USER_ID'
}, {
 headers : {
 Authorization `Bearer ${access_token}`,
 'short-lived-token': 'SHORT_LIVED_TOKEN',
 }
})

The short-lived token can only be used once and only for the action corresponding to the action request confirmed by the user.