6

I'm trying to distinguish between a couple of Django authentication backends (which are external packages and I preferably don't want to modify them) in my views. django.contrib.auth docs says auth backends (settings.AUTHENTICATION_BACKENDS) will be tried in order and the first that does authenticate, will return and set request.user and if any raises an exception, authentication is refused. But it does not say how can I distinguish between requests depending on which backend has authenticated the user.

Is this possible? and how?

zaadeh
  • 1,711
  • 2
  • 23
  • 37
  • Possible duplicate of [Django - Read the current's user authentication backend class](https://stackoverflow.com/questions/5025367/django-read-the-currents-user-authentication-backend-class) – OrangeDog May 09 '18 at 14:44

1 Answers1

8

As explained in Django docs for authentication backends settings:

Once a user has authenticated, Django stores which backend was used to authenticate the user in the user’s session, and re-uses the same backend for the duration of that session whenever access to the currently authenticated user is needed. This effectively means that authentication sources are cached on a per-session basis

Actually, this information is stored when function login(request, user, backend=None) is used (see django.contrib.auth.__init__.py). After user has been authenticated, following session information are stored:

SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
HASH_SESSION_KEY = '_auth_user_hash'
# [...]
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = backend
request.session[HASH_SESSION_KEY] = session_auth_hash

So, you should check current request's session for key BACKEND_SESSION_KEY to find the backend used to authenticate user.

Antwane
  • 20,760
  • 7
  • 51
  • 84
  • Thanks, but while this is supposed to generally work, It's worth to know that if you don't want to put an auth backend in `settings.AUTHENTICATION_BACKENDS` **and** the backend has not implemented passing the optional `backend` param to call to `django.contrib.auth.login()` (which lots of them dont), then this would not work. In this case I had to resort to receiving login and logout signals that are hopefully sent and are sent correctly (with passing `request` object) from auth backends and setting a suitable flag in `request.session` in signal handler manually. – zaadeh Sep 18 '17 at 12:19
  • You should use `django.contrib.auth.BACKEND_SESSION_KEY`, not `'_auth_user_backend'` directly. – OrangeDog May 09 '18 at 14:43