Python中使用ADAL调用Microsoft Graph API报错:Python API调用失败
使用Python的adal库访问Microsoft Graph API的问题及解决方案
问题描述
尝试用Python的adal库访问Microsoft Graph API获取用户数据时,运行脚本出现依赖库加载异常,同时代码存在逻辑问题。
原代码
import requests import adal # Define your Microsoft Azure AD app details client_id = 'YOUR_CLIENT_ID' client_secret = 'YOUR_CLIENT_SECRET' tenant_id = 'YOUR_TENANT_ID' resource_url = 'https://graph.microsoft.com' # Define the URL for the Microsoft Graph API to get the logged-in user's details graph_url = 'https://graph.microsoft.com/v1.0/me' # Create a function to acquire an access token def get_access_token(): authority_url = f'https://login.microsoftonline.com/%7Btenant_id%7D' context = adal.AuthenticationContext(authority_url) token = context.acquire_token_with_client_credentials(resource_url, client_id, client_secret) return token.get('accessToken') # Make a request to the Microsoft Graph API def get_user_details(access_token): headers = { 'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json', } response = requests.get(graph_url, headers=headers) if response.status_code == 200: user_data = response.json() print("User Details:") print(f"Display Name: {user_data.get('displayName')}") print(f"Email: {user_data.get('userPrincipalName')}") else: print(f"Failed to get user details. Status code: {response.status_code}") print(response.text)
报错信息
File "graph.py", line 2, in <module> import adal File "...../python/site-packages/adal/__init__.py", line 34, in <module> from .authentication_context import AuthenticationContext File "...../python/site-packages/adal/authentication_context.py", line 34, in <module> from .token_request import TokenRequest File "...../python/site-packages/adal/token_request.py", line 34, in <module> from . import self_signed_jwt File "...../python/site-packages/adal/self_signed_jwt.py", line 35, in <module> import jwt File "...../python/site-packages/jwt/__init__.py", line 1, in <module> from .api_jwk import PyJWK, PyJWKSet File "...../python/site-packages/jwt/api_jwk.py", line 7, in <module> from .algorithms import get_default_algorithms, has_crypto, requires_cryptography File "...../python/site-packages/jwt/algorithms.py", line 12, in <module> from .utils import ( File "...../python/site-packages/jwt/utils.py", line 7, in <module> from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurve File "...../python/site-packages/cryptography/hazmat/primitives/asymmetric/ec.py", line 11, in <module> from cryptography.hazmat._oid import ObjectIdentifier File "...../python/site-packages/cryptography/hazmat/_oid.py", line 9, in <module> from cryptography.hazmat.bindings._rust import ( pyo3_runtime.PanicException: Python API call failed
解决步骤
1. 修复依赖库兼容性问题
报错源于cryptography库的Rust绑定异常,是版本不兼容或安装不完整导致的:
- 卸载现有
cryptography:pip uninstall cryptography -y - 安装与
adal兼容的指定版本:pip install cryptography==3.4.8 - 同步
pyjwt版本:pip install pyjwt==2.1.0
2. 修正权限URL错误
原代码中authority_url使用了URL编码的大括号,无法正确替换tenant_id变量,需修改为:
authority_url = f'https://login.microsoftonline.com/{tenant_id}'
3. 调整API调用逻辑
/me接口仅适用于用户上下文(如授权码模式),而client_credentials(客户端凭据)模式无关联用户,需改用支持应用权限的接口,比如/users:
- 将
graph_url修改为:graph_url = 'https://graph.microsoft.com/v1.0/users'
4. 配置Azure AD应用权限
在Azure门户中给应用添加Microsoft Graph的应用权限(如User.Read.All),并完成管理员同意,否则会返回权限不足错误。
修正后的完整代码
import requests import adal # 替换为你的Azure AD应用信息 client_id = 'YOUR_CLIENT_ID' client_secret = 'YOUR_CLIENT_SECRET' tenant_id = 'YOUR_TENANT_ID' resource_url = 'https://graph.microsoft.com' # 使用支持客户端凭据模式的用户列表接口 graph_url = 'https://graph.microsoft.com/v1.0/users' def get_access_token(): # 修正后的权限URL authority_url = f'https://login.microsoftonline.com/{tenant_id}' context = adal.AuthenticationContext(authority_url) token = context.acquire_token_with_client_credentials(resource_url, client_id, client_secret) return token.get('accessToken') def get_user_details(access_token): headers = { 'Authorization': 'Bearer ' + access_token, 'Content-Type': 'application/json', } response = requests.get(graph_url, headers=headers) if response.status_code == 200: user_data = response.json() print("User List:") for user in user_data.get('value', []): print(f"Display Name: {user.get('displayName')}, Email: {user.get('userPrincipalName')}") else: print(f"Failed to get user details. Status code: {response.status_code}") print(response.text) # 执行调用 if __name__ == "__main__": access_token = get_access_token() if access_token: get_user_details(access_token)
内容的提问来源于stack exchange,提问作者Prajwal Khot
相关产品推荐
相关产品推荐

