Files
jambonz-api-server/lib/auth/index.js
2022-11-10 14:34:04 -05:00

105 lines
3.5 KiB
JavaScript

const Strategy = require('passport-http-bearer').Strategy;
const {getMysqlConnection} = require('../db');
const {hashString} = require('../utils/password-utils');
const debug = require('debug')('jambonz:api-server');
const jwt = require('jsonwebtoken');
const sql = `
SELECT *
FROM api_keys
WHERE api_keys.token = ?`;
function makeStrategy(logger, retrieveKey) {
return new Strategy(
async function(token, done) {
//logger.debug(`validating with token ${token}`);
jwt.verify(token, process.env.JWT_SECRET, async(err, decoded) => {
if (err) {
if (err.name === 'TokenExpiredError') {
logger.debug('jwt expired');
return done(null, false);
}
/* its not a jwt obtained through login, check api leys */
checkApiTokens(logger, token, done);
}
else {
/* validated -- make sure it is not on blacklist */
try {
const s = `jwt:${hashString(token)}`;
const result = await retrieveKey(s);
if (result) {
debug(`result from searching for ${s}: ${result}`);
logger.info('jwt invalidated after logout');
return done(null, false);
}
} catch (err) {
debug(err);
logger.info({err}, 'Error checking blacklist for jwt');
}
const {user_sid, service_provider_sid, account_sid, email, name, scope, permissions} = decoded;
const user = {
service_provider_sid,
account_sid,
user_sid,
jwt: token,
email,
name,
permissions,
hasScope: (s) => s === scope,
hasAdminAuth: scope === 'admin',
hasServiceProviderAuth: scope === 'service_provider',
hasAccountAuth: scope === 'account'
};
logger.debug({user}, 'successfully validated jwt');
return done(null, user, {scope});
}
});
}
);
}
const checkApiTokens = (logger, token, done) => {
getMysqlConnection((err, conn) => {
if (err) {
logger.error(err, 'Error retrieving mysql connection');
return done(err);
}
conn.query(sql, [token], (err, results, fields) => {
conn.release();
if (err) {
logger.error(err, 'Error querying for api key');
return done(err);
}
if (0 == results.length) return done(null, false);
if (results.length > 1) {
logger.info(`api key ${token} exists in multiple rows of api_keys table!!`);
return done(null, false);
}
// found api key
const scope = [];
if (results[0].account_sid === null && results[0].service_provider_sid === null) {
scope.push.apply(scope, ['admin', 'service_provider', 'account']);
}
else if (results[0].service_provider_sid) {
scope.push.apply(scope, ['service_provider', 'account']);
}
else {
scope.push('account');
}
const user = {
account_sid: results[0].account_sid,
service_provider_sid: results[0].service_provider_sid,
hasScope: (s) => scope.includes(s),
hasAdminAuth: scope.length === 3,
hasServiceProviderAuth: scope.includes('service_provider'),
hasAccountAuth: scope.includes('account') && !scope.includes('service_provider')
};
logger.info(user, `successfully validated with scope ${scope}`);
return done(null, user, {scope});
});
});
};
module.exports = makeStrategy;