From cb8b4458f4fadabc354a4325e82840aa2ce43485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Garc=C3=ADa=20Garz=C3=B3n?= Date: Thu, 25 Jul 2024 08:40:16 +0200 Subject: [PATCH] GH-42: Covering jwt cases and modify others I added a case of exception that should be handled: as auth errors: jwt validation errors Using same approach as expiration check, but maybe it should be a HttpException in order to be properly handled both by fastapi and users. Also unexpected errors are not transformed to 500 either on the test setup. Maybe because we are not using Fastapi TestClient. --- tests/test_middleware.py | 42 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/tests/test_middleware.py b/tests/test_middleware.py index 8902936..ffa6934 100644 --- a/tests/test_middleware.py +++ b/tests/test_middleware.py @@ -1,5 +1,7 @@ import pytest from httpx import AsyncClient +from fastapi.responses import JSONResponse +from fastapi_oauth2.exceptions import OAuth2AuthenticationError @pytest.mark.anyio @@ -31,40 +33,54 @@ async def test_middleware_on_logout(get_app): async def test_middleware_do_not_interfer_user_errors(get_app): app=get_app() @app.get('/unexpected_error') - def unexpected(): + def my_entry_point(): undefined_id # Intended code error async with AsyncClient(app=app, base_url="http://test") as client: - response = await client.get("/unexpected_error") - assert response.status_code == 500 # Internal server error + with pytest.raises(NameError): + await client.get("/unexpected_error") @pytest.mark.anyio async def test_middleware_ignores_custom_exceptions(get_app): class MyCustomException(Exception): pass app=get_app() @app.get('/custom_exception') - def custom_exception(): + def my_entry_point(): raise MyCustomException() async with AsyncClient(app=app, base_url="http://test") as client: - response = await client.get("/custom_exception") - assert response.status_code == 500 # Internal server error + with pytest.raises(MyCustomException): + await client.get("/custom_exception") @pytest.mark.anyio async def test_middleware_ignores_handled_custom_exceptions(get_app): - class MyCustomException(Exception): pass + class MyHandledException(Exception): pass app=get_app() - @app.exception_handler(MyCustomException) + @app.exception_handler(MyHandledException) async def unicorn_exception_handler(request, exc): return JSONResponse( status_code=418, - content={"message": f"I am a Teapot!"}, + content={"details": "I am a custom Teapot!"}, ) - @app.get('/custom_exception') - def custom_exception(): - raise MyCustomException() + @app.get('/handled_exception') + def my_entry_point(): + raise MyHandledException() async with AsyncClient(app=app, base_url="http://test") as client: - response = await client.get("/custom_exception") + response = await client.get("/handled_exception") assert response.status_code == 418 # I am a teapot! + assert response.json() == {"details": "I am a custom Teapot!"} + +@pytest.mark.anyio +async def test_middleware_reports_invalid_jwt(get_app): + async with AsyncClient(app=get_app(with_ssr=False), base_url="http://test") as client: + await client.get("/auth") # Simulate login + # Insert a bad token instead + from jose import jwt + badtoken=jwt.encode({"bad": "token"}, 'badsecret', 'HS256') + client.cookies.update(dict(Authorization=f"Bearer: {badtoken}")) + + with pytest.raises(OAuth2AuthenticationError, match="401: Signature verification failed.") as ctx: + response = await client.get("/user") +