Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-login not working as expected

Flask-login appears not to "save user in session". On the /login handler, the user is logged in and remembered via login_user(user, remember=True), but upon opening any other page, the user returned is the AnonymousUser, not the logged in user from User class.

Here is the simple user class with accompanying methods for getting the user from another class used for database storage.

class User():
    def __init__(self, user):
        self.user = user

    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    # Flask-Login is technically able to support these.
    # We don't swing that way.
    def is_anonymous(self):
        return False

    @staticmethod
    def get(userid):
        print 'getuser instance'
        return User(find_user_by_username(userid))

    def get_id(self):
        return self.user.username

    def __repr__(self):
        return '<User %r>' % self.user.username

    def get_auth_token(self):
        print 'gettingtoken'
        data = [self.user.id, self.user.username]
        return login_serializer.dumps(data)

The methods for getting the user, and user loader are as follows:

def find_user_by_username(username):
    print 'find by find_user_by_username'
    i = TwitterUser.query.filter_by(username=username).first()
    if i is not None:
        print 'found user'
        return i
    print 'didnt found'
    return None

@login_manager.user_loader
def load_user(userid):
    print "userloader"
    return User.get(userid)

@login_manager.token_loader
def token_load(token):
    print 'readingtoken'
    max_age = app.config["REMEMBER_COOKIE_DURATION"].total_seconds()
    data = login_serializer.loads(token, max_age=max_age)
    print 'data: ', data
    user = User.get(data[1])
    if user:
        return user
    return None

I don't need passwords for authentication, I use OAuth, so I would like to check the user token stored in the user table. I suspect that something is wrong with the token_load() or with the get_auth_token() methods.

Two sample routed I did to explain the behavior are:

@app.route('/login')
def login():
    user = User.get('stackoverflow')
    print "login"
    if user.user is None:
        newUser = TwitterUser('stackoverflow', '[email protected]', 0, 0, 0, 0, 'something', 'something')
        db.session.add(newUser)
        db.session.commit()
        print 'added user'
        return redirect('/login')
    login_user(user, remember=True)
    return str(current_user)

@app.route('/user')
def user():
    return str(current_user)

These debugging return values return, in the first case:

<User u'stackoverflow'>

and in the second case:

<flask_login.AnonymousUser object at 0x02D455F0>

So, basically, is is evident that although the login_user() managed to log in the user and set the current_user as it should be, but when loading some other view, the AnonymousUser is returned as current_user.

One interesting thing, it might be important is that I never see the gettingtoken string, so I can't confirm the token_load function is being called at all.

I have opened another question regarding this, but upon further examination I think the issue is unrelated to the matter described there, thus the reasoning behind this question.

like image 579
wont_compile Avatar asked Aug 07 '14 09:08

wont_compile


1 Answers

I tried your code and it does work for me (with changes) - you must have done something wrong outside what you have shown here. In particular, readingtoken was output as expected, and current_user was the logged in user in user view.

In particular, check that you did install the login manager to the application:

app = Flask(__name__)
app.config['SECRET_KEY'] = '123123123'
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.session_protection = "strong"
login_serializer = URLSafeTimedSerializer(app.secret_key)

and see that the plugin versions are proper; mine are

  • Flask 0.10.1
  • Flask-Login 0.2.11
  • itsdangerous 0.24

Also, you might want to use the TwitterUser with UserMixin instead of wrapping 1 "user" object inside another.

like image 173