Flask集成Auth0疑问:如何在请求头中放置授权令牌?
如何在请求头中携带Auth0授权令牌?
我正在项目中集成Auth0,但不清楚怎么把授权令牌(authorization token)放到请求头里。我已经跟着Auth0官方文档操作了,但还是有困惑,以下是我目前的代码:
auth.py
ENV_FILE = find_dotenv() if ENV_FILE: load_dotenv(ENV_FILE) oauth = OAuth(app) oauth.register( "auth0", client_id=env.get("AUTH0_CLIENT_ID"), client_secret=env.get("AUTH0_CLIENT_SECRET"), client_kwargs={ "scope": "openid profile email", }, server_metadata_url=f'https://{env.get("AUTH0_DOMAIN")}/.well-known/openid-configuration' ) # 登录验证装饰器 def login_required(func): @wraps(func) def decorated_function(*args, **kwargs): if not session.get("user"): return redirect(url_for("login")) return func(*args, **kwargs) return decorated_function require_auth = ResourceProtector() validator = Auth0JWTBearerTokenValidator( "dev-dzlqn0602x1umzhg.us.auth0.com", "https://localhost:5000" ) require_auth.register_token_validator(validator) @app.route("/login") def login(): return oauth.auth0.authorize_redirect( redirect_uri=url_for("callback", _external=True) ) @app.route("/callback", methods=["GET", "POST"]) def callback(): token = oauth.auth0.authorize_access_token() session["user"] = token return redirect("/") @app.route("/public") def public(): """无需访问令牌""" response = ( "这是公开接口!无需认证即可访问。" ) return jsonify(message=response) @app.route("/private") @require_auth(None) def private(): """需要有效访问令牌""" response = ( "这是私有接口!需要认证才能访问。" ) return jsonify(message=response) @app.route("/private-scoped") @require_auth("read:all") def private_scoped(): """需要有效访问令牌及指定权限""" response = ( "这是带权限的私有接口!需要认证且拥有read:all权限才能访问。" ) return jsonify(message=response) @app.route("/logout") def logout(): session.clear() return redirect( "https://" + env.get("AUTH0_DOMAIN") + "/v2/logout?" + urlencode( { "returnTo": url_for("home", _external=True), "client_id": env.get("AUTH0_CLIENT_ID"), }, quote_via=quote_plus, ) )
解决方法
1. 后端内部调用时添加令牌
你的代码已经在callback路由将Auth0返回的令牌存入session["user"],其中包含access_token字段。如果后端需要调用其他受保护的API,直接从session取出令牌并构造请求头:
import requests @app.route("/call-external-protected-api") @login_required def call_external_api(): access_token = session["user"]["access_token"] headers = { "Authorization": f"Bearer {access_token}" } res = requests.get("https://your-target-protected-api", headers=headers) return jsonify(result=res.json())
2. 前端请求私有接口时携带令牌
如果是前端页面调用你的/private这类接口,需要在请求头里添加Authorization: Bearer <access_token>:
以JavaScript的fetch为例:
fetch("/private", { method: "GET", headers: { "Authorization": `Bearer ${localStorage.getItem("auth_access_token")}` } }) .then(res => res.json()) .then(data => console.log(data));
要实现这个,你需要在callback路由把令牌传递给前端,比如渲染模板时注入:
@app.route("/callback", methods=["GET", "POST"]) def callback(): token = oauth.auth0.authorize_access_token() session["user"] = token # 渲染首页时将access_token传给模板 return render_template("home.html", access_token=token["access_token"])
然后在模板里把令牌存入localStorage:
<script> localStorage.setItem("auth_access_token", "{{ access_token }}"); </script>
3. 令牌验证的关键配置修正
你的Auth0JWTBearerTokenValidator第二个参数是API的Audience(受众),必须和Auth0控制台中你创建的API的Audience完全一致,不是你的应用地址。如果你的API Audience是https://my-api.example.com,修正如下:
validator = Auth0JWTBearerTokenValidator( "dev-dzlqn0602x1umzhg.us.auth0.com", "https://my-api.example.com" # 替换为Auth0中设置的API Audience )
内容的提问来源于stack exchange,提问作者Nicolas Pullen
相关产品推荐
相关产品推荐

