pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.5 KiB
208 lines
5.5 KiB
from typing import Union
|
|
|
|
import pytest
|
|
from fastapi import FastAPI, Security
|
|
from fastapi.security.api_key import APIKeyBase, APIKeyCookie, APIKeyHeader, APIKeyQuery
|
|
from fastapi.security.http import HTTPBase, HTTPBearer, HTTPDigest
|
|
from fastapi.security.oauth2 import OAuth2
|
|
from fastapi.security.open_id_connect_url import OpenIdConnect
|
|
from fastapi.testclient import TestClient
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"auth",
|
|
[
|
|
APIKeyQuery(name="key", not_authenticated_status_code=403),
|
|
APIKeyHeader(name="key", not_authenticated_status_code=403),
|
|
APIKeyCookie(name="key", not_authenticated_status_code=403),
|
|
],
|
|
)
|
|
def test_apikey_status_code_403_on_auth_error(auth: APIKeyBase):
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for APIKey** classes.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 403
|
|
assert response.json() == {"detail": "Not authenticated"}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"auth",
|
|
[
|
|
APIKeyQuery(name="key", not_authenticated_status_code=403, auto_error=False),
|
|
APIKeyHeader(name="key", not_authenticated_status_code=403, auto_error=False),
|
|
APIKeyCookie(name="key", not_authenticated_status_code=403, auto_error=False),
|
|
],
|
|
)
|
|
def test_apikey_status_code_403_on_auth_error_no_auto_error(auth: APIKeyBase):
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for APIKey** classes with
|
|
`auto_error=False`.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"auth",
|
|
[
|
|
HTTPBearer(not_authenticated_status_code=403),
|
|
OpenIdConnect(not_authenticated_status_code=403, openIdConnectUrl="/openid"),
|
|
OAuth2(
|
|
not_authenticated_status_code=403,
|
|
flows={"password": {"tokenUrl": "token", "scopes": {}}},
|
|
),
|
|
],
|
|
)
|
|
def test_oauth2_status_code_403_on_auth_error(auth: Union[HTTPBase, OpenIdConnect]):
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for security classes that
|
|
follow rfc6750.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 403
|
|
assert response.json() == {"detail": "Not authenticated"}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"auth",
|
|
[
|
|
HTTPBearer(not_authenticated_status_code=403, auto_error=False),
|
|
OpenIdConnect(
|
|
not_authenticated_status_code=403,
|
|
openIdConnectUrl="/openid",
|
|
auto_error=False,
|
|
),
|
|
OAuth2(
|
|
not_authenticated_status_code=403,
|
|
flows={"password": {"tokenUrl": "token", "scopes": {}}},
|
|
auto_error=False,
|
|
),
|
|
],
|
|
)
|
|
def test_oauth2_status_code_403_on_auth_error_no_auto_error(
|
|
auth: Union[HTTPBase, OpenIdConnect],
|
|
):
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for security classes that
|
|
follow rfc6750.
|
|
With `auto_error=False`. Response code should be 200
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_digest_status_code_403_on_auth_error():
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for `Digest` scheme.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
auth = HTTPDigest(not_authenticated_status_code=403)
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 403
|
|
assert response.json() == {"detail": "Not authenticated"}
|
|
|
|
|
|
def test_digest_status_code_403_on_auth_error_no_auto_error():
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for `Digest` scheme with
|
|
`auto_error=False`.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
auth = HTTPDigest(not_authenticated_status_code=403, auto_error=False)
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
|
|
|
|
def test_httpbase_status_code_403_on_auth_error():
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for `HTTPBase` class.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
auth = HTTPBase(scheme="Other", not_authenticated_status_code=403)
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 403
|
|
assert response.json() == {"detail": "Not authenticated"}
|
|
|
|
|
|
def test_httpbase_status_code_403_on_auth_error_no_auto_error():
|
|
"""
|
|
Test temporary `not_authenticated_status_code` parameter for `HTTPBase` class with
|
|
`auto_error=False`.
|
|
"""
|
|
|
|
app = FastAPI()
|
|
|
|
auth = HTTPBase(scheme="Other", not_authenticated_status_code=403, auto_error=False)
|
|
|
|
@app.get("/")
|
|
async def protected(_: str = Security(auth)):
|
|
pass # pragma: no cover
|
|
|
|
client = TestClient(app)
|
|
|
|
response = client.get("/")
|
|
assert response.status_code == 200
|
|
|