Token Handling
Overview
MDRest4i supports creating, refreshing and validating Java Web Tokens (JWT) using HS256 and RS256 Algorithms. The standards used follow the details and examples found on the jwt.io website.
The encryption and signature of MDRest4i JWT tokens use either an IBM i DCM application, a custom IBM i Key Store or a pre-supplied public and private key.
The signature of a token can also be verified using the MDR_verifySign() procedure.
MDRest4i also supports creating, validating Personal Access Tokens (PAT). It uses the ILE-bindable API, CEERAN0 to encode this.
Token Handling Procedures
All token handling procedures in MDRest4i require the copybook MDRST/QRPGLERSC.MDRTOKEN. The MDRTOKEN *SRVPGM is automatically bound in via the MDRFRAME binding directory.
Creating Tokens
MDRTOKEN is supplied with procedures MDR_CreateToken and MDR_create_JWT_RS256_DCM The main parameter in this procedure is the creds data structure.
Validating Tokens
The validation of a JWT or PAT token by MDREst4i works as follows:
- Tokens created by MDRest4i are stored in the table MDRST/MDRDCRED.
- A token is passed to the REST API request either as an Authorization header Bearer Token, or as a custom HTTP header
- The procedures MDR_ValidateToken or MDR_ValidateAuthToken are used to check the existence, and expiry status of the supplied token.
- For JWT Tokens, the JWT Claims data structure is returned by MDR_ValidateToken, MDR_ValidateAuthToken, and MDR_getClaims procedures from the service program MDRTOKEN
Refreshing Tokens
Token Handling Components
The MDRest4i Token handling is supplied with these development and runtime components:
Name | Type | Descriptio |
---|---|---|
MDRTOKEN | *SRVPGM | This service program is bound in to all REST Providers via Binding Directory MDRFRAME. It contains the ILE module MDRTOKEN with all of the token handling procedures exported. |
MDRST/QRPGLESRC.MDRTOKEN | RPGLE COPYBOOK | This copybook contains the procedures and documentation fpr the MDRTOKEN procedures |
MDRST/MDRDCRED | DB2 TABLE/PF | A Physical file containing saved tokens. |
MDRST/EXAMPLE.MDRTKNAPI | REST API | A REST API that demonstrates the creation of JWT tokens via REST. |
MDRST/EXAMPLE.MDRTKNREF | REST API | A Rest API that demonstrates the refresh of a JWT token using the refresh token issued by MDRest4i via REST. |
MDRST/EXAMPLE.MDRTKNTST | REST API | A Rest API that demonstrates the refresh of a JWT token using the refresh token issued by MDRest4i via REST. |
MDRDCRED Token Store
Tokens (and their configuration) created by MDRest4i functions are stored in table MDRST/MDRDCRED. If REST API/Provider uses MDR_ValidateToken, it checks the existence of the provided token in this TABLE:
CREATE or replace TABLE ++OBJLIB++/MDRDCRED (
-- Client ID: can be any value used to identify this credential
CLIENTID VARCHAR(36) NOT NULL DEFAULT '' ,
-- Application ID: can be any value used to identify this credential
APPID VARCHAR(20) NOT NULL DEFAULT '' ,
-- Usage Type: A=API, C=Consumer, B=Both, O=Other
USETYP CHAR(1) NOT NULL DEFAULT '' ,
-- Credential Type: B=Basic, T=Bearer(Token) R=Remote
CREDTYP CHAR(1) NOT NULL DEFAULT '' ,
-- tkntype: Token Type :
-- PAT= Personal Access Token,
-- JWT=JSON Web Token,
-- JWS=JSON Web Signature
TKNTYP CHAR(3) NOT NULL DEFAULT '' ,
-- algor: Encryption/Decryption Algorithm & Key type
-- UUID = Random 36 byte value
-- HS256 = Secret and SHA256 Encryption for Signature
-- RS256-DCM = RS256 using DCM App
-- RS256-KST = RS256 using PF and Lib Key Store
-- RS256-PVT = RS256 using Private & Public Keys
ALGOR VARCHAR(20) NOT NULL DEFAULT '' ,
-- Authentication Token
AUTHTOKEN VARCHAR(4096) NOT NULL DEFAULT '' ,
-- User Name - usually used in consumers to obtain token
USERNAME VARCHAR(256) NOT NULL DEFAULT '',
-- Password - usually used in consumers to obtain token
PASSWD VARCHAR(1024) NOT NULL DEFAULT '' ,
-- small JSON payload for JWT Claims or small JWS body as JSON string
CLAIMS VARCHAR(1024) NOT NULL DEFAULT '' ,
-- DCM Application used for signatures
DCMAPP VARCHAR(50) NOT NULL DEFAULT '' ,
-- Path to keystore
KEYSTORE VARCHAR(256) NOT NULL DEFAULT '' ,
-- Keystore user
KEYSTUSER VARCHAR(256) NOT NULL DEFAULT '' ,
-- Keystore password
KEYSTPWD VARCHAR(256) NOT NULL DEFAULT '' ,
-- Client Secret
CLISECRET VARCHAR(2048) NOT NULL DEFAULT '' ,
-- Public key used for algor=RS256-PVT
PUBLICKEY VARCHAR(2048) NOT NULL DEFAULT '' ,
-- Private key used for algor=RS256-PVT
PRIVATEKEY VARCHAR(2048) NOT NULL DEFAULT '' ,
-- URI used to validate token
AUTSVR VARCHAR(2048) NOT NULL DEFAULT '' ,
-- URI used to get new, or refresh token
TOKSVR VARCHAR(2048) NOT NULL DEFAULT '' ,
-- Refresh Method: Automatic or Manual
REFRESHMTH CHAR(10) NOT NULL DEFAULT '' ,
-- Token used to request refresh of new token after expiry of current one
REFRESHTKN VARCHAR(4096) NOT NULL DEFAULT '' ,
-- Token Expiry period
ATOKENEXP INTEGER NOT NULL DEFAULT 0 ,
RTOKENEXP INTEGER NOT NULL DEFAULT 0 ,
-- Unit of measure used for Auth/Refresh token expiry
EXPIRYUNIT CHAR(10) NOT NULL DEFAULT '' ,
-- issued at time in epoch timestamp format
CLAIMSIAT BIGINT NOT NULL DEFAULT 0 ,
-- expiry time in epoch timestamp format
CLAIMSEXP BIGINT NOT NULL DEFAULT 0 ,
-- Token Issuer
ISSUER CHAR(36) NOT NULL DEFAULT '' ,
ISSUETIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
-- Issue User/Jobname/jobnumber
ISSUELOG CHAR(64) NOT NULL DEFAULT '' ,
UPDATETIME TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
-- Issue User/Jobname/jobnumber
UPDATELOG CHAR(64) NOT NULL DEFAULT '' ,
PRIMARY KEY( CLIENTID , APPID, AUTHTOKEN ) ) RCDFMT MDRDCREDF;
LABEL ON TABLE ++OBJLIB++/MDRDCRED
IS 'MDRest4i - Credential Store' ;
LABEL ON COLUMN ++OBJLIB++/MDRDCRED
( CLIENTID IS 'Client ID' ,
APPID IS 'Application ID' ,
USETYP IS 'Usage Type' ,
CREDTYP IS 'CredTyp' ,
algor IS 'Alg-Keys' ,
AUTHTOKEN IS 'Auth Token' ,
USERNAME IS 'User Name' ,
PASSWD IS 'Password' ,
CLAIMS IS 'JSON Payload/Claims' ,
DCMAPP IS 'DCM Application',
KEYSTORE IS 'Keystore Path',
KEYSTUSER IS 'Keystore User',
KEYSTPWD IS 'Keystore Pwd',
CLISECRET IS 'Client Secret' ,
PUBLICKEY IS 'Public Key' ,
PRIVATEKEY IS 'Private Key' ,
AUTSVR IS 'Auth Server' ,
TOKSVR IS 'Token Server' ,
REFRESHMTH IS 'Refresh Method' ,
REFRESHTKN IS 'Refresh Token' ,
ATOKENEXP IS 'Auth Token Expiry' ,
RTOKENEXP IS 'Refresh Token Expiry' ,
EXPIRYUNIT IS 'Time Unit of Measure' ,
CLAIMSIAT IS 'IssuedAt time(epoch)',
CLAIMSEXP IS 'Expiry Timestamp(epoch)',
ISSUER IS 'Token Issuer' ,
ISSUETIME IS 'Issue Timestamp' ,
ISSUELOG IS 'Issue User/Job' ,
UPDATETIME IS 'Update Timestamp' ,
UPDATELOG IS 'Update User/Job' ) ;
Default & Mandatory Values
Use the following creds subfields as applicable:
Creating an RS256 JWT Token Using DCM
creds.claims - JWT claims payload
At least one of the "iat" or "exp" name value pairs must be supplied in the claims JSON. These are used to determine the expiry of the token. iat = token issue timestamp in Epoch format. This is moved to creds.claimsiat. Along with the Example:
Item | Subfields & Notes |
---|---|
creds.claims JWT claims payload | At least one of the "iat" or "exp" name value pairs must be supplied in the claims JSON. exp = token expiry timestamp in Epoch format. This is moved to creds.claimsexp |
For an RS256 Token | dcmApp is required if a DCM application is being used for the certs. If a custom KeyStore us being used: keystore, keystUser and keystPwd must be supplied. |
For an HS256 token | cliSecret (Client Secret - which is a max 32 byte string) is mandatory. |
For any token | Below are the other mandatory entries in data structure "creds": algor clientId appId claims atokenExp rtokenExp expiryUnit For more details on each, see the MDRDCRED_t description above |
MDRTKNEXP Data Area
The data area MDRTKNEXP contains the following default values, in the event these are not supplied in the creds subfields when calling procedure MDR_createToken. These values are used by procedure MDR_createToken, to create the token expiry value - ie creds.expclaims.
Pos | Value Description |
---|---|
1-10 | Valid duration period of the authorization token |
11-20 | The expiry units used to calculate the actually expiry timestamp. seconds, minutes etc. |
21-30 | Valid duration period of the refresh token |
Please refer refer to MDRST/EXAMPLE.MDRTKNAPI example to see how this data area is being used when the necessary header parameters for auth token expiry, refresh token exp and expiry unit are not supplied.
If the MDRTKNEXP values are blank, atokenExp is set to 180 and the expiry unit is then set as *seconds. Likewise, if the value in "rtokenExp" is 0, this is set to the epoch time equivalent of 24 hours.
If a valid expiryunit is neither supplied nor found in the data area "MDRTKNEXP", it is set as *seconds by default.
The value "atokenexp" will be used while refreshing the token to set the "claimsExp" as the current timestamp + atokenExp in specified expiry units.
The value "rtokenexp" is used to check the expiry of the refresh token. The calculation of refresh token expiry as an Epoch timestamp is: "rtokenExp" + "issueTime". This value is compared with the current timestamp to see if refresh token is expired
MDR_CreateToken
For RS256 Token, either the "dcmApp" or the "keystore", "keystUser" and keystPwd" must be supplied. For HS256 token, cliSecret (which is a 32 byte string) is mandatory. Below are the other mandatory entries in data strcture "creds":
"algor", "clientId", "appId", "claims", "atokenExp", "rtokenExp", "expiryUnit"
The data area "MDRTKNEXP" contains default token expiry "duration" from the position 1-10, the expiry units SECONDS, MINUTES etc. are on 11-20 and the default refresh token expiry "duration" from 21-30. You can use them in the API if the requester hasn't supplied token expiry or refresh token expiry via header parms. refer "MDRTKNAPI" example to see how this data area is being used when the necessary header parameters for auth token expiry, refresh token exp and expiry unit are not supplied. If "atokenExp" is still having the value 0, it is set to 180 and the expiry unit is then set as "SECONDS". Likewise, if the value in "rtokenExp" is 0, this is set to the epoch time equivalent of 24 hours. If the valid "expiryunit" is neither supplied and nor found in the data area "MDRTKNESP", it is set as "SECONDS" by default
The value "atokenexp" will be used while refreshing the token to set the "claimsExp" as the current timestamp + atokenExp in specified expiry units.
The value "rtokenexp" is used to check the expiry of the refresh token. The calculation of refresh token expiry is being done from "rtokenExp" added with "issueTime" and this value is compared with the current timestamp to see if refresh token is expired.
In the new API, at least one of the "iat" or "exp" must be supplied, otherwise give an error to requester