Created
January 3, 2019 09:28
-
-
Save joduplessis/fca5a8cd4e867ca70bc6854cea77d174 to your computer and use it in GitHub Desktop.
Custom HAPI.js plugin for handling JWT authentication on routes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
}; | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
// 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 | |
}); | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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