Shahryar Saljoughi
Shahryar Saljoughi

Reputation: 3059

Check if Flask-HTTPAuth is authenticated inside view

I'm using Flask-HTTPAuth for authentication. I want to display different data from a view depending on if the request was authenticated or not. Decorating the view with auth.login_required only shows it to authenticated users. How can I test if the request was authenticated with Flask-HTTPAuth?

auth = HTTPBasicAuth()

@app.route("/clothesInfo")
@auth.login_required
def show_info():
    return jsonify(blah blah blah)

Upvotes: 4

Views: 1638

Answers (3)

Jérôme
Jérôme

Reputation: 14674

Things are simpler since April 2020.

Flask-HTTPAuth 4.0.0 added optional argument to login required to do exactly this.

From the docs:

An optional optional argument can be set to True to allow the route to execute also when authentication is not included with the request, in which case auth.current_user() will be set to None. Example:

@app.route('/private')
@auth.login_required(optional=True)
def private_page():
    user = auth.current_user()
    return "Hello {}!".format(user.name if user is not None else 'anonymous')

Upvotes: 1

davidism
davidism

Reputation: 127260

You can decorate a function that returns None with login_required. Calling it while not authenticated will return an error response, calling it while authenticated will return None.

# a dummy callable to execute the login_required logic
login_required_dummy_view = auth.login_required(lambda: None)

def is_authenticated():
    try:
        # default implementation returns a string error
        return login_required_dummy_view() is None
    except HTTPException:
        # in case auth_error_callback raises a real error
        return False

@app.route('/info')
def info():
    if is_authenticated():
        # logged in view

    else:
        # basic view

See also Default login_required rather than adding decorator everywhere.

Upvotes: 3

Miguel Grinberg
Miguel Grinberg

Reputation: 67509

What you want is actually very easy to implement. In your verify_password callback, you will get username and password set to '' when the user does not provide credentials. You can still return True from that function, and that will allow the anonymous user to access the endpoint.

The following example demonstrates this technique:

auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username, password):
    if username == '' or password == '':
        # anonymous user, we still let them in
        g.current_user = None
        return True
    g.current_user = my_verify_function(username, password)
    return g.current_user is not None

@app.route("/clothesInfo")
@auth.login_required
def show_info():
    if g.current_user:
        # prepare data for authenticated users here
        pass
    else:
        # prepare data for anonymous users here
        pass
    return jsonify(data)

Upvotes: 6

Related Questions