In this lesson, you will learn how to harden your SignalR endpoints by implementing Content Security Policies (CSP) and secure headers to prevent cross-site scripting and unauthorized connection hijacking.
When running SignalR in production, your real-time hubs are exposed to the public web. By default, browsers might allow your SignalR client to execute scripts or establish connections from untrusted origins. To lock this down, we must enforce strict security headers and a restrictive CSP.
Implementing Secure Headers
At the middleware level, you should ensure that your application sends headers that instruct the browser to block malicious behavior. Specifically, for SignalR, you want to ensure X-Content-Type-Options is set to nosniff and X-Frame-Options is set to DENY or SAMEORIGIN to prevent clickjacking via iframes.
In your Program.cs, configure the middleware to inject these headers:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; connect-src 'self' wss://your-api.com;");
await next();
});
Content Security Policy (CSP) for WebSockets
The connect-src directive in your CSP is critical for SignalR. Since SignalR relies on WebSocket (wss://) or long-polling connections, you must explicitly whitelist the domains permitted to initiate those connections. If you allow connect-src 'self', the browser will block any attempt to connect to a WebSocket server that does not share the same origin as your application.
This prevents "Cross-Site WebSocket Hijacking," where an attacker lures a user to a malicious site that attempts to open a WebSocket connection to your SignalR hub using the victim's authenticated cookies. By enforcing a strict CSP, the browser will refuse the handshake request before it even reaches your hub.
Always ensure your default-src is restrictive and only explicitly add the necessary endpoints for your real-time traffic. This defense-in-depth approach ensures that even if an attacker finds an XSS vulnerability elsewhere in your app, they cannot easily pivot to intercepting your real-time data streams.
Key Takeaway: Harden your SignalR production environment by enforcing a strict Content Security Policy that explicitly whitelists WebSocket origins and utilizes standard security headers to block site-embedding attacks.