How To Authorize a User Using the GitHub OAuth API , Python and Flask: Part Two.

Build and Test the Application Locally.

Lyle Okoth
7 min readMay 19, 2022

In the previous article, we set up the development environment. In this article we will build and test the application locally. So what exactly does the application do and how does it work? For a start, it simply allows us to register and authenticate a user. Rather than coming up with a new username and email address, our users use the information already held by GitHub to register and authenticate.

This application has two parts:

  • User Registration for new users
  • User authentication for returning users

For this series of articles we will simply authenticate a user and later on we will create a registration module. For the application to work, we need a client id and client secret both of which are given out by GitHub once you register your app with them. Once those two are obtained:

  • We start by sending out a GET request to https://github.com/login/oauth/authorize?client_id=client_id with the client id given earlier on;
  • Then GitHub sends back a request token to a callback URL that was specified during registration;
  • Using this request token, the client id and client secret, we can then send a POST request to https://github.com/login/oauth/access_token?client_id=client_id&client_secret=client_secret&code=request_token to get an access token;
  • Using the access token, we send a GET request to ‘https://api.github.com/user' to get the users data.

The application will have three routes:

  • The /index route for testing out the application. Accepts GET requests and serves out JSON response of the form:
  • The /home route that serves out the home page. This contains a button that a user can click to start the authentication process.
  • The /github/callback route that handles the authentication. Shows a prompt to the user to authorize our application then displays the user data on a dashboard:

Application registration

Head on over to GitHub OAuth and register a new application:

Set the Application name to any name that you want, the Homepage URL as http://127.0.0.1:5000 and Authorization callback URL as http://127.0.0.1:5000/github/callback. After registering the application, in the resulting page, click on the Generate a new client secret button.

Create a .env file at the project root and add the following:

CLIENT_ID=xxxxxxxxxxxxxxx
CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

The Application Design

The main focus of this application is the back-end design, so little consideration is given to the front-end. We will have two main functions:

  • get_request_token() that will take in a client id, a client secret and an access token and give us back a request token
  • get_user_data() that will take in a request token and give us user data. Once we have the user data we can then get the user data and display them on a simple dashboard .

The application requirements

Open up requirements.txt and add the following project requirements. The flask module is used to build the API, the requests module will be used to make requests to the GitHub API, python-dotenv will be used to load environment variables while gunicorn will be used in production to run our application:

Then open up requirements-dev.txt and add the following:

Commitizen will be used to format our commit messages, pre-commit will be used to run our pre-commit hooks at every commit and pytest will be used to test our code. Add the following to the Makefile:

The Makefile simplifies our commands. The four make targets update the pip utility, install production requirements, install development requirements, runs the application and tests the application respectively. Create a file named setup.cfg at the project root and add the following:

This file provides configuration for the flake8 and isort tools that are used to ensure code quality. More on them in a different tutorial. Create another file named .pylintrc at the project root and add the contents of this .pylintrc file. This file contains configurations for the pylint tool. Add the following to pytest.ini file:

This file provides configuration for pytest.

The index route

Start by creating the following tests for the index route; the conftest.py that will hold configurations for our tests:

For testing the index route, we will have two unit tests under the tests/unit/test_index.py:

  • One tests to assure us that on a GET request to the index, we get a response code of 200 indicating the request was successful.
  • The other test assures us that in case a method other than GET such as POST results in a 405 method not allowed error.

To run the tests we will install the project requirements then use Make to run them. The pytest configuration are found in the pytest.ini file shown above, while for flake8 and isort, setup.cfg configures them. The .pylintrc file configures the pylint tool; all these tools will be run against our codes at each commit. At the command-line:

make install
make install-dev
make test

The tests will fail,so let us create the application for them; in the API/__init__.py file, add the following:

Then in the API/routes.py add the following:

We also need some environment variables that will be used by the flask application i.e the FLASK_ENV and FLASK_APP. Open the .env at the project root and add the following:

Now try running the tests and they will pass:

make test

The home route

For testing the /home route and /github/callback functionality, we will have to mock the GitHub API. I will go through that in a different post. Check out the API/tests folder for the other tests. For now let’s just write out the code for the home route:

For the application to run, we have to supply the client id and client secret. For that, let us create the application configuration. Open API/config.py and add the following:

This file loads configuration from environment variables. The values are loaded form the .env file using the load_dotenv() function from the dotenv module. The variables include:

  • CLIENT_ID that we obtained earlier on from GitHub.
  • CLIENT_SECRET that we also obtained earlier on.

Now create the template used to render the home page. Create a folder named templates within the API folder, then create a file named home.html and add the following:

This template will be rendered when the /home route is accessed. It is passed the client id, which forms part of the URL accessed when the GitHub Login button is pressed. To run the application, create a file called manage.py at the project root and add the following:

At this point, run the application.

make run

and access the /home endpoint. The home page is rendered:

The callback route

Next, we create the callback route, /github/callback that will authenticate the user and display their information. Add the following to API/routes:

There are two methods that need creation, get_access_token() and get_user_data(). Open API/helpers.py and add the following:

To display the user data, the /github/callback route renders a dashboard using the user data obtained from GitHub. Create a dashboard.html file in the API/templates folder and add the following:

At this point, the application is ready to run. At the command-line start the application and then navigate to http://127.0.0.1:5000/home. Click on the GitHub Login button, then authorize the application. You will then be redirected to the callback route that displays your user data:

And that’s it, you have successfully used the GitHub OAuth API to authenticate a user. To finish it off, let us push the code to GitHub;

git add .
git commit -m “feat: created and deployed the auth app locally.”

This will probably create errors, due to the pre-commit hooks that we set up in the previous article. In case they inconvenience your workflow, just disable them from the .pre-commit-config.yml file, by commenting them out. Otherwise just correct the errors indicated and re-run the above commands until no more errors appear. Then push your code to GitHub:

git push

Create a pull request against the development branch and merge it. In this part two of the series:

  • We described how to authorize a user using the GitHub OAuth API.
  • We created an app with the GitHub OAuth API.
  • We then created three routes for implementing user authentication using the GitHub OAuth API.
  • We tested and deployed the application locally.

In the next article, the code will be deployed to Heroku. The code for this application is here github-oauth-app. I am Lyle, a junior software engineer with a passion for developing, testing and deploying scalable services. You can find me on twitter, linkedin, github and here’s my portfolio. See you next time.

--

--

Lyle Okoth

Conversational AI Engineer | Building conversational AI agents that work with humans to automate various workflows.