Authentication (D-SCA)
Authentication Provider setup and guidelines
Every integrator must provide an Authentication Provider for account number enrolment and payment requests. These
requests contain an encrypted data object with data generated by the Authentication Provider. For network token
enrolment, the integrator signs NetworkTokenEnrolmentData directly.
Authentication Provider requirements
To facilitate an authenticated payment, the Authentication Provider must provide a signed JWS token
verified by EPP.
This JWS needs to contain a PermissionGrant object that is encoded in the JWS token. It must have
the structure as seen in the Components overview.
You must use a robust signing algorithm. We accept ES256 or PS256 as the signing algorithm.
The digest field in the PermissionGrant object is an unpadded, URL-safe Base64 encoded SHA-256 hash of a compact
UTF-8 JSON permission statement. Properties must appear in the order specified for the permission type, with no
insignificant whitespace.
For Account Number Enrolment
The approveAccount.v1 permission statement contains these properties in order:
nonce: Must match the nonce in thePermissionGrantobject.accountNumber: The account number of the enrolment session.merchantName: The merchant name provided during information exchange.
For Network Token Enrolment
The integrator creates NetworkTokenEnrolmentData containing iss, iat, nin, bankIdentificationNumber, and the
original token fields, then signs it with the integrator's private key as a compact JWS using ES256 or PS256.
Include the resulting value as signedNetworkTokenEnrolmentData in EnrolmentCardholderAuthenticationData.
During manual onboarding, provide EPP with the public certificate corresponding to this private signing key. EPP
associates the certificate with the integrator profile and uses it to verify signedNetworkTokenEnrolmentData.
The Merchant Name is part of the information exchange as seen in our checklist.
For Payment
nonce: Must be the same as the corresponding nonce in the PermissionGrant object.
merchantReference: Set by Wallet.
creditorName: Merchant display name. Set by Wallet.
amount: Set by Wallet.
currency: Set by Wallet.
Authentication field guidelines.
Some values from (./getting-started.md#checklist-for-information-exchange) must be used to create the DSCA digest and encrypted data object.
| Value | Usage |
|---|---|
| Merchant Name | Used in account number enrolment for the digest.merchantName value. |
| Encryption Issuer | The Token Requestor ID assigned to the integrator. Use it as the outer iss for account number enrolment and payment, and as the signed iss for network token enrolment. |
| Permission Grant Issuer | The Authentication Provider ID. Use it as PermissionGrant.iss for account number enrolment and payment. |
Wallet requirements
Account number enrolment and payment requests contain encryptedCardholderAuthenticationData with
verifiedCardholderAuthenticationSignedData in the decrypted object. Network token enrolment contains
signedNetworkTokenEnrolmentData in the decrypted object.
Encrypt the complete cardholder authentication data object using the public certificate from EPP received in point 8
of setting up your EPP integration. The
verifiedCardholderAuthenticationSignedData object can be reviewed in our
Components overview.
For account number enrolment and payment, the outer iss field is received from EPP and identifies the configured
integrator. For network token enrolment, include this value as iss inside the signed NetworkTokenEnrolmentData.
A corresponding Merchant Name will also be provided. This must be encoded as merchantName in the permission
statement used to calculate the digest.
Illustrated EPP-Wallet-Authentication Provider interoperability
For account number enrolment and payment, the Permission Grant with corresponding Digest validation is based on the Open Banking Europe and Berlin Group NextGen PSD2 guidelines. This ensures the integrity of the user's authentication and the account number enrolment or payment.
First a PermissionGrant object is created. Its structure can be reviewed in
the Components overview.
This object is then encoded in a signed JWS token signed using the private key of the Authentication Provider.
The signature is then validated in EPP.
This leads to the following account number enrolment and payment sequence. Note that in some scenarios, the Authentication Provider and the Integrator might be the same organizational entity depending on your operating model.
Enrolment example
The account number enrolment flow uses the following permission statement.
This is then encoded in a JWS token signed by the Authentication Provider's private key. The JWS token is then sent to EPP for validation as part of the Integrator's Payment/enrolment request.
Enrolment used as example, same fundamental structure applies for payment.
This data object must then be encrypted using the public certificate provided by EPP.
For account number enrolment, include the result in encryptedCardholderAuthenticationData.
The combined data structure for a request can also be considered as seen below. Enrolment used as an example, the same fundamental structure applies for payment. The green color indicates Integrator, while the blue color indicates Authentication provider.
For network token enrolment, the integrator signs NetworkTokenEnrolmentData directly. The compact JWS is included as
signedNetworkTokenEnrolmentData instead of enrolmentData and
verifiedCardholderAuthenticationSignedData.
Payment example
Payment PermissionGrant.
IMPORTANT NOTE: The Amount must be given with fractional digits. The decimal separator is a dot. This is different from the Minor Units format in the root of the Payment Request.
EncryptedPaymentCardholderAuthenticationData should result in the following PaymentCardholderAuthenticationData object.
This data object must then be encrypted using the public certificate provided by EPP.
For payment, include the result in encryptedCardholderAuthenticationData.
The combined data structure for a request can also be considered as seen below. The green color indicates Integrator, while the blue color indicates Authentication provider.
Digest validation examples
While the exact implementation may vary per Integrator/Coding language, the resulting digest logic must match the following result
Bash example Payment
echo -n '{"nonce":"550e8400-e29b-41d4-a716-446655440000","id":"merchantReference","payments":[{"paymentId":"merchantReference","amount":"100","currency":"NOK","creditorName":"merchantDisplayName"}]}' \
| sha256sum - \
| awk '{print $1}' \
| xxd -r -p \
| base64 \
| tr -d '=' \
| tr '/+' '_-'
Script explanation: A SHA-256 hash is created from the JSON object. The resulting hash is then converted to binary and
encoded as a Base64 string. First tr is used to remove padding. Then tr is used to make the Base64 URL safe.
The script above should produce the following output:
QomjM9YUvFcj0bd0Xjr39uMTaKzb1D54H_YAbHicy4Q
You may use this to verify your own implementation.
Account Number Enrolment Digest
The compact JSON input for approveAccount.v1 is:
{"nonce":"a05b53be-718e-4df2-80ac-83696b711111","accountNumber":"12341212345","merchantName":"test-enrolment-name"}
The resulting digest is:
-PAwASn3A47p15X48mrqBL-pWdcKtktj8bqTYCW0yn4
Java example for Payment
record PaymentPermissionStatement(
String nonce,
String id,
List<PaymentPermissionStatement.Payment> payments
) {
record Payment(
String paymentId,
String amount,
String currency,
String creditorName
) {
}
String digest() throws NoSuchAlgorithmException, JsonProcessingException {
return Base64.getUrlEncoder()
.withoutPadding()
.encodeToString(MessageDigest.getInstance("SHA-256").digest(new ObjectMapper().writeValueAsBytes(this)));
}
}
Follow by
new PaymentPermissionStatement(
"550e8400-e29b-41d4-a716-446655440000",
"merchantReference",
List.of(new Payment(
"merchantReference",
"100.50",
"NOK",
"merchantDisplayName"
))).
digest();