Skip to content

Skip setting cookies when using websockets with api key param #94

Description

@SeijDeLeon

request.state.cookies_to_set.append({"key": API_KEY_COOKIE_NAME, "value": api_key})

Error when using ?api_key=test param in a websocket request. The api key gets through, but then the move_api_key function wants to call cookies_to_set which fails. Seems that the issue is you can't set cookies with the websocket.

  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 184, in app
    await wrap_app_handling_exceptions(app, session)(scope, receive, send)
  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
    raise exc
  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
    await app(scope, receive, sender)
  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 181, in app
    await func(session)
  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/fastapi/routing.py", line 796, in app
    await dependant.call(**solved_result.values)
  File "/Users/seij/Repos/bluesky-httpserver/src/bluesky_httpserver/routers/core_api.py", line 1215, in console_output_ws
    principal, accepted = await _authenticate_websocket(websocket, scopes)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/seij/Repos/bluesky-httpserver/src/bluesky_httpserver/routers/core_api.py", line 1184, in _authenticate_websocket
    principal = get_current_principal_websocket(websocket=websocket, scopes=scopes)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/seij/Repos/bluesky-httpserver/src/bluesky_httpserver/authentication.py", line 516, in get_current_principal_websocket
  File "/Users/seij/Repos/bluesky-httpserver/src/bluesky_httpserver/authentication.py", line 298, in get_current_principal
    )
  File "/Users/seij/Repos/bluesky-httpserver/src/bluesky_httpserver/authentication.py", line 256, in move_api_key
    # The `set_cookies` HTTP middleware initializes `request.state.cookies_to_set`.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/seij/Repos/bluesky-httpserver/.venv/lib/python3.12/site-packages/starlette/datastructures.py", line 686, in __getattr__
    raise AttributeError(message.format(self.__class__.__name__, key))
AttributeError: 'State' object has no attribute 'cookies_to_set'

Replacing line 256 with the above worked for me. I tested through a browser client and through Postman.

Proposed fix:

        # The `set_cookies` HTTP middleware initializes `request.state.cookies_to_set`.
        # That middleware is not executed for WebSocket connections, so guard here
        # to avoid AttributeError when `state.cookies_to_set` is missing.
        if hasattr(request.state, "cookies_to_set"):
            request.state.cookies_to_set.append({"key": API_KEY_COOKIE_NAME, "value": api_key})
        else:
            # No place to store a cookie for this request (likely a WebSocket).
            # Silently skip setting the cookie — browsers opening a websocket
            # with ?api_key=... should set the cookie via an HTTP request instead.
            logger.debug("Skipping moving api_key to cookie: request.state.cookies_to_set missing")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions