JSON Web Token Helper

The JSON Web Token Helper contains handlers which allows you to generate, decode and verify JSON Web Tokens. It follows the industry standard RFC 7519 which is a means for representing claims as a JSON object to be transferred between two parties. The JWT helper uses the HMAC SHA256, SHA384 or SHA512 hashing algorithm to sign tokens and a RSA public/private key pair to encrypt the hashed signing input in case an asymmetric signing algorithm is preferred. The RSA key length is 4096 bits.

If you are not familiar with JSON Web Tokens you can read about the concept at https://jwt.io.

Note: If the server engine used is not LC Create, this helper requires the LiveCode Builder (library) extension com.livecode.library.json which needs to be stored in application/extensions. So, the path to the extension is application/extensions/com.livecode.library.json/module.lcm. Please read about how to include/load the LiveCode JSON extension in chapter "Extensions".

Note: HMAC SHA384 and SHA512 hashing algorithms are not supported on LiveCode server prior to version 9.

Loading this Helper

This helper is loaded using the following code:

rigLoadHelper "jwt"

The Key

The key (secret) used to sign the token should be saved to a file named "jwt.lc" in application/config. Preferably this key is a binary string which implicitly needs to be base64 encoded. If you don't specify a key it will be generated for you - provided that file permissions allow - using the LiveCode randomBytes(64) function and saved to application/config/jwt.lc on calling the handler to encode a token. Keep in mind that if your server is not totally under your control it's impossible to ensure key security so you may want to think carefully before using it for anything that requires high security.

The RSA Public/Private Key Pair

The optional RSA public/private key pair used to encrypt the hashed signing input should be saved to a file "jwtPrivate4096" and "jwtPublic4096" respectively in application/config. If the keys are missing they will be generated for you on first request provided that file permissions allow and that the OpenSSL suite of command line tools is installed.

Handler Reference

The following handlers are available:

rigJWTencode(pHeader, pPayload, pNumBits, pAlg)

This function generates and returns a JSON Web Token.

Parameters

Example using the default header and the default signing algorithm (HS256 on LIveCode server below vesion 9 and HS512 on LiveCode server version 9 or higher):

put the seconds into tIAT
put tIAT + 10 into tNBF
put tIAT + 60 into tEXP
put uuid() into tJTI
put "sub, jwt test, name," && tUsername & ", admin, true, iat," && tIAT & ", nbf," \
	&& tNBF & ", exp," && tEXP & ", jti," && tJTI into tJWTpayload

put rigJWTencode( , tJWTpayload) into tJWT

put tJWT into tTokenA["jwt"]

# rigSetHeader DOES NOT WORK WITH AJAX, USE: put header ...
# GENERATES AN OBJECT ON CLIENT SIDE. SO, DON'T USE JSON.parse() TO PROCESS THE DATA
put header "Content-type: application/json; charset=UTF-8"
put JsonExport(tTokenA)

Following a variant using an array as second parameter:

put the seconds into tIAT
put tIAT + 10 into tNBF
put tIAT + 60 into tEXP

# NOTE: SECONDS NEED TO BE A STRING, OTHERWISE THE DATA OF JSONEXPORT IS NOT VALID.
put tIAT & "" into tJWTpayloadA["iat"]
put tNBF & "" into tJWTpayloadA["nbf"]
put tEXP & "" into tJWTpayloadA["exp"]
put "jwt test" into tJWTpayloadA["sub"]
put tUsername into tJWTpayloadA["name"]
put "true" into tJWTpayloadA["admin"]
put uuid() into tJWTpayloadA["jti"]

put rigJWTencode( , tJWTpayloadA) into tJWT

put tJWT into tTokenA["jwt"]

# rigSetHeader DOES NOT WORK WITH AJAX, USE: put header ...
# GENERATES AN OBJECT ON CLIENT SIDE. SO, DON'T USE JSON.parse() TO PROCESS THE DATA
put header "Content-type: application/json; charset=UTF-8"
put JsonExport(tTokenA)

These two examples above assume that the client side provides code which handles the response in form of a JSON object.

Example for the assignment of a signing algorithm, in this case RSA384, using the default header:

put rigJWTencode( , tJWTpayload, 384, "RS") into tJWT

rigJWTdecode(pToken)

Decode and validate a JSON Web Token.

Parameters

Example:

put "The secret data." into tSecretData

put rigJWTdecode() into tJWTA

if tJWTA["valid"] is TRUE then
  
  put the seconds into tCurrentTime
  put TRUE into tTimeValid

  if tCurrentTime < tJWTA["payload"]["nbf"] then
    put "Token not yet valid." into tA["responsedata"]
    put FALSE into tTimeValid
  else if tCurrentTime > tJWTA["payload"]["exp"] then
    put "Token expired." into tA["responsedata"]
    put FALSE into tTimeValid
  end if
  
  if tTimeValid is TRUE then
    if tJWTA["valid"] then
      put tSecretData into tA["responsedata"]
    else
      put tJWTA["response"] into tA["responsedata"]
    end if
  end if
	
else-- if tJWTA["valid"] is TRUE
  # RESPONSE IS ERROR "HTTP/1.0 400 Bad Request" OR "HTTP/1.0 401 Unauthorized"
  put tJWTA["response"] into tA["responsedata"]
  rigSetStatusHeader word 2 of tJWTA["response"]
end if -- if tJWTA["valid"] is TRUE

# rigSetHeader DOES NOT WORK WITH AJAX, USE: put header ...
# GENERATES AN OBJECT ON CLIENT SIDE. SO, DON'T USE JSON.parse() TO PROCESS THE DATA
put header "Content-type: application/json; charset=UTF-8"
put JsonExport(tA)

The example above assumes that the client side provides code which handles the response in form of a JSON object.

Data Returned

This function returns an array including the following keys: