How to calculate and verify a JWT (JSON Web Token)

With EasyMorph it’s possible to easily build and verify JWT tokens signed by using HS256, HS384 and HS512 algorithms. JSON Web Token (JWT) (RFC 7519) is a compact, URL-safe means of representing claims to be transferred between two parties.

Prerequisites:
EasyMorph v 4.4.1 or later

This short article has an attachment with sample code. Any mention of table names or modules are related to this code.

  1. First, create a JWT payload. (Table payload_json in module Main). Required actions: Calculate new column(s), Generate GUID and Construct json.

    Fields "iat" (Issued At), "exp" (Expiration Time) Claim, "nbf" (Not Before) Claim are unix timestaps (RFC NumericDate). EasyMorph has built-in functions to work with dates. But there is no function like tounixtime, we’ll need to perform some date calculations (in extended syntax).

       //  "exp" (Expiration Time) = token expiration is in 1 hour from now
       let expiration_utc_time = utctime(addhours(now(),1))
       let unixtimedelta_in_days = expiration_utc_time - fromunixtime(0)
    
       // convert time delta from days to seconds (unix timestamp)
       floor(unixtimedelta_in_days * 24*60*60)

    Sample output for JWT payload

    {"iss":"issuer@site.com","sub":"issuer@site.com","iat":1599481688,"exp":1599485288,"jti":"df3681bc-3d07-4682-9e58-f463cdcd3381","name":"User name","nbf":1599481688,"role":["Admin","Manager"]}
  2. Construct JWT header (Table json_header in module encode jwt).
    Required actions: Calculate new column(s) and Construct json.

    Sample output

    {"alg":"HS256","typ":"JWT"}
  3. Encode and sign JWT header and JWT payload. (Table JTW encode in module encode jwt)
    Header and payload must be encoded into base64url (a special url safe type of base64). Result of encoding need to be concatenated via dot (.).

    let encoded_data = encode('Base64url',[header]) & '.' & encode('Base64url',[json_payload])

Then sign encoded_data with secret key. For HS256 HS384 HS512 algorithms just use appropriate HMAC function with required secret_key. Since hmachex generates hex, the result must be converted from hex to base64url via hexdecode.

   let hash_alg =
       if {alg} = 'HS256' then 'SHA256' else 
       if {alg} = 'HS384' then 'SHA384' else 
       if {alg} = 'HS512' then 'SHA512' else
       '<not supported>'
   let signature = hexdecode('base64url', hmachex(hash_alg,encoded_data,{secret_key}))      

The final encoded and signed JWT token composed via expression

encoded_data & '.' & signature

and looks like a very long string

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJpc3N1ZXJAc2l0ZS5jb20iLCJzdWIiOiJpc3N1ZXJAc2l0ZS5jb20iLCJpYXQiOjE1OTk0ODc0MjMsImV4cCI6MTU5OTQ5MTAyMywianRpIjoiNjcyOGU1MGYtOTM2My00MzQwLWI2Y2UtYjc0OWI3ZTliMWYxIiwibmFtZSI6IlVzZXIgbmFtZSIsIm5iZiI6MTU5OTQ4NzQyMywicm9sZSI6WyJBZG1pbiIsIk1hbmFnZXIiXX0.yC78OEs8YIRc21mtPbQK7YQ_bqcZ5fbKId-GYUGjTYU
  1. Passing a JWT token to the web service (Table Create JWT sample in module Main)
    Generated JWT Token can be passed to the web service by using Iterate Web request action. First, create a column with header value like 'Bearer ' & [JWT] and then bind this column to header Authorization.

  2. Verifying and decoding JWT (Table JWT decode in module decode jwt)
    Verification is done by signature validation and expiration time checking. Other fields, like nbf, iss, are not validated by this code, so you need to do this manually (if required). If JTW token is valid, module will return a json payload.

JWT encode_decode.morph (26.6 KB)