You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MSAL与Streamlit获取Access Token失败,报错AADSTS9002327求助

问题排查与解决方案

错误根源分析

AADSTS9002327错误的核心原因是Azure Entra ID应用注册类型与你的应用架构不匹配:你注册了「单页应用(SPA)」类型,但Streamlit是服务器端应用,需要用「Web应用/API」类型;同时你误用了MSAL的PublicClientApplication(面向桌面/移动等公共客户端),服务器端应用需使用ConfidentialClientApplication。

步骤1:修正Azure Entra ID应用注册

  1. 进入Azure门户 -> 你的Entra ID应用注册
  2. 删除原SPA类型的重定向URI,添加Web类型的重定向URI:
    • http://localhost:8503
    • http://localhost:8501
  3. 切换到「证书和密码」页面,创建一个客户端密码(记录下密码值,只显示一次)
  4. 确保已添加所需的API权限(比如Microsoft Graph的User.Read权限,若需要全局访问需完成管理员同意)

步骤2:修改Streamlit代码

替换原代码为以下版本,核心变化是改用ConfidentialClientApplication,并实现服务器端标准的授权码流:

import streamlit as st
from msal import ConfidentialClientApplication
import requests

# 配置参数
CLIENT_ID = "<你的客户端ID>"
TENANT_ID = "<你的租户ID>"
CLIENT_SECRET = "<你创建的客户端密码>"
AUTHORITY = f"https://login.microsoftonline.com/{TENANT_ID}"
REDIRECT_URI = "http://localhost:8503"  # 可替换为localhost:8501
SCOPES = ["https://graph.microsoft.com/User.Read"]  # 明确Microsoft Graph权限的完整路径

# 初始化MSAL保密客户端应用
app = ConfidentialClientApplication(
    CLIENT_ID,
    authority=AUTHORITY,
    client_credential=CLIENT_SECRET
)

def generate_auth_url():
    # 生成Azure认证跳转URL
    return app.get_authorization_request_url(
        SCOPES,
        redirect_uri=REDIRECT_URI,
        prompt="select_account"
    )

def exchange_code_for_token(auth_code):
    # 用授权码兑换access_token
    return app.acquire_token_by_authorization_code(
        auth_code,
        scopes=SCOPES,
        redirect_uri=REDIRECT_URI
    )

# Streamlit UI逻辑
st.title("Azure Entra ID 登录验证")

# 处理认证回调:检查URL中的授权码参数
query_params = st.experimental_get_query_params()
if "code" in query_params:
    auth_code = query_params["code"][0]
    token_result = exchange_code_for_token(auth_code)
    
    if "access_token" in token_result:
        st.session_state.token = token_result["access_token"]
        # 清除URL中的code参数,避免重复处理
        st.experimental_set_query_params()
        st.success("登录成功!")
        
        # 可选:调用Microsoft Graph API获取用户信息验证token有效性
        headers = {"Authorization": f"Bearer {token_result['access_token']}"}
        user_info = requests.get("https://graph.microsoft.com/v1.0/me", headers=headers).json()
        st.write(f"欢迎,{user_info['displayName']}")
    else:
        st.error(f"Token获取失败: {token_result.get('error_description', '未知错误')}")

# 显示登录入口或已登录状态
if "token" not in st.session_state:
    auth_url = generate_auth_url()
    st.markdown(f"[点击登录Azure Entra ID]({auth_url})", unsafe_allow_html=True)
else:
    st.write("Access Token:", st.session_state.token)

st.write(st.session_state)

关键修改点说明

  • 改用ConfidentialClientApplication:服务器端应用属于保密客户端,需要客户端密码完成身份验证,规避SPA的跨域限制
  • 使用授权码流:符合Web应用的标准OAuth2流程,是服务器端应用获取token的正确方式
  • 明确Scopes格式:Microsoft Graph的权限需要完整URL路径(如https://graph.microsoft.com/User.Read),而非仅User.Read
  • 处理回调参数:通过st.experimental_get_query_params()捕获授权码,完成token兑换后清除URL参数避免重复触发

额外注意事项

  • 确保Streamlit运行在你配置的重定向URI端口(8503或8501)
  • 客户端密码不要硬编码在代码中,生产环境建议用环境变量管理
  • 若需访问其他业务API,需在Azure应用注册中添加对应权限并完成同意操作

内容的提问来源于stack exchange,提问作者Tony wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 04:35:29