Johannes Pertl
Johannes Pertl

Reputation: 983

How do I authenticate with HTTP Digest?

I'm currently authenticating with basic, following this tutorial:

import secrets

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

http_basic = HTTPBasic()

def authorize_basic(credentials: HTTPBasicCredentials = Depends(http_basic)):
    correct_username = secrets.compare_digest(credentials.username, "test")
    correct_password = secrets.compare_digest(credentials.password, "test")
    if not (correct_username and correct_password):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Basic"},
        )

@app.get("/auth/", dependencies=[Depends(authorize_basic)])
def auth():
    return {"success": "true"}

How do I use HTTPDigest instead?

Upvotes: 4

Views: 2174

Answers (1)

rednafi
rednafi

Reputation: 1731

I know this question was asked quite a while ago but this example from the FastAPI test suite shows how to do it.

You can rewrite the above example as follows:

import base64
import secrets

from fastapi import Depends, FastAPI, HTTPException, Security, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest

http_digest = HTTPDigest()

app = FastAPI()


def authorize_digest(credentials: HTTPAuthorizationCredentials = Security(http_digest)):
    # Credentials returns the token as string.
    incoming_token = credentials.credentials

    # Let's say you want to generate the digest token from username and pass.
    expected_username = "test"
    expected_password = "test"

    # Digest tokens are encoded via base64 encoding algo.
    expected_token = base64.standard_b64encode(
        bytes(f"{expected_username}:{expected_password}", encoding="UTF-8"),
    )

    correct_token = secrets.compare_digest(
        bytes(incoming_token, encoding="UTF-8"),
        expected_token,
    )
    if not correct_token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect digest token",
            headers={"WWW-Authenticate": "Digest"},
        )


@app.get("/auth/", dependencies=[Depends(authorize_digest)])
def auth():
    return {"success": "true"}

You can get the token using your username and password from your shell (assuming you're using a Unix-y system):

python -c 'import base64; h = base64.urlsafe_b64encode(b"test:test"); print(h)'

This assumes that both your username and password are test. It'll print the following:

b'dGVzdDp0ZXN0'

You can use this token and send a request to this API via curl:

curl -X 'GET' 'http://localhost:5000/auth/' \
        -H 'accept: application/json' \
        -H "Authorization: Digest dGVzdDp0ZXN0" \
        -H 'Content-Type: application/json' \

This prints out the success response:

{"success":"true"}

Upvotes: 2

Related Questions