9

I have created a blueprint that handles authenticating. This blue print uses Flask-Login. And has the following, as well as more code not shown.

In the blueprint I have the following:

from flask.ext.login import LoginManager
from flask.ext.login import UserMixin
from flask.ext.login import current_user
from flask.ext.login import login_required
from flask.ext.login import login_user
from flask.ext.login import logout_user

auth_print = Blueprint('auth_print', __name__)
login_manager = LoginManager()
login_manager.login_view = '/login'

class User(UserMixin):

  user_store = {}  # Stores the users that are already logged in.

  def __init__(self, user_id):
    self.user_store[user_id] = self  # add the user to the user_store
    self.username = user_id  # the user_id is in fact the username
    self.id = unicode(user_id)

  def sign_out(self):
    logout_user()
    try:
      del self.user_store[self.id]
    except KeyError:
      pass

  @classmethod
  def get(cls, user_id):
    return cls.user_store.get(user_id)

@login_manager.user_loader
def load_user(user_id):
  return User.get(user_id)

def get_current_user():
  return current_user

@login_required
@auth_print.route('/')
def user():
  return "Welcome, and thanks for logging in."

Then I have a small app I would like to add authentication to.

Small App

import the_above_module
app.register_blueprint(the_above_module.auth_print) # register the blueprint

@the_above_module.login_required
@app.route('/profile')
def protected():
    name = the_above_module.get_current_user().username
    return "Thank you for logging in."

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

Now I know the blueprint's @login_required is working because if I open the browser and go to localhost:8000/ I have to sign in.

However if I go to localhost:8000/profile the login_required decorator never gets triggered. I thus get an error because there is no current user.

Why would @login_required work in the blueprint and not in the app, even when im sure to maintain the same name spaces?

syntonym
  • 7,134
  • 2
  • 32
  • 45
steve
  • 2,488
  • 5
  • 26
  • 39

3 Answers3

25

You have to change the order of the decorators. Quoting the Flask documentation:

So how would you use that decorator now? Apply it as innermost decorator to a view function. When applying further decorators, always remember that the route() decorator is the outermost:

@app.route('/secret_page') 
@login_required 
def secret_page():
    pass
syntonym
  • 7,134
  • 2
  • 32
  • 45
2

When we want the user not to access the private page or the page which requires login for that case flask provides decorators.

@app.route("/welcome")
@login_required  # If the user is not logged in then it will redirected to unauthorized_handler
def welcome_page():
     return """<h1> welcome user</h1>"""

@login_manager.unauthorized_handler     # In unauthorized_handler we have a callback URL 
def unauthorized_callback():            # In call back url we can specify where we want to 
       return redirect(url_for('login')) # redirect the user in my case it is login page!

I hope your problem is solved !!!

Felix Schwarz
  • 2,938
  • 4
  • 28
  • 41
sunny
  • 95
  • 6
0
@login_manager.unauthorized_handler
def unauthorized_callback():
    return redirect(url_for('website.index'))