return { getToken() { return new Promise(async (resolve, reject) => { try { getRedisKey = function () { return `fhir-${fhirSettings.jwt.clientId}`; }; const tokenEntry = await redis.hGetAll(getRedisKey()); const currentTimeInSeconds = Math.floor(new Date().getTime() / 1000); if (tokenEntry.exp >= currentTimeInSeconds) { resolve(JSON.parse(tokenEntry.token)); return; } // start the expiry base before we create a new token let expiryInSeconds = Math.floor(new Date().getTime() / 1000); // Define headers const headers = { alg: "RS256", typ: "JWT", }; // Define your payload const payload = { iss: fhirSettings.jwt.client_id, sub: fhirSettings.jwt.client_id, aud: fhirSettings.token_url, }; // Define token options (optional) const options = { expiresIn: "4m", // Token expires in 1 hour notBefore: "0", algorithm: "RS384", keyid: "iva_id_1234", jwtid: uuidv5("jwtid", fhirSettings.jwt.uuid_namespace), }; let data = qs.stringify({ grant_type: "client_credentials", client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", client_assertion: jwt.sign( payload, fhirSettings.jwt.privateKey, options ), }); let config = { method: "post", maxBodyLength: Infinity, url: fhirSettings.token_url, headers: { "Content-Type": "application/x-www-form-urlencoded", }, data: data, }; const result = await axios(config); if (result.status == 200) { expiryInSeconds += result.data.expires_in; console.log( `fhirInterface.getToken: Adding ${getRedisKey()} to redis with expiry=${new Date( expiryInSeconds * 1000 )}` ); await redis.hSet(getRedisKey(), "exp", expiryInSeconds); await redis.hSet(getRedisKey(), "token", JSON.stringify(result.data)); resolve(result.data); } else { reject(result.status); } } catch (err) { console.log("fhirInterface.getToken: Error getting Token"); console.log(err); if (err.response) { console.log(err.response.data); // => the response payload } reject(err); } }); }, };