Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get method of aioauth.collections.HTTPHeaderDict class is not case-insensitive #97

Open
PrieJos opened this issue Aug 20, 2024 · 0 comments
Assignees
Labels
bug Something isn't working

Comments

@PrieJos
Copy link
Contributor

PrieJos commented Aug 20, 2024

Hi aioauth Team,

The get method of the class aioauth.collections.HTTPHeaderDict is not case-insensitive. Due to this, the create_token_response method of the aioauth.server.AuthorizationServer is unable to authenticate the client based on the Authorization header passed in to the token endpoint (ie. whenever client is authenticate using HTTP basic). The issue is caused indeed because the get method of HTTPHeaderDict is not case-insensitive that makes this following line to retrieve an empty string:

authorization = request.headers.get("Authorization", "")

The solution is as easy as override the following methods inherited from UserDict when defining HTTPHeaderDict. This is indeed the patched version of HTTPHeaderDict I am using:

class PatchedHTTPHeaderDict(HTTPHeaderDict):
    """Patch version of class `HTTPHeaderDict`."""

    def __init__(self, **kw: t.Any) -> None:
        """Object initialization."""
        super().__init__(**{k.lower(): v for k, v in kw.items()})

    def __delitem__(self, key: str) -> None:
        """Item deletion."""
        return super().__delitem__(key.lower())

    def get(self, key: str, default: t.Any = None) -> t.Any:
        """Case-insentive get."""
        try:
            return self[key]
        except KeyError:
            return default

Expected Result

I was expected the code line above to retrieve the HTTP basic value from Authorization header as passed in to the original token request.

Actual Result

The code line above results in a empty string.

Reproduction Steps

Authenticate the client using HTTP Basic when calling the token endpoint. For example, like in this pytest function I have in my project where I am using the starlette.testclient.TestClient as a test http client:

class TestAuthorizationCodeGrant:
    """Test cases for authorization code grant flow."""

    def test_successful_flow(
        self,
        fastplay_client: "TestClient",
        client_info: ClientInfoTuple,
        request_state: str,
        http_basic: "HTTPBasicFixture",
    ) -> None:
        """Test a successful OAuth 2.0 authorization code flow."""
        # Authorization request
        authorization_response = fastplay_client.get(
            "/auth/oauth2/authorize",
            params={
                "response_type": "code",
                "client_id": client_info.client_id,
                "redirect_uri": client_info.redirect_uri,
                "scope": "",
                "state": request_state,
            },
            auth=(http_basic.username, http_basic.password),
            # headers={AuthNEngine.API_KEY_HEADER: api_key.key},
        )

        # Authorization response check
        assert authorization_response.status_code == HTTPStatus.FOUND
        assert authorization_response.next_request is not None
        redirect_url = authorization_response.next_request.url
        assert str(redirect_url).startswith(client_info.redirect_uri)
        assert redirect_url.params["state"] == request_state
        assert redirect_url.params["scope"] == ""
        authorization_code = redirect_url.params["code"]
        assert len(authorization_code) > 0

        # Access token request
        token_response = fastplay_client.post(
            "/auth/oauth2/token",
            data={
                "grant_type": "authorization_code",
                "code": authorization_code,
                "redirect_uri": client_info.redirect_uri,
                "client_id": client_info.client_id,
            },
            auth=(client_info.client_id, client_info.client_secret),
        )
        assert token_response.status_code == HTTPStatus.OK

System Information

Python Version (3.x): 3.12
aioauth Version (0.x): 1.6.0
Framework (FastAPI / starlette, aiohttp, sanic, etc.)
- fastapi 0.112.0
- starlette 0.37.2
@PrieJos PrieJos added the bug Something isn't working label Aug 20, 2024
PrieJos added a commit to PrieJos/aioauth that referenced this issue Aug 22, 2024
Fix case sensitiveness in HTTPHeaderDict. See issue aliev#97 for
more details.
PrieJos added a commit to PrieJos/aioauth that referenced this issue Sep 17, 2024
Fix case sensitiveness in HTTPHeaderDict. See issue aliev#97 for
more details.

(cherry picked from commit 126aae7)
aliev added a commit that referenced this issue Oct 12, 2024
Fix case sensitiveness in HTTPHeaderDict (#97)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants