Azure令牌在Directus中验证失败,返回INVALID_CREDENTIALS 401错误
解决Directus中Azure(Microsoft)Bearer令牌无效的401问题
核心问题分析
你遇到的问题根源有两个:
- 你用Python生成令牌的**客户端凭证流(client_credentials)**不符合Directus的认证逻辑,Directus的OpenID认证依赖用户上下文,这种无用户关联的服务端令牌无法通过验证。
- 你的Directus配置可能存在细节错误,导致用户身份令牌无法被正确解析。
解决方案
1. 改用符合Directus要求的用户身份令牌获取方式
Directus的认证需要绑定用户身份,必须通过授权码流获取包含用户信息的令牌,而非服务端到服务端的客户端凭证流。
方式一:通过Directus登录页面获取令牌
直接访问Directus登录页,选择Microsoft登录,登录成功后从浏览器开发者工具的localStorage中复制directus_access_token,用该令牌测试API请求。
方式二:Python模拟授权码流(自动化场景)
需要用户手动完成一次登录获取授权码,后续可用刷新令牌续期,示例代码如下:
import requests # 1. 生成授权URL,引导用户登录并复制授权码 auth_url = ( "https://login.microsoftonline.com/你的租户ID/oauth2/v2.0/authorize?" "client_id=你的ClientID" "&response_type=code" "&redirect_uri=http://localhost:8055/auth/microsoft/callback" # 必须和Azure门户配置的重定向URI一致 "&scope=openid email user.read" "&response_mode=query" ) print("请访问以下URL登录并复制授权码:", auth_url) code = input("输入授权码:") # 2. 用授权码交换用户身份令牌 token_url = "https://login.microsoftonline.com/你的租户ID/oauth2/v2.0/token" data = { "grant_type": "authorization_code", "client_id": "你的ClientID", "client_secret": "你的ClientSecret", "code": code, "redirect_uri": "http://localhost:8055/auth/microsoft/callback", "scope": "openid email user.read" } response = requests.post(token_url, data=data) token_data = response.json() access_token = token_data["access_token"] # 3. 用该令牌访问Directus API api_url = "http://localhost:8055/items/example" headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json" } response = requests.get(api_url, headers=headers) print(response.json())
2. 检查Directus的.env配置细节
确认以下配置项正确:
- AUTH_MICROSOFT_ISSUER_URL:应为
https://login.microsoftonline.com/你的租户ID/v2.0(无需拼接.well-known/openid-configuration,Directus会自动处理) - AUTH_MICROSOFT_SCOPE:必须包含
openid和email(对应你设置的IDENTIFIER_KEY="email"),建议简化为openid email profile - AUTH_MICROSOFT_IDENTIFIER_KEY:如果Azure令牌中未返回
email字段,可改为sub(用户唯一ID) - Azure门户配置:必须添加
http://localhost:8055/auth/microsoft/callback作为应用的重定向URI
3. 验证令牌内容
用Python的pyjwt库解码令牌,检查核心字段是否符合要求:
import jwt token = "你的用户身份令牌" decoded = jwt.decode(token, options={"verify_signature": False}) print(decoded)
需确认:
- 包含
email(或sub,取决于你的IDENTIFIER_KEY设置)字段 iss字段与AUTH_MICROSOFT_ISSUER_URL完全一致exp字段对应的时间在未来(令牌未过期)
内容的提问来源于stack exchange,提问作者Blanch
相关产品推荐
相关产品推荐

