Skip to content Skip to sidebar Skip to footer

Flask-login User Is Set To Anonymous After Login

im new to flask and flask-login and ive been struggling with this for days. Im trying to log a user in like this: from creds import auth_username, auth_password, pgsql_dbuser, pgsq

Solution 1:

Another reason you might not be able to log a user in or current_user is Anonymous after going through your login form: The active=false flag is set on the user in the db. This behavior is confirmed in the docs:

flask_login.login_user(user, remember=False, duration=None, force=False, fresh=True)[source] Logs a user in. You should pass the actual user object to this. If the user’s is_active property is False, they will not be logged in unless force is True.

This will return True if the log in attempt succeeds, and False if it fails (i.e. because the user is inactive).

So, when you call login_user, you can do this: login_user(user, remember=form.remember_me.data, force=True), if you want to allow inactive users to log in.


Solution 2:

So.. I managed to get it to work, but not using the user_loader callback. For whatever reason, my user loader exhibits the same behaviour as this: Flask-login with static user always yielding 401- Unauthorized

Anyway, I used a request_loader callback instead based on this example: http://gouthamanbalaraman.com/blog/minimal-flask-login-example.html

so for a user logging in, which starts here:

if bcrypt.check_password_hash(password_hash, candidate_password):
    user_object = User(user, password_hash)
    result = login_user(user_object) # <- here for successful login
    token = user_object.get_auth_token(user, password_hash) 
    return redirect(url_for('loggedin', token=token))

I create a user object which has the user's id and their password hash. then i log the user in. then i create a time-serialized token of the user id and password hash using itsdangerous. the get_auth_token function is part of the User class. it looks like this:

class User():

    def __init__(self, user, password_hash):
        self.user = user
        self.password = password_hash
        .
        .
        .
    def get_auth_token(self, user, password):
        data = [str(self.user), self.password]
        return serializer.dumps(data, salt=serializer_secret)

you need to create a serializer at the beginning of your code somewhere:

serializer = URLSafeTimedSerializer(serializer_secret)

So after the token is created, pass it to the loggedin view as a URL query parameter. When you try to load a login_required page, like my loggedin page, which is where login_user redirects me to after a successful login, the request_loader callback is executed. it looks like this:

@login_manager.request_loader
def load_user_from_request(request):
    if request.args.get('token'):
        token = request.args.get('token')
        max_age = 1
        try:
            data = serializer.loads(token, salt=serializer_secret, max_age=max_age)
            username = data[0]
            password_hash = data[1]
            found_user = finduserindbbyuuid(username)
            found_password = checkuserpasswordindbbyuuid(username)
            if found_user and found_password == password_hash:
                user_object = User(found_user, password_hash)
                if (user_object.password == password_hash):
                    return user_object
                else:
                    return None
            else:
                return None

        except BadSignature, e:
            pass
    else:
        return None

This is the point where my user_loader was failing. I was logging in successfully, but the user_loader was always returning None and so my user would be deemed as anonymous.

So with the request loader, it checks that the request URL contains a 'token' argument in the query string. if so, it takes its value and using itsdangerous, deserializes the data. you can make the token expire with timed serializers, but there are also non timed ones. after the token is deserialized, take the user and password hash and check in the database if they exist, in exactly the same way that the user_loader was supposed to work.. i imagine? my user_loader didnt work so i was most probably doing it wrong.

anyway if a user and password match in the db, then return the user object and bam, login works.

Im not sure if im doing it the right way, cos pretty much flying by the seat of my pants. i saw examples where people used the token_loader, rather than the request_loader callback function, to load the token, but i couldnt figure out how to set & get the auth token to & from the client. maybe ill figure it out... one day...

if you have the same problem, maybe this might help? or just let me know what you think

cheers


Solution 3:

I found this page when searching for help with Flask-Login + Flask-Dance. I was seeing current_user as AnonymousUserMixin in a handler with the @login_required decorator. In my case making sure @app.route is on the line above @login_required fixed the problem. The correct order is in the docs: https://flask-login.readthedocs.io/en/latest/#flask_login.login_required.


Post a Comment for "Flask-login User Is Set To Anonymous After Login"