Custom authentication scheme for Django Rest Framework

I’m developing a native iOS app that needs to interface with an existing Django web project via a RESTful API. For this particular project I’ve chosen to use the well-maintained Django Rest Framework to handle creating the API.

I’ve decided to use OAuth2 authentication between the iOS app and the Django project and I’ve set everything up following the Django Rest Framework documentation for using OAuth2 authentication. Followed the simple CURL test and I’m able to communicate with all of my endpoints successfully.

So, what’s the problem?

Let me give a little background to help you understand how I arrived at the need for a custom authentication scheme.

Restricting the API to Authenticated Users

As the title indicates, this project requires user authentication to access the API regardless of the method (GET, POST, PUT, etc). Django Rest Framework makes this easy enough by providing a permissions class called IsAuthenticated which will deny permission to any unauthenticated user, and allow permission otherwise.

I implemented this in the settings files per the documentation to override the default of allowing anyone to view the API:

With the default authentication class of  'rest_framework.authentication.SessionAuthentication' and the permission class above I have now restricted my API to authenticated users.

Adding OAuth2 API Access

To get OAuth2 authentication up and running I configured the DEFAULT_AUTHENTICATION_CLASSES  in my settings file as indicated in the documentation. Here’s the recommended settings configuration for OAuth2 with my permission class from above:

 Configure Super User Access to the Web Browsable API

Now we’ve arrived at the problem. Our developers can’t access the web browsable API because we’re requiring authentication and the only authentication scheme available is OAuth2.

As a developer, the web browsable API is one of my favorite parts of the Django Rest Framework project. The web browsable API makes it much easier to work with, visualize, and debug our API endpoints.

Adding  'rest_framework.authentication.SessionAuthentication' back to the  'DEFAULT_AUTHENTICATION_CLASSES' tuple would certainly work. However, it would also make the web browsable API available to any authenticated user which we don’t want.

My solution was to write a custom authentication scheme for the Django Rest Framework that restricted session authentication to only allow superusers to view the web browsable API. In order to do so I decided to extend the  'rest_framework.authentication.SessionAuthentication' class and overwrite the authentication method.

I created a file called authentication.py  in my projects  Accounts app which we use to give other custom functionality to users. Of course, you could name and place this file wherever it best suits your project.

Here is my entire custom authentication.py file:

I implemented it into my settings file as I did the other authentication classes:

There you have it. All authenticated users have access to the API via OAuth2 Authentication and only super users are able to view the web browsable API.