Part 8: Expanding our Service with GitHub
This is part eight of a tutorial blog series from Ben Finkel addressing the challenges, solutions, and implementation of sound authentication. By the end of this series, you will be confident in your ability to implement an authentication system — even with little-to-no background.
We could call it quits right now since we are successfully authenticating with Google as our provider. Of course, we may not want to force our users to use Google. They might already have accounts with other providers and we'd like to give them some choices. Besides, if we were only going to use Google we could have used the Google Identity Platform API library and saved a lot of work.
Let's get a little more hip and offer GitHub as an authentication option. If we've done our work correctly, it should be as simple as:
Copying the googleOAuth.py file and adjusting the details as necessary for GitHub.
Adding the function calls to the lookup tables at the top of our oAuth.py file.
By the way, here is the starting page for developing on GitHub*: https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
The GitHub implementation
Let's look at what we'll need to change in order to implement GitHub. After creating a copy of the googleOAuth.py file and naming it githubOAuth.py, we'll need to:
1. Acquire a new client_id and client_secret from GitHub. Recall that these are specific to our app and the provider in question, so GitHub has to provide us a way to generate these values. We can do that by reading the documentation above which leads us here: https://github.com/login.
Note: We still callback to the appspot url because that's where our app is running. Once you successfully complete this process, GitHub provides a client id and secret.
2. Next, we need updated endpoints for GitHub. We know we'll need a grant auth endpoint and an access token exchange endpoint. Getting ID information will be specific and we'll cover that in a moment. The endpoints for GitHub are covered at the developer OAuth page we just linked earlier: https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/.
Grant Token: https://github.com/login/oauth/authorize (See Step 1)
Access Token: https://github.com/login/oauth/access_token (See Step 2)
3. This page also details the values we need to supply for each call. The Grant Auth requires 'client_id', 'redirect_uri', 'scope', and optionally 'state' (which, of course, we'll use). We can update our query_auth tuple removing the 'response_type' variable and changing to the appropriate scope value. GitHub's scope documentation (here) indicates that "user:email" will provide access to the user's email addresses.
For the access token exchange we'll need to remove 'grant_type.' Also note that in order to get JSON back, we'll need to add a header: Accept: application/json.
This will be done in our GetAccessToken call later.
4. Next, we'll update our calls. The SignIn function should not have to change at all, but our function for getting an Access Token will need to be updated. The initial call and exchange for an access token just needs a header value added to ensure we get JSON back (or we could adjust to accept a different response as documented by GitHub), but acquiring identity information will be unique for GitHub. GitHub details its API reference at this url, and indicates the universal endpoint for its OAuth APIs as: https://api.github.com/.
This URL gets appended with the user/emails endpoint documented on that page. In the script above you can see we updated our endpoint_email to reflect this value.
The example user object shows the structure of the JSON that will be returned. We'll get a collection of emails where one will be indicated as the "primary."
5. Finally, we'll update our oauth.py file to include this library and add a sign-in link to our main.py application.
Notice how trivial it is to add these providers to our library and app. We've isolated the work in each provider's specific .py file making this step easy peasy.
Deploy your app to the cloud, browse to it in a browser, and sign-in with GitHub!
Up next, we'll discuss how to get our app rolling with OpenID Connect, making authentication even easier than we've done here.
You can read the full tutorial series in these weekly installments:
Part 1: Authentication for the Modern Web
Part 2: Delegating Authentication
Part 3: Let's Play on the OAuth 2.0 Playground
Part 4: Let's Start Running Code
Part 5: Authorization Grant, Our First OAuth Dance Steps
Part 6: Authorization Request, An OAuth "State" of Mind
Part 7: Authorization Grant, Final OAuth Dance Steps
Part 8: Expanding our Service with Github
Part 9: OAuth 2.0: Authorization, Not Authentication
This series will conclude in April 2016.
Public Git for entire codebase: https://github.com/benfinkelcbt/OAuthLibrary
* One of the primary reasons I chose Google and GitHub for these demos was due to the clean and clear documentation they have for this process. As you work with various providers, you'll find yourself frustrated by the frequently out-of-date or non-functioning APIs and documentation.
The moral of this story: Adding a new provider can be a non-trivial task. Be prepared for some research whenever you wish to update your provider list.
Not a subscriber? Start your free week. https://cbt.gg/1rbm0Kx
delivered to your inbox.