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);
});