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

FastAPI中如何获取重定向URL哈希标记#后的参数?

问题

使用FastAPI对接Azure AD的Authorization Grant Flow实现登录时,遇到回调URL参数通过#(URL Fragment)传递的问题,导致后端回调接口无法获取code和state参数。

登录跳转代码

@app.get("/auth/oauth/{provider_id}")
async def oauth_login(provider_id: str, request: Request):
    if config.code.oauth_callback is None:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="No oauth_callback defined",
        )

    provider = get_oauth_provider(provider_id)
    if not provider:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Provider {provider_id} not found",
        )

    random = random_secret(32)

    params = urllib.parse.urlencode(
        {
            "client_id": provider.client_id,
            "redirect_uri": f"{get_user_facing_url(request.url)}/callback",
            "state": random,
            **provider.authorize_params,
        }
    )
    response = RedirectResponse(
        url=f"{provider.authorize_url}?{params}")
    samesite = os.environ.get("CHAINLIT_COOKIE_SAMESITE", "lax")  # type: Any
    secure = samesite.lower() == "none"
    response.set_cookie(
        "oauth_state",
        random,
        httponly=True,
        samesite=samesite,
        secure=secure,
        max_age=3 * 60,
    )
    return response

回调接口代码

@app.get("/auth/oauth/{provider_id}/callback")
async def oauth_callback(
    provider_id: str,
    request: Request,
    error: Optional[str] = None,
    code: Optional[str] = None,
    state: Optional[str] = None,
):
    if config.code.oauth_callback is None:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="No oauth_callback defined",
        )
    provider = get_oauth_provider(provider_id)
    if not provider:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Provider {provider_id} not found",
        )

    if not code or not state:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Missing code or state",
        )
    response.delete_cookie("oauth_state")
    return response

Azure AD回调时会将code和state放在URL的Fragment部分(示例:http://localhost/callback#code=xxxxxx&state=yyyyyy),而这部分内容不会被浏览器发送到后端,导致FastAPI接口无法直接获取参数。

解决方案

1. 修正Azure AD授权流程配置(优先推荐)

Azure AD返回Fragment参数通常是因为误配置为Implicit Flow,而非你需要的Authorization Grant Flow(Authorization Code Flow)。需调整Azure AD应用注册设置:

  • 进入Azure AD应用注册的「身份验证」页面
  • 在「平台配置」中找到对应的Web平台,取消勾选「允许隐式流」(若仅需ID令牌可单独勾选)
  • 确认授权流程设置为Authorization Code Flow
  • 确保登录跳转代码中的provider.authorize_params包含response_type=code(这是Authorization Code Flow的核心参数,Implicit Flow使用response_type=token或id_token)

调整后,Azure AD会通过QueryString(?)传递code参数,现有FastAPI回调接口即可正常获取参数。

2. 前端中转处理(无法修改Azure AD配置时使用)

由于URL Fragment不会发送到后端,需通过前端JavaScript提取参数后再转发给后端:

  • 创建静态HTML中转页(如callback.html),用于提取Fragment参数并转为QueryString重定向
  • 修改登录跳转代码中的redirect_uri指向该中转页

示例中转页面代码(callback.html)

<!DOCTYPE html>
<html>
<head>
    <script>
        // 提取Fragment中的参数
        const fragmentParams = new URLSearchParams(window.location.hash.slice(1));
        // 构造包含QueryString的回调URL
        const redirectUrl = `/auth/oauth/azure/callback?${fragmentParams.toString()}`;
        // 重定向到FastAPI回调接口
        window.location.replace(redirectUrl);
    </script>
</head>
<body>
    正在处理登录...
</body>
</html>

修改登录跳转中的redirect_uri

将原代码中的:

"redirect_uri": f"{get_user_facing_url(request.url)}/callback",

替换为:

"redirect_uri": f"{get_user_facing_url(request.url)}/callback.html",

前端会先接收带Fragment的回调,提取参数后转为QueryString再请求FastAPI接口,后端即可正常获取code和state。

内容的提问来源于stack exchange,提问作者Shabir jan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:17:03