Guest User

Untitled

a guest
Jul 6th, 2019
131
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use strict';
  2.  
  3. const logger = require('./logger')(module.filename);
  4. const NodeRSA = require('node-rsa');
  5. const jwt = require('jsonwebtoken');
  6. const fs = require('fs');
  7.  
  8. const loadKeyFromDisk = (path) => {
  9.   return new Promise((resolve, reject) => {
  10.     fs.readFile(path, 'utf-8', (error, data) => {
  11.       if (error) {
  12.         reject(error);
  13.         return;
  14.       }
  15.       resolve(data);
  16.     });
  17.   });
  18. };
  19. const saveKeyToDisk = (path, key) => {
  20.   return new Promise((resolve, reject) => {
  21.     fs.writeFile(path, key, 'utf-8', (error) => {
  22.       if (error) {
  23.         reject(error);
  24.         return;
  25.       }
  26.       resolve();
  27.     });
  28.   });
  29. };
  30.  
  31. module.exports = async (keyPath) => {
  32.   let invalidationByUserUUID = {};
  33.   let invalidBefore = Math.floor(new Date().getTime()/1000);
  34.  
  35.   let jwtPublicKey, jwtPrivateKey;
  36.   const generateNewKeyPair = async () => {
  37.     logger.debug('Generating private and public key for JWT sessions...');
  38.     const keyPair = new NodeRSA({b: 2048});
  39.     jwtPrivateKey = keyPair.exportKey('private');
  40.     jwtPublicKey = keyPair.exportKey('public');
  41.     await saveKeyToDisk(keyPath, jwtPrivateKey);
  42.     logger.success('Done');
  43.   };
  44.   try {
  45.     jwtPrivateKey = await loadKeyFromDisk(keyPath);
  46.     logger.debug('Loading private and public key for JWT sessions...');
  47.     const keyPair = new NodeRSA();
  48.     keyPair.importKey(jwtPrivateKey, 'private');
  49.     jwtPublicKey = keyPair.exportKey('public');
  50.     logger.success('Done');
  51.   } catch(error) {
  52.     if(error.code !== 'ENOENT') {
  53.       logger.fatal(error);
  54.     }
  55.     generateNewKeyPair();
  56.   }
  57.  
  58.   return {
  59.     generateNewKeyPair: async () => {
  60.       await generateNewKeyPair();
  61.       invalidationByUserUUID = {};
  62.       invalidBefore = Math.floor(new Date().getTime()/1000);
  63.     },
  64.     sign: (payload) => {
  65.       const restriction = invalidationByUserUUID[payload.userUuid];
  66.       if(restriction) payload.invalidationCounter = restriction;
  67.  
  68.       return jwt.sign(payload, jwtPrivateKey, {algorithm:'RS256'});
  69.     },
  70.     verify: (token) => {
  71.       try {
  72.         const payload = jwt.verify(token, jwtPublicKey, {algorithm:['RS256']});
  73.         return ((!invalidationByUserUUID[payload.userUuid] || payload.invalidationCounter === invalidationByUserUUID[payload.userUuid]) && payload.iat >= invalidBefore)? payload : false;
  74.       } catch(e) {
  75.         logger.warning(e);
  76.         return false;
  77.       }
  78.     },
  79.     invalidateOldUserToken: (userUuid) => {
  80.       invalidationByUserUUID[userUuid] = invalidationByUserUUID[userUuid]+1 || 1;
  81.     }
  82.   };
  83. };
RAW Paste Data