Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Token Based Authentication in Django

Tags:

django

I am trying to figure out the best way to implement token based authentication in my django app. An external, non-django application is setting a cookie, with a token, and I have a webservice that can retrieve user information based off of that token. If the user has the cookie set, they should not need to authenticate on my site and should be automatically logged in based on the info passed back by the web service. As I see it, there are a few different options to perform the actual check and I'm not sure which is best:

  1. Write a custom decorator like the one in this snippet and use it instead of login_required.
  2. Call a custom authenticate method inside base_site through an ajax call. On every page, a check would be made and if the cookie exists and is valid, then the user would be automatically logged in.
  3. Add some javascript to the LOGIN_REDIRECT_URL page that will check/validate the cookie in an ajax call, and automatically redirect back to the referrer if the cookie authenticated.

Is there an option I am missing? Ideally, there would be a way to build this into login_required, without having to write a custom decorator.

like image 375
Bacon Avatar asked Feb 17 '11 00:02

Bacon


People also ask

Which is the best authentication for Django?

JSON Web Token Authentication JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token.

What is token-based authentication explain with example?

Token-based authentication is a protocol that generates encrypted security tokens. It enables users to verify their identity to websites, which then generates a unique encrypted authentication token.

How do I get Django tokens?

You can get the token from the request. auth attribute. It returns a DRF Token instance. If you want only the key then you can access it with the request.


1 Answers

Before searching for code, be sure you read the documentation. http://docs.djangoproject.com/en/1.2/topics/auth/#other-authentication-sources Also read the supplied Django source.

You want to create three things.

  1. Middleware to capture the token. This is where most of the work happens. It checks for the token, authenticates it (by confirming it with the identity manager) and then logs in the user.

  2. Authentication backend to find Users. This is a stub. All it does is create users as needed. Your identity manager has the details. You're just caching the current version of the user on Django's local DB.

Here's the middleware (edited).

from django.contrib.auth import authenticate, login  class CookieMiddleware( object ):     """Authentication Middleware for OpenAM using a cookie with a token.     Backend will get user.     """     def process_request(self, request):         if not hasattr(request, 'user'):             raise ImproperlyConfigured()          if "thecookiename" not in request.COOKIES:             return         token= request.COOKIES["thecookiename"]         # REST request to OpenAM server for user attributes.         token, attribute, role = identity_manager.get_attributes( token )         user = authenticate(remote_user=attribute['uid'][0])         request.user = user         login(request, user) 

The identity_manager.get_attributes is a separate class we wrote to validate the token and get details on the user from the IM source. This, of course, has to be mocked for testing purposes.

Here's a backend (edited)

class Backend( RemoteUserBackend ):     def authenticate(**credentials):         """We could authenticate the token by checking with OpenAM         Server.  We don't do that here, instead we trust the middleware to do it.         """         try:             user= User.objects.get(username=credentials['remote_user'])         except User.DoesNotExist:             user= User.objects.create(username=credentials['remote_user'] )         # Here is a good place to map roles to Django Group instances or other features.         return user 

This does not materially change the decorators for authentication or authorization.

To make sure of this, we actually refresh the User and Group information from our identity manager.

Note that the middleware runs for every single request. Sometimes, it's okay to pass the token to the backed authenticate method. If the token exists in the local user DB, the request can proceed without contacting the identity manager.

We, however, have complex rules and timeouts in the identity manager, so we have to examine every token to be sure it's valid. Once the middleware is sure the token is valid, we can then allow the backend to do any additional processing.

This isn't our live code (it's a little too complex to make a good example.)

like image 152
S.Lott Avatar answered Sep 30 '22 20:09

S.Lott