X

Best Practices from Oracle Development's A‑Team

Creating a JWT Token for an Assertion Grant Type Flow

Olaf Heimburger
A-Team Cloud Solution Architect
 

Introduction

In an recent post I explained how to use the IDCS Assertion Grant Type Flow to create a personalized JWT Access Token. But I deliberatly excluded any sample code for obvious reasons: There are just too many libraries and programming languages available to create such a token. On the other hand, the way to create the token is very similar in every programming language. As a result, I present a sample code snippet here.

Prerequisites

To create a JWT token, we need to

  • Understand the JSON Web Token structure
  • Have a Signing Key Pair
  • Have a JWT library

JSON Token Structure

The JWT is represented as a concatenation of three segments: Header segment, Claim segment, and the Signature segment. All segments are JSON objects which are base64url encoded and separated by a period ('.').

JWT Header Segment

The JWT Header segment describes the cryptographic operations applied to the Header and the Claim segments. A typical Header segment looks like this:

Header = { "typ": "JWT", "alg": "RS256", "kid": "<certificate_alias>", "x5t": "<certificate_thumbprint>" }

The claims kid and x5t are used as a reference to the signing certificate, where kid is set to the alias name used at the target and x5t to the thumbprint of the signing certificate. Only one is needed and when both are present the x5t will be used.

JWT Claim Segment

The Claim segment is the payload of an JWT and contains all the useful information. When creating a User Assertion for the Assertion Grant Type Flow the Claim segment looks like this:

Claim = { "sub": "<user_name>", "aud": [ "https://identity.oraclecloud.com/" ], "iss": "<issuer_id>", "exp": <token_lifetime>, "prn": "<user_name>", "iat": <time_issued>, "jti": "<unique JWT ID>" }

JWT Signature Segment

The Signature segment is created by the JWT library and signs the Header and Claim segments.

Signing Key Pair

Creating a Signing Key Pair can be done in many ways and with many tools. It can be an easy self-signed private key or a fully authorized key with a certificate from a well-known Certification Authority.

For this example, we use the standard JVM keytool process to create a self-signed private/public key pair and a certificate.

  • Create a self-signed key pair with a certificate valid for five years:keytool -genkey -keyalg RSA -alias <your_alias> -keystore <keystore_file> -storepass <password> -validity 1825 -keysize 2048
  • Export the certificate:keytool -exportcert -alias <your_alias> -rfc -file <filename> -keystore <keystore_file> -storepass <password>

JWT Library

Picking a JWT Library is mainly dependent on the programming language, the programmer's preferences, and some company-related approval processes. For example, when I write code for the WebLogic Server Enterprise Edition and also install the Fusion Middleware Infrastructure Libraries (aka JRF files) the easiest is to pick the Oracle Security Developer Tools (OSDT) and use the Oracle JSON Web Token class.

The Code Sample

The following code sample is divided in four parts:

  1. Get the private key and the related public key certificate
  2. Create the JWT Header segment
  3. Create the JWT Claim segment
  4. Create the JWT Signature segment and serialize it in one call

The code is pretty straight forward and should speak for itself.

try { // Get the private key and the public certificate KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream(kstore), storepass.toCharArray()); PrivateKey privateKey = (PrivateKey)keystore.getKey(privateAlias, privatePass.toCharArray()); X509Certificate cert = (X509Certificate)keystore.getCertificate(certAlias); // Create the JWT JwtToken token = new JwtToken(); // Header segment token.setAlgorithm(JwtToken.SIGN_ALGORITHM.RS256.toString()); token.setType(JwtToken.JWT); token.setHeaderParameter("kid", certAlias); token.setX509CertThumbprint(cert); // Claim segment token.setIssuer(issuer); token.setPrincipal(userName); token.setClaimParameter("sub", userName); token.setClaimParameter("aud", audience); // Issuer and expiry time long currentTimeInMillis = System.currentTimeMillis(); Date issuerDate = new Date(currentTimeInMillis); long expirationTimeInMillis = TimeUnit.DAYS.toMillis(1); long updatedExprirationTimeInMillis = currentTimeInMillis + expirationTimeInMillis; Date expirationDate = new Date(updatedExprirationTimeInMillis); token.setExpiryTime(expirationDate); token.setIssueTime(issuerDate); // Unique ID to prevent token replay token.setJwtID(UUID.randomUUID().toString()); // Add Signature segment and serialize as base64url encoded return token.signAndSerialize(privateKey); } catch (Exception e) { // ... catch code }

Summary

This short addedum to my previous post Authentication and User Identity Propagation for API Calls gives you a head start in creating a User Assertion JWT. No matter which programming language or library you use, the steps are very similar.

References

 

 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha