Azure AD Login Guide

Python script setup, ROPC flow, environment configuration

Written By jazilkalim

Last updated 3 months ago

What is Azure AD Login?

The Azure AD Login script provides a streamlined way to authenticate with CampusMindAI using your Microsoft Azure Active Directory credentials. Instead of interactive browser-based login, this script uses the Resource Owner Password Credentials (ROPC) flow to programmatically obtain authentication tokens.

Why Use the Azure AD Login Script?

This script is essential for:

  • Automated Workflows: Enable CI/CD pipelines and automated testing

  • Server-Side Applications: Backend services that need API access

  • Batch Processing: Scripts that process data or perform bulk operations

  • Development & Testing: Quick authentication during development

Prerequisites

Required Software

  1. Python 3.7+: Ensure Python is installed on your system

  2. pip: Python package manager (usually included with Python)

Required Python Packages

Install the necessary dependencies:

pip install msal python-dotenv

Required Credentials

You'll need the following from your Azure AD administrator:

  • Client ID: Application (client) ID from Azure AD App Registration

  • Tenant ID: Directory (tenant) ID from Azure AD

  • Client Secret: Client secret value from Azure AD App Registration

  • Username: Your organizational email address

  • Password: Your Azure AD account password

Important Security Requirement

Your email account must be added as an Owner or have appropriate permissions in the Azure AD App Registration. Contact your Azure administrator if authentication fails due to permission issues.

Setup Instructions

Step 1: Create Environment File

Create a file named .env in your project directory:

touch .env

Step 2: Add Credentials to .env File

Open the .env file and add your credentials:

AZURE_AD_CLIENT_ID=your-client-id-here
AZURE_AD_TENANT_ID=your-tenant-id-here
AZURE_AD_CLIENT_SECRET=your-client-secret-here
AZURE_AD_USERNAME=your-email@company.com
AZURE_AD_PASSWORD=your-password-here

Security Note: Never commit the .env file to version control. Add it to .gitignore:

echo ".env" >> .gitignore

Step 3: Create the Authentication Script

Create a file named azure_login.py:

import msal
import os
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Get Azure AD configuration from environment variables
client_id = os.getenv('AZURE_AD_CLIENT_ID')
tenant_id = os.getenv('AZURE_AD_TENANT_ID')
client_secret = os.getenv('AZURE_AD_CLIENT_SECRET')
username = os.getenv('AZURE_AD_USERNAME')
password = os.getenv('AZURE_AD_PASSWORD')

# Define required permissions (scopes)
scopes = [f"api://{client_id}/access_as_user"]

# Microsoft's authentication endpoint for your organization
authority = f"https://login.microsoftonline.com/{tenant_id}"

# Create the authentication application
app = msal.ConfidentialClientApplication(
    client_id=client_id,
    client_credential=client_secret,
    authority=authority
)

# Attempt authentication with username and password
result = app.acquire_token_by_username_password(
    username=username,
    password=password,
    scopes=scopes
)

# Check if authentication was successful
if "access_token" in result:
    print(result["access_token"])
else:
    print("Authentication failed:")
    print(result.get("error"))
    print(result.get("error_description"))

How to Use the Script

Running the Script

Execute the script from your terminal:

python azure_login.py

Successful Output

If authentication succeeds, the script will output your Azure AD access token:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1yNS1BVW...

Failed Authentication

If authentication fails, you'll see an error message:

Authentication failed:
invalid_grant
AADSTS50126: Error validating credentials due to invalid username or password.

Using the Token

Step 1: Copy the Token

Copy the entire token string from the script output.

Step 2: Exchange for CampusMindAI Token

Send the Azure AD token to the CampusMindAI login endpoint:

curl -X GET https://<baseURL>/api/v1/login \
  -H "Authorization: Bearer <your-azure-ad-token>"

Step 3: Receive JWT Token

The API will respond with a CampusMindAI-specific JWT token:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer"
}

Step 4: Use JWT Token for API Calls

Include the JWT token in all subsequent API requests:

curl -X POST https://<baseURL>/api/v1/list_users \
  -H "Authorization: Bearer <jwt-token>" \
  -H "Content-Type: application/json" \
  -d '{"page": 1, "limit": 10}'

Understanding the Code

Loading Environment Variables

load_dotenv()

Loads credentials from the .env file, keeping sensitive data out of your code.

Defining Scopes

scopes = [f"api://{client_id}/access_as_user"]

Specifies the permissions your application needs. This scope allows access to your backend API.

Creating the MSAL Application

app = msal.ConfidentialClientApplication(
    client_id=client_id,
    client_credential=client_secret,
    authority=authority
)

Creates a confidential client application that can authenticate users using the ROPC flow.

Acquiring the Token

result = app.acquire_token_by_username_password(
    username=username,
    password=password,
    scopes=scopes
)

Authenticates with Azure AD using username and password credentials.

Troubleshooting

Common Errors

ErrorCauseSolution

AADSTS50126

Invalid username or password

Verify credentials in .env file

AADSTS700016

Application not found

Check AZURE_AD_CLIENT_ID value

AADSTS90002

Tenant not found

Verify AZURE_AD_TENANT_ID value

AADSTS7000215

Invalid client secret

Check AZURE_AD_CLIENT_SECRET value

AADSTS65001

User doesn't have consent

Contact admin to grant permissions

Permission Issues

If you receive permission-related errors:

  1. Verify your email is added as an Owner in Azure AD App Registration

  2. Ensure ROPC flow is enabled for the application

  3. Check that your account has the required API permissions

Environment Variable Issues

If variables aren't loading:

# Add debug output
print(f"Client ID loaded: {client_id is not None}")
print(f"Tenant ID loaded: {tenant_id is not None}")

Ensure the .env file is in the same directory as your script.

Security Considerations

Best Practices

  1. Never Hardcode Credentials: Always use environment variables

  2. Secure the .env File: Set appropriate file permissions

    chmod 600 .env
    
  3. Rotate Secrets Regularly: Update client secrets periodically

  4. Use Service Accounts: For production, use dedicated service accounts

  5. Monitor Token Usage: Review authentication logs for suspicious activity

Token Storage

  • Never store tokens in version control

  • Use secure storage mechanisms (e.g., Azure Key Vault) in production

  • Clear tokens from memory after use in sensitive environments

Advanced Configuration

Custom Token Caching

For applications that make frequent API calls, implement token caching:

import msal

# Create token cache
cache = msal.SerializableTokenCache()

# Create app with cache
app = msal.ConfidentialClientApplication(
    client_id=client_id,
    client_credential=client_secret,
    authority=authority,
    token_cache=cache
)

# Try to get token from cache first
accounts = app.get_accounts()
if accounts:
    result = app.acquire_token_silent(scopes, account=accounts[0])
else:
    result = app.acquire_token_by_username_password(
        username=username,
        password=password,
        scopes=scopes
    )

Error Handling

Add comprehensive error handling:

try:
    result = app.acquire_token_by_username_password(
        username=username,
        password=password,
        scopes=scopes
    )
    
    if "access_token" in result:
        return result["access_token"]
    else:
        raise Exception(f"Auth failed: {result.get('error_description')}")
        
except Exception as e:
    print(f"Error during authentication: {str(e)}")
    raise

Additional Resources