Skip to content

auth

auth

Authentication utilities — JWT tokens, password hashing, cookie helpers, and auth middleware.

Follows the shared secrets-loading pattern from config.py. JWT secret is loaded from a .jwt_secret file in the project root, auto-generated on first use.

hash_password

hash_password(password: str) -> str

Hash a password with bcrypt and return the hash string.

Truncates the password to 72 bytes (bcrypt's maximum) before hashing. Each call generates a fresh salt.

Parameters:

Name Type Description Default
password str

The plaintext password to hash.

required

Returns:

Type Description
str

A bcrypt hash string prefixed with $2b$.

verify_password

verify_password(plain: str, hashed: str) -> bool

Verify a plain-text password against a bcrypt hash.

Truncates the plaintext to 72 bytes to match the hash_password truncation behavior.

Parameters:

Name Type Description Default
plain str

The plaintext password to verify.

required
hashed str

The bcrypt hash string to compare against.

required

Returns:

Type Description
bool

True if the password matches the hash, False otherwise.

create_access_token

create_access_token(
    user_id: str,
    secret: str,
    expires_delta: timedelta | None = None,
) -> str

Create a signed JWT access token (HS256).

Parameters:

Name Type Description Default
user_id str

The user's unique identifier (sub claim).

required
secret str

The HMAC signing secret.

required
expires_delta timedelta | None

Token TTL. Defaults to 15 minutes.

None

Returns:

Type Description
str

Encoded JWT string with claims: sub, exp, iat, type="access".

decode_access_token

decode_access_token(token: str, secret: str) -> dict

Decode and validate a JWT access token.

Parameters:

Name Type Description Default
token str

The encoded JWT string.

required
secret str

The HMAC signing secret.

required

Returns:

Type Description
dict

Decoded claims dict on success.

Raises:

Type Description
ValueError

If the token is expired, tampered, or invalid.

require_admin async

require_admin(request: Request) -> dict

Validate current user is an admin (FastAPI dependency).

Checks authentication via get_current_user, then queries the database for the user's role. Returns 403 Forbidden if the user is not an admin.

Parameters:

Name Type Description Default
request Request

The FastAPI Request object.

required

Returns:

Type Description
dict

The user claims dict if admin.

Raises:

Type Description
HTTPException

403 if user is not an admin, 401 if not authenticated.

set_refresh_cookie(
    response: Response, refresh_token: str
) -> None

Set the refresh_token httpOnly cookie on the response.

The cookie: - Is httpOnly (not accessible to JavaScript) - Has path=/auth/refresh (only sent on refresh requests) - Has max_age=604800 (7 days in seconds) - Uses configurable SameSite, Secure, and Domain

clear_refresh_cookie(response: Response) -> None

Clear the refresh_token cookie by setting max_age=0.

Sets the cookie value to empty string with max_age=0 on the /auth/refresh path. Uses the same SameSite, Secure, and Domain configuration as the set operation to ensure the browser correctly removes the cookie cross-origin.

Parameters:

Name Type Description Default
response Response

FastAPI Response object to attach the cookie to.

required

get_current_user async

get_current_user(
    request: Request,
    credentials: Optional[
        HTTPAuthorizationCredentials
    ] = Depends(bearer_scheme),
) -> dict

FastAPI dependency that extracts and validates the current user from the request.

Checks the Authorization header first (Bearer token), then falls back to the "access_token" cookie.

Returns:

Type Description
dict

The decoded JWT claims dict on success.

Raises:

Type Description
HTTPException(401)

If no valid token is found.