Search code examples
azureauthenticationazure-active-directorysingle-sign-onmsal

MSAL for non-SPA? Server side authentication?


I am new to Azure so please bear with me. My company uses Azure Active Directory and Azure SSO for most of the in-house applications for internal use. Most of the applications are built using React on AWS S3 for front end and AWS Lambda for the back end. With React, we use MSAL for client side SSO authentication and we just register Azure app (with user groups) for both front end and back end authorization/user control.

My team is about to start a new project. We want to stick with the similar authentication mechanism, but the problem is we are building a traditional monolithic non-SPA application (possibly using Flask and running in a docker container). The application will still redirect users to Azure SSO for authentication but the server-side has to know about the ID token(?) as the front-end will need to make AJAX request to server.

With a non-SPA application in my case, how does the authentication work? What do I need to do to implement this? Should I still use MSAL for the purpose? Or should I use something else? Following some of the tutorials, I have already registered an Azure app with the right user group, though I may not have configured any options for the SSO purposes. How does the server code interact with the Azure app in order to authenticate and verify the users?

I am sorry that I have a background of building app with traditional way of authenticating on server, I may not have grasped very well on the concept of Azure SSO. Your help is much appreciated. All code snippets for reference would be useful to me.

Even though I have done some Google finding previously, I don't think I have found much on non-SPA authentication. Maybe I am looking at the wrong direction. Please also let me know about any references if relevant. Thank you.


Solution

  • To implement authentication in a traditional monolithic non-SPA application using Azure Active Directory/Microsoft Entra ID and Azure Single Sign-On (SSO), you can indeed still use the Microsoft Authentication Library (MSAL)

    • Since Flask is server-side, your backend will handle the authentication and token validation.
    • However, for a server-side application like Flask, you will rely on the Authorization Code Flow with MSAL or simply handle token validation using other libraries on the server.

    Below is the outline how it is implemented:

    • After successful user authentication, Microsoft Entra ID will redirect the user back to your application with an authorization code in the URL query parameters.
    • After receiving the authorization code, the server-side (Flask) application will exchange this authorization code for ID tokens and access tokens
    • The client (your front-end) will receive the ID token, which must be included in the header of any requests to your server.

    Sample :

    Refer for more MsDoc

    from flask import Flask, redirect, session, request, url_for
    import msal
    import os
    
    app = Flask(__name__)
    app.secret_key = os.urandom(24)  
    app.config['SESSION_TYPE'] = 'filesystem'
    
    CLIENT_ID = 'your-client-id'  
    CLIENT_SECRET = 'your-client-secret'  
    AUTHORITY = 'https://login.microsoftonline.com/your-tenant-id'  
    REDIRECT_URI = 'http://localhost:5000/getAToken'  
    SCOPE = ['User.Read'] 
    
    @app.route('/')
    def home():
           if 'id_token' in session:
            return f"Hello, {session['user_name']}"  
        return redirect(url_for('login'))
    
    @app.route('/login')
    def login():
        msal_app = msal.ConfidentialClientApplication(
            CLIENT_ID, 
            authority=AUTHORITY, 
            client_credential=CLIENT_SECRET
        )
        
        auth_url = msal_app.get_authorization_request_url(
            SCOPE, 
            redirect_uri=REDIRECT_URI
        )
        return redirect(auth_url)
    
    @app.route('/getAToken')
    def get_a_token():
       
        code = request.args.get('code')  
        msal_app = msal.ConfidentialClientApplication(
            CLIENT_ID, 
            authority=AUTHORITY, 
            client_credential=CLIENT_SECRET
        )
        
        result = msal_app.acquire_token_by_authorization_code(
            code, 
            scopes=SCOPE, 
            redirect_uri=REDIRECT_URI
        )
        
        if 'id_token' in result:
           
            session['id_token'] = result['id_token']
            session['user_name'] = result['id_token_claims'].get('preferred_username')
        
        return redirect(url_for('home'))  
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    enter image description here

    Note that: MSAL is primarily used on the client side to handle token acquisition, but in the server-side context, you can use MSAL to handle token validation and even acquire tokens on behalf of the user using the Authorization Code Flow.

    • Ensure that tokens are stored securely on the server-side (e.g., in the Flask session).

    References:

    AzureAD/microsoft-authentication-library-for-js: Microsoft Authentication Library (MSAL) for JS

    microsoft-authentication-library-for-js/lib/msal-node/docs/faq.md at dev · AzureAD/microsoft-authentication-library-for-js