PyMSALRuntime
PyMSALRuntime is the Python interop package for the Microsoft Authentication Library (MSAL) Runtime. It acts as a low-level bridge, enabling Python applications, primarily through the MSAL Python library, to interact with the underlying OS-level authentication broker for enhanced security and single sign-on experiences. The current version is 0.20.2, released on January 9, 2026, with frequent updates to align with the MSAL ecosystem.
Warnings
- gotcha PyMSALRuntime is a native extension. If pre-built wheels are not available for your specific Python version and operating system architecture (e.g., Windows ARM64), `pip install` may fail, requiring C/C++ build tools (like Microsoft Visual C++ Build Tools on Windows).
- breaking Older versions of PyMSALRuntime (e.g., <0.18.1) might have compatibility issues or lack pre-built wheels for newer Python versions like 3.13. If you are using an older `msal` version that pins to an older `pymsalruntime`, this could cause installation failures.
- gotcha On Linux, `PyMsalRuntime` v0.20.0 has been noted to require `libwebkitgtk`. If this library is missing, applications using `pymsalruntime` (via `msal`) for interactive flows on Linux might encounter errors or unexpected behavior.
Install
-
pip install pymsalruntime
Imports
- MsalRuntime
from pymsalruntime._pymsalruntime import MsalRuntime
Quickstart
import os
from msal import PublicClientApplication
# Configure your application
# You would typically get CLIENT_ID from your Azure AD application registration
# You might also need a 'tenant_id' or 'authority' depending on your scenario
CLIENT_ID = os.environ.get('MSAL_CLIENT_ID', 'YOUR_CLIENT_ID_HERE')
AUTHORITY = os.environ.get('MSAL_AUTHORITY', 'https://login.microsoftonline.com/common')
# Initialize a PublicClientApplication with broker enabled
# PyMSALRuntime is leveraged under the hood when 'enable_broker=True' on Windows/macOS
app = PublicClientApplication(CLIENT_ID, authority=AUTHORITY, enable_broker=True)
# Define the scope(s) for which you want to acquire a token
scopes = ['User.Read']
# Acquire a token silently (if a cached token exists and is valid)
result = app.acquire_token_silent(scopes, account=None)
if not result:
# If no token is cached or it's expired, acquire it interactively (will open a browser/broker window)
print("No cached token found or expired. Acquiring interactively...")
flow = app.initiate_auth_code_flow(scopes=scopes)
print(f"Please go to this URL and authorize: {flow['auth_uri']}")
result = app.acquire_token_by_auth_code_flow(flow, {
'code': input('Enter the authorization code: ')
})
if 'access_token' in result:
print("Access token acquired successfully!")
print(f"Token expires on: {result.get('expires_on')}")
# You can now use result['access_token'] to call protected APIs
else:
print(f"Token acquisition failed: {result.get('error_description', result.get('error'))}")