123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /**
- NOTE: This is not a database table, this is a model of a Token object that can be created/loaded
- and then has abilities after that.
- */
- const _ = require('lodash');
- const jwt = require('jsonwebtoken');
- const crypto = require('crypto');
- const config = require('../lib/config');
- const error = require('../lib/error');
- const logger = require('../logger').global;
- const ALGO = 'RS256';
- module.exports = function () {
- let token_data = {};
- const self = {
- /**
- * @param {Object} payload
- * @returns {Promise}
- */
- create: (payload) => {
- if (!config.getPrivateKey()) {
- logger.error('Private key is empty!');
- }
- // sign with RSA SHA256
- const options = {
- algorithm: ALGO,
- expiresIn: payload.expiresIn || '1d'
- };
- payload.jti = crypto.randomBytes(12)
- .toString('base64')
- .substring(-8);
- return new Promise((resolve, reject) => {
- jwt.sign(payload, config.getPrivateKey(), options, (err, token) => {
- if (err) {
- reject(err);
- } else {
- token_data = payload;
- resolve({
- token: token,
- payload: payload
- });
- }
- });
- });
- },
- /**
- * @param {String} token
- * @returns {Promise}
- */
- load: function (token) {
- if (!config.getPublicKey()) {
- logger.error('Public key is empty!');
- }
- return new Promise((resolve, reject) => {
- try {
- if (!token || token === null || token === 'null') {
- reject(new error.AuthError('Empty token'));
- } else {
- jwt.verify(token, config.getPublicKey(), {ignoreExpiration: false, algorithms: [ALGO]}, (err, result) => {
- if (err) {
- if (err.name === 'TokenExpiredError') {
- reject(new error.AuthError('Token has expired', err));
- } else {
- reject(err);
- }
- } else {
- token_data = result;
- // Hack: some tokens out in the wild have a scope of 'all' instead of 'user'.
- // For 30 days at least, we need to replace 'all' with user.
- if ((typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, 'all') !== -1)) {
- token_data.scope = ['user'];
- }
- resolve(token_data);
- }
- });
- }
- } catch (err) {
- reject(err);
- }
- });
- },
- /**
- * Does the token have the specified scope?
- *
- * @param {String} scope
- * @returns {Boolean}
- */
- hasScope: function (scope) {
- return typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, scope) !== -1;
- },
- /**
- * @param {String} key
- * @return {*}
- */
- get: function (key) {
- if (typeof token_data[key] !== 'undefined') {
- return token_data[key];
- }
- return null;
- },
- /**
- * @param {String} key
- * @param {*} value
- */
- set: function (key, value) {
- token_data[key] = value;
- },
- /**
- * @param [default_value]
- * @returns {Integer}
- */
- getUserId: (default_value) => {
- const attrs = self.get('attrs');
- if (attrs && typeof attrs.id !== 'undefined' && attrs.id) {
- return attrs.id;
- }
- return default_value || 0;
- }
- };
- return self;
- };
|