I love Django. I’ve been using it since it was part of the Ellington Content Management System (CMS), and I appreciate its opinionated stance on the web stack. While its opinions have changed over time, Django has always been level-headed and, in my opinion, one of the best managed open-source projects.
When developing front-end heavy websites, you invariably need supporting web services, and for Django, the most popular solution is Django REST Framework (DRF). DRF is loved for its reusability across projects and how it integrates with other libraries within the Django ecosystem, but it isn’t always a perfect fit.
Specifically, I don’t think I’ve been on a project where authentication wasn’t one of the pieces that we had to replace. DRF integrates with Django’s typical auth subsystem perfectly, but we didn’t want to rely on session cookies because of the support issues they raise — especially for non-web clients.
To avoid using session cookies, we turn to the next simplest solution: Bearer Tokens.
Bearer Tokens are simple strings typically used by APIs protected by OAuth. They are opaque strings with no intrinsic meaning to the clients using them, similar to session cookies. In addition, Bearer Tokens:
In our latest situation, we wanted the Bearer Tokens to be short-lived but renewable and we wanted them to be issued on a per-device-per-user basis. These can be used across multiple domains served by a common back-end. From the server’s perspective, we are managing users and devices, not users and sites. Users or devices can be logged in and out individually, or en masse.
Bearer Tokens look good — and DRF ships with support for them — but the DRF implementation has a few shortcomings we need to address. Specifically, DRF tokens:
Django-Rest-Knox (DRK) has entered the chat.
DRK offers a token mechanism that can be plugged directly into DRF to address those limitations. It adds mechanisms for key rotation, token renewal and usage tracking. Plus, the tokens are stored cryptographically.
Once added to a DRF project’s INSTALLED_APPS, just swap in DRK’s auth to your DRF settings via settings.py:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication',), ... }
Then, expose its auth endpoints via your urls.py:
urlpatterns = [ … url(r'api/auth/', include('knox.urls')) … ]
Next, you’ll have login
, logout
and logout_all
endpoints that clients can use to manage their tokens for the remainder of your REST APIs. There are DRK-specific settings you can use to tweak some of its behavior — like TOKEN_TTL, TOKEN_LIMIT_PER_USER and AUTO_REFRESH, as well as a host of other less critical settings. DRK’s auth views are subclasses of DRF’s APIView, so you can further refine them.
DRK also makes use of Django’s signal system. It will send signals for logins, logouts and token expirations. You will receive signals for each— or other signal handlers for authentication events — if they include the user and the request object. This allows you to collect data on device types and other metrics that may be important to you. DRK even ships with a simple admin interface defined if you use the Django admin.
In short, DRK offers the simplest solution for what can easily become a very complex issue. Plus, if your needs become even more complex, DRK likely won’t stand in your way.