Using Custom Authentication Backends in Django
Tags: django, python, tutorial, productivity
Published: 2019-10-08 18:02:24

---
title: Using Custom Authentication Backends in Django
published: true
description: If you’re working in an organization with an established product line that serves live users, supporting a new site with Django probably means integrating with an existing authentication system.
tags: django, python, tutorial, productivity
cover_image: https://thepracticaldev.s3.amazonaws.com/i/b80zzuafliabsw7s270x.jpg
series: Django Tutorials on Kite's Blog
canonical_url: https://kite.com/blog/python/custom-django-authentication/
---

Many organizations use widely-adopted authentication systems provided by services like Google, Facebook, or GitHub. A few Python packages provide authentication integration with these services, but most of them expect you to be handling the final user accounts on with Django. What happens when you need to work with user accounts that live in another system altogether?

In this article, you’ll see the interface that Django exposes for authenticating to an external system. By the end, you should understand the pieces involved in mapping an external system’s information to Django’s native `User` objects in order to work with them on your own site.

## Django’s default authentication

In the [Django User Authentication System](https://kite.com/blog/python/django-authentication/), we covered the basics of how default authentication works in Django. Ultimately, you can interact with `User` objects and understand if a user `is_authenticated` or not. Using the default authentication system, you can make use of many of Django’s built-in features like its login and logout views and password reset workflow.

When working with an external authentication system, you have to manage these pieces yourself. Some of them may not make sense to you depending on how your authentication system works.

## Authentication backends

As with many of Django’s systems, authentication is modeled as a plugin system. Django will try to authenticate users through a series of authentication backends. The default backend checks a user’s username and password against all the existing `User` objects in the database to authenticate them. The `AUTHENTICATION_BACKENDS` setting is your entrypoint to intercept this workflow and point Django to your external system.

An authentication backend is a class that, minimally, implements two methods:

- `get_user(user_id)` — a `user_id` can be whatever unique identifier your external system uses to distinguish users, and `get_user` returns either a user object matching the given `user_id` or `None`.
- `authenticate(request, **credentials)` — the `request` is the current HTTP request, and the credentials keyword arguments are whatever credentials your external system needs to check if a user should be authenticated or not. This is often a username and password, but it could be an API token or some other scheme. `authenticate` returns an authenticated `User` object or `None`.

Inside your authentication backend’s authenticate method, you can pass along the credentials to your external system via a REST API or another common authentication scheme like LDAP or SAML.

Using the wonderful [Yes or No?](https://yesno.wtf/) API, you could build an authentication backend that authenticates a user occasionally if the API permits:

```python
import requests

class FickleAuthBackend:
    def authenticate(self, request, username):
        response = requests.get(
            'https://yesno.wtf/api/'
        ).json()
        return User(username=username, password='') if response['answer'] == 'yes' else None
```

While `authenticate` can return a user object or `None`, it may also return an `AnonymousUser` object, or raise `PermissionDenied` to explicitly halt any further authentication checks. This allows for a variety of ways to proceed, and anonymous users may still have certain permissions. You’ll want to account for that in your middleware and views.

If the external user service provides additional information about the user, `get_user` might be a good place to grab some of that data. You can add attributes to the user object in `authenticate` before you return it if you’d like, but be careful of how many attributes you add dynamically.

## Permissions

I also covered Django’s permission scheme in The Django User Authentication System: when given a user, you can inquire about their permissions generally or against specific objects using the `has_perm` method. Custom authentication backends can override permission checking methods and Django will check against those first before falling back to its default checks. This allows you to make queries to your external system about permissions in addition to authentication:

... [continue with Permissions](https://kite.com/blog/python/custom-django-authentication/) see the code, and more Django tutorials by Dane!

*Dane Hillard has an upcoming book "Practices of the Python Pro" coming this month (October 2019)*