Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to make Flask-Login's login_required the default

Tags:

python

flask

People also ask

Does Flask Login use session?

By default, Flask-Login uses sessions for authentication. This means you must set the secret key on your application, otherwise Flask will give you an error message telling you to do so.

Is Flask Login secure?

the login process seems secure. But you didn't check the potential existing user in the signup form, or existing email address. Unless this is managed by the underlying User schema. And you should require a minimal password complexity.


I did this in my instruments project. I use the before_request decorator:

@app.before_request
def check_valid_login():
    login_valid = 'user' in session # or whatever you use to check valid login

    if (request.endpoint and 
        'static' not in request.endpoint and 
        not login_valid and 
        not getattr(app.view_functions[request.endpoint], 'is_public', False) ) :
        return render_template('login.html', next=request.endpoint)

and I then created an is_public() decorator for the few places that would need to be accessible without login:

def public_endpoint(function):
    function.is_public = True
    return function

If you are using blueprints and need to protect an entire blueprint with a login, you can make the entire before_request to require login.

This is what I use for my CMS blueprint:

@cms.before_request
@login_required
def before_request():
    if g.user.role != ROLE_ADMIN:
        abort(401)

If you need only to check if the user is logged in (and not if the user has privileges) you can simply pass the function


This is a follow up ( bit more pythonic but thats debatable ) to @MalphasWats already great answer.

Also includes an important security fix suggested by @nonagon.

Explanation of the vulnerability with 'static' in request.endpoint:

Imagine that there is route which can be user defiened in some way, like a profile link for example.

If the user sets his name lets say Static Joe, then:

"Static Joe" --slugifys--> /usr/profiles/static_joe.

This way making this route public. This is just asking for trouble.


Here is the route guard function which is appened before every request handling:

@app.before_request
def check_route_access():
    if any([request.endpoint.startswith('static/'),
            current_user.is_authenticated,  # From Flask-Login
            getattr(app.view_functions[request.endpoint],'is_public',False)]):
        return  # Access granted
    else:
        return redirect(url_for('users.login_page'))

( Flask-Login is an excellent module and makes session handling a breeze )

And here is the decorator ( @public_route ) which you can use to allow access to special pages that need public access by default. (register page, login page):

def public_route(decorated_function):
    decorated_function.is_public = True
    return decorated_function

I had to secure a REST API and I have solved finally like this:

@app.before_request
@auth.login_required
def login_required_for_all_request():    
    pass  

(Actually I used also the connexion framework so I had to use: @app.app.before_request )


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!