from base64 import b64encode from wsgiref.validate import validator import pytest from paste import authenticate from ..common_wsgi import call_app def get_auth(environ): assert environ assert "test.check_token" in environ class MockAuth: @staticmethod def check_token(tok): return environ["test.check_token"](tok) return MockAuth() @pytest.fixture def app(): @validator @authenticate(get_auth) # type: ignore @validator def app(_, start_response): start_response("200 OK", [("Content-Type", "text/plain")]) return [b"Hello, world!"] return app @pytest.mark.parametrize("method", ["GET", "HEAD"]) def test_unauthenticated_request(app, method): environ = {"REQUEST_METHOD": method} response = call_app(app, environ) assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers @pytest.mark.parametrize("method", ["GET", "HEAD"]) def test_unauthenticated_request_with_key(app, method): environ = { "REQUEST_METHOD": method, "HTTP_AUTHORIZATION": "ApiKey AAAA", } response = call_app(app, environ) assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_no_header(app, method): environ = {"REQUEST_METHOD": method} response = call_app(app, environ) assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) @pytest.mark.parametrize("key", ["ApiKey AAAA", "APIKey AAA", "APIKey AAAA", "AAAA"]) def test_authenticate_malformed_key(app, method, key): environ = {"REQUEST_METHOD": method, "HTTP_AUTHORIZATION": key} response = call_app(app, environ) assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_check_token_fail(app, method): check_token_called = False token = b"test" def check_token(tok): nonlocal check_token_called assert tok == token check_token_called = True return False environ = { "REQUEST_METHOD": method, "test.check_token": check_token, "HTTP_AUTHORIZATION": f"APIKey {b64encode(token).decode()}", } response = call_app(app, environ) assert check_token_called assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_check_token_success(app, method): check_token_called = False token = b"test" def check_token(tok): nonlocal check_token_called assert tok == token check_token_called = True return True environ = { "REQUEST_METHOD": method, "test.check_token": check_token, "HTTP_AUTHORIZATION": f"APIKey {b64encode(token).decode()}", } response = call_app(app, environ) assert check_token_called assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers