fastapi/security/http.py PYTHON 418 lines View on github.com → Search inside
1import binascii2from base64 import b64decode3from typing import Annotated45from annotated_doc import Doc6from fastapi.exceptions import HTTPException7from fastapi.openapi.models import HTTPBase as HTTPBaseModel8from fastapi.openapi.models import HTTPBearer as HTTPBearerModel9from fastapi.security.base import SecurityBase10from fastapi.security.utils import get_authorization_scheme_param11from pydantic import BaseModel12from starlette.requests import Request13from starlette.status import HTTP_401_UNAUTHORIZED141516class HTTPBasicCredentials(BaseModel):17    """18    The HTTP Basic credentials given as the result of using `HTTPBasic` in a19    dependency.2021    Read more about it in the22    [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/).23    """2425    username: Annotated[str, Doc("The HTTP Basic username.")]26    password: Annotated[str, Doc("The HTTP Basic password.")]272829class HTTPAuthorizationCredentials(BaseModel):30    """31    The HTTP authorization credentials in the result of using `HTTPBearer` or32    `HTTPDigest` in a dependency.3334    The HTTP authorization header value is split by the first space.3536    The first part is the `scheme`, the second part is the `credentials`.3738    For example, in an HTTP Bearer token scheme, the client will send a header39    like:4041    ```42    Authorization: Bearer deadbeef1234643    ```4445    In this case:4647    * `scheme` will have the value `"Bearer"`48    * `credentials` will have the value `"deadbeef12346"`49    """5051    scheme: Annotated[52        str,53        Doc(54            """55            The HTTP authorization scheme extracted from the header value.56            """57        ),58    ]59    credentials: Annotated[60        str,61        Doc(62            """63            The HTTP authorization credentials extracted from the header value.64            """65        ),66    ]676869class HTTPBase(SecurityBase):70    model: HTTPBaseModel7172    def __init__(73        self,74        *,75        scheme: str,76        scheme_name: str | None = None,77        description: str | None = None,78        auto_error: bool = True,79    ):80        self.model = HTTPBaseModel(scheme=scheme, description=description)81        self.scheme_name = scheme_name or self.__class__.__name__82        self.auto_error = auto_error8384    def make_authenticate_headers(self) -> dict[str, str]:85        return {"WWW-Authenticate": f"{self.model.scheme.title()}"}8687    def make_not_authenticated_error(self) -> HTTPException:88        return HTTPException(89            status_code=HTTP_401_UNAUTHORIZED,90            detail="Not authenticated",91            headers=self.make_authenticate_headers(),92        )9394    async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None:95        authorization = request.headers.get("Authorization")96        scheme, credentials = get_authorization_scheme_param(authorization)97        if not (authorization and scheme and credentials):98            if self.auto_error:99                raise self.make_not_authenticated_error()100            else:101                return None102        return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials)103104105class HTTPBasic(HTTPBase):106    """107    HTTP Basic authentication.108109    Ref: https://datatracker.ietf.org/doc/html/rfc7617110111    ## Usage112113    Create an instance object and use that object as the dependency in `Depends()`.114115    The dependency result will be an `HTTPBasicCredentials` object containing the116    `username` and the `password`.117118    Read more about it in the119    [FastAPI docs for HTTP Basic Auth](https://fastapi.tiangolo.com/advanced/security/http-basic-auth/).120121    ## Example122123    ```python124    from typing import Annotated125126    from fastapi import Depends, FastAPI127    from fastapi.security import HTTPBasic, HTTPBasicCredentials128129    app = FastAPI()130131    security = HTTPBasic()132133134    @app.get("/users/me")135    def read_current_user(credentials: Annotated[HTTPBasicCredentials, Depends(security)]):136        return {"username": credentials.username, "password": credentials.password}137    ```138    """139140    def __init__(141        self,142        *,143        scheme_name: Annotated[144            str | None,145            Doc(146                """147                Security scheme name.148149                It will be included in the generated OpenAPI (e.g. visible at `/docs`).150                """151            ),152        ] = None,153        realm: Annotated[154            str | None,155            Doc(156                """157                HTTP Basic authentication realm.158                """159            ),160        ] = None,161        description: Annotated[162            str | None,163            Doc(164                """165                Security scheme description.166167                It will be included in the generated OpenAPI (e.g. visible at `/docs`).168                """169            ),170        ] = None,171        auto_error: Annotated[172            bool,173            Doc(174                """175                By default, if the HTTP Basic authentication is not provided (a176                header), `HTTPBasic` will automatically cancel the request and send the177                client an error.178179                If `auto_error` is set to `False`, when the HTTP Basic authentication180                is not available, instead of erroring out, the dependency result will181                be `None`.182183                This is useful when you want to have optional authentication.184185                It is also useful when you want to have authentication that can be186                provided in one of multiple optional ways (for example, in HTTP Basic187                authentication or in an HTTP Bearer token).188                """189            ),190        ] = True,191    ):192        self.model = HTTPBaseModel(scheme="basic", description=description)193        self.scheme_name = scheme_name or self.__class__.__name__194        self.realm = realm195        self.auto_error = auto_error196197    def make_authenticate_headers(self) -> dict[str, str]:198        if self.realm:199            return {"WWW-Authenticate": f'Basic realm="{self.realm}"'}200        return {"WWW-Authenticate": "Basic"}201202    async def __call__(  # type: ignore203        self, request: Request204    ) -> HTTPBasicCredentials | None:205        authorization = request.headers.get("Authorization")206        scheme, param = get_authorization_scheme_param(authorization)207        if not authorization or scheme.lower() != "basic":208            if self.auto_error:209                raise self.make_not_authenticated_error()210            else:211                return None212        try:213            data = b64decode(param).decode("ascii")214        except (ValueError, UnicodeDecodeError, binascii.Error) as e:215            raise self.make_not_authenticated_error() from e216        username, separator, password = data.partition(":")217        if not separator:218            raise self.make_not_authenticated_error()219        return HTTPBasicCredentials(username=username, password=password)220221222class HTTPBearer(HTTPBase):223    """224    HTTP Bearer token authentication.225226    ## Usage227228    Create an instance object and use that object as the dependency in `Depends()`.229230    The dependency result will be an `HTTPAuthorizationCredentials` object containing231    the `scheme` and the `credentials`.232233    ## Example234235    ```python236    from typing import Annotated237238    from fastapi import Depends, FastAPI239    from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer240241    app = FastAPI()242243    security = HTTPBearer()244245246    @app.get("/users/me")247    def read_current_user(248        credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]249    ):250        return {"scheme": credentials.scheme, "credentials": credentials.credentials}251    ```252    """253254    def __init__(255        self,256        *,257        bearerFormat: Annotated[str | None, Doc("Bearer token format.")] = None,258        scheme_name: Annotated[259            str | None,260            Doc(261                """262                Security scheme name.263264                It will be included in the generated OpenAPI (e.g. visible at `/docs`).265                """266            ),267        ] = None,268        description: Annotated[269            str | None,270            Doc(271                """272                Security scheme description.273274                It will be included in the generated OpenAPI (e.g. visible at `/docs`).275                """276            ),277        ] = None,278        auto_error: Annotated[279            bool,280            Doc(281                """282                By default, if the HTTP Bearer token is not provided (in an283                `Authorization` header), `HTTPBearer` will automatically cancel the284                request and send the client an error.285286                If `auto_error` is set to `False`, when the HTTP Bearer token287                is not available, instead of erroring out, the dependency result will288                be `None`.289290                This is useful when you want to have optional authentication.291292                It is also useful when you want to have authentication that can be293                provided in one of multiple optional ways (for example, in an HTTP294                Bearer token or in a cookie).295                """296            ),297        ] = True,298    ):299        self.model = HTTPBearerModel(bearerFormat=bearerFormat, description=description)300        self.scheme_name = scheme_name or self.__class__.__name__301        self.auto_error = auto_error302303    async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None:304        authorization = request.headers.get("Authorization")305        scheme, credentials = get_authorization_scheme_param(authorization)306        if not (authorization and scheme and credentials):307            if self.auto_error:308                raise self.make_not_authenticated_error()309            else:310                return None311        if scheme.lower() != "bearer":312            if self.auto_error:313                raise self.make_not_authenticated_error()314            else:315                return None316        return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials)317318319class HTTPDigest(HTTPBase):320    """321    HTTP Digest authentication.322323    **Warning**: this is only a stub to connect the components with OpenAPI in FastAPI,324    but it doesn't implement the full Digest scheme, you would need to subclass it325    and implement it in your code.326327    Ref: https://datatracker.ietf.org/doc/html/rfc7616328329    ## Usage330331    Create an instance object and use that object as the dependency in `Depends()`.332333    The dependency result will be an `HTTPAuthorizationCredentials` object containing334    the `scheme` and the `credentials`.335336    ## Example337338    ```python339    from typing import Annotated340341    from fastapi import Depends, FastAPI342    from fastapi.security import HTTPAuthorizationCredentials, HTTPDigest343344    app = FastAPI()345346    security = HTTPDigest()347348349    @app.get("/users/me")350    def read_current_user(351        credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)]352    ):353        return {"scheme": credentials.scheme, "credentials": credentials.credentials}354    ```355    """356357    def __init__(358        self,359        *,360        scheme_name: Annotated[361            str | None,362            Doc(363                """364                Security scheme name.365366                It will be included in the generated OpenAPI (e.g. visible at `/docs`).367                """368            ),369        ] = None,370        description: Annotated[371            str | None,372            Doc(373                """374                Security scheme description.375376                It will be included in the generated OpenAPI (e.g. visible at `/docs`).377                """378            ),379        ] = None,380        auto_error: Annotated[381            bool,382            Doc(383                """384                By default, if the HTTP Digest is not provided, `HTTPDigest` will385                automatically cancel the request and send the client an error.386387                If `auto_error` is set to `False`, when the HTTP Digest is not388                available, instead of erroring out, the dependency result will389                be `None`.390391                This is useful when you want to have optional authentication.392393                It is also useful when you want to have authentication that can be394                provided in one of multiple optional ways (for example, in HTTP395                Digest or in a cookie).396                """397            ),398        ] = True,399    ):400        self.model = HTTPBaseModel(scheme="digest", description=description)401        self.scheme_name = scheme_name or self.__class__.__name__402        self.auto_error = auto_error403404    async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None:405        authorization = request.headers.get("Authorization")406        scheme, credentials = get_authorization_scheme_param(authorization)407        if not (authorization and scheme and credentials):408            if self.auto_error:409                raise self.make_not_authenticated_error()410            else:411                return None412        if scheme.lower() != "digest":413            if self.auto_error:414                raise self.make_not_authenticated_error()415            else:416                return None417        return HTTPAuthorizationCredentials(scheme=scheme, credentials=credentials)

Code quality findings 3

Ensure functions have docstrings for documentation
info maintainability missing-docstring
def make_authenticate_headers(self) -> dict[str, str]:
Ensure functions have docstrings for documentation
info maintainability missing-docstring
def make_not_authenticated_error(self) -> HTTPException:
Ensure functions have docstrings for documentation
info maintainability missing-docstring
def make_authenticate_headers(self) -> dict[str, str]:

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.

Generated by searchcode.com · powered by code_get_file + code_get_findings