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
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
{ "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 Name | Description | Required |
---|---|---|
jti | JWT Id - A unique identifier for this JWT. This field should change each time a JWT is generated. | Y |
iat | Issued 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 |
iss | Issuer - An identifier of who is issuing the JWT. We use this value to contain the Api Key identifier or name. | Y |
aud | Audience - 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 |
exp | Expiration - 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 Names | Description | Required |
---|---|---|
OrgUnitId | The merchant SSO OrgUnitId | Y |
Payload | The JSON data object being sent to Cardinal. This object is usually an Order object | Y |
ObjectifyPayload | A 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 customization | N |
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 |
ReturnUrl | The 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 }