Skip to content

[BUG] WebSocket callbacks do not expose request cookies/headers on callback_context #3814

Description

@i-murray

Describe your context

dash                      4.2.0
dash-enterprise-auth      (current)
  • Backend: FastAPI (Dash(name, backend="fastapi")); the same issue exists for the Quart backend.

Describe the bug

When a callback runs over the WebSocket transport (declared with websocket=True, or via websocket_callbacks=True), the request cookies and headers are not available on dash.callback_context. They are empty.

The HTTP transport populates these correctly (via Dash._initialize_context), but the WebSocket context builder (create_ws_context in dash/backends/ws.py) never sets cookies, headers, args, path, remote, or origin.

This breaks any authentication helper that reads the request context. In our case, running our apps on Dash Enterprise, dash_enterprise_auth.get_user_data() reads the kcIdToken cookie (or the Plotly-User-Data header on older Dash Enterprise) from callback_context.cookies. Over WebSocket it receives {}.

Steps to reproduce

from dash import Dash, html, dcc, Input, Output, ctx

app = Dash(__name__, backend="fastapi")

app.layout = html.Div([
    dcc.Input(id="q", type="text"),
    html.Div(id="out"),
])

@app.callback(Output("out", "children"), Input("q", "value"), websocket=True)
def show_cookies(value):
    # Over HTTP this is populated; over WebSocket it is empty.
    return f"cookies={dict(ctx.cookies)} headers={bool(ctx.headers)}"

if __name__ == "__main__":
    app.run(debug=True)
  1. Run the app and open it in a browser (so the request carries cookies).
  2. Type into the input to trigger the websocket=True callback.
  3. Observe ctx.cookies is {} and ctx.headers is empty.
  4. Change the callback to a normal HTTP callback (remove websocket=True) and observe the cookies/headers are present.

Expected behavior

callback_context.cookies and callback_context.headers (and args, path, remote, origin) should be populated for WebSocket callbacks just as they are for HTTP callbacks, so authentication/session helpers behave consistently across transports.

Actual behavior

callback_context.cookies/headers are empty for WebSocket callbacks, causing auth helpers such as dash_enterprise_auth.get_user_data() to fail.

Root cause

create_ws_context in dash/backends/ws.py builds the callback context but omits the request metadata that Dash._initialize_context sets for the HTTP path. The WebSocket handshake request (which carries the cookies/headers) is available in the backend WebSocket handlers (_fastapi.py / _quart.py) but is never forwarded into the context.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

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