3D Secure 2.0



Issued On:

13th Jan 2020

Implementing 3D Secure 2.0 for Direct Integrations


Introduction to 3D Secure

3D secure is an additional layer of verification for Card not present (CNP) transactions.

There are 2 versions available for 3D secure:

3D Secure 1.0: In 3D secure 1.0, customers are redirected to the issuer's website to provide additional authentication data such as password or SMS verification code.

3D Secure 2.0: In 3D secure 2.0, customers are not redirected to issuer’s website but performs authentication within a merchant’s website or mobile app using passive, biometric, and two-factor authentication approaches.3-D Secure 2.0 is compliant with EU "strong customer authentication (SCA)" mandates.

Combined with confusing web redirect experiences which made 3DS 1.0 fail customers and businesses. Not only did 3DS 1.0 lack native in-app and web flows, but it also introduced confusing and difficult-to-remember authentication prompts.This resulted in legitimate customers dropping out of the payment flow.

3D Secure 2.0 addresses many of 1.0’s issues, while bringing benefits across a wider set of use cases for businesses all over the world. By supporting additional data during transactions, risk-based decisions will be possible on whether to authenticate or not.

3D Secure 2 Implementation Flow

3DS 2.0 transactions can go through either a frictionless flow or challenge flow based on the requirements of the issuers.

Frictionless Flow

Frictionless flow allows a transaction to be processed without additional intervention from the card holder for the authentication process by exchanging all necessary information in the background using the shopper’s device fingerprint.

Challenge Flow

Challenge flow requires a customer’s intervention for the authentication process based on secure customer authentication factors.


APEXX supports integration for 3DS 2.0 via Cardinal Cruise Hybrid Integration method.

Integration Overview

  1. JWT(JSON Web Token) Creation

  2. Include the Script

  3. Configure It

  4. Listen for Events

  5. Initialize It

  6. Include BIN Detection

  7. Lookup Request (Enrollment)

  8. Handling the Lookup Response (Enrollment Response)

  9. Continue with CCA(Cardinal's Consumer Authentication)

  10. Handling the CCA Response

  11. Validate JWT

  12. Verify Authentication

  13. Authorisation


Cardinal Cruise Account Credentials

As part of registering for Cardinal Cruise, we receive 3 values that are used to authenticate yourself with Cardinal. JWT creation requires that these values have been generated and handed off to the Cardinal. We will provide you with these details during the onboarding process based on your preference.

  1. API Identifier - A non-secure value that should be passed within the JWT under the iss claim.

  2. Org Unit Id - a non-secure value that should be passed within the JWT under the OrgUnitId claim.

  3. API Key - A secure value that should only ever be known between you and Cardinal. This value should never be rendered or displayed anywhere your users could find it. The API Key should only be used to sign the JWT and to verify a JWT signature from Cardinal. It should never be included within the JWT itself.

Integration Steps

  1. JWT(JSON Web Token) Creation

What is JWT?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA
For more information:
Code Samples :

The below code samples are to provide you with a basic idea on how to generate JWT.

Example payload : 


  "jti": "19ec6910-5048-11e6-8c35-8789b865ff15",  //UUID

  "iat": 1577091197, //JWT initialisation time

  "iss": "<API Identifier >",

  "OrgUnitId": "<Org Unit Id>",

  "Payload": {

    "OrderDetails": {

      "OrderNumber": "19ec6910-5048-11e6-8c35-8789b865ff15" //your transactionId



  "ObjectifyPayload": true,

  "exp": 1577096197 //JWT expiration time


Please find the field details for the Payload object from the below link:

JWT library: 

You can find JWT libraries as per your requirement from here

You can find the code for generating JWT from the below link.

Note:  A JWT is comprised of 3 sections of URL base64 encoded strings of data separated by a period. The first 2 sections are JSON objects while the last section is a digital signature that has been URL base64 encoded.

JWT Sample: 


-> Header - A small JSON object that specifies what type of algorithm was used to generate the digital signature. This section is denoted in the above example in red.

-> Payload - A JSON object that contains the data being sent from one party to another. This is where all request data the merchant sends to Cardinal lives and vise Versa. This section is denoted in the above example in green.

-> Signature - A URL base64 encoded the hash value of the header and payload. This is used to verify the contents of the JWT have not been tampered with. Signatures are generated using a shared secret value so only the creator and consumer have the ability to create the signature. As long as the shared secret stays a secret between the 2 parties no one should be able to spoof the signature. Signatures are verified by the consumer recreating the hash value and checking that it matches the one attached to the JWT. This section is denoted above in blue.

Decrypt JWT: You can use this link

  1. Include the Script 

Add Songbird.js to your site just like any other client-side script - through a script tag. 

Test environment :

<script src=""></script>

    Production environment :

<script src=""></script>

More information:

  1. Configure It

Using the Cardinal.configure() function allows you to pass a configuration object into Songbird.

There are different configuration options that can be used to initialize Songbird through Cardinal.configure function. You can call this function once per page load. you can configure your root level configuration like logging, button, payment, etc.



logging: {

 level: "on"  // on - Enable logging



    For more configuration options refer to the below link:

  1. Listen for Events

  • This function sets up an event subscription with Songbird to trigger a callback function when the event is triggered by Songbird.

  • You can subscribe to an event using the Cardinal.on() function structured like:



Cardinal.on('payments.setupComplete', function(){

    // Do something


  • payments.setupComplete : This optional event triggers when Songbird has successfully initialized, after calling the Cardinal.setup() function. This event will not trigger if an error occurred during your Cardinal.setup() call.

    • payments.validatedThis event is triggered when the transaction has been finished. This is how Songbird hands back control to your webpage. This event is triggered with the alternative payment brand results that require a payment authorization. The ActionCode (SUCCESS, NOACTION, FAILURE, ERROR) field should be used to determine the overall state of the transaction. Additional information can be found in the fields ErrorNumber and ErrorDescription if the ActionCode indicates an issue was encountered.

  1. Initialize It

  • You need to authenticate your system and set up CCA or all the Alternative Payment brands your account is configured for. 

  • Cardinal.setup() will initiate the communication process with Cardinal.

  • You should only call this function once per page load.

  • A common way to pass your JWT into this JavaScript function is to place the JWT value into a hidden input on page load. Within Cardinal.setup(), you can then look for that element and select its value.

JWT hidden field in the HTML : 

<input type="hidden" id="JWTContainer" value="[Insert your JWT here]" />

Cardinal Setup : 

Cardinal.setup("init", {

        jwt: document.getElementById("JWTContainer").value


Note: Cardinal.setup does not catch errors. Use the payments.validated event for the catch errors.

  1. Include BIN Detection 

  • An event to profile a bin (e.g. first 6 of card number) up to the full card number of the consumer (e.g. max of 19 digits). 

  • This event will wait for a static amount of time before resolving to allow for device data collection to complete. The implementor should wait for this event to complete before moving forward with a transaction.

  • This event will need to occur before the Lookup Request (Enrollment).

  • You can check the bin details whether it is correct or not and a way to specifically run the EMV 3DS Method URL.

  • If no Method URL was provided, Cardinal will not perform additional device data collection at this time.

  • The bin.process event will return a promise that will be fulfilled when the EMV 3DS Method URL 'attempt' has been completed. The promised result will include a single object containing the result of the 3DS Method URL attempt. 


Cardinal.trigger("bin.process", 520000)

 .then(function(results) {


    if(results.Status) {

        // Bin profiling was successful. 

    } else {

        // Bin profiling failed



    // An error occurred during profiling


For more details bin.process :

  1. Lookup Request (Enrollment)

  • This is the first transaction of the Lookup/Authenticate pair that is used to process the Consumer Authentication transaction request. 

  • All the fields of the transaction request have different roles like the TransactionType (Credit/Debit) value will dictate how the transaction will be processed. 

  • You must ensure that Cardinal has the proper Acquiring Merchant Identification Number and corresponding Acquiring Bank Identification Numbers (BINs) configured in your account. 

  • For the lookup request, you need to call our 3DSEnrol API  with some extra fields like below.




  // 3DS Enrol request


    ”three_ds_required” : ”true”,

    “three_ds_version”: ”2.0”,

    “reference_id”: “string” // it should be sessionId of cardinal


  1. Handling the Lookup Response (Enrollment Response)

  • The Lookup Response will return an ACSUrl, paReq, reference_id, authentication_transaction_id, three_ds_enrollment, three_ds_version and specification_version field.

  • The lookup response verifies that the transaction is eligible for Authentication or not by the three_ds_enrollment element.

  • If the three_ds_enrollment element contains a true value, then Authentication is available and you need to redirect to the ACSUrl to complete the transaction.

  • If the three_ds_enrollment element value is false, then you are NOT eligible for Authentication.

  • After calling our enrollment API, you will receive a lookup response like below:



              "_id": "string"

"created_at": "string",



“three_ds_required": true,

"three_ds_version": "2.0",

"acsURL": "string",

"paReq": "string",

"three_ds_enrollment" : true,

“reference_id”: ”string”,

"authentication_transaction_id": "string",


"specification_version": "string"



  1. Continue with CCA 

  • After the Lookup Response is returned, take the acsURL, Payload, and TransactionId and include them in the Cardinal.continue function in order to proceed with the authentication session.

  • The Cardinal.continue will display a modal window and automatically post the consumer's session over to the acs url for authentication.  


    Field                      Enrollment response field

AcsUrl  =          acsURL

Payload =          paReq

transactionId =  authentication_transaction_id




AcsUrl:"",             Payload:"eyJtZXNzYWdlVHlwZSI6IkNSZXEiLCJtZXNzYWdlVmVyc2lvbiI6IjIuMi4wIiwidGhyZWVEU1NlcnZlclRyYW5zSUQiOiI1YmJjZjRkYS1iZWU5LTQwNWUtYjE2NS04ZjEzMWQ0NjYxZTkiLCJhY3NUcmFuc0lEIjoiNWVlY2ZlY2YtODUwYy00MGEyLTgyOGYtZjA5MGE4NWM1ZWRkIiwiY2hhbGxlbmdlV2luZG93U2l6ZSI6IjAyIn0"



OrderDetails: {

TransactionId: "J10RCDJbUOLW7St1j9O0"



  1. Handling the CCA Response 

  • Songbird.js will handle all the user interactions until CCA has returned back the authentication result. The next step in the integration is to add logic to your payments.validated event to handle specific return values for CCA.

  • You will receive two elements in the response: JSON data, JWT

  • The field ActionCode should be used as the primary transaction status indicator.

  • Below are the possible values for ActionCode and what they indicate:

    • NOACTION - Authentication was not applicable.

    • SUCCESS - Authentication was completed successfully.

    • FAILURE - Authentication resulted in a failure.

    • ERROR - An error was encountered. 

For more details :

JSON Response Example:


 "iss": "<API Identifier>",

 "iat": 1577091255,

 "exp": 1577098455,

 "jti": "61729408-0c2a-4be6-8ee2-892b4d05ce00",

 "ConsumerSessionId": "1_7076814d-5117-4940-9e4e-aa92a8b03c01",

 "ReferenceId": "1_7076814d-5117-4940-9e4e-aa92a8b03c01",

 "aud": "19ec6910-5048-11e6-8c35-8789b865ff15",

 "Payload": {

  "Validated": true,

  "Payment": {

     "Type": "CCA",

     "ProcessorTransactionId": "J10RCDJbUOLW7St1j9O0",

     "ExtendedData": {

     "CAVV": "MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",

     "ECIFlag": "02",

     "ThreeDSVersion": "2.2.0",

     "PAResStatus": "Y",

     "SignatureVerification": "Y"



  "ActionCode": "SUCCESS",

  "ErrorNumber": 0,

  "ErrorDescription": "Success"



JWT Response Example:


  1. JWT Validation

  • Once the response JWT is received in the payments.validated event, you will need to send the response JWT to your backend to verify and extract the results.

  • Note: JWT validation should only ever be done on the server side for security reasons.

  • You can validate JWT by JAVA, .NET, or PHP programs in the backend.

For more information and code samples:

  1. Authorisation

  • After the successful validation of JWT, you need to call 3DS Verify Authentication API with the external authentication data.

  • You will receive a final response SUCCESS or FAILED after authorisation.

For API request/response:

Request Example:


"_id": "string",

“paRes”: “string”,

"three_ds_authentication": {

"xid": "string",

"cavv": "string",

"cavv_algorithm": "string",

"3ds_status": "string",

"eci": "string",

"3ds_enrolled": "string",

"directory_server_transaction_id": "string",

"3ds_transaction_status_reason": "string",

"3ds_score": "string",

"3ds_preference": "string",

"3ds_mode": "string",

"3ds_version": "string",

"3ds_result": "string",

"3ds_server_transaction_id": "string"