Azure应用连接OneDrive身份验证异常:非管理员用户触发MFA要求
问题描述
通过编程方式连接OneDrive并下载文件,当前代码管理员用户可正常运行,但租户内非管理员用户使用时会收到「必须使用MFA」的提示。疑问:该问题是因为管理员身份差异导致,还是注册的应用权限存在问题?(注:租户MFA设置不可修改)
代码示例
import logging import requests import json import msal import requests CLIENT_ID = '' TENANT_ID = '' AUTHORITY_URL = 'https://login.microsoftonline.com/{}'.format(TENANT_ID) RESOURCE_URL = 'https://graph.microsoft.com/' API_VERSION = 'v1.0' USERNAME = '' # Office365 user's account username PASSWORD = '' SCOPES = ['Sites.ReadWrite.All','Files.ReadWrite.All'] # Add other scopes/permissions as needed. # Creating a public client app, Acquire a access token for the user and set the header for API calls cognos_to_onedrive = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY_URL) token = cognos_to_onedrive.acquire_token_by_username_password(USERNAME,PASSWORD,SCOPES) headers = {'Authorization': 'Bearer {}'.format(token['access_token'])} r = requests.get('https://graph.microsoft.com/v1.0/me/drives/{drive_id}/root:/DropFileOut', headers=headers).json() print(r)
问题分析与解决方案
核心原因
这不是应用权限的问题,而是认证方式与租户MFA策略的冲突:
- 你当前使用的是用户名密码流(ROPC),该认证方式本身不支持MFA验证。
- 租户大概率对非管理员用户启用了强制MFA登录策略,而管理员账号被排除在该策略之外(很多组织为避免管理员账号锁死,会单独配置MFA规则或暂时豁免),所以管理员用ROPC流能正常获取令牌,非管理员用户触发MFA要求后,ROPC无法处理就报错。
可行解决方案(因MFA设置不可修改)
1. 切换为授权码流(推荐)
授权码流是微软官方推荐的用户交互型认证方式,天然支持MFA,流程如下:
- 用户通过浏览器跳转至微软登录页,完成MFA验证后授权应用访问资源。
- 应用获取授权码,兑换为访问令牌和刷新令牌,后续可用刷新令牌自动获取新的访问令牌,无需重复登录。
调整后的代码示例:
import msal import requests CLIENT_ID = '' TENANT_ID = '' AUTHORITY_URL = f'https://login.microsoftonline.com/{TENANT_ID}' SCOPES = ['Sites.ReadWrite.All', 'Files.ReadWrite.All'] # 初始化公共客户端应用 app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY_URL) # 生成授权URL auth_url = app.get_authorization_request_url(SCOPES) print(f"请访问以下URL完成授权:{auth_url}") authorization_code = input("请输入授权码:") # 用授权码兑换令牌 result = app.acquire_token_by_authorization_code(authorization_code, SCOPES) if 'access_token' in result: headers = {'Authorization': f'Bearer {result["access_token"]}'} r = requests.get('https://graph.microsoft.com/v1.0/me/drives/{drive_id}/root:/DropFileOut', headers=headers).json() print(r) else: print(f"获取令牌失败:{result.get('error_description')}")
2. 后台服务场景:客户端凭证流(无用户交互)
如果你的应用是后台服务,无法进行用户交互,可改用客户端凭证流:
- 需在Azure AD中为应用配置应用权限(而非当前的委托权限),比如
Files.ReadWrite.All(应用权限)。 - 该方式无需用户参与,应用直接用自身身份获取令牌,访问租户内被授权的资源(注意:不能用
/me端点,需通过用户ID或驱动器ID指定具体资源)。
内容的提问来源于stack exchange,提问作者Abhishek Rai
相关产品推荐
相关产品推荐

