From 0ec4f63926e3edf3856e27e50b69ad5075c31ef6 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Wed, 19 Feb 2020 13:01:34 +1000 Subject: [PATCH] Fix JWT expire time going crazy. Now set to 1day --- backend/internal/token.js | 276 +++++++++++++++++++------------------- backend/models/token.js | 16 +-- 2 files changed, 140 insertions(+), 152 deletions(-) diff --git a/backend/internal/token.js b/backend/internal/token.js index 3a5191f6..f5b446a6 100644 --- a/backend/internal/token.js +++ b/backend/internal/token.js @@ -7,158 +7,156 @@ const TokenModel = require('../models/token'); module.exports = { - /** - * @param {Object} data - * @param {String} data.identity - * @param {String} data.secret - * @param {String} [data.scope] - * @param {String} [data.expiry] - * @param {String} [issuer] - * @returns {Promise} - */ - getTokenFromEmail: (data, issuer) => { - let Token = new TokenModel(); + /** + * @param {Object} data + * @param {String} data.identity + * @param {String} data.secret + * @param {String} [data.scope] + * @param {String} [data.expiry] + * @param {String} [issuer] + * @returns {Promise} + */ + getTokenFromEmail: (data, issuer) => { + let Token = new TokenModel(); - data.scope = data.scope || 'user'; - data.expiry = data.expiry || '30d'; + data.scope = data.scope || 'user'; + data.expiry = data.expiry || '1d'; - return userModel - .query() - .where('email', data.identity) - .andWhere('is_deleted', 0) - .andWhere('is_disabled', 0) - .first() - .then(user => { - if (user) { - // Get auth - return authModel - .query() - .where('user_id', '=', user.id) - .where('type', '=', 'password') - .first() - .then(auth => { - if (auth) { - return auth.verifyPassword(data.secret) - .then(valid => { - if (valid) { + return userModel + .query() + .where('email', data.identity) + .andWhere('is_deleted', 0) + .andWhere('is_disabled', 0) + .first() + .then(user => { + if (user) { + // Get auth + return authModel + .query() + .where('user_id', '=', user.id) + .where('type', '=', 'password') + .first() + .then(auth => { + if (auth) { + return auth.verifyPassword(data.secret) + .then(valid => { + if (valid) { - if (data.scope !== 'user' && _.indexOf(user.roles, data.scope) === -1) { - // The scope requested doesn't exist as a role against the user, - // you shall not pass. - throw new error.AuthError('Invalid scope: ' + data.scope); - } + if (data.scope !== 'user' && _.indexOf(user.roles, data.scope) === -1) { + // The scope requested doesn't exist as a role against the user, + // you shall not pass. + throw new error.AuthError('Invalid scope: ' + data.scope); + } - // Create a moment of the expiry expression - let expiry = helpers.parseDatePeriod(data.expiry); - if (expiry === null) { - throw new error.AuthError('Invalid expiry time: ' + data.expiry); - } + // Create a moment of the expiry expression + let expiry = helpers.parseDatePeriod(data.expiry); + if (expiry === null) { + throw new error.AuthError('Invalid expiry time: ' + data.expiry); + } - return Token.create({ - iss: issuer || 'api', - attrs: { - id: user.id - }, - scope: [data.scope] - }, { - expires: expiry.unix() - }) - .then(signed => { - return { - token: signed.token, - expires: expiry.toISOString() - }; - }); - } else { - throw new error.AuthError('Invalid password'); - } - }); - } else { - throw new error.AuthError('No password auth for user'); - } - }); - } else { - throw new error.AuthError('No relevant user found'); - } - }); - }, + return Token.create({ + iss: issuer || 'api', + attrs: { + id: user.id + }, + scope: [data.scope], + expiresIn: data.expiry + }) + .then(signed => { + return { + token: signed.token, + expires: expiry.toISOString() + }; + }); + } else { + throw new error.AuthError('Invalid password'); + } + }); + } else { + throw new error.AuthError('No password auth for user'); + } + }); + } else { + throw new error.AuthError('No relevant user found'); + } + }); + }, - /** - * @param {Access} access - * @param {Object} [data] - * @param {String} [data.expiry] - * @param {String} [data.scope] Only considered if existing token scope is admin - * @returns {Promise} - */ - getFreshToken: (access, data) => { - let Token = new TokenModel(); + /** + * @param {Access} access + * @param {Object} [data] + * @param {String} [data.expiry] + * @param {String} [data.scope] Only considered if existing token scope is admin + * @returns {Promise} + */ + getFreshToken: (access, data) => { + let Token = new TokenModel(); - data = data || {}; - data.expiry = data.expiry || '30d'; + data = data || {}; + data.expiry = data.expiry || '1d'; - if (access && access.token.getUserId(0)) { + if (access && access.token.getUserId(0)) { - // Create a moment of the expiry expression - let expiry = helpers.parseDatePeriod(data.expiry); - if (expiry === null) { - throw new error.AuthError('Invalid expiry time: ' + data.expiry); - } + // Create a moment of the expiry expression + let expiry = helpers.parseDatePeriod(data.expiry); + if (expiry === null) { + throw new error.AuthError('Invalid expiry time: ' + data.expiry); + } - let token_attrs = { - id: access.token.getUserId(0) - }; + let token_attrs = { + id: access.token.getUserId(0) + }; - // Only admins can request otherwise scoped tokens - let scope = access.token.get('scope'); - if (data.scope && access.token.hasScope('admin')) { - scope = [data.scope]; + // Only admins can request otherwise scoped tokens + let scope = access.token.get('scope'); + if (data.scope && access.token.hasScope('admin')) { + scope = [data.scope]; - if (data.scope === 'job-board' || data.scope === 'worker') { - token_attrs.id = 0; - } - } + if (data.scope === 'job-board' || data.scope === 'worker') { + token_attrs.id = 0; + } + } - return Token.create({ - iss: 'api', - scope: scope, - attrs: token_attrs - }, { - expiresIn: expiry.unix() - }) - .then(signed => { - return { - token: signed.token, - expires: expiry.toISOString() - }; - }); - } else { - throw new error.AssertionFailedError('Existing token contained invalid user data'); - } - }, + return Token.create({ + iss: 'api', + scope: scope, + attrs: token_attrs, + expiresIn: data.expiry + }) + .then(signed => { + return { + token: signed.token, + expires: expiry.toISOString() + }; + }); + } else { + throw new error.AssertionFailedError('Existing token contained invalid user data'); + } + }, - /** - * @param {Object} user - * @returns {Promise} - */ - getTokenFromUser: user => { - let Token = new TokenModel(); - let expiry = helpers.parseDatePeriod('1d'); + /** + * @param {Object} user + * @returns {Promise} + */ + getTokenFromUser: (user) => { + const expire = '1d'; + const Token = new TokenModel(); + const expiry = helpers.parseDatePeriod(expire); - return Token.create({ - iss: 'api', - attrs: { - id: user.id - }, - scope: ['user'] - }, { - expiresIn: expiry.unix() - }) - .then(signed => { - return { - token: signed.token, - expires: expiry.toISOString(), - user: user - }; - }); - } + return Token.create({ + iss: 'api', + attrs: { + id: user.id + }, + scope: ['user'], + expiresIn: expire + }) + .then(signed => { + return { + token: signed.token, + expires: expiry.toISOString(), + user: user + }; + }); + } }; diff --git a/backend/models/token.js b/backend/models/token.js index 965ebf91..2b7125cb 100644 --- a/backend/models/token.js +++ b/backend/models/token.js @@ -19,23 +19,15 @@ module.exports = function () { let self = { /** * @param {Object} payload - * @param {Object} [user_options] - * @param {Integer} [user_options.expires] * @returns {Promise} */ - create: (payload, user_options) => { - - user_options = user_options || {}; - + create: (payload) => { // sign with RSA SHA256 let options = { - algorithm: ALGO + algorithm: ALGO, + expiresIn: payload.expiresIn || '1d' }; - if (typeof user_options.expires !== 'undefined' && user_options.expires) { - options.expiresIn = user_options.expires; - } - payload.jti = crypto.randomBytes(12) .toString('base64') .substr(-8); @@ -51,10 +43,8 @@ module.exports = function () { payload: payload }); } - }); }); - }, /**