Appearance
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.
Solution | Description |
---|---|
Web Native | This method uses exclusively web-based technologies provided by Treezor. |
Mobile SDK | This 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.
Step | Device | |
---|---|---|
Queuing new SCA proof requests from the non-enrolled device /core-connect/sca/scaOperations | Non-enrolled | |
Retrieving the queued SCA proof request on an enrolled device /core-connect/sca/scaOperations | Enrolled | |
Generating SCA proof on the enrolled device | Enrolled | |
Updating the queue with the signed SCA proof /core-connect/sca/scaOperations/{id} | Enrolled | |
Retrieving the signed proof from the queue on the non-enrolled device /core-connect/sca/scaOperations/{id} | Non-enrolled | |
Sending the SCA proofed query to Treezor from the non-enrolled device | Non-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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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:
Endpoint | Description |
---|---|
/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
Attribute | Type | Description |
---|---|---|
dataToSign | string | The expected data to be signed for the desired endpoint and action. |
actionName | string | Must be one of the allowed actions. We recommend you concatenate the HTTP verb and the route name (e.g., postPayouts ). |
actionDescription | string | Describes the action to help the User understand what they are validating. |
requestBy | string | The User id that must sign the operation. This value is either:
|
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}'
1
2
3
4
2
3
4
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>",
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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}'
1
2
3
4
2
3
4
Here is an example of {payload}
:
json
{
"dataToSign": {
"iat": {currentTimestampInMillisecond},
},
"actionName": "postPayouts",
"actionDescription": "Creates a payout",
"requestBy": "<userId>",
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Returns an object containing the UUIDv4 (scaOperationRequestId
) of the operation, allowing you to check on its evolution later on.
json
{
"scaOperationRequestId": "<UUIDv4>"
}
1
2
3
2
3
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}'
1
2
2
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": ""
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
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}'
1
2
2
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": "",
}
]
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
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 proofscaProof
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
}'
1
2
3
4
5
6
7
2
3
4
5
6
7
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==",
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
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.