JWT Documentation


Cardinal Cruise uses JWT's as a method of passing signed data from one party to another. We're actually using JWS (JSON Web Signature) which is a more specific variant of the JWT spec, however for simplicity the rest of this article will reference it as a JWT.

For more in depth information on JWT's please review the JWT documentation

JWT Anatomy

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. The sections are as such:

  • header - A small JSON object that specifies what type of algorithm was used to generate the digital signature. This section is denoted in the below 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 below example in green.
  • signature - A url base64 encoded 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 to the one attached to the jwt. This section is denoted below in blue.

Example Jwt:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5YTAwYTYzMC0zNzFhLTExZTYtYTU5Ni1kZjQwZjUwMjAwNmMiLCJpYXQiOjE0NjY0NDk4MDcsImlzcyI6Ik1pZGFzLU5vRFYtS2V5IiwiUGF5bG9hZCI6eyJPcmRlckRldGFpbHMiOnsiT3JkZXJOdW1iZXIiOjE1NTc4MjAyMzY3LCJBbW91bnQiOiIxNTAwIiwiQ3VycmVudENvZGUiOiI4NDAiLCJUcmFuc2FjdGlvbklkIjoiOVVzaGVoRFFUcWh1SFk5SElqZTAifX0sIk9yZ1VuaXRJZCI6IjU2NGNkY2JjYjlmNjNmMGM0OGQ2Mzg3ZiIsIk9iamVjdGlmeVBheWxvYWQiOnRydWV9.eaU8LZJnMtY3mPl4vBXVCVUuyeSeAp8zoNaEOmKS4XY

Decoded Header
{
  "typ":"JWT",
  "alg":"HS256"
}
Decoded Body
{
  "jti": "9a00a630-371a-11e6-a596-df40f502006c",
  "iat": 1466449807,
  "iss": "Midas-NoDV-Key",
  "Payload": {
    "OrderDetails": {
      "OrderNumber": 15578202367,
      "Amount": "1500",
      "CurrencyCode": "840",
      "TransactionId": "9UshehDQTqhuHY9HIje0"
    }
  },
  "OrgUnitId": "564cdcbcb9f63f0c48d6387f",
  "ObjectifyPayload": true
}


JWT and Cardinal Cruise

Cardinal Cruise leverages JWT's as a vehicle to send signed data to and from the merchant. The Merchant is required to send a JWT on any valid Cardinal Cruise request. They can optionally send additional, or newer data by using Songbird to append additional data to your request. However JWT's are the preferred method of passing data, as the data is signed and we can verify that it has not been tampered with. Data sent by Songbird does not include this additional layer of security. Cardinal will always reply back with a JWT signed with the merchants Api Key when it can. This allows the merchant the ability to validate that the response from Cardinal has not been tampered with.

Request JWT's

Request JWT's are JWT's that have been created by the merchant to be sent to Cardinal. These JWT's are, at minimum, used to authenticate the merchant with Cardinal Servers.

Authentication JWT

An authentication JWT is a JWT being used simply to authenticate the merchant. This means there is no transactional data with the JWT payload. This is done by omitting the 'Payload' claim in the JWT. These are generally used when a merchant is relying on passing all transactional data via Songbird. Below is a sample JSON structure of a authentication JWT.

{
  "jti": "a5a59bfb-ac06-4c5f-be5c-351b64ae608e",
  "iat": 1448997865,
  "iss": "56560a358b946e0c8452365ds",
  "OrgUnitId": "565607c18b946e058463ds8r",
  "exp": 1449001465
}

Transactional JWT

A transactional JWT is a JWT that includes an Object payload within the JWT. This is the preferred method of integration as the order data has been signed and can be easily verified by the Cardinal systems. Additional information can be passed in on the JavaScript layer to add more information or even override the JWT information. Below is a sample of a transactional JWT.

{
	"jti": "a5a59bfb-ac06-4c5f-be5c-351b64ae608e",
	"iat": 1448997865,
	"iss": "56560a358b946e0c8452365ds",
	"OrgUnitId": "565607c18b946e058463ds8r",
	"Payload": {
		"OrderDetails": {
			"OrderNumber": "0e5c5bf2-ea64-42e8-9ee1-71fff6522e15",
			"Amount": "1500",
			"CurrencyCode": "840"
		}
	},
	"ObjectifyPayload": true,
	"exp": 1449001465
}

Transactional JWT for Cruise API Example

A Transactional JWT for the Cardinal Cruise API integration is a JWT that includes an Account Object payload within the JWT. This is the preferred method of integration as the card bin to full card number has been signed and can be easily verified by the Cardinal systems.  In addition, if a merchant only stores the card bin to full card number within their backend system, then this method provides a way to bring the card bin to the web layer.  

A ReturnUrl can also be included to know when Device Data Collection completed, please see below ReturnUrl field in the Custom Claims

Device Fingerprint SaveBrowser Request
{
  "jti": "7b9e0f50-a4a7-11e8-91e8-795883ca8f10",
  "iat": "1534789987",
  "iss": "Midas-TwoDotOh-Key",
  "OrgUnitId": "59c2745f2f3e7357b4aa516a",
  "ReturnUrl": "http://merchanturl.com/cart/collect-returnurl",
  "Payload": {
    "Consumer": {
      "Account": {
        "AccountNumber": "400001000",
		"CardType": "CB"
      }
    }
  },
  "ObjectifyPayload": true
}

CardType

CardType is a required when a co-branded card is used. 

For card brands where their BIN ranges overlap with another networks allocated ranges, we require the CardType to identify the data set we should reference to retrieve Card Range Data i.e., 3DS Method. Without the Card Type specified, we would match on the overlapping card networks data and would not be able to run the appropriate corresponding 3DS Method. 

Supported Values:

  • CB
  • EFTPOS
  • ITMX
  • UPI
  • MADA

Payload

Within the JWT payload object, fields are considered 'Claims'. There are 2 basic types of claims, common and custom. A common claim is a claim that has been predefined by the JWT spec and should be used in a standard way. This allows 2 parties to communicate with common fields with little to no planning. Custom claims are claims that are custom to a particular implementation. They're basically fields defined by people using the JWTs that will only have meaning within their application(s).

{
  "jti": "03e4d6e0-394e-11e6-8399-a9207aa80eae",
  "iat": 1466691791,
  "exp": 1466699785,
  "iss": "Midas-NoDV-Key",
  "Payload": {
    "Consumer": {
      "Account": {
        "AccountNumber": "400001000",
		"CardType": "CB"
      }
    },
    "OrderDetails": {
      "OrderNumber": "18833858938",
      "Amount": "1500",
      "CurrencyCode": "840",
      "TransactionId": "abc123doerayme"
    }
  },
  "OrgUnitId": "56d9b40cb9f63f146c3ad6f2",
  "ObjectifyPayload": true
}

Common Claims

The JWT spec defines some common fields that can be used to send data back and forth. These fields are all lower case and limited to 3 characters. Cardinal Cruise is currently using the following fields within our JWT:

Claim NameDescriptionRequired
jtiJWT Id - A unique identifier for this JWT. This field should change each time a JWT is generated.Y
iatIssued At - The epoch time in seconds of when the JWT was generated. This allows us to determine how long a JWT has been around and whether we consider it expired or not.Y
issIssuer - An identifier of who is issuing the JWT. We use this value to contain the Api Key identifier or name.Y
audAudience - Cardinal populates this field on response JWT to contain the request jti field. This allows merchant to match up request JWTs with response JWTs.Y
expExpiration - The numeric epoch time that the JWT should be consider expired. This value is ignored if its larger than 2hrs. By default we will consider any JWT older than 2hrs.N

Custom Claims

These are fields that are specific to Cardinal Cruise and will not work with any other JWT related service

Claim NamesDescriptionRequired
OrgUnitId

The merchant SSO OrgUnitId

Y
PayloadThe JSON data object being sent to Cardinal. This object is usually an Order objectY
ObjectifyPayloadA boolean flag that indicates how Centinel Api should consume the Payload claim. When set to true, this tells Centinel Api the Payload claim is an object. When set to false, the Payload claim is a stringified object. Some Jwt libraries do not support passing objects as claims, this allows those who only allow strings to use their libraries without customizationN

ConfirmUrl

The confirm url Cardinal should redirect users to when the user has been redirected away from your website to complete an alternative payment brand. This url will need to receive a post with the response JWT.

N
ReturnUrlThe ReturnUrl is a claim used within the Cardinal Cruise API integration that allows for the integrator to know when the Device Data Collection and StepUpUrl interactions completed. N


Object vs String Payload Claim

This section relates to the Payload custom claim, which resides within the Payload section of the JWT.

Some JWT libraries do not allow claims to be passed as objects. Due to this we added support for Centinel Api to support both an object payload claim or a serialized object payload claim. By default Centinel Api will assume that the payload claim is a JSON object literal. If the custom claim 'ObjectifyPayload' exists with a value of 'false' then Centinel Api will treat the Payload field as a serialized JSON object. If ObjectifyPayload is omitted from the Payload section of the JWT then a value of true for ObjectifyPayload is assumed, meaning the default payload claim parsing is as an object literal.

However the request came into Centinel Api, Centinel Api will respond back with a JWT structured in the same way. So if a merchant sends a serialized payload with the ObjectifyPayload flag set to false, Centinel Api will respond with a JWT with a serialized Payload and ObjectifyPayload set to false.

Below is a sample of a serialized payload claim request jwt

{
	"jti": "29311a10-5048-11e6-8c35-8789b865ff15",
	"iat": 1448997875,
	"iss": "56560a358b946e0c8452365ds",
	"OrgUnitId": "565607c18b946e058463ds8r",
	"Payload": "{\"OrderDetails\":{\"OrderNumber\":\"19ec6910-5048-11e6-8c35-8789b865ff15\",\"Amount\":\"1500\",\"CurrencyCode\":\"840\"}}",
	"ObjectifyPayload" false
	"exp": 1449001465
}