mirror of https://github.com/tiangolo/fastapi.git
Merge 0fc3ff387d into 272204c0c7
This commit is contained in:
commit
8fd7fc814e
|
|
@ -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**.
|
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.
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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**.
|
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.
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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"}
|
||||||
|
|
@ -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"}
|
||||||
Loading…
Reference in New Issue