This is a simple class in order to generate, validate or blacklist a JSON Web Token.
Signature is encrypted with HS256 algorithm.
Set validityInSecond = 3600
Set jwt = ##class(dc.auth.jwt.JWTGenerator).generate("MySecretKey",validityInSecond)
Generated token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1ODc1ODQ2OTksInN1YiI6ImlyaXNvd25lciIsImlzcyI6IklSSVMtSVJJU0FQUCIsImV4cCI6MTU4NzU4ODI5OSwibmJmIjoxNTg3NTg0Njk5LCJqdGkiOiIxMTExNCJ9.r-tyzZBPBE5_OeFjkr355QEztriswX3EkN68Ck9Em-M
{
"alg": "HS256",
"typ": "JWT"
}
{
"iat": 1587584761,
"sub": "irisowner",
"iss": "IRIS-IRISAPP",
"exp": 1587588361,
"nbf": 1587584761,
"jti": "11215"
}
Set validityInSecond = 3600
Set addPayloadData = { "name" : "Mike Wazowski", "sub":"override sub property" }
Set jwt = ##class(dc.auth.jwt.JWTGenerator).generate("MySecretKey",validityInSecond,addPayloadData)
Generated token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiTWlrZSBXYXpvd3NraSIsInN1YiI6Im92ZXJyaWRlIHN1YiBwcm9wZXJ0eSIsImlhdCI6MTU4NzU4NTcyMywiaXNzIjoiSVJJUy1JUklTQVBQIiwiZXhwIjoxNTg3NTg5MzIzLCJuYmYiOjE1ODc1ODU3MjMsImp0aSI6IjExNjE5In0.ZeV7J2KQKFO7l3ZZghrN0mLFhkhcErD80bTFdXXeIjo
Payload data :
{
"name": "Mike Wazowski",
"sub": "override sub property",
"iat": 1587585723,
"iss": "IRIS-IRISAPP",
"exp": 1587589323,
"nbf": 1587585723,
"jti": "11619"
}
Force a payload without merging with default payload strucure:
Set validityInSecond = 3600
Set payload = { "name" : "Mike Wazowski", "sub":"irisuser", "iat":1587584761,"exp":1587588361, "aud":"1.2.3.4" }
Set jwt = ##class(dc.auth.jwt.JWTGenerator).generate("MySecretKey",validityInSecond,payload,0,.jwtObj)
Generated token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiTWlrZSBXYXpvd3NraSIsInN1YiI6ImlyaXN1c2VyIiwiaWF0IjoxNTg3NTg0NzYxLCJleHAiOjE1ODc1ODgzNjEsImF1ZCI6IjEuMi4zLjQifQ.zytuIRD56lvAnb-WnguIfbn9-t8RwSzfI_9PbBHzq8U
Payload data :
{
"name": "Mike Wazowski",
"sub": "irisuser",
"iat": 1587584761,
"exp": 1587588361,
"aud": "1.2.3.4"
}
If you pass by reference a fifth argument to isValid method you may retrieve the dc.auth.jwt.JWTGenerator object instance.
Set isValid = ##class(dc.auth.jwt.JWTGenerator).isValid(jwt,"MySecretKey",.sc,,.jwtObj)
If the token is invalid, you can retrieve an error message with the status passed by reference
Write $SYSTEM.Status.GetOneErrorText(sc)
Ex: ERROR #5001: Signature Mismatch.
If you pass by reference a fifth argument to isValid method you may retrieve the dc.auth.jwt.JWTGenerator object instance.
It’s useful for payload data access ex :
zw jwt.payload
Payload property is a %DynamicObject.
Set payLoadMatch = {"name":"Mike Wazowski", "aud":"127.0.0.1"}
Set isValid = ##class(dc.auth.jwt.JWTGenerator).isValid(jwt,"MySecretKey",.sc,payLoadMatch,.jwtObj)
Write $SYSTEM.Status.GetOneErrorText(sc)
Result : ERROR #5001: aud mismatch.
We can also check if aud value match in specific list :
Set payLoadMatch = {"name":"Mike Wazowski", "aud": ["127.0.0.1","1.2.3.4"] }
Set isValid = ##class(dc.auth.jwt.JWTGenerator).isValid(jwt,"MySecretKey",.sc,payLoadMatch,.jwtObj)
Write $SYSTEM.Status.GetOneErrorText(sc)
Result : OK
Blacklist method use jti
property to store the blacklisted jwt.
If you use your own payload structure without jti property, blacklist method fail and return ERROR #5001: jti is null
.
example :
Set validityInSecond = 3600
Set jwt = ##class(dc.auth.jwt.JWTGenerator).generate("MySecretKey",validityInSecond) ; Generate a token for blacklist testing
Do ##class(dc.auth.jwt.JWTGenerator).blackList(jwt)
Now check the validity :
Set isValid = ##class(dc.auth.jwt.JWTGenerator).isValid(jwt,"MySecretKey",.sc)
Write !,$SYSTEM.Status.GetOneErrorText(sc)
Result : ERROR #5001: Token is black listed.
Remove all token from the blacklist:
Do ##class(dc.auth.jwt.JWTGenerator).purgeBlackList(0)
Remove only expired from the blacklist:
Do ##class(dc.auth.jwt.JWTGenerator).purgeBlackList()
Make sure you have git and Docker desktop installed.
zpm
install jwt-generator
Clone/git pull the repo into any local directory
$ git clone https://github.com/intersystems-community/objectscript-docker-template.git
Open the terminal in this directory and run:
$ docker-compose build
$ docker-compose up -d
This repository is ready to code in VSCode with ObjectScript plugin.
Install VSCode, Docker and ObjectScript plugin and open the folder in VSCode.
Open /src/cls/PackageSample/ObjectScript.cls class and try to make changes - it will be compiled in running IRIS docker container.
Feel free to delete PackageSample folder and place your ObjectScript classes in a form
/src/Package/Classname.cls
Read more about folder setup for InterSystems ObjectScript
The script in Installer.cls will import everything you place under /src into IRIS.
The simplest dockerfile which starts IRIS and imports Installer.cls and then runs the Installer.setup method, which creates IRISAPP Namespace and imports ObjectScript code from /src folder into it.
Use the related docker-compose.yml to easily setup additional parametes like port number and where you map keys and host folders.
Use .env/ file to adjust the dockerfile being used in docker-compose.
Dockerfile-zpm builds for you a container which contains ZPM package manager client so you are able to install packages from ZPM in this container.
As an example of usage in installs webterminal
Dockerfile-web starts IRIS does the same what Dockerfile does and also sets up the web app programmatically
Settings file to let you immedietly code in VSCode with VSCode ObjectScript plugin)
Config file if you want to debug with VSCode ObjectScript