JWT Creation

Cardinal Cruise utilizes a JWT to handle authentication and to assist in passing secure data between you and Cardinal. The JWT is a JWS with the signature using a SHA-256 HMAC hash algorithm. The JWT must be created server-side and sent to the front end to be injected into the JavaScript initialization code. Creating a JWT client-side is not a valid activation option. Each order should have a uniquely generated JWT associated with it.

Learn more about JWT's.

Helpful JWT external pages:


Cardinal Credentials

As part of registering for Cardinal Cruise you will have received 3 values that are used to authenticate yourself with Cardinal. JWT creation requires that these values have been generated and handed off to you. Failure to properly authenticate using these values will result in API failures and will prevent transaction processing.

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

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

  • 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.

JWT Fields

A valid generic transaction JWT must contain the below values. Additional fields may be required to complete an integration with some payment brands. Please review the payment brand's documentation for more details on if a payment brand needs additional fields.

Required Claims

Please note that each claim key is case sensitive.

Claim NameDescription
jtiJWT Id - A unique identifier for this JWT. This field should change each time a JWT is generated.
iat

Issued At - A unix timestamp since epoch in seconds for when the JWT was generated. This value should be generated using UTC only. This allows us to determine how long a JWT has been around and whether we consider it expired or not.

issIssuer - An identifier of who is issuing the JWT. We use this value to contain the Api Key identifier or name.
OrgUnitId

The merchant SSO OrgUnitId

PayloadThe JSON data object being sent to Cardinal. This object is usually an Order object

Optional Claims

The following claims are available for use but are not currently required for a valid JWT:

Claim NamesDescription
ReferenceIdThis is a merchant supplied identifier that can be used to match up data collected from Cardinal Cruise and Centinel. Centinel can then use data collected to enable rules or enhance the authentication request.
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 customization
expExpiration - The numeric epoch time that the JWT should be consider expired. This value is ignored if its larger than 2 hrs. By default we will not consider any JWT older than 2 hrs.

Other Claims

The following claims are conditionally required when doing some transactional flows:

Claim NameDescriptionFlow Required
ConfirmUrlThe merchant endpoint that will receive the post back from the payment brand that contains the Centinel API response JWT describing the result of redirecting to the payment brand.Redirect

JWT Payload Example

Below is an example of the JSON content of a basic JWT Payload where we are passing an object within the Payload claim:

Raw JWT Sample
{
	"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,
	"ReferenceId": "c88b20c0-5047-11e6-8c35-8789b865ff15",
	"exp": 1449001465,
	"ConfirmUrl": 'https://mywebsite.com/confirmHandler'
}

Below is an example of the JSON content of a basic JWT Payload where we are passing a string within the Payload claim:

Stringified JWT Sample
{
	"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
	"ReferenceId": "074fda80-5048-11e6-8c35-8789b865ff15"
	"exp":1449001465,
	"ConfirmUrl": 'https://mywebsite.com/confirmHandler'
}

Code Samples

The below code samples are to provide you with a basic idea on how to generate JWT's within a few languages. 

We do not recommend using these samples unmodified in a production environment. They are intended as examples only.


Generating a Server JWT in .NET

We recommend using an existing third party library to assist you in generating a JWT. The JWT.io website contains a list of libraries with their feature sets. Check it out here. In the below sample we will focus on using this JWT (GitHub.com) library.

Dependencies

When using nuget you can grab the JWT library by installing the package 'JsonWebTokens'. It has been reported that some versions of .Net will need to install an additional dependency 'System.Security.Cryptography.Primitives' for 'JsonWebTokens' to work properly.


Controller
// This sample code was written using the JSON Web Token Handler library.

using System.Configuration;
using System.Web.Mvc;
using CardinalCruiseDemoSite.Helpers;
using CardinalCruiseDemoSite.Models.View;

namespace CardinalCruiseDemoSite.Controllers
{
    public class HomeController : Controller
    {
        private readonly JwtHelper _jwtHelper = new JwtHelper();

        public ActionResult Index()
        {
            var apiKey = ConfigurationManager.AppSettings["APIKey"];
            var apiIdentifier = ConfigurationManager.AppSettings["APIIdentifier"];
            var orgUnitId = ConfigurationManager.AppSettings["OrgUnitId"];

            var jwt = _jwtHelper.GenerateJwt(apiKey, apiIdentifier, orgUnitId);

            return View(new CardinalCruiseViewModel {JWT = jwt});
        }
    }
}
View Model
namespace CardinalCruiseDemoSite.Models.View
{
    public class CardinalCruiseViewModel
    {
        public string JWT { get; set; }
    }
}

This is an example of a JWT object class.

JWT Helper
using System;
using System.Collections.Generic;
using CardinalCruiseDemoSite.Models;
using JWT;

namespace CardinalCruiseDemoSite.Helpers
{
    public class JwtHelper
    {
        public string GenerateJwt(string apiKey, string apiIdentifier, string orgUnitId)
        {
            var payload = new Dictionary<string, object>
            {
                {"exp", DateTime.UtcNow.AddDays(365).ToUnixTime()},
                {"iat", DateTime.UtcNow.ToUnixTime()},
                {"jti", Guid.NewGuid()},
                {"iss", apiIdentifier},
                {"OrgUnitId", orgUnitId},
                {
                    "Payload", new Order
                    {
                        OrderDetails = new OrderDetails
                        {
                            OrderNumber = Guid.NewGuid().ToString()
                        }
                    }
                }
            };

            return JsonWebToken.Encode(payload, apiKey, JwtHashAlgorithm.HS256);
        }
    }
}

It is important that you generate the JWT expiration using UNIX time. We recommend using a library such as NodaTime from NodaTime.org to help with this. If you are unable to use a third party library, here is a helper function you may use (this is used in the example above):

Time Helper
using System;

namespace CardinalCruiseDemoSite.Helpers
{
    public static class DateTimeHelper
    {
        public static long ToUnixTime(this DateTime date)
        {
            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            return Convert.ToInt64((date - epoch).TotalSeconds);
        }
    }
}

Generating a Server JWT in Java

We recommend using an existing third party library to assist you in generating a JWT. The JWT.io website contains a list of approved libraries, with their feature sets. Check it out here.

JWT Generator Utility
// This sample code was written using the Java JWT
// library (https://github.com/jwtk/jjwt) found at JWT.io

import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.security.Key;
import java.util.Date;
import java.util.UUID;

import javax.crypto.spec.SecretKeySpec;

public class generateJWT {
  
	public static String apiKey = "";
	public static String apiIdentifier = "";
	public static String orgUnitId = "";
  
	// Sample method to construct a JWT
	public static String createJWT(String jwtId, long ttlMillis, Order orderObject) {
  
		// The JWT signature algorithm we will be using to sign the token
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
  
		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);
  
		// We will sign our JWT with our API Key
		byte[] apiKeySecretBytes = apiKey.getBytes();
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, 
		signatureAlgorithm.getJcaName());
  
		// Let's set the JWT Claims
		JwtBuilder builder = Jwts.builder()
			.setId(jwtId)     
			.setIssuedAt(now)
			.setIssuer(apiIdentifier)
			.claim("OrgUnitId", orgUnitId)
			.claim("Payload", orderObject)
			.signWith(signatureAlgorithm, signingKey);
  
		// Add the expiration or TTL (Time To Live) for this JWT
		if (ttlMillis > 0) {
			long expMillis = nowMillis + ttlMillis;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);
		}
  
		// Builds the JWT and serializes it to a compact, URL-safe string
		return builder.compact();
	}
}

Generating a Server JWT in PHP

We recommend using an existing third party library to assist you in generating a JWT. The JWT.io website contains a list of approved libraries, with their feature sets. Check it out here.

<?php
	/* 
	composer.json Example:
	{
		"require": {
			"lcobucci/jwt": "3.1.0" // Note: Requires PHP 7
			}
	}
	*/
	
	require "vendor/autoload.php"; // Autoload.php is generated by Composer
	
	use Lcobucci\JWT\Builder;
	use Lcobucci\JWT\Signer\Hmac\Sha256;
	
	$GLOBALS['ApiKey'] = '[INSERT_API_KEY_HERE]';
	$GLOBALS['ApiId'] = '[INSERT_API_KEY_ID_HERE]';
	$GLOBALS['OrgUnitId'] = '[INSERT_ORG_UNIT_ID_HERE]';
	
	$_SESSION['TransactionId'] = uniqid();
	
	$_SESSION['Order'] = array(
		"OrderDetails" => array(
			"OrderNumber" =>  'ORDER-' . strval(mt_rand(1000, 10000)),
			"Amount" => '1500',
			"CurrencyCode" => '840'
			)
	);
	
	function generateJwt($orderTransactionId, $orderObj){
	
		$currentTime = time();
		$expireTime = 3600; // expiration in seconds - this equals 1hr
	
		$token = (new Builder())->setIssuer($GLOBALS['ApiId']) // API Key Identifier (iss claim)
					->setId($orderTransactionId, true) // The Transaction Id (jti claim)
					->setIssuedAt($currentTime) // Configures the time that the token was issued (iat claim)
					->setExpiration($currentTime + $expireTime) // Configures the expiration time of the token (exp claim)
					->set('OrgUnitId', $GLOBALS['OrgUnitId']) // Configures a new claim, called "OrgUnitId"
					->set('Payload', $_SESSION['Order']) // Configures a new claim, called "Payload", containing the OrderDetails
					->set('ObjectifyPayload', true)
					->sign(new Sha256(), $GLOBALS['ApiKey']) // Sign with API Key
					->getToken(); // Retrieves the generated token
	
		return $token; // The JWT String
	}
	
	echo generateJwt($_SESSION['TransactionId'], $_SESSION['Order']);
?>