async def test_user_session_dependency( secret: str, signer: typing.Type[Fernet], session_id: str, app: FastAPI, settings: SessionSettings, ): """ Check that a user session will be injected as a dependency. """ async def index(session: AsyncSession = Depends(get_user_session)) -> Response: await session.set("test", "passed") await session.save() return Response(status_code=status.HTTP_200_OK) manager = SessionManager( secret=secret, signer=signer, settings=settings, ) app.add_middleware( SessionMiddleware, manager=manager, ) app.session = manager app.add_api_route("/", index) async with AsyncClient(app=app, base_url="http://testserver") as client: response = await client.get( "/", cookies={settings.SESSION_COOKIE_NAME: encrypt_session(signer, session_id)}, ) session = await manager.load_session(AsyncMock(), session_id) assert response.status_code == status.HTTP_200_OK assert list(await session.get("test")).pop() == "passed"
async def close_session( response: Response, manager: SessionManager = Depends(get_session_manager), ) -> Response: response = manager.unset_cookie(response) response.status_code = status.HTTP_200_OK return response
async def test_handling_invalid_cookie( signer: typing.Type[Fernet], secret: str, session_id: str, app: FastAPI, settings: SessionSettings, ): """ Check that a session middleware handles a request with an invalid cookie """ manager = SessionManager( secret=secret, signer=signer, settings=settings, on_load_cookie=AsyncMock(return_value=secrets.token_urlsafe(8)), ) app.add_middleware(SessionMiddleware, manager=manager, strict=True) async with AsyncClient(app=app, base_url="http://testserver") as client: with pytest.raises(InvalidCookieException): response = await client.get( "/", cookies={ # Try to temper a user session id settings.SESSION_COOKIE_NAME: sha256( session_id.encode("utf-8") ).hexdigest() }, ) assert response.status_code == status.HTTP_400_BAD_REQUEST
async def test_handling_valid_cookie( signer: typing.Type[Fernet], secret: str, session_id: str, app: FastAPI, settings: SessionSettings, mocker: MockerFixture, ): """ Check that a session middleware handles a request with a valid cookie """ on_load_cookie_mock = AsyncMock(return_value=session_id) manager = SessionManager( secret=secret, signer=signer, settings=settings, on_load_cookie=on_load_cookie_mock, ) app.add_middleware( SessionMiddleware, manager=manager, ) async with AsyncClient(app=app, base_url="http://testserver") as client: response = await client.get( "/", cookies={settings.SESSION_COOKIE_NAME: encrypt_session(signer, session_id)}, ) assert on_load_cookie_mock.called is True
async def test_missing_user_session_dependency( secret: str, signer: typing.Type[Fernet], session_id: str, app: FastAPI, settings: SessionSettings, ): """ Check that a user session will be injected as a dependency. """ async def index(session: AsyncSession = Depends(get_user_session)) -> Response: return Response(status_code=status.HTTP_200_OK) on_missing_session_mock = AsyncMock( return_value=Response(status_code=status.HTTP_401_UNAUTHORIZED) ) manager = SessionManager( secret=secret, signer=signer, settings=settings, on_load_cookie=AsyncMock(return_value=secrets.token_urlsafe(8)), ) app.add_exception_handler(MissingSessionException, on_missing_session_mock) app.add_middleware( SessionMiddleware, manager=manager, ) app.session = manager app.add_api_route("/", index) async with AsyncClient(app=app, base_url="http://testserver") as client: response = await client.get( "/", # Generate an invalid session cookie # also disable a callback for an invalid cookie # in order to trigger a callback on missing a user session cookies={settings.SESSION_COOKIE_NAME: session_id}, ) assert response.status_code == status.HTTP_401_UNAUTHORIZED assert on_missing_session_mock.called is True
async def test_ignoring_invalid_cookie( signer: typing.Type[Fernet], secret: str, session_id: str, app: FastAPI, settings: SessionSettings, ): """ Check that a session middleware ignores a request with an invalid cookie """ async def index(response: Response) -> Response: response.status_code = status.HTTP_200_OK return response session = SessionManager( secret=secret, signer=signer, settings=settings, on_load_cookie=AsyncMock(return_value=session_id), ) app.add_middleware( SessionMiddleware, manager=session, ) app.add_api_route("/", index) async with AsyncClient(app=app, base_url="http://testserver") as client: response = await client.get( "/", cookies={ # Try to temper a user session id settings.SESSION_COOKIE_NAME: sha256( session_id.encode("utf-8") ).hexdigest(), }, ) assert response.status_code == status.HTTP_200_OK
async def init_session( response: Response, manager: SessionManager = Depends(get_session_manager) ) -> Response: response = manager.set_cookie(response, session_id_generator(app)) response.status_code = status.HTTP_200_OK return response