Skip to content

Latest commit

 

History

History

github-oauth-with-hapi-v16

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
  • npm init -y
  • npm install hapi@16 hapi-auth-cookie@7 bell@8 --save
  • generate a session key: export SESSION_KEY=$(node -e "console.log(require('crypto').randomBytes(64).toString('hex'))")
  • go to github.com > Settings > Developer Settings > OAuth Apps and add a new app
    • you can use your personal web page for the application URL and a temporary callback URL
    • you can change the callback URL later
  • set the client ID: export GITHUB_CLIENT_ID=YOUR_CLIENT_ID
  • set the client secret: export GITHUB_CLIENT_SECRET=YOUR_CLIENT_SECRET
  • test with ngrok:
  • deploy with now:
  • live demo is at https://github-oauth-with-hapi-example.now.sh/
'use strict';

const Hapi = require('hapi');
const HapiAuthCookie = require('hapi-auth-cookie');
const Bell = require('bell');

const server = new Hapi.Server();

server.connection({port: process.env.PORT || 3000});

async function start() {
  await server.register(HapiAuthCookie);
  await server.register(Bell);

  server.auth.strategy('session', 'cookie', {
    password: process.env.SESSION_KEY,
    redirectTo: '/',
  });

  server.auth.strategy('github', 'bell', {
    provider: 'github',
    scope: ['user:email'],
    password: process.env.SESSION_KEY,
    clientId: process.env.GITHUB_CLIENT_ID,
    clientSecret: process.env.GITHUB_CLIENT_SECRET,
    forceHttps: true,  // needed to use ngrok when testing locally
  });

  server.route({
    method: 'GET',
    path: '/',
    config: {
      auth: {strategy: 'session', mode: 'try'},
      plugins: {'hapi-auth-cookie': {redirectTo: false}},
      handler: (request, reply) => {
        if (request.auth.credentials) {
          const {username, email} = request.auth.credentials;
          reply(`<pre>${JSON.stringify({username, email}, null, 2)}</pre>
                 <p>Go to <a href="/secret">/secret</a> to see a protected page!</p>`);
        } else {
          reply('Go to <a href="/login">/login</a> to sign in!');
        }
      }
    }
  });

  server.route({
    method: ['GET', 'POST'],
    path: '/login',
    config: {
      auth: 'github',
      handler: (request, reply) => {
        if (! request.auth.isAuthenticated) {
          return reply(`Auth failed: ${request.auth.error.message}`);
        }

        const {username, email} = request.auth.credentials.profile;
        request.cookieAuth.set({username, email});

        return reply.redirect('/');
      }
    }
  });

  server.route({
    method: 'GET',
    path: '/secret',
    config: {
      auth: 'session',
      handler: (request, reply) => {
        reply('You should only see this when logged in.');
      }
    }
  });

  server.route({
    method: 'GET',
    path: '/logout',
    handler: (request, reply) => {
      request.cookieAuth.clear();
      reply.redirect('/');
    }
  });

  await server.start();
}

start().then(() => {
  console.log(`Server running at: ${server.info.uri}`);
}).catch(err => {
  console.error(err);
  process.exit(1);
});