Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Join us at Qlik Connect 2026 in Orlando, April 13–15: Register Here!
cancel
Showing results for 
Search instead for 
Did you mean: 
elbomode
Contributor
Contributor

Qlik Sense (Nov 2025+) – WebSocket connections via JWT fail with 403 (CSWSH)

Summary

After upgrading to Qlik Sense Enterprise on Windows (November 2024 and later, including November 2025 Patch 2), WebSocket connections to the Qlik Engine (QIX) that previously worked may start failing with “Handshake status 403 Forbidden”.

This mainly affects non-browser clients (Python, Java, .NET, etc.) that connect via a JWT virtual proxy.

This behavior is expected and caused by an extended security mechanism:
Cross-Site WebSocket Hijacking (CSWSH) prevention, which expands CSRF protection to WebSocket connections.

Typical symptoms

  • WebSocket handshake returns 403 Forbidden

  • JWT authentication succeeds

  • A Qlik session is created

  • A CSRF token is issued

  • The WebSocket connection is still rejected

Typical Proxy log message:
“Cross-Site Websocket Hijacking attack prevention check failed. Possible Cross-Site Websocket Hijacking attack (CSWSH) discovered.”

What changed

Starting with Qlik Sense November 2024+, WebSocket connections are subject to the same CSRF and Origin validation rules as HTTP requests.

Important consequences:

  • JWT alone is no longer sufficient for WebSocket authentication

  • JWT is used only to establish a session

  • The WebSocket connection must

    • reuse the same session

    • include a valid CSRF token

    • send an allowed Origin

    • NOT send an Authorization header

Common misconceptions

  • Adding the client IP to the host allow list (incorrect)

  • Sending “Authorization: Bearer <token>” in the WebSocket handshake

  • Reusing the Set-Cookie header as a Cookie header

  • Assuming CORS headers fix the issue for non-browser clients

  • Mixing short hostnames and FQDNs inconsistently

Required Virtual Proxy configuration

For the JWT virtual proxy, the Host allow list must contain the exact host names used by the client, for example:

Do not add client IP addresses.
The scheme (https) matters.

Additional response headers (CORS) are not required for service or script-based WebSocket clients.

Correct connection model (critical)

A two-phase approach is required.

Phase 1 – HTTP: establish session and CSRF

Use Authorization: Bearer <JWT> only here.

Call:
https://<host>/<virtual-proxy>/qps/csrftoken

Result:

  • CSRF token returned in the response header “qlik-csrf-token”

  • Session cookie (for example X-Qlik-Session-jwt)

Phase 2 – WebSocket: connect to QIX

Do NOT send an Authorization header.

Send only:

  • Session cookie

  • CSRF token

  • Origin header

Optionally, the CSRF token can also be sent as a query parameter.

 

Example (Python, simplified)

  • Use Bearer token only for the HTTP request to /qps/csrftoken

  • Extract qlik-csrf-token from the response header

  • Reuse the session cookie

  • Open the WebSocket without Authorization header

  • Send Cookie, CSRF token, and Origin

(Implementation details depend on the WebSocket library used.)

Important details

Origin

  • Must exactly match an entry in the virtual proxy host allow list

  • Scheme (https) is significant

  • Must be sent only once

CSRF token

  • Provided via response header (qlik-csrf-token)

  • Must match the active session

  • Session cookie is mandatory

Authorization header

  • Used only during HTTP session setup

  • Must not be sent during the WebSocket handshake

WebSocket subprotocol

  • Do not force “qlik.api”

  • If the server does not echo it back, forcing it causes client-side errors

Success indicator

A successful WebSocket handshake returns:

HTTP/1.1 101 Switching Protocols

After this, normal QIX JSON-RPC communication (OpenDoc, GetDocList, etc.) works as expected.

Conclusion

The 403 error after upgrading is not a bug, but the result of intentional security hardening.

JWT creates the session — the session authenticates the WebSocket.

Once non-browser clients follow the session + CSRF + Origin model, WebSocket connections work reliably again.

Labels (3)
1 Reply
korsikov
Partner - Specialist III
Partner - Specialist III

I think you are need update topic and change affected QlikSense to Nov 2024+.  Not 2025+
Anyway. Could the same issue occur when using the browser client to access the Qlik Sense server on the company's private network via a VPN connection?