UNPKG

hapi-auth-github

Version:

Quick & Simple GitHub Authentication for Hapi.js apps

124 lines (111 loc) 4.26 kB
'use strict'; var OPTIONS; // global object set when plugin loads var crypto = require('crypto'); // http://nodejs.org/api/crypto.html var pkg = require('../package.json'); var request = require('./http_request'); var querystring = require('querystring'); // nodejs.org/api/querystring.html /** * make_post_data simply extracts the code and state (hash) from the request * and combines those data with the GitHub Client Id & Secret as a query string * @param {Object} req - the request object sent by GitHub with code & state * @returns {Object} the stringified object required to request OAuth2 Token */ function make_post_data (req) { return querystring.stringify({ client_id: process.env.GITHUB_CLIENT_ID, client_secret: process.env.GITHUB_CLIENT_SECRET, code: req.query.code, state: req.query.state }); } /** * http.request options for requesting the OAuth2 token * see: developer.github.com/v3/oauth/#github-redirects-back-to-your-site * @param {String} post_data the POST data we are sending to GitHub * @returns {Object} data & headers we are sending to GitHub in our HTTP request */ function token_options (post_data) { return { body: post_data, // see make_post_data above headers: { 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': post_data.length }, hostname: process.env.GITHUB_HOSTNAME || 'github.com', method: 'POST', path: '/login/oauth/access_token', port: 443 }; } /** * http request to get the profile of the person that just authenticated * see: https://developer.github.com/v3/users/#get-the-authenticated-user * @param {Object} access_json returned by GitHub OAuth access_token request. * @returns {Object} data & headers we are sending to GitHub in our HTTP request */ function user_options (access_json) { return { headers: { 'Authorization': 'token ' + access_json.access_token, 'Accept': 'application/json', 'User-Agent': 'hapi-auth-github' // a User-Agent is *REQUIRED*!! }, hostname: process.env.GITHUB_API_HOSTNAME || 'api.github.com', method: 'GET', path: '/user', port: 443 }; } /** * this plugin creates the github Oauth Callback URL * e.g: /githubauth where github calls back to with the OAuth code * @param {Object} server - the Hapi server object/instance * @param {Object} options - any valid request options (e.g. method or path) * @param {Function} next - called once plugin has been registered * @returns {Boolean} callback - no point returning anything else ...! */ exports.register = function (server, options, next) { OPTIONS = options; // should we check the options have been set? server.route([ { method: 'GET', // ping path: process.env.GITHUB_AUTH_REDIRECT_URL, // must be identical to Authorized callback URL config: { auth: false }, handler: function (req, reply) { var post_data = make_post_data(req); var options1 = token_options(post_data); request(options1, function (err, oauth_access_token_json) { var options2; var profile = null; server.log('error', err); // see: github.com/dwyl/hapi-error#logging options2 = user_options(oauth_access_token_json); request(options2, function (oauth_err, user_profile) { if (oauth_err) { server.log('error', oauth_err); // add "good" logging to see logs } else { profile = user_profile; } OPTIONS.handler(req, reply, oauth_access_token_json, profile); return true; }); }); } } ]); return next(); // everything worked, continue booting the hapi server! }; exports.register.attributes = { pkg: pkg }; module.exports.login_url = function () { var params = { client_id: process.env.GITHUB_CLIENT_ID, redirect_uri: process.env.BASE_URL + process.env.GITHUB_AUTH_REDIRECT_URL, scope: OPTIONS.SCOPE, state: crypto.createHash('sha256') .update(Math.random().toString()) .digest('hex') }; var qs = querystring.stringify(params); var url = 'https://github.com/login/oauth/authorize?' + qs; return url; };