dwyl/hapi-auth-jwt2-cookie-example

View on GitHub
server.js

Summary

Maintainability
A
25 mins
Test Coverage
require('env2')('.env');
var Hapi        = require('hapi');     // https://github.com/nelsonic/learn-hapi
var hapiAuthJWT = require('hapi-auth-jwt2'); // http://git.io/vT5dZ
var JWT         = require('jsonwebtoken');   // used to sign our content
var port        = process.env.PORT || 8000;  // allow port to be set
var aguid       = require('aguid')  // https://github.com/ideaq/aguid
var redis       = require('redis'); // https://github.com/docdis/learn-redis
var url         = require('url');   // node core!
var assert      = require('assert');

var cookie_options = {
  ttl: 365 * 24 * 60 * 60 * 1000, // expires a year from today
  encoding: 'none',    // we already used JWT to encode
  isSecure: false,      // warm & fuzzy feelings
  isHttpOnly: true,    // prevent client alteration
  clearInvalid: false, // remove invalid cookies
  strictHeader: true,  // don't allow violations of RFC 6265
  path: '/'            // set the cookie for all routes
}


// bring your own validation function
var validate = function (decoded, request, callback) {
  console.log(" - - - - - - - DECODED token:");
  console.log(decoded);
  // do your checks to see if the session is valid
  request.redis.get(decoded.id, function (rediserror, reply) {

    console.log(' - - - - - - - REDIS reply - - - - - - - ', reply);
    var session;
    if(reply) {
      session = JSON.parse(reply);
    }
    else { // unable to find session in redis ... reply is null
      return callback(rediserror, false);
    }

    if (session.valid === true) {
        console.log('I\'m here');
      return callback(rediserror, true);
    }
    else {
      return callback(rediserror, false);
    }
  });
};

var server = new Hapi.Server();
server.connection({ port: port });

server.register([
  hapiAuthJWT,
  { register: require('hapi-redis-connection')} // no options required
  ], function (err) {
  assert(!err); // halt if error
  // see: http://hapijs.com/api#serverauthschemename-scheme
  server.auth.strategy('jwt', 'jwt', true,
  { key: process.env.JWT_SECRET,
    validateFunc: validate,
    verifyOptions: { ignoreExpiration: true, algorithms: [ 'HS256' ] }
  });

  server.route([
    {
      method: "GET", path: "/", config: { auth: false },
      handler: function(request, reply) {
        reply({text: 'Token not required'});
      }
    },
    {
      method: ['GET','POST'], path: '/restricted', config: { auth: 'jwt' },
      handler: function(request, reply) {
        return reply({text: 'You used a Token!'});
      }
    },
    { // implement your own login/auth function here
      method: ['GET','POST'], path: "/auth", config: { auth: false },
      handler: function(request, reply) {
        var session = {
          valid: true, // this will be set to false when the person logs out
          id: aguid(), // a random session id
          exp: new Date().getTime() + 30 * 60 * 1000 // expires in 30 minutes time
        }
        // create the session in Redis
        request.redis.set(session.id, JSON.stringify(session));
        // sign the session as a JWT
        var token = JWT.sign(session, process.env.JWT_SECRET); // synchronous
        console.log(token);
        reply({text: 'Check Browser Cookie or Auth Header for your Token (JWT)'})
        .header("Authorization", token)
        .state("token", token, cookie_options)
      }
    },
    {
      method: ['GET','POST'], path: "/logout", config: { auth: 'jwt' },
      handler: function(request, reply) {
        // implement your own login/auth function here
        var session;
        request.redis.get(request.auth.credentials.id, function(rediserror, redisreply) {

          session = JSON.parse(redisreply)
          console.log(' - - - - - - SESSION - - - - - - - -')
          console.log(session);
          // update the session to no longer valid:
          session.valid = false;
          session.ended = new Date().getTime();
          // create the session in Redis
          request.redis.set(session.id, JSON.stringify(session));

          return reply({text: 'You have been logged out'})
          .unstate('token', cookie_options);
        })
      }
    }
  ]);
  server.start(() => console.log('Now Visit: http://127.0.0.1:'+port) );

});

module.exports = server;