All files index.js

97.44% Statements 38/39
83.33% Branches 20/24
100% Functions 3/3
97.44% Lines 38/39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 921x 1x 1x 1x 1x 1x   1x 1x         1x                   23x 23x 23x 23x   23x 1x     22x 22x     22x   22x 1x     21x       21x 21x                   21x 21x 21x       21x 2x     21x 21x 21x   21x 1x       20x 20x 20x   20x           1x          
import Debug from 'debug';
import merge from 'lodash.merge';
import omit from 'lodash.omit';
import pick from 'lodash.pick';
import DefaultVerifier from './verifier';
import { Strategy as JWTStrategy, ExtractJwt } from 'passport-jwt';
 
const debug = Debug('feathers-authentication-jwt');
const defaults = {
  name: 'jwt',
  bodyKey: 'accessToken'
};
 
const KEYS = [
  'secret',
  'header',
  'entity',
  'service',
  'passReqToCallback',
  'session',
  'jwt'
];
 
export default function init (options = {}) {
  return function jwtAuth () {
    const app = this;
    const _super = app.setup;
 
    if (!app.passport) {
      throw new Error(`Can not find app.passport. Did you initialize feathers-authentication before feathers-authentication-jwt?`);
    }
 
    let authOptions = app.get('auth') || {};
    let jwtOptions = authOptions[options.name] || {};
 
    // NOTE (EK): Pull from global auth config to support legacy auth for an easier transition.
    let jwtSettings = merge({}, defaults, pick(authOptions, KEYS), jwtOptions, omit(options, ['Verifier']));
 
    if (typeof jwtSettings.header !== 'string') {
      throw new Error(`You must provide a 'header' in your authentication configuration or pass one explicitly`);
    }
 
    Iif (typeof jwtSettings.secret === 'undefined') {
      throw new Error(`You must provide a 'secret' in your authentication configuration or pass one explicitly`);
    }
 
    let Verifier = DefaultVerifier;
    let strategyOptions = merge({
      secretOrKey: jwtSettings.secret,
      jwtFromRequest: ExtractJwt.fromExtractors([
        ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
        ExtractJwt.fromHeader(jwtSettings.header.toLowerCase()),
        ExtractJwt.fromBodyField(jwtSettings.bodyKey)
      ])
    }, jwtSettings.jwt, omit(jwtSettings, ['jwt', 'header', 'secret']));
 
    // Normalize algorithm key
    Eif (!strategyOptions.algorithms && strategyOptions.algorithm) {
      strategyOptions.algorithms = Array.isArray(strategyOptions.algorithm) ? strategyOptions.algorithm : [strategyOptions.algorithm];
      delete strategyOptions.algorithm;
    }
 
    // Support passing a custom verifier
    if (options.Verifier) {
      Verifier = options.Verifier;
    }
 
    app.setup = function () {
      let result = _super.apply(this, arguments);
      let verifier = new Verifier(app, jwtSettings);
 
      if (!verifier.verify) {
        throw new Error(`Your verifier must implement a 'verify' function. It should have the same signature as a jwt passport verify callback.`);
      }
 
      // Register 'jwt' strategy with passport
      debug('Registering jwt authentication strategy with options:', strategyOptions);
      app.passport.use(jwtSettings.name, new JWTStrategy(strategyOptions, verifier.verify.bind(verifier)));
      app.passport.options(jwtSettings.name, jwtSettings);
 
      return result;
    };
  };
}
 
// Exposed Modules
Object.assign(init, {
  defaults,
  ExtractJwt,
  Verifier: DefaultVerifier
});