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
相关产品推荐
相关产品推荐

