Skip to content

Cross-Device SCA

When to use cross-device SCA

If you expose a web application that uses the Treezor API in any way, it must also enforce SCA. This means having at least one enrolled device capable of generating SCA proofs.

Without an SCA proof, Users can connect to your back end but can't make any request to the Treezor API. Your web application would then be limited to non-Treezor features.

You can however delegate the generation of SCA proofs to another device that has been previously enrolled, therefore allowing for full-featured web application experience from any device.

In a nutshell, when logging in from a computer using a non-enrolled web browser, the User either:

  • Logs only into your backend and cannot make any request to the Treezor API, or
  • Approves the login attempt from an enrolled device, using the methods described in this article.

Treezor offers 2 solutions to delegate SCA proofs to an enrolled device.

SolutionDescription
Web NativeThis method uses exclusively web-based technologies provided by Treezor.
Mobile SDKThis method consists in running your mobile application, but is only relevant if you provide both a mobile and a web application.

Process

Cross-Device SCA implies the following steps.

StepDevice
1Queuing new SCA proof requests from the non-enrolled device
/core-connect/sca/scaOperations
Non-enrolled
2Retrieving the queued SCA proof request on an enrolled device
/core-connect/sca/scaOperations
Enrolled
3Generating SCA proof on the enrolled deviceEnrolled
4Updating the queue with the signed SCA proof
/core-connect/sca/scaOperations/{id}
Enrolled
5Retrieving the signed proof from the queue on the non-enrolled device
/core-connect/sca/scaOperations/{id}
Non-enrolled
6Sending the SCA proofed query to Treezor from the non-enrolled deviceNon-enrolled
Sequence diagram

Find below the code for the exhaustive diagram for you to view in Mermaid.

sequenceDiagram
    autonumber
    actor endUser as End user
    participant notenr as Not-enrolled device
    participant enr as Enrolled device
    participant agent as Your back end
    participant trz as Treezor
    endUser->>notenr: Try to make a sensitive operation or a login
    notenr->>agent: Queue new SCA proof requests (POST /core-connect/sca/scaOperations)
    agent->>trz: POST /core-connect/sca/scaOperations with end user JWT
    trz->>trz: Store operation request
    trz->>agent: Return SCA Operation ID
    agent->>notenr: Return SCA Operation ID
    par Pulling on non-enrolled device
        loop Every X seconds
            notenr-->agent: Pull the SCA Operation status (GET /core-connect/sca/scaOperations/{operationId})
            agent-->trz: GET /core-connect/sca/scaOperations/{operationId} with end user JWT
        end
    and End user validates operation on enrolled device
        alt Send a notification to end-user enrolled device (if it's mobile device)
            agent->>enr: Send push notification
        end
        endUser->>enr: Log in (with SCA)
        enr->>agent: Send credentials
        agent->>agent: Validate credentials
        agent->>trz: Get end user JWT (delegated_end_user grant type)
        endUser->>enr: List SCA Operation PENDING
        enr->>agent: Request SCA Operation PENDING (GET /core-connect/sca/scaOperations)
        agent->>trz: Request SCA Operation PENDING (GET /core-connect/sca/scaOperations) with end user JWT
        trz->>agent: Response
        agent->>enr: Response
        endUser-->enr: Trigger SCA to validate operation
        alt User refuse operation
            endUser-->enr: Refuse operation
            enr-->agent: PUT /core-connect/sca/scaOperations/{operationId}
            agent->>trz: PUT /core-connect/sca/scaOperations/{operationId} with end user JWT
            notenr-->endUser: Display message "Your operation was refused"
        end
        enr-->agent: Send SCA Proof
        agent-->trz: PUT /core-connect/sca/scaOperations/{operationId} with SCA proof and end user JWT
        notenr-->endUser: Display message "Operation validated"
    end
    
    notenr->>agent: Call the requested endpoint like POST /beneficiaries
    agent->>trz: Call the requested endpoint like POST /beneficiaries with the SCA proof generated on enrolled device

Prerequisites

Treezor exposes a set of endpoints to queue and update operations mandating an SCA signature.

On your back end, you should proxy the following endpoints:

EndpointDescription
/core-connect/sca/scaOperations/Queue an operation that requires SCA signature
/core-connect/sca/scaOperations/Retrieve a list of all operations pending SCA signature
/core-connect/sca/scaOperations/{scaOperationRequestId}Retrieve a specific operating pending SCA signature
/core-connect/sca/scaOperations/{scaOperationRequestId}Update a pending operation with the appropriate signature (SCA proof)

Create the operation on the web browser Non-enrolled

The end user submits an operation on your web app using a form (e.g., creating a Beneficiary) which you save to the queue as it cannot be sent to Treezor without an SCA proof.

Attributes

AttributeTypeDescription
dataToSign stringThe expected data to be signed for the desired endpoint and action.
actionName stringMust be one of the allowed actions. We recommend you concatenate the HTTP verb and the route name (e.g., postPayouts).
actionDescriptionstringDescribes the action to help the User understand what they are validating.
requestBystringThe User id that must sign the operation. This value is either:
  • Mandatory if your {accessToken} was obtained with grant_type = client_credentials
  • Optional if your {accessToken} was obtained with grant_type = delegated_end_user as the User id is already available in the JWT
Bulb icon

Tip – iat attribute always available in dataToSign

While the iat (current timestamp in milliseconds) is only necessary for WebAuthn signing, Treezor provides it regardless of the Treezor SCA proofing options (SDK, SDK Abstraction, WebAuthn). This way, you don't have to alter the dataToSign depending on the signing solution which isn't known at the time of operation queuing.

Examples

Below is an example to request an SCA proof of a per-operation action (the creation of a Beneficiary).

bash
curl -X POST {baseUrl}/core-connect/sca/scaOperations/ \
    --header 'Authorization: Bearer {accessToken}' \
    --header 'Content-Type: application/json' \
    -d '{payload}'

Here is an example of {payload}:

json
{
    "dataToSign": {
        "iat": {currentTimestampInMillisecond},
        "url":"{baseURL}/v1/beneficiaries?accessTag=12345",
        "body":{
            "userId": "12345",
            "name": "Alex Oak",
            "address": "15 Magnolia road",
            "iban": "FR113000300030592123456789",
            "bic": "SOGEFRPPXXX",
            "usableForSct": true
        }
    },
    "actionName": "postPayouts",
    "actionDescription": "Creates a payout",
    "requestBy": "<userId>",
}

Below is an example to obtain an SCA proof that can be used authenticate the User with a grant_type set to delegated_end_user, allowing for per-session operations.

bash
curl -X POST {baseUrl}/core-connect/sca/scaOperations/ \
    --header 'Authorization: Bearer {accessToken}' \
    --header 'Content-Type: application/json' \
    -d '{payload}'

Here is an example of {payload}:

json
{
    "dataToSign": {
        "iat": {currentTimestampInMillisecond},
    },
    "actionName": "postPayouts",
    "actionDescription": "Creates a payout",
    "requestBy": "<userId>",
}

Returns an object containing the UUIDv4 (scaOperationRequestId) of the operation, allowing you to check on its evolution later on.

json
{
    "scaOperationRequestId": "<UUIDv4>"
}

This pending operation is made available via the /core-connect/sca/scaOperations/{scaOperationRequestId}?userId={userId} endpoint.

Checking for signature Non-enrolled

The browser should display a message indicating to the end user that they must check their enrolled device for pending operations.

In the meantime the browser must continuously check if a signature has been provided yet.

To do so, check the status attribute of the scaOperation by either:

  • Querying your /core-connect/sca/scaOperations/{scaOperationRequestId} endpoint at fixed intervals (e.g., every 5 seconds), or
  • Using HTTP long-polling to be updated as soon as the operation gets signed.

The status is initially valued to PENDING and can change to REFUSED or VALIDATED upon User confirmation on the enrolled device.

Example

bash
curl -X GET {baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId} \
    --header 'Authorization: Bearer {accessToken}'

Returns the following.

json
{
    "scaOperationRequestId": "<UUIDv4>",
    "dataToSign": {},
    "actionName": "postPayouts", 
    "actionDescription": "Creates a payout",
    "createdAt": "{date time with timezone, RFC 3339}",
    "status": "PENDING|REFUSED|VALIDATED",
    "validatedAt": "{date time with timezone, RFC 3339}"|null,
    "refusedAt": "{date time with timezone, RFC 3339}"|null,
    "scaProof": ""
}

Push to the enrolled device Enrolled

If you have implemented push notifications with your Mobile or Web App, you should push a notification to the device asking it to check for pending SCA operations.

SCA Signature on enrolled device Enrolled

Your Mobile or Web App has retrieved the operations (/core-connect/sca/scaOperations) either:

  • By automatically following the push notification or
  • By the action of the end user who opened the App and clicked on your Pending operations button.

From the enrolled device, and with a JWT obtained with a grant_type = delegated_end_user

bash
curl -X GET {baseUrl}/core-connect/sca/scaOperations/ \
    --header 'Authorization: Bearer {accessToken}'
Bulb icon

Tip – You may also:

  • Filter SCA operations by appending ?status=PENDING to the URL.
  • Retrieve only the specific SCA operation using {baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId}.

Returns the list of SCA Operations.

json
[
    {
        "scaOperationRequestId": "<UUIDv4>",
        "dataToSign": {},
        "actionName": "", 
        "actionDescription": "",
        "createdAt": "{date time with timezone, RFC 3339}",
        "status": "PENDING|REFUSED|VALIDATED",
        "validatedAt": "{date time with timezone, RFC 3339}"|null,
        "refusedAt": "{date time with timezone, RFC 3339}"|null,
        "scaProof": "", 
    }
]

You can now display the details of the pending operation to your end user so that can make sure that they validate or refuse the correct operation.

If the end user decides to approve the operation, you:

  • Use the SDK, SDK wrapper or Web Native option to sign the operation.
  • Update the operation (/core-connect/sca/scaOperations/{scaOperationRequestId}) with the SCA proof scaProof generated on the enrolled device.
bash
curl -X PUT {baseUrl}/core-connect/sca/scaOperations/{scaOperationRequestId} \
    --header 'Authorization: Bearer {accessToken}' \
    --header 'Content-Type: application/json' \
    -d '{
        "status": "REFUSED|VALIDATED",
        "scaProof": "" # the scaProof is only mandatory if status=VALIDATED
}'
Lock icon

Security – Grant Type

This endpoint is only accessible using a JWT obtained with grant_type = delegated_end_user

Final submission on the web browser Non-enrolled

Using periodic requests to /core-connect/sca/scaOperations/{scaOperationRequestId}?userId={userId} or using HTTP long-polling, the web browser is informed that the previously created operation is now signed.

json
{
    "scaOperationRequestId": "<UUIDv4>",
    "dataToSign": {},
    "actionName": "postPayouts", 
    "actionDescription": "Creates a payout",
    "createdAt": "{date time with timezone, RFC 3339}",
    "status": "VALIDATED",
    "validatedAt": "{date time with timezone, RFC 3339}",
    "refusedAt": null,
    "scaProof": "ZHVtbXlwYXNzY29kZQ==.ZHVtbXl3ZWJhdXRobg==",
}

The browser can now submit the operation to Treezor, along with the SCA proof.

The request therefore has exactly the same structure as if it was sent from the enrolled device itself.