You've already forked nginx-proxy-manager
							
							
				mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-10-30 18:05:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			140 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  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;
 | |
| };
 |