0
votes

I have simple python flask app with flask-login implemented. I have two functions to load template called first.html and second.html both of them are protected by a @login_required decorator. Below is the code I have written

#!/usr/bin/python

from app import app
from flask import render_template,request,redirect,abort
from flask_login import login_required,url_for,login_user,logout_user,LoginManager
from app.models.models import Users
import md5
from itsdangerous import URLSafeTimedSerializer


loginManager = LoginManager()
loginManager.init_app(app)
loginManager.login_view = 'signin'
loginManager.login_message = 'Please log in'


@loginManager.user_loader
def load_user(name):
     user = Users.query.get(name)
     return user

@loginManager.token_loader
def load_token(token):
     print 'In Token Loader'
     serializer = URLSafeTimedSerializer(app.secret_key)
     data = serializer.loads(token)
     username = data[0]

     user = Users.query.get(name)
     print user
     return user


@app.route('/logout')
def logout():
    print 'executing logout'
    logout_user()
    return render_template('login.html')


@app.route('/login',methods=['GET','POST'])
def signin():
    if request.method == 'GET':
        return render_template('login.html')
    if request.method == 'POST':
        username =  request.form.get('username')
        password = request.form.get('password')

        salted_password = password + app.secret_key
        hashedpassword = md5.new(salted_password).hexdigest()

        user = Users.query.filter(Users.username == username).first()
        if user == None:
            return render_template('login.html')
        storedPass = user.password

        if storedPass == hashedpassword:
             login_user(user, remember=True)

             nex = request.args.get('next')
             return redirect(nex or url_for('first'))
        return render_template('login.html')

@app.route('/first')
@login_required
def first():
    return render_template('first.html')

@app.route('/second')
@login_required
def second():
     return render_template('second.html')

Now I access http://locahost:5000/login and login view is loaded. I entered the valid user and password which is authenticated successfully and gets a redirect to url_for('first')

Since first function is decorated with @login_required I am getting the login page again. As per my understanding from documentation, @token_loader called will be called and it handles the token and loads the first.html but this is not happening and login view is loaded again.

If i remove the @login_required decorator from first function, the the first.html is loaded.

I am missing something in invoking the token validation in my code and I am not sure what it is.

My User data model class looks like below

#!/usr/bin/python

from app import db,app
from itsdangerous import URLSafeTimedSerializer

class Users(db.Document):
    uid = db.StringField()
    username = db.StringField()
    password = db.StringField()

    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return unicode(self.uid)

    def get_auth_token(self):
        serializer = URLSafeTimedSerializer(app.secret_key)
        return serializer.dumps([self.username,self.password])

Thanks

1

1 Answers

0
votes

I changed the user_loader callback to

@loginManager.user_loader
def load_user(userid)
     user = Users.query.filter(Users.uid == userid).first()
     return user

and this solves the issue I am facing and it is generation a cookie called 'REMEMBER_ME' in my browser. But still I am finding a way to called the token_loader callback and when it would be called.