mirror of
https://github.com/jambonz/jambonz-api-server.git
synced 2026-10-09 21:14:00 +00:00
Feature/jwt auth (#75)
* initial changes for jwt auth * return permissions as an array of string * Add JWT expiration environment variable (#74) * allow fromHost in createCall REST API * add JWT_EXPIRES_IN=<mins> env variable, 60 mins by default * add jwt expiration in register.js and signin.js * fix tests - add permissions and scope to encoded obj in jwt Co-authored-by: Dave Horton <daveh@beachdognet.com> Co-authored-by: eglehelms <e.helms@cognigy.com> * return only the jwt-token in the api response Co-authored-by: EgleH <egle.helms@gmail.com> Co-authored-by: eglehelms <e.helms@cognigy.com>
This commit is contained in:
co-authored by
eglehelms
EgleH
parent
110c4ed0d8
commit
35214a04dc
+47
-41
@@ -1,12 +1,19 @@
|
||||
const router = require('express').Router();
|
||||
const {getMysqlConnection} = require('../../db');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const {verifyPassword} = require('../../utils/password-utils');
|
||||
|
||||
const {promisePool} = require('../../db');
|
||||
const sysError = require('../error');
|
||||
const retrievePemissionsSql = `
|
||||
SELECT p.name
|
||||
FROM permissions p, user_permissions up
|
||||
WHERE up.permission_sid = p.permission_sid
|
||||
AND up.user_sid = ?
|
||||
`;
|
||||
const retrieveSql = 'SELECT * from users where name = ?';
|
||||
const tokenSql = 'SELECT token from api_keys where account_sid IS NULL AND service_provider_sid IS NULL';
|
||||
|
||||
|
||||
router.post('/', (req, res) => {
|
||||
router.post('/', async(req, res) => {
|
||||
const logger = req.app.locals.logger;
|
||||
const {username, password} = req.body;
|
||||
if (!username || !password) {
|
||||
@@ -14,48 +21,47 @@ router.post('/', (req, res) => {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
getMysqlConnection((err, conn) => {
|
||||
if (err) {
|
||||
logger.error({err}, 'Error getting db connection');
|
||||
try {
|
||||
const [r] = await promisePool.query(retrieveSql, username);
|
||||
if (r.length === 0) {
|
||||
logger.info(`Failed login attempt for user ${username}`);
|
||||
return res.sendStatus(403);
|
||||
}
|
||||
logger.info({r}, 'successfully retrieved user account');
|
||||
const isCorrect = await verifyPassword(r[0].hashed_password, password);
|
||||
if (!isCorrect) return res.sendStatus(403);
|
||||
const force_change = !!r[0].force_change;
|
||||
const [t] = await promisePool.query(tokenSql);
|
||||
if (t.length === 0) {
|
||||
logger.error('Database has no admin token provisioned...run reset_admin_password');
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
conn.query(retrieveSql, [username], async(err, results) => {
|
||||
conn.release();
|
||||
if (err) {
|
||||
logger.error({err}, 'Error getting db connection');
|
||||
return res.sendStatus(500);
|
||||
|
||||
if (process.env.JAMBONES_AUTH_USE_JWT) {
|
||||
const [p] = await promisePool.query(retrievePemissionsSql, r[0].user_sid);
|
||||
const permissions = p.map((x) => x.name);
|
||||
const obj = {user_sid: r[0].user_sid, scope: 'admin', force_change, permissions};
|
||||
if (r[0].service_provider_sid) {
|
||||
obj.scope = 'service-provider';
|
||||
obj.service_provider_sid = r[0].service_provider_sid;
|
||||
}
|
||||
if (0 === results.length) {
|
||||
logger.info(`Failed login attempt for user ${username}`);
|
||||
return res.sendStatus(403);
|
||||
else if (r[0].account_sid) {
|
||||
obj.scope = 'account';
|
||||
obj.account_sid = r[0].account_sid;
|
||||
}
|
||||
|
||||
logger.info({results}, 'successfully retrieved account');
|
||||
const isCorrect = await verifyPassword(results[0].hashed_password, password);
|
||||
if (!isCorrect) return res.sendStatus(403);
|
||||
|
||||
const force_change = !!results[0].force_change;
|
||||
|
||||
getMysqlConnection((err, conn) => {
|
||||
if (err) {
|
||||
logger.error({err}, 'Error getting db connection');
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
conn.query(tokenSql, (err, tokenResults) => {
|
||||
conn.release();
|
||||
if (err) {
|
||||
logger.error({err}, 'Error getting db connection');
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
if (0 === tokenResults.length) {
|
||||
logger.error('Database has no admin token provisioned...run reset_admin_password');
|
||||
return res.sendStatus(500);
|
||||
}
|
||||
res.json({user_sid: results[0].user_sid, force_change, token: tokenResults[0].token});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
const token = jwt.sign(
|
||||
obj,
|
||||
process.env.JWT_SECRET,
|
||||
{ expiresIn: parseInt(process.env.JWT_EXPIRES_IN || 60) * 60 }
|
||||
);
|
||||
res.json({token});
|
||||
}
|
||||
else {
|
||||
res.json({user_sid: r[0].user_sid, force_change, token: t[0].token});
|
||||
}
|
||||
} catch (err) {
|
||||
sysError(logger, res, err);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ router.post('/', async(req, res) => {
|
||||
account_sid: userProfile.account_sid,
|
||||
email: userProfile.email,
|
||||
name: userProfile.name
|
||||
}, process.env.JWT_SECRET, { expiresIn: '1h' });
|
||||
}, process.env.JWT_SECRET, { expiresIn: parseInt(process.env.JWT_EXPIRES_IN || 60) * 60 });
|
||||
|
||||
logger.debug({
|
||||
user_sid: userProfile.user_sid,
|
||||
|
||||
@@ -68,7 +68,7 @@ router.post('/', async(req, res) => {
|
||||
const token = jwt.sign({
|
||||
user_sid: userProfile.user_sid,
|
||||
account_sid: userProfile.account_sid
|
||||
}, process.env.JWT_SECRET, { expiresIn: '1h' });
|
||||
}, process.env.JWT_SECRET, { expiresIn: parseInt(process.env.JWT_EXPIRES_IN || 60) * 60 });
|
||||
|
||||
logger.debug({
|
||||
user_sid: userProfile.user_sid,
|
||||
|
||||
Reference in New Issue
Block a user