-
-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
@cached_property on blueprint.session.token causing session leak? #430
Comments
That's some impressive detective work! This seems like a real problem. I have two questions:
|
Thanks for looking into it! I spent some time this morning trying to research answers to your questions:
|
I am trying this workaround to force "request-global" instance of OAuth2Session. Using flask.g in OAuth2ConsumerBlueprint seems like a proper fix for this issue. class SaferFlaskDanceOAuth2Session:
def __init__(self, *args, **kwargs):
self._args = args
self._kwargs = kwargs
@property
def _instance(self):
if not hasattr(g, "_oauth2_session"):
g._oauth2_session = OAuth2Session(*self._args, **self._kwargs)
return g._oauth2_session
def __getattr__(self, name):
if name == "token":
return self._instance.blueprint.token
else:
return getattr(self._instance, name)
def __setattr__(self, name, value):
if name in {"_args", "_kwargs"}:
super().__setattr__(name, value)
elif name != "token":
setattr(self._instance, name, value)
def __delattr__(self, name):
if name != "token":
delattr(self._instance, name)
def __del__(self):
if g and hasattr(g, "_oauth2_session"):
del g._oauth2_session |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I noticed a concerning potential race condition today while using flask-dance via the Flask local dev server. Here's the setup:
flask_dance.contrib.github.authorized
in order to check if the session should be pulled from GitHub.I tried to trace the code paths within flask-dance and I think that the use of
@cached_property
on either the blueprint'ssession.token
or on the blueprint'ssession
itself is part of the problem. Even thoughflask_dance.contrib.github
is a LocalProxy tog.flask_dance_github
(which is equivalent togithub_bp.session
) that isn't sufficient for separation between threads --@cached_property
's cache is associated with the blueprint, which is global across all threads/requests.Basically, what I think is happening in my case is:
authorized()
blueprint endpointgithub_bp.session.token
github.authorized
github_bp.session.token
, which is cached by@cached_property
github.get("/user")
to fetch the full session infoauthorized()
blueprint endpoint concludes, and the session is set as expected to the original requestI've done a little testing of my app that is deployed in a test environment using gunicorn (which separates requests into processes). I haven't been able to reproduce the problem there yet, but because it's stochastic, I haven't fully ruled it out yet. Regardless, though, this seems like a concern as login sessions should never leak across threads.
Lastly, I tried a quick patch to take out the use of
@cached_property
forsession
andsession.token
, and it seemed to fix the issue -- I was unable to trigger the bad behavior even when the logs showed the possibility of a race condition.Should we consider removing
@cached_property
or replace it with something that uses a thread-local cache?The text was updated successfully, but these errors were encountered: