diff --git a/docs/en/docs/tutorial/security/index.md b/docs/en/docs/tutorial/security/index.md index 6f460d627..077d8d6d7 100644 --- a/docs/en/docs/tutorial/security/index.md +++ b/docs/en/docs/tutorial/security/index.md @@ -104,3 +104,34 @@ FastAPI provides several tools for each of these security schemes in the `fastap In the next chapters you will see how to add security to your API using those tools provided by **FastAPI**. And you will also see how it gets automatically integrated into the interactive documentation system. + +## API Key in Header + +An API key is a simple secret string that a client sends with every request. +It is often used for: + +- machine-to-machine communication, +- internal services, +- simple “service access” authentication instead of full user accounts. + +In OpenAPI, this is represented with the `apiKey` security scheme, and it can be sent in a **query parameter**, a **header**, or a **cookie**. + +FastAPI provides tools for these in the `fastapi.security` module, including `APIKeyHeader` for header-based API keys. + +### Define an API key in a header + +In this example, the client must send an API key in the HTTP header `X-API-Key`. +We’ll require the exact value `"supersecret"` to access a protected route. + +```Python +from typing import Optional + +from fastapi import FastAPI, HTTPException, Security, status +from fastapi.security import APIKeyHeader + +app = FastAPI() + +API_KEY = "supersecret" +API_KEY_NAME = "X-API-Key" + +api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False) diff --git a/docs/es/docs/tutorial/security/index.md b/docs/es/docs/tutorial/security/index.md index e4d75d8a4..606767f4c 100644 --- a/docs/es/docs/tutorial/security/index.md +++ b/docs/es/docs/tutorial/security/index.md @@ -103,3 +103,35 @@ FastAPI proporciona varias herramientas para cada uno de estos esquemas de segur En los siguientes capítulos verás cómo agregar seguridad a tu API usando esas herramientas proporcionadas por **FastAPI**. Y también verás cómo se integra automáticamente en el sistema de documentación interactiva. + + +## API Key en el Header + +Una API key es una cadena secreta sencilla que un cliente envía con cada petición. +Suele utilizarse para: + +- comunicación entre servicios, +- servicios internos, +- autenticación simple por “acceso al servicio” en lugar de cuentas de usuario completas. + +En OpenAPI, esto se representa con el esquema de seguridad `apiKey`, que puede enviarse en un **parámetro de consulta**, un **header**, o una **cookie**. + +FastAPI incluye utilidades para esto en el módulo `fastapi.security`, incluyendo `APIKeyHeader` para API keys basadas en headers. + +### Definir la API key en un header + +En este ejemplo, el cliente debe enviar una API key en el header HTTP `X-API-Key`. +Requeriremos que el valor sea exactamente `"supersecret"` para acceder a una ruta protegida. + +```Python +from typing import Optional + +from fastapi import FastAPI, HTTPException, Security, status +from fastapi.security import APIKeyHeader + +app = FastAPI() + +API_KEY = "supersecret" +API_KEY_NAME = "X-API-Key" + +api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False) diff --git a/docs_src/security/tutorial_api_key_header.py b/docs_src/security/tutorial_api_key_header.py new file mode 100644 index 000000000..b06c6fe59 --- /dev/null +++ b/docs_src/security/tutorial_api_key_header.py @@ -0,0 +1,30 @@ +from typing import Optional + +from fastapi import FastAPI, HTTPException, Security, status +from fastapi.security import APIKeyHeader + +app = FastAPI() + +API_KEY = "supersecret" +API_KEY_NAME = "X-API-Key" + +api_key_header = APIKeyHeader(name=API_KEY_NAME, auto_error=False) + + +async def get_api_key(api_key: Optional[str] = Security(api_key_header)) -> str: + if api_key is None: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="Not authenticated", + ) + if api_key != API_KEY: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="Invalid API key", + ) + return api_key + + +@app.get("/protected-route") +async def protected_route(api_key: str = Security(get_api_key)): + return {"message": "You are authorized"} diff --git a/tests/test_tutorial/test_security/test_tutorial_api_key_header.py b/tests/test_tutorial/test_security/test_tutorial_api_key_header.py new file mode 100644 index 000000000..9bf65470b --- /dev/null +++ b/tests/test_tutorial/test_security/test_tutorial_api_key_header.py @@ -0,0 +1,33 @@ +import pytest +from fastapi.testclient import TestClient + + +@pytest.fixture(name="client") +def get_client() -> TestClient: + from docs_src.security.tutorial_api_key_header import app + + return TestClient(app) + + +def test_no_api_key(client: TestClient) -> None: + response = client.get("/protected-route") + assert response.status_code == 403, response.text + assert response.json() == {"detail": "Not authenticated"} + + +def test_invalid_api_key(client: TestClient) -> None: + response = client.get( + "/protected-route", + headers={"X-API-Key": "wrong"}, + ) + assert response.status_code == 403, response.text + assert response.json() == {"detail": "Invalid API key"} + + +def test_valid_api_key(client: TestClient) -> None: + response = client.get( + "/protected-route", + headers={"X-API-Key": "supersecret"}, + ) + assert response.status_code == 200, response.text + assert response.json() == {"message": "You are authorized"}