Setting the user.request object to an Azure AD user
Setting request.user to a Django user after someone logs in via Azure Active Directory.
I am using Azure Active Directory for sign-in in my Django application. There is an entire tutorial on how to set this up at Microsoft's website - https://learn.microsoft.com/en-us/training/modules/msid-django-web-app-sign-in/
Now that we can sign-in using Azure AD, the Django default sign-in is left as is, and not used. But there still is a auth_user
table created during makemigrations
and migrate
. the auth_user
table is the one that Django references for the default Djangp's built-in user login.
If you are syncing the users in Django's default auth_user
table with the Azure AD usernames, then you can auto-signin to the Django user system post logging in via Azure AD.
This is achieved by integrating a custom middleware.
Assuming your app's name is application
, create a file called custom_middleware.py in the application
folder.
Let us create a function containing the following code :
def getAzureADDetails(request):
claims = request.identity_context_data._id_token_claims
exclude_claims = ['iat', 'exp', 'nbf', 'uti', 'aio', 'rh']
claims_to_display = {claim: value for claim, value in claims.items() if claim not in exclude_claims}
return dict(claims_to_display)
The above is Microsoft's standard code for extracting user login info from the Azure AD session.
Now let's create the middleware class. The middleware class requires __call__
to be defined and a response to be returned.
Code before response = self.get_response(request)
would be executed before the view is rendered, while code after response = self.get_response(request)
would be executed after the view the rendered. We specifically need our logic to be inserted after response = self.get_response(request)
.
from ms_identity_web import IdentityWebPython
class CustomMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print("Middleware: Custom code is running!")
# Code to run before the view is called
response = self.get_response(request)
# Code to run after the view is called and before the response is returned
azureAD = getAzureADDetails(request)
# A user has logged in to the django application via the AD login
if len(azureAD) > 0:
claims = request.identity_context_data._id_token_claims
try:
user = User.objects.get(email=claims['preferred_username'])
request.user = user
except User.DoesNotExist:
print("not able to find AD user from django's auth_users table")
return response
So now enter 'application.custom_middleware.CustomMiddleware',
in the MIDDLEWARE list in settings.py. For example, it should look similar to this sample snippet :
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'application.custom_middleware.CustomMiddleware', # This was inserted
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Now, in views.py request.user.is_authenticated
would be True
when someone logs into your Django app via Microsoft's Azure Active Directory.
Note: here I have assumed that your auth_users
table has the data filled in with your Azure Active Directory users. This can be done by an insert from another source when a new AD user logs in or is created.