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)
- Run the app and open it in a browser (so the request carries cookies).
- Type into the input to trigger the
websocket=True callback.
- Observe
ctx.cookies is {} and ctx.headers is empty.
- 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.
Describe your context
Describe the bug
When a callback runs over the WebSocket transport (declared with
websocket=True, or viawebsocket_callbacks=True), the requestcookiesandheadersare not available ondash.callback_context. They are empty.The HTTP transport populates these correctly (via
Dash._initialize_context), but the WebSocket context builder (create_ws_contextindash/backends/ws.py) never setscookies,headers,args,path,remote, ororigin.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 thekcIdTokencookie (or thePlotly-User-Dataheader on older Dash Enterprise) fromcallback_context.cookies. Over WebSocket it receives{}.Steps to reproduce
websocket=Truecallback.ctx.cookiesis{}andctx.headersis empty.websocket=True) and observe the cookies/headers are present.Expected behavior
callback_context.cookiesandcallback_context.headers(andargs,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/headersare empty for WebSocket callbacks, causing auth helpers such asdash_enterprise_auth.get_user_data()to fail.Root cause
create_ws_contextindash/backends/ws.pybuilds the callback context but omits the request metadata thatDash._initialize_contextsets 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.