Skip to content

Title: MDRTOKEN Copybook Date: 2024-07-03

MDRTOKEN COPYBOOK

This copybook is supplied with the MDRest4i Product. It can be found in MDRST/QRPGLESRC. It contains the templates and ILE procedures available in the MDRTOKEN service program.

Example Program

Please see MDRST/EXAMPLE.MDRTKNAPI for an example REST API program. This program demonstrates how to call the various available MDRTOKEN functions.

MDRDCRED_t MDRDCRED template

This is a data structure template based on table MDRDCRED:

Subfield Description
clientid Client ID - can be any value used to identify this credential
appid Application ID- can be any value used to identify this credential
usetyp Usage Type - A=API, C=Consumer, B=Both, O=Other
credtyp Credential Type - B=Basic, T=Bearer(Token) R=Remote
tkntyp Token Type:
PAT= Personal Access Token,
JWT=JSON Web Token,
JWS=JSON Web Signature
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
authtoken Authentication Token
username User Name - usually used in consumers to obtain token
passwd Password - usually used in consumers to obtain token
payload JSON payload for JWT Claims or JWS body as JSON string
dcmapp DCM Application used for signatures
keystore Path to keystore
keystuser Keystore user
keystpwd Keystore password
cliSecret Client Secret
publickey Public key used for jwtalgo=RS256-PVT
privatekey Private key used for jwtalgo=RS256-PVT
autsvr URI used to validate token
toksvr URI used to get new, or refresh token
refreshmth Refresh Method - Automatic or Manual
refreshtkn Token used to refresh expired token
atokenexp authToken Token Expiry period
rtokenexp refreshtkn Token Expiry period
claimsiat "iat" value from claims payload
claimsExp "exp" value from claims payload
expiryunit Unit of measure used for Auth/Refresh token expiry
issuer username of person who created token
issuetime Issued timestamp
issueLog Issue User/Jobname/jobnumber etc
updatetime MDRDCRED Record update timestamp
updatelog Update User/Jobname/jobnumber etc
dcl-ds MDRDCRED_t qualified template;
  clientid varchar(36) ;
  appid varchar(20) ;
  usetyp char(1) ;
  credtyp char(1) ;
  tkntyp char(3) ;
  algor varchar(20) ;
  authtoken varchar(4096);
  username varchar(256) ;
  passwd varchar(1024) ;
  claims varchar(1024);
  dcmapp varchar(50) ;
  keystore varchar(256) ;
  keystuser varchar(256) ;
  keystpwd varchar(256) ;
  clisecret varchar(2048) ;
  publickey varchar(2048) ;
  privatekey varchar(2048);
  autsvr varchar(2048) ;
  toksvr varchar(2048) ;
  refreshmth char(10) ;
  refreshtkn varchar(4096) ;
  atokenexp int(10) ;
  rtokenexp int(10) ;
  claimsiat int(10) ;
  claimsexp int(10) ;
  expiryunit char(10) ;
  issuer char(36) ;
  issuetime timestamp ;
  issuelog char(64) ;
  updatetime timestamp ;
  updatelog char(64) ;
end-ds;

MDR_claims_t

This is a data structures template used to contain key/value pairs for a JWT Token:

dcl-ds MDR_tknClaims_t qualified template;
  claimKey varchar(50);
  claimVal varchar(1024);
end-ds;

MDR_createToken

Creates a auth and refresh token and saves details in MDRDCRED as requested

Note

see MDRST/QRPGLESRC.MDRTKNAPI for an example how to use this function.

see https://wiki.midrangedynamics.com/manuals/MDRest4i/manual/create-rs256-token/ for adetailed help on how to create an RS256 JWT token

Parameters
@param (input/output) creds = credentials data structure
@param (outout) errMsg = any error messages from creation
@param (input) save = *ON=save, *OFF=don't save, details to MDRDCRED
               Note: if not passed this is set to *ON by default

@return *ON if created/saved, *OFF if failed```
Example
  Status = MDR_createToken(creds:errorMsg:*off) or
  Status = MDR_createToken(creds:errorMsg)
Prototype
dcl-pr MDR_createToken ind;
  creds likeds(MDRDCRED_t);
  errMsg varchar(200);
  save ind const options(*nopass);
end-pr;

Token Validation Constants

dcl-c c_VALID const('V');
dcl-c c_INVALID const('I');
dcl-c c_NOTFOUND const('N');
dcl-c c_EXPIRED const('E');
dcl-c c_INVALIDSIGN const('S');

MDR_validateToken

Validates a token. The third parameter is optional and if supplied, the second part of the token (i.e. claims payload) is decoded from base64 back to JSON string, parsed and the JSON key/value pairs loaded in this data structure parameter

  • Check if the token is valid and has three values separated by dots
  • Check if the token exists in MDRDCRED database
  • Check if the auth token is valid by comparing current timestamp with the value in claimsIat and doesn't exceed MDRDCRED.claimsexp
  • Extract the claims from the JWT claims section of te token, and return JSON key/value pairs in third data structure parameter
Parameters
@param (input) authToken = auth token for validation
@param (output) errMsg = any error messages from creation
                Possible messages: Token not found in database
                                   Token expired
                                   Token signature invalid
@param (output) tknClaims = array of key/value pairs of the JWT token claims.

@return V=Valid, N=Not found, E=Expired, S=Invalid Signature
Example
Status = MDR_validateToken(aToken:errorMsg)
Status = MDR_validateToken(aToken::tknClaimsDS)
Prototype
dcl-pr MDR_validateToken char(1);
  authToken varchar(4096);
  errMsg varchar(200);
  tknClaims dim(20) likeds(MDR_tknClaims_t) options(*nopass);
end-pr;

MDR_validateAuthToken

Retrieves the auth token from the API request via cgi channel and then it calls MDR_ValidateToken to validate the token. The fourth parameter is optional and if supplied, the second part of the token (i.e. claims payload) is decoded from base64 back to JSON string, parsed and the JWT claims JSON key/value pairs loaded in this data structure. See MDR_tknClaims_t for details.

Parameters
@param (input) handle: threadsafe handler key
@param (output) authToken = auth token as retrieved from API and validated
@param (output) errMsg = any error messages from creation
                Possible messages: Token not found in database
                                   Token expired
                                   Token signature invalid
@param (output) tknClaims = array of key/value pairs of the JWT token claims.

@return V=Valid, N=Not found, E=Expired, S=Invalid Signature,
        X=Not a bearer token
Example
Status = MDR_validateAuthToken(handle:authToken:erorrMsg) or
Status = MDR_validateAuthToken(handle:authToken:erorrMsg:tknClaimsDS)
Prototype
dcl-pr MDR_validateAuthToken char(1);
  handle like(MDR_Handle_t);
  authToken varchar(4096);
  errMsg varchar(200);
  tknClaims dim(20) likeds(MDR_tknClaims_t) options(*nopass);
end-pr;

MDR_refreshToken

Refreshes the auth token and saves details in MDRDCRED

Note

Only the refresh token is required to be supplied in the "creds" data structure and rest all fields can be sent as blank/zeros. After the procedure call, the data structure "creds" will have all the values loaded from the MDRDCRED credentials file with the new auth/refresh token

Parameters
@param (input/output) creds = credentials data structure but only the refresh
                          token from the DS is used
@param (outout) errMsg = any error messsages from refresh
@param (input) save = *ON=save, *OFF=don't save, details to MDRDCRED
              Note: if not passed this is set to *On by default

@return *ON if refreshed/saved, *OFF if failed
Example
Status = MDR_refreshToken(creds:errorMsg:*off) or
Status = MDR_refreshToken(creds:errorMsg)
Prototype
dcl-pr MDR_refreshToken ind;
  creds likeds(MDRDCRED_t);
  errMsg varchar(200);
  save ind const options(*nopass);
end-pr;

MDR_verifySign

Verifies the token signature provided and returns status. The procedure reads the credentials DB file to find the DCM application or client secret depending on the algorithm along with other details to recreate the signature and then match with the third part of the token

// Note: This procedure accepts "creds" data structure but only "authToken" is used

@param (input/output) creds = credentials data structure @param (output) errMsg = any error messsages from validation

@return V=Valid, N=Not found, S=Token Invalid Signature

Example:

Status = MDR_verifySign(creds:errMsg)

dcl-pr MDR_verifySign char(1);
  creds likeds(MDRDCRED_t);
  errMsg varchar(200);
end-pr;

MDR_deleteToken

Deletes the MDRCRED credentials record for clientid, appid or the auth token

NOTE: Only the auth token or "clientId" and "appId" is required to be supplied in "creds" data structure.

@param (input/output) creds = credentials data structure @param (outout) errMsg = any error messages from creation

@return ON if deleted, OFF if delete failed

Example:

StatusFlag = MDR_deleteToken(creds:errorMsg)

dcl-pr MDR_deleteToken ind;
  creds likeds(MDRDCRED_t);
  errMsg varchar(200);
end-pr;

MDR_CalculateNewEpochTime

Calculate Epoch time time from given epoch time, duration and time unit

@param (input) epochTime = Base value of epoch Time @param (input) duration = duration to add to epoch time @param (input) timeUnit = e.g. SECONDS or S, MINUTES or M HOURS or H, DAYS or D

@return new value in epochtimestamp

Example: newEpochTimeStamp = MDR_CalculateNewEpochTime(inputEpochTime:ValueToAdd:'*SECONDS')

dcl-pr MDR_CalculateNewEpochTime int(20);
  epochTime int(20) const;
  duration int(10) value;
  timeUnit char(10) const;
end-pr;

MDR_CvtToEpochTimestamp

Convert supplied timestamp to Epoch time

@param (input) timeStampVal = timestamp value requested for conversion

@return epoch timestamp

Example: newEpochTimeStamp = MDR_CalculateNewEpochTime(timeStampValue)

dcl-pr MDR_CvtToEpochTimestamp int(20);
  timeStampVal timestamp const;
end-pr;

MDR_getClaims

Parse the claims payload and return key/value pairs in an array

@param (input) jsonClaims = JSON string to be parsed for key/value pairs @param (output) tknClaims = data structure array containing json key/values

Example: MDR_getClaims(claimsPayload:claims_ds)

dcl-pr MDR_getClaims;
  jsonClaims varchar(2048);
  tknClaims likeds(MDR_tknClaims_t) dim(20);
end-pr;

MDR_createJWT_RS256_DCM

Creates a JWT Token using RS256-DCM algorithm from request JSON body. Returns *ON if OK, plus tokenResp ds with the token details

@param (input) handle: threadsafe handler key @param (input) body = request JSON body @param (input/output) creds = details to create/save Token @param (output) tokenResp = created token response ds @param (output) errorMsg = error message (if any) @param (input) save = option to save token to MDRDCRED

@return indicator *ON if successful

Example JWT Claim Payloads

Below are two example payloads that can be used to generate JWT tokens, using RS256 Algorithm with public and private keys from the IBM i DCM:

{
  "clientid": "CLT002",
  "appid": "App002",
  "tkntyp": "JWT",
  "algor": "RS256-DCM",
  "claims": {
    "department": "Customer Care",
    "country": "US",
    "area": "Area1",
    "iat": 1720684763
  },
  "dcmapp": "MDREST4I",
  "atokenexp": 60,
  "rtokenexp": 120,
  "expiryunit": "*SECONDS"
}
{
  "clientid": "CLT002",
  "appid": "App002",
  "tkntyp": "JWT",
  "algor": "RS256-DCM",
  "claims": {
    "department": "Customer Care",
    "country": "US",
    "area": "Area1",
    "exp": 1720684763
  },
  "dcmapp": "MDREST4I",
  "atokenexp": 60,
  "rtokenexp": 120,
  "expiryunit": "*SECONDS"
}

Here is the prototype:

dcl-pr MDR_create_JWT_RS256_DCM ind;
    handle like(MDR_Handle_t);
    body varchar(2048:4) options(*varsize) ccsid(*utf8);
    creds likeds(MDRDCRED_t);
    tokenResp likeds(tokenResp_t);
    errorMsg varchar(100:4);
    save ind const options(*nopass);
end-pr;