Skip to content

Instantly share code, notes, and snippets.

@joduplessis
Created January 3, 2019 09:28
Show Gist options
  • Save joduplessis/fca5a8cd4e867ca70bc6854cea77d174 to your computer and use it in GitHub Desktop.
Save joduplessis/fca5a8cd4e867ca70bc6854cea77d174 to your computer and use it in GitHub Desktop.
Custom HAPI.js plugin for handling JWT authentication on routes.
const jwt = require('./jwt');
const SECRET = "yoursupersecret";
export const AuthJwt = {
name: 'AuthJwt',
version: '1.0.0',
register: async function (server, options) {
server.auth.scheme('jwt', (server, options) => {
return {
authenticate: function (request, h) {
const req = request.raw.req;
// If it's not there
if (!req.headers.authorization) return h.response({message: 'No auth token present'}).code(401).takeover();
if (!req.headers.authorization.split(' ')[1]) return h.response({message: 'No Bearer prefix'}).code(401).takeover();
try {
const { authorization } = req.headers;
const token = authorization.split(' ')[1];
const payload = jwt.decode(token, SECRET);
const { sub, exp } = payload;
// If it's expired
if (exp < Date.now()/1000) return h.response({message: 'Expired token, please log in'}).code(401).takeover();
return h.authenticated({ credentials: { user: sub } });
} catch (err) {
return h.response({message: 'Token invalidated.'}).code(401).takeover();
}
}
};
});
}
}
...
// Register the plugin in your HAPI app
await app.register(AuthJwt);
// Tell HAPI to use this for any JWT strategy routes
app.auth.strategy('jwt', 'jwt');
// Example route
app.route({
method: ['DELETE', 'POST', 'PUT'],
path: '/task/{id?}',
options: { auth: 'jwt', },
handler: TaskController
});
...
import crypto from 'crypto';
const SECRET = "yoursupersecret";
/*
* General JWT auth helper methods
*/
exports.encode = function(payload, secret) {
const header = {
typ: 'JWT',
alg: 'HS256'
};
const jwt = base64Encode(JSON.stringify(header)) + '.' + base64Encode(JSON.stringify(payload));
return jwt + '.' + sign(jwt, secret);
}
exports.decode = function(token, secret) {
const segments = token.split('.');
if (segments.length!==3) throw new Error('Token structure not correct');
const header = JSON.parse(base64Decode(segments[0]));
const payload = JSON.parse(base64Decode(segments[1]));
const rawSignature = segments[0] + '.' + segments[1];
if (!verify(rawSignature, SECRET, segments[2])) throw new Error('Verification failed');
return payload;
}
function verify(rawSignature, secret, signature) {
return signature === sign(rawSignature, secret);
}
function sign(str, key) {
return crypto.createHmac('sha256', key).update(str).digest('base64');
}
function base64Encode(str) {
return new Buffer(str).toString('base64');
}
function base64Decode(str) {
return new Buffer(str, 'base64').toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment