flask-dance
flask-dance copied to clipboard
Azure auth - token expired error.
Hi there. I've implemented flask dance on a python website running via AWS Elastic Beanstalk. Initial authentication works fine, however after a period of time the token expires, and I get the below errors (500 server error on the site). I would have expected an expired token would redirect the user to login again?
[Mon Sep 30 01:16:56.209088 2019] [:error] [pid 2778] [remote 172.31.0.71:136] [2019-09-30 01:16:56,207] ERROR in app: Exception on / [GET]
[Mon Sep 30 01:16:56.209131 2019] [:error] [pid 2778] [remote 172.31.0.71:136] Traceback (most recent call last):
[Mon Sep 30 01:16:56.209135 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 2446, in wsgi_app
[Mon Sep 30 01:16:56.209138 2019] [:error] [pid 2778] [remote 172.31.0.71:136] response = self.full_dispatch_request()
[Mon Sep 30 01:16:56.209142 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1951, in full_dispatch_request
[Mon Sep 30 01:16:56.209145 2019] [:error] [pid 2778] [remote 172.31.0.71:136] rv = self.handle_user_exception(e)
[Mon Sep 30 01:16:56.209148 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1820, in handle_user_exception
[Mon Sep 30 01:16:56.209152 2019] [:error] [pid 2778] [remote 172.31.0.71:136] reraise(exc_type, exc_value, tb)
[Mon Sep 30 01:16:56.209155 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/_compat.py", line 39, in reraise
[Mon Sep 30 01:16:56.209165 2019] [:error] [pid 2778] [remote 172.31.0.71:136] raise value
[Mon Sep 30 01:16:56.209168 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1949, in full_dispatch_request
[Mon Sep 30 01:16:56.209171 2019] [:error] [pid 2778] [remote 172.31.0.71:136] rv = self.dispatch_request()
[Mon Sep 30 01:16:56.209174 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask/app.py", line 1935, in dispatch_request
[Mon Sep 30 01:16:56.209177 2019] [:error] [pid 2778] [remote 172.31.0.71:136] return self.view_functions[rule.endpoint](**req.view_args)
[Mon Sep 30 01:16:56.209180 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/current/app/application.py", line 32, in index
[Mon Sep 30 01:16:56.209183 2019] [:error] [pid 2778] [remote 172.31.0.71:136] resp = azure.get("/v1.0/me")
[Mon Sep 30 01:16:56.209186 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/requests/sessions.py", line 546, in get
[Mon Sep 30 01:16:56.209188 2019] [:error] [pid 2778] [remote 172.31.0.71:136] return self.request('GET', url, **kwargs)
[Mon Sep 30 01:16:56.209191 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/flask_dance/consumer/requests.py", line 201, in request
[Mon Sep 30 01:16:56.209194 2019] [:error] [pid 2778] [remote 172.31.0.71:136] **kwargs
[Mon Sep 30 01:16:56.209197 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/requests_oauthlib/oauth2_session.py", line 395, in request
[Mon Sep 30 01:16:56.209200 2019] [:error] [pid 2778] [remote 172.31.0.71:136] http_method=method, body=data, headers=headers)
[Mon Sep 30 01:16:56.209203 2019] [:error] [pid 2778] [remote 172.31.0.71:136] File "/opt/python/run/venv/local/lib/python3.6/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 198, in add_token
[Mon Sep 30 01:16:56.209206 2019] [:error] [pid 2778] [remote 172.31.0.71:136] raise TokenExpiredError()
[Mon Sep 30 01:16:56.209210 2019] [:error] [pid 2778] [remote 172.31.0.71:136] oauthlib.oauth2.rfc6749.errors.TokenExpiredError: (token_expired)
[Mon Sep 30 01:16:56.209232 2019] [:error] [pid 2778] [remote 172.31.0.71:136]
@steven-martins, you're the maintainer for the Azure configuration. Any thoughts on this?
@singingwolfboy I'll try to reproduce this issue in the following days. I'll keep you informed
Hi, just wanted to follow up on this, and advise that I've since added the below code to catch expiry and redirect.
def template():
if not azure.authorized:
return redirect(url_for("azure.login"))
try:
resp = azure.get("/v1.0/me")
assert resp.ok
return render_template('index.html', user_name=resp.json()["displayName"])
except TokenExpiredError as e:
return redirect(url_for("azure.login"))
Just ran into the same issue this weekend where token expiration causes oauthlib.oauth2.rfc6749.errors.TokenExpiredError. Added to @kknd4eva advice above and created a python decorator that allows you to simply place a @login_required right after the @app.route decorator so that you don't have to repeat the exact same logic for each route.
@singingwolfboy @steven-martins I'm would like to help out with a flask-dance-azure quickstart (as it looks like the Azure quickstart got removed after Flask-Dance v1.3.0). I would submit a PR but dont see a repo for https://github.com/singingwolfboy/flask-dance-azure? Maybe even consider @login_required for other providers as well?
from flask import Flask, render_template, redirect, url_for
from flask_dance.contrib.azure import make_azure_blueprint, azure
from functools import wraps
from oauthlib.oauth2.rfc6749.errors import TokenExpiredError
app = Flask(__name__)
app.secret_key = "supersekrit"
blueprint = make_azure_blueprint(
client_id="my-key-here",
client_secret="my-secret-here",
)
app.register_blueprint(blueprint, url_prefix="/login")
# Place @login_required after @app.route to secure endpoint
def login_required(f):
@wraps(f)
def wrap(*args, **kwargs):
#If azure.authorized is False or if users Token is expired --> redirect them to login
if not azure.authorized:
try:
if not azure.authorized:
return redirect(url_for("azure.login"))
resp = azure.get("/v1.0/me")
assert resp.ok
except TokenExpiredError as e:
return redirect(url_for("azure.login"))
return f(*args, **kwargs)
return wrap
@app.route('/')
@login_required
def index():
return render_template('index.html')
@app.route('/myotherroute')
@login_required
def myOtherRoute():
return render_template('myotherroute.html')
Shouldn't be an issue now that you can pass offline_access. See https://github.com/singingwolfboy/flask-dance/pull/428/. @singingwolfboy this issue could be closed.