Skip to content

Commit 1c68f87

Browse files
authored
Azure SignalR with Azure Front Door guide
1 parent 2b84eb4 commit 1c68f87

File tree

6 files changed

+265
-0
lines changed

6 files changed

+265
-0
lines changed
167 KB
Loading
20.5 KB
Loading
202 KB
Loading
117 KB
Loading
137 KB
Loading
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
---
2+
title: How to use SignalR Service with Azure Front Door
3+
description: This article provides information about using Azure SignalR Service with Azure Front Door.
4+
author: kevinguo-ed
5+
ms.author: kevinguo
6+
ms.date: 04/10/2025
7+
ms.service: azure-signalr-service
8+
ms.topic: how-to
9+
---
10+
11+
# How to use Azure SignalR Service with Azure Front Door
12+
13+
Azure Front Door is a modern cloud-native application delivery network (ADN) that provides dynamic site acceleration, global load balancing, TLS termination, and application layer security. It operates at the HTTP/HTTPS layer (Layer 7) and acts as the entry point for web applications—routing and optimizing traffic based on attributes such as URL paths, latency, and health status of backends.
14+
15+
A key benefit of Azure Front Door is its native support for WebSocket and WebSocket Secure (WSS) connections. This enables real-time, bi-directional communication between clients and backend services without requiring any special configuration.
16+
17+
In this guide, we demonstrate how to use Azure Front Door with Azure SignalR Service to front-end your real-time applications. By routing traffic through Front Door, you can:
18+
- Leverage WebSocket support with global reach and edge acceleration,
19+
- Apply centralized security policies, such as WAF rules and rate limiting,
20+
- Reduce public exposure of your backend services.
21+
22+
As shown in the diagram, you’ll configure Azure Front Door to route WebSocket traffic to your SignalR-powered application backend. This setup ensures that your real-time functionality benefits from low-latency, scalable, and secure traffic handling through Azure’s global edge network.
23+
24+
This article contains two parts,
25+
26+
- [The first part](#set-up-and-configure-azure-front-door) shows how to configure Azure Front Door so that the clients can access SignalR through it.
27+
- [The second part](#secure-signalr-service) shows how to secure SignalR Service by adding access control to SignalR Service and only allow traffic from Azure Front Door.
28+
29+
:::image type="content" source="./media/signalr-howto-work-azure-front-door/architecture.jpg" alt-text="Diagram that shows the architecture of using SignalR Service with Azure Front Door.":::
30+
[!!!! Diagram missing !!!!]
31+
32+
33+
## Set up and configure Azure Front Door
34+
35+
### Create an Azure SignalR Service resource
36+
37+
Follow [the article](./signalr-quickstart-azure-signalr-service-arm-template.md) and create a SignalR Service resource
38+
39+
### Create an Azure Front Door resource
40+
41+
On the [Azure portal](https://portal.azure.com/), search for **Front Door** and **Create**.
42+
43+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/create-front-door.jpg" alt-text="Screenshot of creating an Azure Front Door resource.":::
44+
45+
46+
### Quick test
47+
Conduct quick tests to verify that SignalR endpoint is healthy and Azure Front Door resource is correctly configured.
48+
49+
- Send a request to `<your-SignalR-resource-endpoint>/client` and it should return _400_ with error message _'hub' query parameter is required._ This means that the request arrived at SignalR Service and the service performed validation as expected.
50+
```bash
51+
curl -v <your-SignalR-resource-endpoint>/client
52+
```
53+
returns
54+
```
55+
< HTTP/1.1 400 Bad Request
56+
< ...
57+
<
58+
'hub' query parameter is required.
59+
```
60+
- Send a request to the same health endpoint of Azure SignalR through Azure Front Door `http://<the-hostname-of-your-Azure-Front-Door-resource>/client`. Go to the Overview tab of the created Azure Front Door resource, and locate the endpoint hostname
61+
62+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/afd-hostname.jpg" alt-text="Screenshot of the the hostname of Azure Front Door resource":::
63+
64+
```bash
65+
curl -I http://<the-hostname-of-your-Azure-Front-Door-resource>/client
66+
```
67+
It should also return _400_ with error message _'hub' query parameter is required._ This confirms that the request successfully went through Azure Front Door to SignalR Service.
68+
69+
```
70+
< HTTP/1.1 400 Bad Request
71+
< ...
72+
<
73+
'hub' query parameter is required.
74+
```
75+
76+
### Run a SignalR sample app through Azure Front Door
77+
78+
Now that we have verified that the traffic can reach SignalR Service through Azure Front Door. Next, we use a barebone sample app to demonstrate Azure Front Door's ability to route WebSocket traffic without configuration. We take a step-by-step approach so that you can follow along, if needed.
79+
80+
#### Create the project
81+
```bash
82+
mkdir afd-demo
83+
cd afd-demo
84+
85+
touch afd-demo.csproj
86+
```
87+
88+
Paste in the content to the `afd-demo.csproj` file. This project uses only the "Microsoft.Azure.SignalR" package.
89+
```json
90+
<Project Sdk="Microsoft.NET.Sdk.Web">
91+
<PropertyGroup>
92+
<TargetFramework>net7.0</TargetFramework>
93+
<Nullable>enable</Nullable>
94+
<ImplicitUsings>enable</ImplicitUsings>
95+
<RootNamespace>afd_demo</RootNamespace>
96+
</PropertyGroup>
97+
<ItemGroup>
98+
<PackageReference Include="Microsoft.Azure.SignalR" Version="1.30.2" />
99+
</ItemGroup>
100+
</Project>
101+
```
102+
103+
#### Configure app settings
104+
Create an `appsettings.json` file and paste in the content below. The values will be referenced in the `Program.cs` file, which we create in the next step.
105+
```bash
106+
touch appsettings.json
107+
```
108+
109+
[!INCLUDE [Connection string security comment](includes/signalr-connection-string-security-comment.md)]
110+
111+
```json
112+
{
113+
"Azure": {
114+
"SignalR": {
115+
"ConnectionString": "<the-connection-string-of-your-Azure-SignalR-resource>"
116+
},
117+
"AFD": {
118+
"Endpoint": "<the-endpoint-of-your-Azure-Front-Door-resource>"
119+
}
120+
}
121+
}
122+
```
123+
124+
#### Create `Program.cs` file
125+
```bash
126+
touch Program.cs
127+
```
128+
129+
Paste in the code below to the `Program.cs` file. The web app defines a SignalR hub and serves `index.html` at the web root.
130+
```csharp
131+
using Microsoft.Azure.SignalR;
132+
var builder = WebApplication.CreateBuilder(args);
133+
134+
// Reads in the configuration from `appsettings.json`
135+
var azureSignalRConnectionString = builder.Configuration["Azure:SignalR:ConnectionString"];
136+
var afdEndpoint = builder.Configuration["Azure:AFD:Endpoint"];
137+
138+
builder.Services.AddSignalR().AddAzureSignalR(o =>
139+
{
140+
o.Endpoints = new Microsoft.Azure.SignalR.ServiceEndpoint[1]
141+
{
142+
new Microsoft.Azure.SignalR.ServiceEndpoint(azureSignalRConnectionString)
143+
{
144+
// Instructs SignalR server to return a `ClientEndpoint` to SignalR clients, with which they establish a connection. In our case, it's the endpoint of the Azure Front Door resource you just created.
145+
ClientEndpoint = new Uri(afdEndpoint),
146+
}
147+
};
148+
});
149+
150+
var app = builder.Build();
151+
app.UseStaticFiles();
152+
153+
app.UseRouting();
154+
155+
app.MapHub<DemoHub>("/demohub");
156+
157+
app.MapGet("/", async context =>
158+
{
159+
var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "index.html");
160+
context.Response.ContentType = "text/html";
161+
await context.Response.SendFileAsync(path);
162+
});
163+
164+
app.Run();
165+
```
166+
167+
#### Define a SignalR hub
168+
```bash
169+
mkdir hubs && cd hubs
170+
touch demohubs.cs
171+
```
172+
173+
Paste in the code below to the `demohubs.cs` file. For simplicity, the hub exposes only `BroadcastMessage` method to SignalR client, which broadcasts the received message to all connected SignalR clients.
174+
```csharp
175+
using Microsoft.AspNetCore.SignalR;
176+
177+
public class DemoHub : Hub
178+
{
179+
public Task BroadcastMessage(string message) =>
180+
Clients.All.SendAsync("broadcastMessage", message);
181+
}
182+
```
183+
184+
#### Define Web UI
185+
Make sure you're at the root of the project folder.
186+
```bash
187+
mkdir wwwroot && cd wwwroot
188+
touch index.html
189+
```
190+
191+
Paste in the code below to `index.html`. The user interface consists of a `<textarea>` to receive text input from user and a `<button>` to send the user input through a SignalR connection. Since we defined the SignalR server's behavior to broadcast received messages, you will see the same message logged to the browser console.
192+
```html
193+
<!DOCTYPE html>
194+
<html>
195+
196+
<head>
197+
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
198+
<meta name="viewport" content="width=device-width">
199+
<meta http-equiv="Pragma" content="no-cache" />
200+
<meta http-equiv="Expires" content="0" />
201+
<title>Azure SignalR with Azure Front Door as the reverse proxy</title>
202+
</head>
203+
204+
<body>
205+
<div>
206+
<textarea id="message" style="display: block; width: 100%; padding: 5px 10px; max-width: 400px; margin-bottom: 8px;"
207+
placeholder="Your message..."></textarea>
208+
<button id="btn-send" disabled>Send</button>
209+
</div>
210+
211+
<!--Reference the SignalR library. -->
212+
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
213+
214+
<script type="module">
215+
document.addEventListener("DOMContentLoaded", async function () {
216+
const connection = new signalR.HubConnectionBuilder()
217+
.withUrl("/demohub")
218+
.build();
219+
220+
connection.on("broadcastMessage", (msg) => {
221+
console.log(msg)
222+
})
223+
await connection.start();
224+
document.getElementById("btn-send").removeAttribute("disabled")
225+
226+
document.getElementById("btn-send").addEventListener("click", () => {
227+
const message = document.getElementById("message").value
228+
if (message !== "") {
229+
connection.send("broadcastMessage", message)
230+
document.getElementById("message").value = ""
231+
} else {
232+
alert("Message body is empty. Please enter message.")
233+
}
234+
})
235+
})
236+
</script>
237+
</body>
238+
239+
</html>
240+
```
241+
242+
#### Run the app and verify the flow of message through Azure Front Door
243+
That's all the code to the sample. Let's run the app.
244+
245+
```bash
246+
dotnet restore
247+
dotnet run
248+
```
249+
250+
Open http://localhost:5129 from the browser and use `F12` keyboard shortcut to open developer tools. Head to the network panel, you can see that the WebSocket connection is indeed established with Azure Front Door.
251+
252+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/network-panel-afd.jpg" alt-text="Screenshot of the running app establishing a WebSocket connection with Azure Front Door.":::
253+
254+
Try to type something in the text box and hit the send button. You will see the message is logged to browser console as expected.
255+
256+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/console-log.jpg" alt-text="Screenshot of the running app establishing a WebSocket connection with Azure Front Door.":::
257+
258+
You can also inspect the flow of messages in the network panel.
259+
260+
:::image type="content" source="./media/signalr-howto-work-with-azure-front-door/network-panel-flow-of-messages.jpg" alt-text="Screenshot of flow of messages in the network panel.":::
261+
262+
263+
## Secure SignalR Service
264+
265+

0 commit comments

Comments
 (0)