From ccaacfc4083038e72ff898ad87bbca5cae5fc54d Mon Sep 17 00:00:00 2001 From: Thaddee Tyl Date: Sat, 21 May 2016 20:43:14 +0200 Subject: [PATCH] Support GitHub OAuth user authentication Issue #529. --- lib/github-auth.js | 63 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- server.js | 4 +++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 lib/github-auth.js diff --git a/lib/github-auth.js b/lib/github-auth.js new file mode 100644 index 0000000..6362989 --- /dev/null +++ b/lib/github-auth.js @@ -0,0 +1,63 @@ +// TODO: +// - add route in server.js +// - document user authorization in try.html + +var querystring = require('querystring'); +var request = require('request'); +var serverSecrets; +try { + // Everything that cannot be checked in but is useful server-side + // is stored in this JSON data. + serverSecrets = require('../secret.json'); +} catch(e) {} + +function setRoutes(server) { + server.route(/^\/github-auth$/, function(data, match, end, ask) { + if (!(serverSecrets && serverSecrets.gh_client_id)) { + return end('This server is missing GitHub client secrets'); + } + var query = querystring.stringify({ + client_id: serverSecrets.gh_client_id, + redirect_uri: 'https://img.shields.io/github-auth/done', + }); + ask.res.statusCode = 302; // Found. + ask.res.setHeader('Location', 'https://github.com/login/oauth/authorize?' + query); + end(''); + }); + server.route(/^\/github-auth\/done$/, function(data, match, end, ask) { + if (!(serverSecrets && serverSecrets.gh_client_id && serverSecrets.gh_client_secret)) { + return end('This server is missing GitHub client secrets'); + } + if (!data.code) { + return end('GitHub OAuth authentication failed to provide a code'); + } + var options = { + url: 'https://github.com/login/oauth/access_token', + headers: { + 'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8', + 'User-Agent': 'Shields.io', + }, + form: querystring.stringify({ + client_id: serverSecrets.gh_client_id, + client_secret: serverSecrets.gh_client_secret, + code: data.code, + }), + method: 'POST', + }; + console.log(JSON.stringify(options)); + request.post(options, function(err, res, body) { + if (err != null) { return end('The connection to GitHub failed'); } + try { + var content = querystring.parse(body); + } catch(e) { return end('The GitHub OAuth token could not be parsed'); } + var token = content.access_token; + if (!token) { + return end('The GitHub OAuth process did not return a user token'); + } + console.log('GitHub OAuth: ' + token); + end('Done!'); + }); + }); +}; + +exports.setRoutes = setRoutes; diff --git a/package.json b/package.json index 66046f7..220896a 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "es6-promise": "~2.1.0", "request": "~2.55.0", "redis": "~1.0.0", - "camp": "~16.0.0", + "camp": "~16.2.0", "semver": "~4.3.3", "bower": "~1.4.1", "promise": "~7.0.0", diff --git a/server.js b/server.js index 59eafa5..79de563 100644 --- a/server.js +++ b/server.js @@ -18,6 +18,7 @@ var LruCache = require('./lru-cache.js'); var badge = require('./badge.js'); var svg2img = require('./svg-to-img.js'); var loadLogos = require('./load-logos.js'); +var githubAuth = require('./lib/github-auth.js'); var querystring = require('querystring'); var serverSecrets; try { @@ -5439,6 +5440,9 @@ var githubHeaders = { 'User-Agent': 'Shields.io', 'Accept': 'application/vnd.github.v3+json' }; +if (serverSecrets && serverSecrets.gh_client_id) { + githubAuth.setRoutes(camp); +} // Personal tokens allow access to GitHub private repositories. // You can manage your personal GitHub token at