Coder Social home page Coder Social logo

Comments (5)

mattupstate avatar mattupstate commented on June 14, 2024

Right on. Thanks for catching this!

from flask-principal.

mehaase avatar mehaase commented on June 14, 2024

Thanks for addressing my comment, however I'm a little surprised (and stumped) at the fix. I expected a simple change to the documentation, but instead it looks like you tried to make the order of flask plugins not matter.

I'm still digesting what exactly changed here (and I noticed this issue on a test server, so I haven't had time to look at it on a dev server yet), but Flask-Login 0.2.9 is creating an infinite loop:

[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/share/foo/lib/foo/bootstrap.py", line 69, in load_user
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     identity_changed.send(app, identity=Identity(user.id))
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/blinker/base.py", line 267, in send
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     for receiver in self.receivers_for(sender)]
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_principal.py", line 469, in _on_identity_changed
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     self.set_identity(identity)
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_principal.py", line 418, in set_identity
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     self._set_thread_identity(identity)
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_principal.py", line 463, in _set_thread_identity
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     identity=identity)
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/blinker/base.py", line 267, in send
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     for receiver in self.receivers_for(sender)]
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/share/foo/lib/foo/views/user.py", line 196, in on_identity_loaded
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     user = current_user._get_current_object()
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 297, in _get_current_object
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     return self.__local()
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 46, in <lambda>
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     current_user = LocalProxy(lambda: _get_user())
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 768, in _get_user
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     current_app.login_manager._load_user()
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 348, in _load_user
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     return self.reload_user()
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 312, in reload_user
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     user = self.user_callback(user_id)
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]   File "/usr/share/foo/lib/foo/bootstrap.py", line 69, in load_user
[Mon Feb 10 19:20:15 2014] [error] [client 4.31.164.110]     identity_changed.send(app, identity=Identity(user.id))

You can see that load_user() ends up calling... load_user(). On my test server, this repeats until I get a RuntimeError: maximum recursion depth exceeded.

This is a new test server, so it took me quite a while to figure out what was going on. (I thought I had botched some step of the deployment process.) Eventually I tried using pip to remove Flask-Login 0.2.9 and replace it with 0.2.7 instead. Boom, problem fixed.

I will post back when I have more details, but my gut reaction is that the documentation still doesn't match the reality of what Flask-Login is actually doing.

from flask-principal.

joshfriend avatar joshfriend commented on June 14, 2024

I was having trouble with this for a while as well. Because I don't want to use the session for user login in a REST api, I can't call login_user from Flask-Login because that tries to set a session cookie. Thus, the current_user is unset until after load_user_from_request returns so I can't call principal.set_identity from inside the request loader without triggering the recursive loop. I solved the issue by adding an intermediate signal callback to catch the user_loaded_from_request signal which sets the identity:

@login_manager.request_loader
def load_user_from_request(request):
    user = get_user(request)
    return user

@user_loaded_from_request.connect
def on_user_loaded_from_request(sender, user):
    principal.set_identity(Identity(user.id))

@identity_loaded.connect
def on_identity_loaded(sender, identity):
    identity.user = current_user
    identity.provides.add(UserNeed(current_user.id))
    # Etc...

It would be nice if there was a way to configure Flask-Login to not use the session at all.

from flask-principal.

bodgit avatar bodgit commented on June 14, 2024

Thanks @joshfriend for your example. I've been trying to tie Flask-Login/Flask-Principal together for a REST API yet I couldn't get the on_identity_loaded method to work if I attempt anything with current_user, I realise now this causes some sort of recursive loop. 👍

from flask-principal.

joshfriend avatar joshfriend commented on June 14, 2024

this causes some sort of recursive loop.

Yes. You cannot use current_user inside login_manager.request_loader because the value that the current_user proxy references is not set until a value is returned from the request_loader. Referencing current_user before it is set causes flask-login to try to load the user from the request by calling request_loader and... 💥 💥 💥

from flask-principal.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.