Setting the user.request object to an Azure AD user

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.