Flask HTTP Basicauth - How does it work?

Werkzeug can decode the Basic Authorization header for you, into the username and password. The rest is up to you to see what you want to do with that information.

The request.authorization attribute returns a Authorization object. For basic authentication headers, only username and password are set.

A project like Flask-Login can help you manage more complex logins with Basic Authorization, and tie that in with a user model you provide. That model can be stored in a database or anything else you so desire.

And you can look at Flask-Security for a more fully integrated security package that uses Flask-Login and other packages to provide Basic Authentication and session based logins.


The Flask-HTTPAuth extension (shameless plug, I'm the author) simplifies the implementation of HTTP Basic Auth. Instead of working with the request.authorization data directly you set up callback functions where you plug the authentication logic.

Regarding your database question, Flask-HTTPAuth makes no assumptions about how your users are stored. You have to provide the logic that retrieves users and validates passwords.


Werkzeug parses the Authorization header into request.authorization, which is an Authorization object.

For security reasons, a browser might only send this header if it first received a 401 error response with a WWW-Authenticate header set. A different client, such as the requests library, will send the header directly.

The simplest demonstration of this is a decorator that checks request.authorization and returns a 401 response if it's not set, or if the credentials were invalid. In practice, you should use an extension such as Flask-Login or Flask-HTTPAuth to manage this.

from functools import wraps
from flask import request

def login_required(f):
    @wraps(f)
    def wrapped_view(**kwargs):
        auth = request.authorization
        if not (auth and check_auth(auth.username, auth.password)):
            return ('Unauthorized', 401, {
                'WWW-Authenticate': 'Basic realm="Login Required"'
            })

        return f(**kwargs)

    return wrapped_view

@app.route('/secret')
@login_required
def secret():
    return f'Logged in as {request.authorization.username}.'
import requests
response = requests.get('http://127.0.0.1:5000/secret', auth=('world', 'hello'))
print(response.text)
# Logged in as world.