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

Azure App Service上Python Dash应用获取微软认证用户信息及本地认证

问题分析与解决方案

你当前使用客户端凭证流(通过acquire_token_for_client获取Token)调用Microsoft Graph的/me接口,该流属于应用级权限,无具体登录用户上下文,而/me接口要求必须使用委托认证流(关联用户上下文),因此返回BadRequest错误。以下是针对性解决步骤:

一、获取登录用户信息的正确方式

Azure App Service的Microsoft Identity Provider(Easy Auth)已自动处理用户登录,会将用户身份信息注入请求头,无需再通过客户端凭证获取Token。

方式1:直接从请求头读取基础用户信息

Easy Auth会在认证请求中添加X-MS-CLIENT-PRINCIPAL等头信息,可直接解析获取用户数据:

from flask import request
import base64
import json

def get_current_user():
    client_principal = request.headers.get('X-MS-CLIENT-PRINCIPAL')
    if not client_principal:
        return None
    
    # 解码Base64格式的用户主体信息
    decoded_data = base64.b64decode(client_principal).decode('utf-8')
    user_data = json.loads(decoded_data)
    
    # 提取核心用户信息
    return {
        'username': user_data['userDetails'],
        'name': user_data['name'],
        'email': next(claim['value'] for claim in user_data['claims'] if claim['typ'] == 'email')
    }

方式2:用用户的Access Token调用Graph接口

若需更详细的用户信息(如部门、头像),可从请求头获取用户专属的Access Token后调用/me接口:

from flask import request
import requests

def get_full_user_details():
    user_access_token = request.headers.get('X-MS-TOKEN-AAD-ACCESS-TOKEN')
    if not user_access_token:
        return None
    
    headers = {'Authorization': f'Bearer {user_access_token}'}
    response = requests.get('https://graph.microsoft.com/v1.0/me', headers=headers)
    response.raise_for_status()
    return response.json()

二、本地运行时的认证配置

本地运行时无法直接使用Azure App Service的Easy Auth,可通过以下两种方案实现认证:

方案1:基于MSAL Flask实现授权码流

  1. 安装依赖:pip install msal flask
  2. 修改app.py集成认证逻辑:
from flask import Flask, redirect, url_for, session, request
import msal
from dash import Dash, html
import dash_mantine_components as dmc

# Azure AD配置
CLIENT_ID = '<你的客户端ID>'
CLIENT_SECRET = '<你的客户端密钥>'
AUTHORITY = 'https://login.microsoftonline.com/<你的租户ID>'
SCOPE = ["User.Read", "openid", "profile"]  # 使用委托权限,而非.default

# 初始化Flask和Dash应用
server = Flask(__name__)
server.secret_key = 'your-secure-secret-key'  # 生产环境需替换为安全密钥
app = Dash(__name__, server=server, use_pages=True, external_stylesheets=stylesheets)

# 登录路由
@server.route('/login')
def login():
    msal_app = msal.ConfidentialClientApplication(
        CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET
    )
    auth_url = msal_app.get_authorization_request_url(
        SCOPE, redirect_uri=url_for('authorized', _external=True)
    )
    return redirect(auth_url)

# 授权回调路由
@server.route('/authorized')
def authorized():
    code = request.args.get('code')
    msal_app = msal.ConfidentialClientApplication(
        CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET
    )
    token_result = msal_app.acquire_token_by_authorization_code(
        code, scopes=SCOPE, redirect_uri=url_for('authorized', _external=True)
    )
    
    if 'access_token' in token_result:
        session['access_token'] = token_result['access_token']
        session['user_info'] = token_result.get('id_token_claims', {})
        return redirect('/')
    return f"登录失败: {token_result.get('error_description')}"

# 登出路由
@server.route('/logout')
def logout():
    session.clear()
    # 重定向到Azure AD登出页,完成后返回应用首页
    logout_url = f"{AUTHORITY}/oauth2/v2.0/logout?post_logout_redirect_uri={url_for('index', _external=True)}"
    return redirect(logout_url)

# 更新Dash布局,添加登录/登出入口
app.layout = dmc.MantineProvider(
    html.Div([
        # 登录/登出导航栏
        html.Div([
            html.A('登录', href='/login') if 'user_info' not in session else html.A('登出', href='/logout'),
            html.Span(f"欢迎, {session.get('user_info', {}).get('name', '')}") if 'user_info' in session else ''
        ], style={'padding': '10px', 'textAlign': 'right'}),
        # 原有布局内容
        dash.page_container
    ])
)

if __name__ == '__main__':
    app.run_server(debug=True, port=8000)

方案2:使用Azure App Service本地调试工具

通过Visual Studio Code的Azure扩展或az webapp up命令启动本地调试,工具会模拟Easy Auth的行为,本地运行时也能获取与部署环境一致的请求头信息。

三、添加登录/登出选项

部署到Azure App Service后,可直接使用Easy Auth提供的内置端点:

  • 登录:访问/.auth/login/aad,登录后自动重定向回应用首页
  • 登出:访问/.auth/logout,登出后可在Azure门户的认证设置中配置重定向页面

在Dash布局中添加对应链接即可:

html.Div([
    html.A('登录', href='/.auth/login/aad', style={'marginRight': '10px'}),
    html.A('登出', href='/.auth/logout')
])

关键注意事项

  1. 确保Azure AD应用注册已配置委托权限(如User.Read),而非应用权限
  2. 本地运行时,需在Azure AD应用注册的「重定向URI」中添加本地地址(如http://localhost:8000/authorized)
  3. 生产环境不要硬编码客户端密钥,应通过Azure App Service的「应用设置」存储敏感信息

内容的提问来源于stack exchange,提问作者Jason Susanto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:47:07