UNPKG

apigee-edge-js

Version:

nodejs library for the administration API for Apigee (Edge and X and hybrid).

139 lines (126 loc) 4.29 kB
// tokenMgmt.js // functions for helping with management of user tokens for Apigee Admin APIs. // ------------------------------------------------------------------ // Copyright 2017-2021 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /* global Buffer */ const path = require('path'), fs = require('fs'), os = require('os'), tokenStashFile = path.join(os.homedir(), '.apigee-edge-tokens'); var stashedTokens; function expiry(token) { // issued_at is in milliseconds; expires_in is in seconds. gah. return token.issued_at + (token.expires_in * 1000); } function isInvalidOrExpired(token) { if (!token || !token.expires_in || !token.access_token || !token.issued_at ){ return true; // invalid } let now = (new Date()).getTime(), tokenExpiry = expiry(token), adjustmentInMilliseconds = 30 * 1000, adjustedNow = now + adjustmentInMilliseconds, invalidOrExpired = (tokenExpiry < adjustedNow); return invalidOrExpired; } function readTokenStash() { if (stashedTokens) { return stashedTokens; } if (fs.existsSync(tokenStashFile)) { stashedTokens = JSON.parse(fs.readFileSync(tokenStashFile, 'utf8')); return stashedTokens; } return null; } function getTokenStashKey(user, loginBaseUrl, mgmtServer) { return user + '##' + mgmtServer + '##' + loginBaseUrl; } function currentToken(user, loginBaseUrl, mgmtServer) { const tokens = readTokenStash(), key = getTokenStashKey(user, loginBaseUrl, mgmtServer), userEntry = tokens && tokens[key]; return userEntry; } function enhanceToken(token) { let iso = {}; if (token.access_token) { //console.log('token: ' + JSON.stringify(token, null, 2)); let parts = token.access_token.split(new RegExp('\\.')); if (parts && parts.length == 3) { try { let payload = Buffer.from(parts[1], 'base64').toString('utf-8'), claims = JSON.parse(payload); // The issued_at and expires_in properties on the token // WRAPPER are inconsistent with the actual token. So let's // overwrite them. if (claims.iat) { let d = new Date(claims.iat * 1000); token.issued_at = d.getTime(); // milliseconds iso.issued_at = d.toISOString(); } if (claims.exp) { let d = new Date(claims.exp * 1000); iso.expires = d.toISOString(); token.expires_in = claims.exp - claims.iat; // seconds } } catch (e) { // not a JWT; probably a googleapis opaque oauth token if (token.issued_at) { let d = new Date(token.issued_at); iso.issued_at = d.toISOString(); if (token.expires_in) { let d = new Date(token.issued_at + token.expires_in * 1000); iso.expires = d.toISOString(); } } } } } token.ISO = iso; return token; } function stashToken(user, loginBaseUrl, mgmtServer, newToken) { let tokens = readTokenStash(); if ( ! tokens) { tokens = {}; } const key = getTokenStashKey(user, loginBaseUrl, mgmtServer); tokens[key] = newToken; // possibly overwrite an existing entry try { let keptTokens = {}; Object.keys(tokens).forEach( key => { if ( ! isInvalidOrExpired(tokens[key] )) { keptTokens[key] = enhanceToken(tokens[key]); } }); tokens = keptTokens; fs.writeFileSync(tokenStashFile, JSON.stringify(keptTokens, null, 2)); fs.chmodSync(tokenStashFile, '600'); } catch (e) { // gulp console.log('Warning: cannot write token stash: ' + e); } stashedTokens = tokens; return tokens; } module.exports = { expiry, isInvalidOrExpired, currentToken, readTokenStash, stashToken };