HTTP Basic Auth

For the simplest cases, you can use HTTP Basic Auth.

In HTTP Basic Auth, the application expects a header that contains a username and a password.

If it doesn't receive it, it returns an HTTP 401 "Unauthorized" error.

And returns a header WWW-Authenticate with a value of Basic, and an optional realm parameter.

That tells the browser to show the integrated prompt for a username and password.

Then, when you type that username and password, the browser sends them in the header automatically.

Simple HTTP Basic Auth

  • Import HTTPBAsic and HTTPBasicCredentials.
  • Create a "security scheme" using HTTPBAsic.
  • Use that security with a dependency in your path operation.
  • It returns an object of type HTTPBasicCredentials:
    • It contains the username and password sent.
from fastapi import Depends, FastAPI
from fastapi.security import HTTPBasic, HTTPBasicCredentials

app = FastAPI()

security = HTTPBasic()


@app.get("/users/me")
def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
    return {"username": credentials.username, "password": credentials.password}

When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:

Check the username

Here's a more complete example.

Use a dependency to check if the username and password are correct.

If the credentials are incorrect, return an HTTPException with a status code 401 (the same returned when no credentials are provided) and add the header WWW-Authenticate to make the browser show the login prompt again:

from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.status import HTTP_401_UNAUTHORIZED

app = FastAPI()

security = HTTPBasic()


def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
    if credentials.username != "foo" or credentials.password != "password":
        raise HTTPException(
            status_code=HTTP_401_UNAUTHORIZED,
            detail="Incorrect email or password",
            headers={"WWW-Authenticate": "Basic"},
        )
    return credentials.username


@app.get("/users/me")
def read_current_user(username: str = Depends(get_current_username)):
    return {"username": username}