Spaces:
Paused
Paused
| from typing import Optional | |
| from fastapi.openapi.models import APIKey, APIKeyIn | |
| from fastapi.security.base import SecurityBase | |
| from starlette.exceptions import HTTPException | |
| from starlette.requests import Request | |
| from starlette.status import HTTP_403_FORBIDDEN | |
| from typing_extensions import Annotated, Doc | |
| class APIKeyBase(SecurityBase): | |
| pass | |
| class APIKeyQuery(APIKeyBase): | |
| """ | |
| API key authentication using a query parameter. | |
| This defines the name of the query parameter that should be provided in the request | |
| with the API key and integrates that into the OpenAPI documentation. It extracts | |
| the key value sent in the query parameter automatically and provides it as the | |
| dependency result. But it doesn't define how to send that API key to the client. | |
| ## Usage | |
| Create an instance object and use that object as the dependency in `Depends()`. | |
| The dependency result will be a string containing the key value. | |
| ## Example | |
| ```python | |
| from fastapi import Depends, FastAPI | |
| from fastapi.security import APIKeyQuery | |
| app = FastAPI() | |
| query_scheme = APIKeyQuery(name="api_key") | |
| @app.get("/items/") | |
| async def read_items(api_key: str = Depends(query_scheme)): | |
| return {"api_key": api_key} | |
| ``` | |
| """ | |
| def __init__( | |
| self, | |
| *, | |
| name: Annotated[ | |
| str, | |
| Doc("Query parameter name."), | |
| ], | |
| scheme_name: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme name. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| description: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme description. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| auto_error: Annotated[ | |
| bool, | |
| Doc( | |
| """ | |
| By default, if the query parameter is not provided, `APIKeyQuery` will | |
| automatically cancel the request and send the client an error. | |
| If `auto_error` is set to `False`, when the query parameter is not | |
| available, instead of erroring out, the dependency result will be | |
| `None`. | |
| This is useful when you want to have optional authentication. | |
| It is also useful when you want to have authentication that can be | |
| provided in one of multiple optional ways (for example, in a query | |
| parameter or in an HTTP Bearer token). | |
| """ | |
| ), | |
| ] = True, | |
| ): | |
| self.model: APIKey = APIKey( | |
| **{"in": APIKeyIn.query}, # type: ignore[arg-type] | |
| name=name, | |
| description=description, | |
| ) | |
| self.scheme_name = scheme_name or self.__class__.__name__ | |
| self.auto_error = auto_error | |
| async def __call__(self, request: Request) -> Optional[str]: | |
| api_key = request.query_params.get(self.model.name) | |
| if not api_key: | |
| if self.auto_error: | |
| raise HTTPException( | |
| status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" | |
| ) | |
| else: | |
| return None | |
| return api_key | |
| class APIKeyHeader(APIKeyBase): | |
| """ | |
| API key authentication using a header. | |
| This defines the name of the header that should be provided in the request with | |
| the API key and integrates that into the OpenAPI documentation. It extracts | |
| the key value sent in the header automatically and provides it as the dependency | |
| result. But it doesn't define how to send that key to the client. | |
| ## Usage | |
| Create an instance object and use that object as the dependency in `Depends()`. | |
| The dependency result will be a string containing the key value. | |
| ## Example | |
| ```python | |
| from fastapi import Depends, FastAPI | |
| from fastapi.security import APIKeyHeader | |
| app = FastAPI() | |
| header_scheme = APIKeyHeader(name="x-key") | |
| @app.get("/items/") | |
| async def read_items(key: str = Depends(header_scheme)): | |
| return {"key": key} | |
| ``` | |
| """ | |
| def __init__( | |
| self, | |
| *, | |
| name: Annotated[str, Doc("Header name.")], | |
| scheme_name: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme name. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| description: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme description. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| auto_error: Annotated[ | |
| bool, | |
| Doc( | |
| """ | |
| By default, if the header is not provided, `APIKeyHeader` will | |
| automatically cancel the request and send the client an error. | |
| If `auto_error` is set to `False`, when the header is not available, | |
| instead of erroring out, the dependency result will be `None`. | |
| This is useful when you want to have optional authentication. | |
| It is also useful when you want to have authentication that can be | |
| provided in one of multiple optional ways (for example, in a header or | |
| in an HTTP Bearer token). | |
| """ | |
| ), | |
| ] = True, | |
| ): | |
| self.model: APIKey = APIKey( | |
| **{"in": APIKeyIn.header}, # type: ignore[arg-type] | |
| name=name, | |
| description=description, | |
| ) | |
| self.scheme_name = scheme_name or self.__class__.__name__ | |
| self.auto_error = auto_error | |
| async def __call__(self, request: Request) -> Optional[str]: | |
| api_key = request.headers.get(self.model.name) | |
| if not api_key: | |
| if self.auto_error: | |
| raise HTTPException( | |
| status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" | |
| ) | |
| else: | |
| return None | |
| return api_key | |
| class APIKeyCookie(APIKeyBase): | |
| """ | |
| API key authentication using a cookie. | |
| This defines the name of the cookie that should be provided in the request with | |
| the API key and integrates that into the OpenAPI documentation. It extracts | |
| the key value sent in the cookie automatically and provides it as the dependency | |
| result. But it doesn't define how to set that cookie. | |
| ## Usage | |
| Create an instance object and use that object as the dependency in `Depends()`. | |
| The dependency result will be a string containing the key value. | |
| ## Example | |
| ```python | |
| from fastapi import Depends, FastAPI | |
| from fastapi.security import APIKeyCookie | |
| app = FastAPI() | |
| cookie_scheme = APIKeyCookie(name="session") | |
| @app.get("/items/") | |
| async def read_items(session: str = Depends(cookie_scheme)): | |
| return {"session": session} | |
| ``` | |
| """ | |
| def __init__( | |
| self, | |
| *, | |
| name: Annotated[str, Doc("Cookie name.")], | |
| scheme_name: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme name. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| description: Annotated[ | |
| Optional[str], | |
| Doc( | |
| """ | |
| Security scheme description. | |
| It will be included in the generated OpenAPI (e.g. visible at `/docs`). | |
| """ | |
| ), | |
| ] = None, | |
| auto_error: Annotated[ | |
| bool, | |
| Doc( | |
| """ | |
| By default, if the cookie is not provided, `APIKeyCookie` will | |
| automatically cancel the request and send the client an error. | |
| If `auto_error` is set to `False`, when the cookie is not available, | |
| instead of erroring out, the dependency result will be `None`. | |
| This is useful when you want to have optional authentication. | |
| It is also useful when you want to have authentication that can be | |
| provided in one of multiple optional ways (for example, in a cookie or | |
| in an HTTP Bearer token). | |
| """ | |
| ), | |
| ] = True, | |
| ): | |
| self.model: APIKey = APIKey( | |
| **{"in": APIKeyIn.cookie}, # type: ignore[arg-type] | |
| name=name, | |
| description=description, | |
| ) | |
| self.scheme_name = scheme_name or self.__class__.__name__ | |
| self.auto_error = auto_error | |
| async def __call__(self, request: Request) -> Optional[str]: | |
| api_key = request.cookies.get(self.model.name) | |
| if not api_key: | |
| if self.auto_error: | |
| raise HTTPException( | |
| status_code=HTTP_403_FORBIDDEN, detail="Not authenticated" | |
| ) | |
| else: | |
| return None | |
| return api_key | |