<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Qlik Sense (Nov 2025+) – WebSocket connections via JWT fail with 403 (CSWSH) in Integration, Extension &amp; APIs</title>
    <link>https://community.qlik.com/t5/Integration-Extension-APIs/Qlik-Sense-Nov-2025-WebSocket-connections-via-JWT-fail-with-403/m-p/2540147#M22702</link>
    <description>&lt;P&gt;I think you are need update topic and change affected QlikSense to Nov &lt;STRONG&gt;2024+.&amp;nbsp;&amp;nbsp;&lt;/STRONG&gt;Not 2025+&lt;BR /&gt;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?&lt;/P&gt;</description>
    <pubDate>Sun, 04 Jan 2026 19:30:08 GMT</pubDate>
    <dc:creator>korsikov</dc:creator>
    <dc:date>2026-01-04T19:30:08Z</dc:date>
    <item>
      <title>Qlik Sense (Nov 2025+) – WebSocket connections via JWT fail with 403 (CSWSH)</title>
      <link>https://community.qlik.com/t5/Integration-Extension-APIs/Qlik-Sense-Nov-2025-WebSocket-connections-via-JWT-fail-with-403/m-p/2539417#M22673</link>
      <description>&lt;P&gt;&lt;STRONG&gt;Summary&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;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”.&lt;/P&gt;&lt;P&gt;This mainly affects non-browser clients (Python, Java, .NET, etc.) that connect via a JWT virtual proxy.&lt;/P&gt;&lt;P&gt;This behavior is expected and caused by an extended security mechanism:&lt;BR /&gt;Cross-Site WebSocket Hijacking (CSWSH) prevention, which expands CSRF protection to WebSocket connections.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Typical symptoms&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;WebSocket handshake returns 403 Forbidden&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;JWT authentication succeeds&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;A Qlik session is created&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;A CSRF token is issued&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The WebSocket connection is still rejected&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Typical Proxy log message:&lt;BR /&gt;“Cross-Site Websocket Hijacking attack prevention check failed. Possible Cross-Site Websocket Hijacking attack (CSWSH) discovered.”&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;What changed&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Starting with Qlik Sense November 2024+, WebSocket connections are subject to the same CSRF and Origin validation rules as HTTP requests.&lt;/P&gt;&lt;P&gt;Important consequences:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;JWT alone is no longer sufficient for WebSocket authentication&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;JWT is used only to establish a session&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The WebSocket connection must&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;reuse the same session&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;include a valid CSRF token&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;send an allowed Origin&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;NOT send an Authorization header&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Common misconceptions&lt;/STRONG&gt;&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Adding the client IP to the host allow list (incorrect)&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Sending “Authorization: Bearer &amp;lt;token&amp;gt;” in the WebSocket handshake&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Reusing the Set-Cookie header as a Cookie header&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Assuming CORS headers fix the issue for non-browser clients&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Mixing short hostnames and FQDNs inconsistently&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Required Virtual Proxy configuration&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;For the JWT virtual proxy, the Host allow list must contain the exact host names used by the client, for example:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;host.example.local&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;A href="https://host.example.local" target="_blank" rel="noopener"&gt;https://host.example.local&lt;/A&gt;&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Do not add client IP addresses.&lt;BR /&gt;The scheme (https) matters.&lt;/P&gt;&lt;P&gt;Additional response headers (CORS) are not required for service or script-based WebSocket clients.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Correct connection model (critical)&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;A two-phase approach is required.&lt;/P&gt;&lt;P&gt;Phase 1 – HTTP: establish session and CSRF&lt;/P&gt;&lt;P&gt;Use Authorization: Bearer &amp;lt;JWT&amp;gt; only here.&lt;/P&gt;&lt;P&gt;Call:&lt;BR /&gt;https://&amp;lt;host&amp;gt;/&amp;lt;virtual-proxy&amp;gt;/qps/csrftoken&lt;/P&gt;&lt;P&gt;Result:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;CSRF token returned in the response header “qlik-csrf-token”&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Session cookie (for example X-Qlik-Session-jwt)&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Phase 2 – WebSocket: connect to QIX&lt;/P&gt;&lt;P&gt;Do NOT send an Authorization header.&lt;/P&gt;&lt;P&gt;Send only:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Session cookie&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;CSRF token&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Origin header&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Optionally, the CSRF token can also be sent as a query parameter.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Example (Python, simplified)&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Use Bearer token only for the HTTP request to /qps/csrftoken&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Extract qlik-csrf-token from the response header&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Reuse the session cookie&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Open the WebSocket without Authorization header&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Send Cookie, CSRF token, and Origin&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;(Implementation details depend on the WebSocket library used.)&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Important details&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Origin&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Must exactly match an entry in the virtual proxy host allow list&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Scheme (https) is significant&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Must be sent only once&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;CSRF token&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Provided via response header (qlik-csrf-token)&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Must match the active session&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Session cookie is mandatory&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Authorization header&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Used only during HTTP session setup&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Must not be sent during the WebSocket handshake&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;WebSocket subprotocol&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Do not force “qlik.api”&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;If the server does not echo it back, forcing it causes client-side errors&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;STRONG&gt;Success indicator&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;A successful WebSocket handshake returns:&lt;/P&gt;&lt;P&gt;HTTP/1.1 101 Switching Protocols&lt;/P&gt;&lt;P&gt;After this, normal QIX JSON-RPC communication (OpenDoc, GetDocList, etc.) works as expected.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;The 403 error after upgrading is not a bug, but the result of intentional security hardening.&lt;/P&gt;&lt;P&gt;JWT creates the session — the session authenticates the WebSocket.&lt;/P&gt;&lt;P&gt;Once non-browser clients follow the session + CSRF + Origin model, WebSocket connections work reliably again.&lt;/P&gt;</description>
      <pubDate>Wed, 17 Dec 2025 13:20:15 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Integration-Extension-APIs/Qlik-Sense-Nov-2025-WebSocket-connections-via-JWT-fail-with-403/m-p/2539417#M22673</guid>
      <dc:creator>elbomode</dc:creator>
      <dc:date>2025-12-17T13:20:15Z</dc:date>
    </item>
    <item>
      <title>Re: Qlik Sense (Nov 2025+) – WebSocket connections via JWT fail with 403 (CSWSH)</title>
      <link>https://community.qlik.com/t5/Integration-Extension-APIs/Qlik-Sense-Nov-2025-WebSocket-connections-via-JWT-fail-with-403/m-p/2540147#M22702</link>
      <description>&lt;P&gt;I think you are need update topic and change affected QlikSense to Nov &lt;STRONG&gt;2024+.&amp;nbsp;&amp;nbsp;&lt;/STRONG&gt;Not 2025+&lt;BR /&gt;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?&lt;/P&gt;</description>
      <pubDate>Sun, 04 Jan 2026 19:30:08 GMT</pubDate>
      <guid>https://community.qlik.com/t5/Integration-Extension-APIs/Qlik-Sense-Nov-2025-WebSocket-connections-via-JWT-fail-with-403/m-p/2540147#M22702</guid>
      <dc:creator>korsikov</dc:creator>
      <dc:date>2026-01-04T19:30:08Z</dc:date>
    </item>
  </channel>
</rss>

