Guide to an OAuth2 API with Django

Halvor Fladsrud Bø
6 min readJun 27, 2018

In this guide I will show you how to configure your next project to use the cutting-edge OAuth2 standard.

I will assume no prior knowledge to Django.

Django

Written in Python, Django is opinionated web framework with a lot of third party packages.

A couple of sites using Django:

  • Disqus
  • Pinterest
  • Giphy

You can find out more and read their documentation at:

OAuth2

If you have ever used a website like Google or Facebook, you have used OAuth2. When you log in with Google, the same thing is happening.

If you want to learn more about it before starting, you can go to their website at:

Setup (5 steps)

First, you need Python. You should have it installed on your machine. If you do not, you can download it at:

1. Setting up Virtualenv

Documentation: https://virtualenv.pypa.io/en/stable/

Although this is not a requirement and your project will work just fine without it, using a virtual environment for your app is recommended. The reason is that you can have different versions of packages for different projects.

You could also use Pipenv. This is more a matter of preference (i personally prefer Pipenv), but Virtualenv is more common. You can check it out here: https://docs.pipenv.org/

2. Setting up our Django project

Now that our environment is set up, the next step is creating our django project. We do this by running:

This should generate a folder named “api”. I usually rename this to “src”.

3. Configure our project

To start building our API we first need to set it up correctly. The settings.py file specifies how Django should set up.

There will already be some settings, but we only need to make some minor changes to the the existing ones, and a few additions.

INSTALLED_APPS: This is where django discovers the different modules that are part of your project.

MIDDLEWARE: Every time a request hits the Django server it runs through the middleware.

REST_FRAMEWORK: These are the settings for Django Rest Frameworks. What we do is change it so that it accepts OAuth2 as authentication.

AUTHENTICATION_BACKENDS: This specifies what authentication system should be used.

4. Add our OAuth2 provider

Then we need to configure our routes so that we can access the provider.

5. Start our server

To get started we need to migrate the database. What this does is create and setup the database.

Then we need to create a superuser. Make sure you remember the username and password.

Lastly we need to run our development server.

Congratulations! You have finished setting up. You can now navigate to 0.0.0.0:8000 in your browser. You should see an error like this.

We now have our sever properly configured to work with OAuth2.

Packages

Now we are ready

Django Rest Framework

Documentation: http://www.django-rest-framework.org/

Django OAuth2 Toolkit

Documentation: https://github.com/jazzband/django-oauth-toolkit

Understanding OAuth2

Getting the grasp on OAuth2 might take some time, but I am going to give you my best explanation.

There are 3 main parts of a OAuth2 system:

Resource Server

This is where the data is stored. We will build this last.

Application

This is someone an integration that needs access to the server. This is created by a developer and is also a server, because you need a private key. You can not have an application in the browser (that is intended for more than one person).

Authorization Server

This is where the contact between the Resource Server and the Application is managed. This is the part Django OAuth2 Toolkit handels.

This could be on another server.

Flow

In theory OAuth2 has a flow like bellow.

Source: https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2

In our case its more like:

The application server, authorization server and resource server will be run on In the same Django app.

Application (4 steps)

Since a client cannot authorize against a authentication server directly, we are going to create an application that allows users to register and start using tokens.

1. Create an app

The first step is to create an app for our users.

We need to install the apps in our settings, so that Django can find it.

2. Create a user serializer

The next step its going to be to create a serializer for the user model. For the ones not familiar with Django. A model specifies how a table in the SQL database should look, and lets you put and extract data from the database. A serializer is a way to create and fetch models in an API format.

The create method overrides the default behavior when saving a user. The details are not too important, but this is importaint to make sure the password is hashed correctly.

Your folder structure should now look like this:

3. Create the views

We will need a couple of views.

  • Register
  • Token (login)
  • Refresh (login next time)
  • Revoke (log out)

You will also have to register this application with your authentication server.

You do this by going to 0.0.0.0:8000/o/applications/.

Settings are as follows:

  • Client type: Confidential
  • Authorization grant type: Resource owner password-based
  • Name: Whatever you want.

You should now get a CLIENT_ID and CLIENT_SECRET, which you can add to the code.

4. Bind the urls

The last step is to create the routes.

First, create a new file in the users app called urls.py. To this you should add:

Also you will need to add these route to you main app.

If you now go to authentication/register/ you should se a nice interface. Feel free to test out the different views.

Resource Server (5 steps)

Now that we have our authentication set up, its time to test it out.

1. Create our app and install it

It should be named unicorn. If you are unsure how to do this, please refer to the section above.

2. Create a model

As previously mentioned a model represents a database table.

3. Create a serializer

The same way we created a serialier for the user model we are going to create a serializer for the unicorn model.

4. Create and register the viewsset

The last step will be to create a view where we can see the unicorns. In this case we will create a viewset to allow us to interact with the model (view, edit, create, delete). To keep it clean I decided to use a model viewset.

In order to see this we need to create a router to route to it. I did this by adding a router in the root urls.py.

5. Run migrations

Since we changed our database, we need to need to run the makemigrations and migrate commands. If you are unsure of how to do this, check out step 5 in the setup section.

Test it out

You should now have you app set up. You can test it by.

Registering a user:

curl -d "username=halfspring&password=1234abcd" "0.0.0.0:8000/authentication/register/"
> {
> "access_token":"<token>",
> "expires_in":36000,
> "token_type":"Bearer",
> "scope":"read write",
> "refresh_token":"5ojnx8ARHQTaK35XfuuMI2eqXsOWew"
> }

Make a unicorn:

curl -H "Authorization: Bearer <token>" -d "name=djangounchained&age=34" 0.0.0.0:8000/v1/unicorn/
> {
> "name":"djangounchained"
> "age":34
> }

Let’s add another one:

curl -H "Authorization: Bearer <token>" -d "name=mylittlepony&age=22" 0.0.0.0:8000/v1/unicorn/

List all the unicorns:

curl -H "Authorization: Bearer <token>" 0.0.0.0:8000/v1/unicorn/
> {
> "name":"djangounchained"
> "age":34
> }

Summary

OAuth 2 is really cool, and the backbone of any modern API. This is a simple example, but there is a lot about both Django Rest Framework and Django OAuth2 Toolkit I did not have time to cover.

--

--

Halvor Fladsrud Bø

Software Engineer. Interested in security, distributed systems and databases. Using this as a scratchpad.