flask-dance icon indicating copy to clipboard operation
flask-dance copied to clipboard

Azure auth - token expired error.

Open kknd4eva opened this issue 6 years ago • 5 comments

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] 

kknd4eva avatar Sep 30 '19 01:09 kknd4eva

@steven-martins, you're the maintainer for the Azure configuration. Any thoughts on this?

singingwolfboy avatar Nov 11 '19 20:11 singingwolfboy

@singingwolfboy I'll try to reproduce this issue in the following days. I'll keep you informed

steven-martins avatar Nov 12 '19 07:11 steven-martins

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"))

kknd4eva avatar Jan 09 '20 03:01 kknd4eva

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')

smacktrace avatar Feb 23 '20 23:02 smacktrace

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.

mgd722 avatar Feb 26 '24 23:02 mgd722