使用Python OAuth2.0调用SMART FHIR服务器时无法获取授权码
问题概述
调用SMART Health IT公共FHIR服务器API时,通过Python OAuth2.0库生成的授权URL访问后,出现以下错误:https://URL/?error=invalid_request&error_description=Invalid+launch+options%3A+SyntaxError%3A+Unexpected+end+of+JSON+input
已用ngrok托管纯前端应用,通过SMART Launcher传入client id和client secret,但卡在授权码获取步骤,同时不清楚如何程序化获取authorization_response。
相关代码片段:
client = WebApplicationClient(client_id) authorize_endpoint = "https://launch.smarthealthit.org/v/r4/auth/authorize" redirect_uri = "https://URL" authorization_url = client.prepare_request_uri( authorize_endpoint, redirect_uri = redirect_uri ) print('Authorization URL: ', authorization_url) parsed_response = client.parse_request_uri_response(authorization_response) authorization_code = parsed_response["code"]
后续令牌获取参考代码:
data = client.prepare_request_body( code = authorization_code, redirect_uri = redirect_uri, client_id = client_id, client_secret = client_secret ) print('Token data: ', data) token_response = requests.post(token_endpoint, data=data, headers={"Content-Type": "application/x-www-form-urlencoded"}) if token_response.status_code == 200: access_token = token_response.json()["access_token"] print("Access Token:", access_token) else: print("Error obtaining access token:", token_response.text)
错误原因
缺少SMART授权必需参数
SMART OAuth2流程要求授权URL必须包含response_type、scope、launch三个核心参数,你的代码只传递了redirect_uri:launch参数是SMART Launcher启动时生成的临时上下文标识,服务器依赖它验证启动合法性,未传递会导致JSON解析失败(空输入引发语法错误)。response_type必须设为code以启用授权码模式。scope定义了请求的FHIR资源权限,比如launch openid fhirUser patient/*.read。
前后端流程脱节
你的应用是纯前端,但用Python后端生成授权URL,手动访问时无法携带SMART Launcher传给前端的launch参数,导致服务器无法识别启动上下文。
解决方案
1. 补全授权URL参数
修改授权URL生成代码,加入必需参数(注意launch参数需要从SMART Launcher的启动请求中获取,比如前端将该参数传递给Python后端):
# 从SMART Launcher启动请求中获取launch参数 launch_param = "实际拿到的launch值" # 定义请求权限范围 scope = "launch openid fhirUser patient/*.read" authorization_url = client.prepare_request_uri( authorize_endpoint, redirect_uri=redirect_uri, response_type="code", scope=scope, launch=launch_param )
2. 程序化获取authorization_response
authorization_response是用户授权后,服务器重定向到redirect_uri时的完整URL(包含code参数),获取方式分两种场景:
- 纯前端应用:在前端路由中捕获重定向URL,比如用JavaScript读取
window.location.href。 - Python后端回调:如果用Python后端作为回调端点,以Flask为例,在回调路由中获取请求URL:
from flask import request @app.route('/callback') def auth_callback(): # 获取包含code的完整回调URL authorization_response = request.url parsed_response = client.parse_request_uri_response(authorization_response) authorization_code = parsed_response["code"] # 后续执行令牌获取逻辑...
3. 匹配SMART Launcher配置
确保SMART Launcher中填写的Redirect URI与代码中的redirect_uri完全一致,包括https协议、完整域名和路径。
额外建议
纯前端应用更适合使用官方SMART JS客户端库(如fhirclient),它专门适配前端授权流程,能自动处理launch参数传递、重定向捕获等细节,避免前后端流程冲突。
内容的提问来源于stack exchange,提问作者The falling star

