Guest User

Untitled

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