In order for your readers to comment on your pages, they must be logged in to GitHub, except a third party, like a gh-pages site, does not have the authority to authenticate GitHub users. Only GitHub knows your readers’ GitHub credentials, and it should stay that way. Fortunately, GitHub provides a way for other sites to securely authenticate its users, even if they use two-factor authentication (2FA).
ghpages-ghcomments uses GitHub issues as the commenting system for gh-pages sites. For a reader to create a comment on an issue, GitHub requires that the commenter be logged in with the public_repo
scope. GitHub allows third parties, like Jekyll gh-pages sites, to let their end users to securely login to GitHub via OAuth.
ghpages-ghcomments is a GitHub web application, which means it has a client_id
and client_secret
pair for using the GitHub API on users’ behalf. GitHub web applications authenticate GitHub users in three steps:
code
.code
for the user’s OAuth token
.The first step requires the gh-pages site to send GitHub its client_id
and requested access scopes. The last step requires the gh-pages site to also send the client_secret
. This is a problem for static and fully public gh-pages sites – if the gh-pages site kept the client_secret
in the site’s yml data, then any user could impersonate that site.
The only way to keep the client_secret
fully secret is to keep it on a separate server where only the gh-pages site has access. Another project, Gatekeeper, has implemented a fast and simple way for GitHub web applications to keep their secrets.
ghpages-ghcomments uses its own Heroku instance of Gatekeeper to complete the GitHub web application authentication flow. This means there are two segments in the trust chain:
To use ghpages-ghcomments on your site, you must:
Creating a GitHub application is painless:
Gatekeeper has a Node.js implementation, which Heroku can directly serve in a web dyno. Creating a Heroku instance of Gatekeeper is a little more involved:
git clone https://github.com/prose/gatekeeper.git
cd gatekeeper
heroku login
APP_NAME
heroku apps:create APP_NAME
XXXX
and YYYY
GitHub application credentials:
heroku config:set OAUTH_CLIENT_ID=XXXX
heroku config:set OAUTH_CLIENT_SECRET=YYYY
git push heroku master
curl https://APP_NAME.herokuapp.com/authenticate/1234
{ "error": "bad_code" }
For more details about Heroku, see their Getting Started and How Heroku Works pages.
Now that you have your own Gatekeeper instance, update _data/gpgc.yml
:
github_application:
client_id: __YOUR_CLIENT_ID__
code_authenticator: https://__YOUR_HEROKU_APP__.herokuapp.com/authenticate/
callback_url: http://__YOUR_CLIENT_CALLBACK_URL__
_data\gpgc.yml
to matchIf you don’t trust a Heroku web application, then you can remove it from the authentication sequence by creating your own GitHub authenticator. At this point, you are using your own GitHub application and your own server-side process to allow your readers to log in to GitHub.
You will still be using the ghpages-ghcomments JavaScript, which expects a specific web interface. Your server-side authenticator must:
code
in the URL.https://github.com/login/oauth/access_token
API to exchange the code
for a token
.{ "token": token }
For a reference implementation, see the Gatekeeper server.js method ` app.get(‘/authenticate/:code’, function(req, res))`.
Now that you have your own server-side authenticator, update _data/gpgc.yml
:
github_application:
client_id: __YOUR_CLIENT_ID__
code_authenticator: https://__YOUR_DOMAIN__/__YOUR_SERVICE__/
callback_url: http://__YOUR_CLIENT_CALLBACK_URL__
_data\gpgc.yml
to match