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
Answer from syntonym on Stack Overflow
🌐
Readthedocs
flask-login.readthedocs.io › en › latest
Flask-Login 0.7.0 documentation
Store the active user’s ID in the Flask Session, and let you easily log them in and out. Let you restrict views to logged-in (or logged-out) users. (login_required)
🌐
Python Programming
pythonprogramming.net › decorator-wrappers-flask-tutorial-login-required
Flask Decorators - Login_Required pages Flask Tutorial
Simple enough, underneath the app.route wrapper, we also add another wrapper, which is the login_required wrapper. Now, in order to even get to the logout function, a user must first attempt to access the URL in the top wrapper, then they also need to satisfy the conditions of the next wrapper, and then they can finally reach the logout() function! Pretty neat! What's more is that we can actually use this sort of dynamic treatment of our users in our templates too! We'll head there next. The next tutorial: Dynamic user-based content Flask Tutorial
🌐
DigitalOcean
digitalocean.com › community › tutorials › how-to-add-authentication-to-your-app-with-flask-login
Add Authentication to Flask Apps with Flask-Login | DigitalOcean
October 22, 2025 - Use the @login_required decorator because it does not make sense to log out a user that is not logged in to begin with. After a user logs out and tries to view the profile page again, they will be presented with an error message: This is because Flask-Login flashes a message when the user is not allowed to access a page.
🌐
Miguel Grinberg
blog.miguelgrinberg.com › post › the-flask-mega-tutorial-part-v-user-logins
The Flask Mega-Tutorial, Part V: User Logins - miguelgrinberg.com
December 3, 2023 - The way Flask-Login protects a view function against anonymous users is with a decorator called @login_required. When you add this decorator to a view function below the @app.route decorator from Flask, the function becomes protected and will not allow access to users that are not authenticated.
🌐
GitHub
gist.github.com › leongjinqwen › a205cbe8185d8c83f9d300cc6c8634f1
Summary on how to use flask-login · GitHub
Optional (Customizing the Login Process) => https://flask-login.readthedocs.io/en/latest/#customizing-the-login-process · if a user try to access route with @login_required decorator without logged in:
Top answer
1 of 7
88

Flask-login doesn't actually have a user backend, it just handles the session machinery to help you login and logout users. You have to tell it (by decorating methods), what represents a user and it is also up to you to figure out how to know if a user is "active" or not (since being "active" can mean different things in different applications).

You should read the documentation and be sure what it does and does not do. Here I am only going to concentrate on wiring it up with the db backend.

To start off with, define a user object; which represents properties for your users. This object can then query databases, or LDAP, or whatever and it is the hook that connects the login mechanism with your database backend.

I will be using the login example script for this purpose.

class User(UserMixin):
    def __init__(self, name, id, active=True):
        self.name = name
        self.id = id
        self.active = active

    def is_active(self):
        # Here you should write whatever the code is
        # that checks the database if your user is active
        return self.active

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True

Once you have the user object created, you need to write a method that loads the user (basically, creates an instance of the User class from above). This method is called with the user id.

@login_manager.user_loader
def load_user(id):
     # 1. Fetch against the database a user by `id` 
     # 2. Create a new object of `User` class and return it.
     u = DBUsers.query.get(id)
    return User(u.name,u.id,u.active)

Once you have these steps, your login method does this:

  1. Checks to see if the username and password match (against your database) - you need to write this code yourself.

  2. If authentication was successful you should pass an instance of the user to login_user()

2 of 7
19

Flask-login will try and load a user BEFORE every request. So yes, your example code below will be called before every request. It is used to check what userid is in the current session and will load the user object for that id.

@login_manager.user_loader
def load_user(userid):
    #print 'this is executed',userid
    return user(userid, 'asdf')        

If you look at the Flask-login source code on github, there is a line under function init_app which goes:

app.before_request(self._load_user)

So before every request, the _load_user function is called. The _load_user functions actually calls another function "reload_user()" based on conditions. And finally, reload_user() function calls your callback function that you wrote (load_user() in your example).

Also, flask-login only provides the mechanism to login/logout a user. It does not care if you are using mysql database.

Find elsewhere
🌐
Readthedocs
flask-user.readthedocs.io › en › v0.5 › authorization.html
Authorization — Documentation - Flask-User - Read the Docs
@roles_required('starving', ['artist', 'programmer']) # Ensures that the user is ('starving' AND (an 'artist' OR a 'programmer')) Note: The nesting level only goes as deep as this example shows. For @login_required only the User model is required
🌐
Readthedocs
flask-login.readthedocs.io › en › 0.6.3
Flask-Login — Flask-Login 0.6.3 documentation
If you have custom requirements for anonymous users (for example, they need to have a permissions field), you can provide a callable (either a class or factory function) that creates anonymous users to the LoginManager with: ... By default, when the user closes their browser the Flask Session is deleted and the user is logged out.
🌐
Python Basics
pythonbasics.org › flask-login
Flask Login Tutorial - Python Tutorial
You can use the Flask-Login module to do access control.
🌐
Reddit
reddit.com › r/flask › flask @login_required how to check if confirmed?
r/flask on Reddit: Flask @login_required how to check if confirmed?
July 27, 2023 -

The code block below only allows users who a logged in to access the profile route.

However, I want to add an additional check to see if the user has been confirmed via email. This is just a boolean column in the database.

What is the best way to add this additional check? I'm looking for a solution that is as simple as using the login_ required decorator

@app.route("/profile")
@login_required
def profile():
    print(current_user)
    return render_template('profile.html', name=current_user.email)

🌐
OneUptime
oneuptime.com › home › blog › how to implement flask-login for authentication
How to Implement Flask-Login for Authentication
February 3, 2026 - # Protected routes using the login_required decorator from flask_login import login_required, current_user @app.route('/dashboard') @login_required def dashboard(): """Dashboard - only accessible to logged in users""" # current_user is automatically ...
🌐
Real Python
realpython.com › using-flask-login-for-user-management-with-flask
Flask by Example (Learning Path) – Real Python
After you implement the main functionality of a web project, it's good to understand how your users interact with your app and where they may run into errors. In this tutorial, you'll enhance your Flask project by creating error pages and logging messages.
🌐
freeCodeCamp
freecodecamp.org › news › how-to-authenticate-users-in-flask
How to Authenticate Users in Flask with Flask-Login
November 1, 2021 - ... class login_form(FlaskForm): email = StringField(validators=[InputRequired(), Email(), Length(1, 64)]) pwd = PasswordField(validators=[InputRequired(), Length(min=8, max=72)]) # Placeholder labels to enable form rendering username = StringField( ...
🌐
The Teclado Blog
blog.teclado.com › protecting-endpoints-in-flask-apps-by-requiring-login
Protecting endpoints in Flask apps by requiring login
October 26, 2022 - For example, if a user requests their "dashboard", we should send them there after their log in—and not to their profile! What we can do for this is, when we send the user to the login endpoint, also include in the URL what part of our application ...
🌐
Readthedocs
flask-login.readthedocs.io › en › 0.3.1
Flask-Login — Flask-Login 0.3.1 documentation
This will set the callback for the needs_refresh method, which among other things is used by fresh_login_required. It takes no arguments, and should return a response to be sent to the user instead of their normal view. ... A proxy for the current user. ... This returns True if the current login is fresh. flask.ext.login.login_user(user, remember=False, force=False, fresh=True)[source]¶
🌐
freeCodeCamp
freecodecamp.org › news › how-to-setup-user-authentication-in-flask
How to Set Up Basic User Authentication in a Flask App
January 3, 2023 - import unittest from base_test import BaseTestCase from flask_login import current_user class TestPublic(BaseTestCase): def test_main_route_requires_login(self): # Ensure main route requres logged in user.
Top answer
1 of 3
35

Have a look at the official flask docs regarding decorators: https://flask.palletsprojects.com/en/1.1.x/patterns/viewdecorators/ or the python docs https://www.python.org/dev/peps/pep-0318/ as well.

Your decorator should look something like:

from functools import wraps
from flask import abort
import jwt

def authorize(f):
    @wraps(f)
    def decorated_function(*args, **kws):
            if not 'Authorization' in request.headers:
               abort(401)

            user = None
            data = request.headers['Authorization'].encode('ascii','ignore')
            token = str.replace(str(data), 'Bearer ','')
            try:
                user = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])['sub']
            except:
                abort(401)

            return f(user, *args, **kws)            
    return decorated_function

... and then in your app.py you may have:

@app.route('/api/game', methods=['POST'])
@authorize
def create(user):
    data = json.loads(request.data)
    ....

In this particular case I have used JWT as token and your token can be different respectively the decoding of the token can be your custom implementation, but the basic mechanisms are pretty much as on the example above.

2 of 3
3

I would place the following decorator function in somewhere common

def validate_api_token(validation_func):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kws):
            api_token = request.headers.get('Authorization')
            is_valid_api_token = validation_func(api_token)
            if is_valid_api_token:
                return f(*args, **kws)

            return 'Invalid API Token', 401

        return decorated_function

    return decorator

For small POC flask apps, if you're ok with storing the tokens in a non-versioned file, the following can work:

# tokens are read from a non-versioned `.tokens` file and loaded into a set
api_tokens = load_api_tokens() 


def simple_api_token_validation(api_token):
    return api_token in api_tokens


@app.route("/v1/my/secret/function", methods=['POST'])
@validate_api_token(simple_api_token_validation)
def my_secret_function():
   body = request.get_json()
   # ...

Another simple option is to query against a database (e.g. redis):

redis_session = Redis(host=REDIS_HOST, password=REDIS_PASSWORD)


def redis_api_token_validation(api_token):
    if not api_token:
        return False

    api_token_hash = hashlib.sha256(api_token.encode()).hexdigest()
    return redis_session.exists(f'api:tokens:{api_token_hash}')


@app.route("/v1/my/secret/function", methods=['POST'])
@validate_api_token(redis_api_token_validation)
def my_secret_function():
   body = request.get_json()
   # ...

Best IMO as @Velin answered is to use jwt to validate the token

🌐
Hackers and Slackers
hackersandslackers.com › flask-login-user-authentication
Handle User Accounts & Authentication in Flask with Flask-Login
April 28, 2024 - from flask import Blueprint, redirect, render_template, flash, request, session, url_for from flask_login import login_required, logout_user, current_user, login_user from .forms import LoginForm, SignupForm from .models import db, User from ...