express-gateway
Version:
A microservices API gateway built on top of ExpressJS
178 lines (140 loc) • 4.6 kB
JavaScript
;
const tokenDao = require('./token.dao.js');
const utils = require('../utils');
const uuidv4 = require('uuid/v4');
const config = require('../../config');
const s = {};
s.save = function (tokenObj, options) {
let rt;
options = options || {};
if (!tokenObj.consumerId) {
return Promise.reject(new Error('invalid token args'));
}
if (options.refreshTokenOnly) {
const rt = createInternalToken(tokenObj, newUuid(), newUuid(), 'refresh_token');
return tokenDao.save(rt, { type: 'refresh_token' })
.then(() => {
return { refresh_token: formExternalToken(rt) };
});
}
const at = createInternalToken(tokenObj, newUuid(), newUuid(), 'access_token');
const tokenSavePromises = [tokenDao.save(at)];
if (options.includeRefreshToken) {
rt = createInternalToken(tokenObj, newUuid(), newUuid(), 'refresh_token');
tokenSavePromises.push(tokenDao.save(rt, { type: 'refresh_token' }));
}
return Promise.all(tokenSavePromises)
.then(() => {
return {
access_token: formExternalToken(at),
refresh_token: formExternalToken(rt)
};
});
};
s.findOrSave = function (tokenObj, options) {
options = options || {};
return this.find(tokenObj, options)
.then(tokens => {
if (tokens.access_token) {
if (options.includeRefreshToken && !tokens.refresh_token) {
return this.save(tokenObj, { refreshTokenOnly: true })
.then(rt => {
tokens.refresh_token = rt.refresh_token;
return tokens;
});
} else return tokens;
}
if (tokens.refresh_token) {
return this.save(tokenObj)
.then(at => {
tokens.access_token = at.access_token;
return tokens;
});
}
return this.save(tokenObj, options);
});
};
s.find = function (tokenObj, options) {
options = options || {};
const tokenQueryCriteria = Object.assign({}, tokenObj);
if (tokenQueryCriteria.scopes && Array.isArray(tokenQueryCriteria.scopes)) {
tokenQueryCriteria.scopes = JSON.stringify(tokenQueryCriteria.scopes.sort());
}
const findQueries = [tokenDao.find(tokenQueryCriteria)];
if (options.includeRefreshToken) {
findQueries.push(tokenDao.find(tokenQueryCriteria, { type: 'refresh_token' }));
}
return Promise.all(findQueries)
.then(([accessToken, refreshToken]) => {
return {
access_token: formExternalToken(accessToken),
refresh_token: formExternalToken(refreshToken)
};
});
};
s.get = function (_token, options) {
options = options || {};
const tokenId = _token.split('|')[0];
return tokenDao.get(tokenId, options)
.then(token => {
if (!token) {
return null;
}
if (token.scopes) {
token.scopes = JSON.parse(token.scopes);
}
token.tokenDecrypted = utils.decrypt(token.tokenEncrypted);
delete token.tokenEncrypted;
return token;
});
};
s.getTokenObject = function (refreshToken) {
return this.get(refreshToken, { type: 'refresh_token' })
.then(rtObj => {
if (!rtObj) {
return null;
}
const tokenObj = Object.assign({}, rtObj);
delete tokenObj.createdAt;
delete tokenObj.updatedAt;
delete tokenObj.expiresAt;
delete tokenObj.tokenDecrypted;
delete tokenObj.id;
return tokenObj;
});
};
s.getTokensByConsumer = function (id, options) {
return tokenDao.getTokensByConsumer(id, options);
};
s.revoke = function (accessToken) {
return this.get(accessToken).then(token => {
if (!token) {
throw new Error('Token not found ' + token);
}
return tokenDao.revoke(token);
});
};
function createInternalToken (criteria, id, token, type) {
let timeToExpiry;
if (type === 'access_token') {
timeToExpiry = config.systemConfig.accessTokens.timeToExpiry;
} else timeToExpiry = config.systemConfig.refreshTokens.timeToExpiry;
const internalTokenObj = Object.assign({
id,
tokenEncrypted: utils.encrypt(token),
expiresAt: Date.now() + timeToExpiry
}, criteria);
if (internalTokenObj.scopes && Array.isArray(internalTokenObj.scopes)) {
internalTokenObj.scopes = JSON.stringify(internalTokenObj.scopes.sort());
}
utils.appendCreatedAt(internalTokenObj);
return internalTokenObj;
}
function formExternalToken (tokenObj) {
if (!tokenObj) return null;
return tokenObj.id.concat('|', utils.decrypt(tokenObj.tokenEncrypted));
}
function newUuid () {
return uuidv4().replace(new RegExp('-', 'g'), '');
}
module.exports = s;