Microsoft Graph API: An Overview
As an Identity and Access Management professional, I've found Microsoft Graph API to be an incredibly powerful tool in my daily work. It's become my go-to solution for automating many Microsoft 365 and Entra ID (formerly Azure AD) tasks. Let me share what I've learned and how you might benefit from it too.
What is Microsoft Graph API?
Microsoft Graph API is a unified gateway to Microsoft's cloud services. Think of it as a single endpoint (https://graph.microsoft.com
) that gives you programmatic access to everything from user accounts and groups to emails, calendars, files, and much more across Microsoft 365, Windows, and Enterprise Mobility + Security.
What makes it special is how it connects previously siloed services. Before Graph API, you'd need to learn different APIs for Exchange, SharePoint, Teams, and Azure AD. Now, there's one consistent approach to work with all Microsoft cloud data.
My Recent Challenge: Automating MFA Management
Recently, I faced a challenge at work: we needed to bulk manage MFA methods for users being offboarded or changing roles. Manually unlinking MFA methods through the admin portal was time-consuming and error-prone.
This is where I turned to Microsoft Graph API with Python, and I'd like to share how you can do the same.
Automating MFA Unlinking with Python and Microsoft Graph API
Let me walk you through a practical example I developed. This script allows you to identify and remove MFA methods from user accounts in Microsoft Entra ID:
# mfa_manager.py
import requests
import msal
import json
import logging
from datetime import datetime
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class EntraMFAManager:
def __init__(self, tenant_id, client_id, client_secret):
self.tenant_id = tenant_id
self.client_id = client_id
self.client_secret = client_secret
self.access_token = None
self.graph_url = "https://graph.microsoft.com/v1.0"
def authenticate(self):
"""Get access token from Microsoft Entra ID"""
try:
# Create MSAL app for authentication
authority = f"https://login.microsoftonline.com/{self.tenant_id}"
app = msal.ConfidentialClientApplication(
client_id=self.client_id,
client_credential=self.client_secret,
authority=authority
)
# Acquire token for Graph API
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
if "access_token" in result:
self.access_token = result["access_token"]
logger.info("Authentication successful")
return True
else:
logger.error(f"Authentication failed: {result.get('error_description', 'Unknown error')}")
return False
except Exception as e:
logger.error(f"Authentication exception: {str(e)}")
return False
def get_user_mfa_methods(self, user_principal_name):
"""Get a user's MFA methods"""
if not self.access_token:
if not self.authenticate():
return None
headers = {
"Authorization": f"Bearer {self.access_token}",
"Content-Type": "application/json"
}
# Get user's authentication methods
url = f"{self.graph_url}/users/{user_principal_name}/authentication/methods"
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
methods = response.json().get("value", [])
logger.info(f"Found {len(methods)} authentication methods for user {user_principal_name}")
return methods
except requests.exceptions.RequestException as e:
logger.error(f"Error getting MFA methods: {str(e)}")
if hasattr(e.response, 'text'):
logger.error(f"Response: {e.response.text}")
return None
def remove_mfa_method(self, user_principal_name, method_id):
"""Remove a specific MFA method from a user"""
if not self.access_token:
if not self.authenticate():
return False
headers = {
"Authorization": f"Bearer {self.access_token}",
"Content-Type": "application/json"
}
url = f"{self.graph_url}/users/{user_principal_name}/authentication/methods/{method_id}"
try:
response = requests.delete(url, headers=headers)
response.raise_for_status()
logger.info(f"Successfully removed authentication method {method_id} for user {user_principal_name}")
return True
except requests.exceptions.RequestException as e:
logger.error(f"Error removing MFA method: {str(e)}")
if hasattr(e.response, 'text'):
logger.error(f"Response: {e.response.text}")
return False
# Example usage
if __name__ == "__main__":
# Replace with your Entra ID (Azure AD) app registration details
TENANT_ID = "your-tenant-id"
CLIENT_ID = "your-client-id"
CLIENT_SECRET = "your-client-secret"
# Initialize the MFA manager
mfa_manager = EntraMFAManager(TENANT_ID, CLIENT_ID, CLIENT_SECRET)
# Example: Process a list of users
users_to_process = ["user1@example.com", "user2@example.com"]
for user in users_to_process:
print(f"\nProcessing user: {user}")
# Get user's MFA methods
mfa_methods = mfa_manager.get_user_mfa_methods(user)
if not mfa_methods:
print(f"No MFA methods found or error occurred for {user}")
continue
# Print current methods
print(f"Found {len(mfa_methods)} authentication methods:")
for method in mfa_methods:
method_id = method.get("id")
method_type = method.get("@odata.type", "").replace("#microsoft.graph.", "")
print(f"- {method_type} (ID: {method_id})")
# Example: Remove phone methods only
phone_methods = [m for m in mfa_methods if "phone" in m.get("@odata.type", "").lower()]
for method in phone_methods:
method_id = method.get("id")
if method_id:
if mfa_manager.remove_mfa_method(user, method_id):
print(f"โ
Successfully removed phone method {method_id}")
else:
print(f"โ Failed to remove phone method {method_id}")
How This Script Works
I built this Python script to solve a real problem we were facing with MFA management. Here's how it works:
Authentication: Uses MSAL (Microsoft Authentication Library) to acquire an access token with the right permissions.
Retrieving MFA Methods: Calls the Graph API endpoint to list all authentication methods for a given user.
Targeted Removal: Can selectively remove specific MFA methods (like phone or authenticator app) based on your needs.
What I love about this approach is that it's flexible enough to handle various scenarios. For example, you could:
Bulk unlink MFA methods during offboarding
Transfer users from one authentication method to another
Generate reports on which authentication methods are being used
Automatically remediate security issues with compromised accounts
Permissions Required
To use this script, you'll need an app registration in Entra ID with the following API permissions:
UserAuthenticationMethod.ReadWrite.All
These permissions require admin consent, so you'll need to be a Global Administrator or have an admin grant these permissions to your application.
What I've Learned
Working with Microsoft Graph API has taught me several valuable lessons:
It's incredibly versatile - The unified API approach lets me solve problems across Microsoft's entire cloud ecosystem.
Authentication is key - Understanding the OAuth 2.0 flow and proper credential management is essential.
Documentation is your friend - Microsoft's Graph Explorer and API reference have been lifesavers.
Rate limiting matters - Production scripts need to implement backoff strategies and be considerate of API limits.
Conclusion
Microsoft Graph API has transformed how I approach automation in Microsoft's ecosystem. From user management to security controls, it provides a consistent, powerful way to interact with Microsoft services programmatically.
The MFA management example I've shared is just one small application. I encourage you to explore Graph API for your own unique use cases - whether it's reporting, automation, or integration with other systems.
If you're just getting started, I highly recommend checking out Microsoft's Graph Explorer to interactively test API calls before writing code. It's been an invaluable tool in my journey.
Last updated