Django Impersonate Auth
Django Impersonate Auth is a simple drop in authentication backend that allows superusers to impersonate regular users in the system.
Impersonation is handled by signing in using the target user's username and the superuser's username and password, separated by a specific character, as the password.
Getting Started
To install this library, you can simply run ::
pip install -e git+https://github.com/JordanReiter/django-impersonate-auth.git#egg=django-impersonate-auth
Then add ::
'impersonate_auth.backends.ImpersonationBackend',
to the AUTHENTICATION_BACKENDS
setting. If you don't currently have a value
for AUTHENTICATION_BACKENDS
, you can add this to your settings file, which
includes the default backend plus
the impersonation backend (both are required to function correctly)::
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'impersonate_auth.backends.ImpersonationBackend',
]
Usage
Using the default separator, a colon, here is an example of how to impersonate
another (non superuser) user:
-
| Normal User:
| Username:testuser
| Password:12345
-
| Super User:
| Username:superuser
| Password:987654321
-
| Super User impersonating Normal User:
| Username:testuser
| Password:superuser:987654321
Settings
The default separator is a colon (:
), but this can be changed using the
IMPERSONATE_AUTH_SEPARATOR
setting. The following code changes it to an
exclamation mark::
IMPERSONATE_AUTH_SEPARATOR = '!'
With this setting, in the example above, Super User would impersonate Normal
User using the password superuser!987654321
.
Important: because the username and password are separated by this character,
it's essential to choose a character that would never be found in a username.
For most login purposes, the colon :
is a good choice because it is neither a
legal character for a Django username or for an email address. [#email]_
Using Custom Authentication Backends
The package provides a mixin, ImpersonationBackendMixin
, which should
provide all the necessary code to implement impersonation for any authentication
backend which uses a combination of username and password. The backend uses the
USERNAME_FIELD
property of the user model, so if you use a custom User model
which uses a different field (for example, E-mail address) then it will still
work correctly.
Adding impersonation to your custom backend just means creating a new class that
extends both your existing and ImpersonationBackendMixin
. For example,
imagine a very insecure authentication backend called SillyBackend
where the
password is simply the username spelled backwards::
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
class SillyBackend(ModelBackend):
'''
A silly backend where the password for a user is their email address backwards.
'''
def authenticate(self, request=None, username=None, password=None):
UserModel = get_user_model()
try:
silly_user = UserModel.objects.get_by_natural_key(username)
except UserModel.DoesNotExist:
silly_user = None
if silly_user and password and password[::-1] == username:
return silly_user
In order to implement the impersonation functionality, you would add the
following code to your backends.py
file::
from impersonate_auth.backends import ImpersonationBackendMixin
class SillyImpersonationBackend(ImpersonationBackendMixin, SillyBackend):
def __init__(self, *args, **kwargs):
super(SillyImpersonationBackend, self).__init__(*args, **kwargs)
No other coding needed! Just make sure to add
path.to.backends.SillyImpersonationBackend
to your
AUTHENTICATION_BACKENDS
setting.