FastAPI集成OneLogin SAML SSO遇Nginx反向代理响应地址错误
解决FastAPI+Nginx反向代理下OneLogin SAML SSO的invalid_response问题
核心报错:
ERROR:routers.auth:Errors occurred: ['invalid_response'] The response was received at https://containerip/ instead of https:myserverurl
问题根源是python3-saml在验证SAML响应时,使用了容器内部IP作为接收地址,与OneLogin发送的外部服务器URL不匹配,导致验证失败。以下是针对性解决方案:
1. 修正prepare_fastapi_request的请求地址解析逻辑
原代码中http_host取的是客户端IP而非反向代理传递的外部主机名,同时存在get_data格式错误,修改后的代码如下:
async def prepare_fastapi_request(request): # 将FastAPI请求转换为python3-saml兼容格式 form_data = await request.form() # 从反向代理Host头获取外部服务器地址 http_host = request.headers.get("host") # 解析端口(若Host中未指定则根据协议默认) if ":" in http_host: server_host, server_port = http_host.split(":", 1) else: server_port = "443" if request.url.scheme == "https" else "80" server_host = http_host rv = { "https": "on" if request.url.scheme == "https" else "off", "http_host": server_host, # 使用外部主机名而非容器IP "server_port": server_port, "script_name": request.url.path, "get_data": dict(request.query_params), # 修正为字典格式,移除多余逗号 "post_data": {}, } if "SAMLResponse" in form_data: rv["post_data"]["SAMLResponse"] = form_data["SAMLResponse"] if "RelayState" in form_data: rv["post_data"]["RelayState"] = form_data["RelayState"] return rv
2. 确认python3-saml的SP配置使用外部服务器URL
确保SAML配置文件中,SP的实体ID和断言消费服务地址设置为你的外部服务器URL,而非容器内部地址:
# 示例SAML配置片段 SAML_CONFIG = { "sp": { "entityId": "https://myserverurl/metadata", "assertionConsumerService": { "url": "https://myserverurl/acs", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" }, "singleLogoutService": { "url": "https://myserverurl/slo", "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" }, # 其他SP配置... }, # IdP配置... }
3. 验证现有Nginx和Uvicorn配置
- Nginx已正确传递代理头:你的配置中
proxy_set_header Host $host;和proxy_set_header X-Forwarded-Proto $scheme;已正确设置,无需额外修改。 - Uvicorn已启用代理头支持:启动命令中的
--proxy-headers和--forwarded-allow-ips "*"参数正确,确保FastAPI能识别反向代理传递的请求信息。
完成以上修改后,python3-saml将使用外部服务器URL验证SAML响应,解决地址不匹配导致的invalid_response错误。
内容的提问来源于stack exchange,提问作者Amogha Varsha
相关产品推荐
相关产品推荐

