Skip to content

Commit 595a81c

Browse files
authored
Improve documents
1 parent 96ca116 commit 595a81c

File tree

2 files changed

+142
-3
lines changed

2 files changed

+142
-3
lines changed

articles/azure-web-pubsub/socketio-serverless-function-binding.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ The attribute for input binding is `[SocketIONegotiation]`.
102102
|---------|---------|
103103
| Hub | The hub name that a client needs to connect to. |
104104
| Connection | The name of the app setting that contains the Socket.IO connection string (defaults to "WebPubSubForSocketIOConnectionString"). |
105+
| UserId | The userId of the connection. It applys to all sockets in the connection. It becomes the `sub` claim in the generated token. |
105106

106107
# [JavaScript Model v4](#tab/javascript-v4)
107108

@@ -139,6 +140,7 @@ app.http('negotiate', {
139140
| name | Variable name used in function code for input connection binding object |
140141
| hub | The hub name that a client needs to connect to. |
141142
| connection | The name of the app setting that contains the Socket.IO connection string (defaults to "WebPubSubForSocketIOConnectionString"). |
143+
| userId | The userId of the connection. It applys to all sockets in the connection. It becomes the `sub` claim in the generated token. |
142144

143145
---
144146

articles/azure-web-pubsub/socketio-serverless-protocol.md

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,20 @@ Explanations of the previous sample:
4141
- The `<hub-name>` in `path` is a concept in Web PubSub for Socket.IO, which provides isolation between hubs.
4242
- The `<access-token>` is a JWT used to authenticate with the service. See (How to generate access token)[] for details.
4343

44-
### Authentication
44+
### Authentication flow
4545

4646
When a client attempts to connect to the service, the process is divided into two distinct steps: establishing an Engine.IO (physical) connection and connecting to a namespace, which is referred to as a socket in Socket.IO terminology. The authentication process differs between these two steps:
4747

4848
1. **Engine.IO connection**: During this step, the service authenticates the client using an access token to determine whether to accept the connection. If the corresponding hub is configured to allow anonymous mode, the Engine.IO connection can proceed without validating the access token. However, for security reasons, it's recommended to disable anonymous mode in production environments.
4949

50+
- The Engine.IO connection url follow the format as shown below. But in most cases, it should be handled by Socket.IO client library.
51+
52+
```
53+
http://<service-endpoint>/clients/socketio/hubs/<hub-name>/?access_token=<access-token>
54+
```
55+
56+
- The details of access token can be found in [here](#authentication-details)
57+
5058
2. **Socket**: After the Engine.IO connection is successfully established, the client SDK sends a payload to connect to a namespace. Upon receiving the socket connect request, the service triggers a connect call to the event handler. The outcome of this step depends on the status code returned by the connect response: a 200 status code indicates that the socket is approved, while a 4xx or 5xx status code results in the socket being rejected.
5159
5260
3. Once a socket is connected, the service triggers a connected call to the event handler. It's an asynchronized call to notify the event handler a socket is successfully connected.
@@ -75,6 +83,89 @@ The event handler may respond with a body like `{ type: ACK, namespace: "/", dat
7583

7684
Client disconnects from a namespace or the corresponding Engine.IO connection closes results in socket close. Service triggers a disconnected event for every disconnected socket. It's an asynchronized call for notification.
7785

86+
## Authentication Details
87+
88+
The service uses bearer token to authenticate. There're two main scenario to use the token.
89+
90+
- Connect of Engine.IO connection. The following request is an example.
91+
92+
```
93+
https://<service-endpoint>/clients/socketio/hubs/<hub-name>/?access_token=<access-token>
94+
```
95+
96+
- RESTful request to send messages or manage connections. The following request is an example.
97+
98+
```
99+
POST {endpoint}/api/hubs/{hub}/:removeFromGroups?api-version=2024-01-01
100+
101+
Headers:
102+
Authorization: Bearer <token>
103+
```
104+
105+
The generation of token can also be devided into two categories: key based authenitcation or identity based authentication.
106+
107+
### **Key based authentication**
108+
109+
The JWT format:
110+
111+
**Header**
112+
113+
```text
114+
{
115+
"alg": "HS256",
116+
"typ": "JWT"
117+
}
118+
```
119+
120+
**Payload**
121+
122+
```text
123+
{
124+
"nbf": 1726196900,
125+
"exp": 1726197200,
126+
"iat": 1726196900,
127+
"aud": "https://sample.webpubsub.azure.com/api/hubs/hub/groups/0~Lw~/:send?api-version=2024-01-01",
128+
"sub": "userId"
129+
}
130+
```
131+
132+
`aud` should keep consistent with the url which you're requesting.
133+
134+
`sub` is the userId of connection. Only available for the Engine.IO connection request.
135+
136+
**Signature**
137+
138+
```text
139+
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), <AccessKey>)
140+
```
141+
142+
The `AccessKey` can be get from the service Azure Portal or from the Azure Cli:
143+
144+
```azcli
145+
az webpubsub key show -g <resource-group> -n <resource-name>
146+
```
147+
148+
### **Identity based authentication**
149+
150+
#### Token for RESTful API
151+
152+
Identity based authentication uses an [`access token`](/entra/identity-platform/access-tokens) signed by Microsoft identity platform.
153+
154+
The application which is used to request a token must use the resource `https://webpubsub.azure.com` or scope `https://webpubsub.azure.com/.default`. And it needs to be granted `Web PubSub Service Owner` Role. For more detail, see [Authorize access to Web PubSub resources using Microsoft Entra ID](./concept-azure-ad-authorization.md)
155+
156+
#### Token for Engine.IO connection
157+
158+
Different from the RESTful API, Engine.IO connection doesn't use the Entra ID token directly. Instead, you must make a RESTful call to the service to get a token and use the returned token as the access token for client.
159+
160+
```Http
161+
POST {endpoint}/api/hubs/{hub}/:generateToken?api-version=2024-01-01
162+
163+
Headers:
164+
Authorization: Bearer <Entra ID Token>
165+
```
166+
167+
For more optional parameters, see [Generate Client Token](/rest/api/webpubsub/dataplane/web-pub-sub/generate-client-token)
168+
78169
## Supported functionality and RESTful APIs
79170

80171
A server can use RESTful APIs to manage Socket.IO clients and send message to clients as well. As Socket.IO reuses the Web PubSub service RESTful APIs, Socket.IO terminology is transformed into Web PubSub terminology. The following documents elaborate the transformation.
@@ -117,6 +208,10 @@ A Socket ID uniquely identifies a socket connection. According to the Socket.IO
117208

118209
```Http
119210
POST {endpoint}/api/hubs/{hub}/:addToGroups?api-version=2024-01-01
211+
212+
Headers:
213+
Authorization: Bearer <access token>
214+
Content-Type: application/json
120215
```
121216

122217
#### Request Body
@@ -136,8 +231,13 @@ Add socket `socketId` in namespace `/ns` to room `rm` in hub `myHub`.
136231
```HTTP
137232
POST {endpoint}/api/hubs/myHub/:addToGroups?api-version=2024-01-01
138233
234+
Headers:
235+
Authorization: Bearer <access token>
236+
Content-Type: application/json
237+
238+
Body:
139239
{
140-
"filter": "'0~L25z~c29ja2V0SWQ' in groups"
240+
"filter": "'0~L25z~c29ja2V0SWQ' in groups",
141241
"groups": [ "'0~L25z~cm0" ]
142242
}
143243
```
@@ -146,6 +246,10 @@ POST {endpoint}/api/hubs/myHub/:addToGroups?api-version=2024-01-01
146246

147247
```Http
148248
POST {endpoint}/api/hubs/{hub}/:removeFromGroups?api-version=2024-01-01
249+
250+
Headers:
251+
Authorization: Bearer <access token>
252+
Content-Type: application/json
149253
```
150254

151255
#### Request Body
@@ -165,8 +269,13 @@ Remove socket `socketId` in namespace `/ns` from room `rm` in hub `myHub`.
165269
```HTTP
166270
POST {endpoint}/api/hubs/myHub/:removeFromGroups?api-version=2024-01-01
167271
272+
Headers:
273+
Authorization: Bearer <access token>
274+
Content-Type: application/json
275+
276+
Body:
168277
{
169-
"filter": "'0~L25z~c29ja2V0SWQ' in groups"
278+
"filter": "'0~L25z~c29ja2V0SWQ' in groups",
170279
"groups": [ "'0~L25z~cm0" ]
171280
}
172281
```
@@ -176,6 +285,8 @@ POST {endpoint}/api/hubs/myHub/:removeFromGroups?api-version=2024-01-01
176285
```Http
177286
POST {endpoint}/api/hubs/{hub}/groups/{group}/:send?api-version=2024-01-01
178287
288+
Headers:
289+
Authorization: Bearer <access token>
179290
Content-Type: text/plain
180291
```
181292

@@ -202,6 +313,11 @@ socket.on('eventName', (arg1, arg2) => {
202313
```HTTP
203314
POST {endpoint}/api/hubs/myHub/groups/0~L25z~c29ja2V0SWQ/:send?api-version=2024-01-01
204315
316+
Headers:
317+
Authorization: Bearer <access token>
318+
Content-Type: text/plain
319+
320+
Body:
205321
42/ns,["eventName","arg1","arg2"]
206322
```
207323

@@ -210,6 +326,8 @@ POST {endpoint}/api/hubs/myHub/groups/0~L25z~c29ja2V0SWQ/:send?api-version=2024-
210326
```Http
211327
POST {endpoint}/api/hubs/{hub}/groups/{group}/:send?api-version=2024-01-01
212328
329+
Headers:
330+
Authorization: Bearer <access token>
213331
Content-Type: text/plain
214332
```
215333

@@ -236,6 +354,11 @@ socket.on('eventName', (arg1, arg2) => {
236354
```HTTP
237355
POST {endpoint}/api/hubs/myHub/groups/0~L25z~cm0/:send?api-version=2024-01-01
238356
357+
Headers:
358+
Authorization: Bearer <access token>
359+
Content-Type: text/plain
360+
361+
Body:
239362
42/ns,["eventName","arg1","arg2"]
240363
```
241364

@@ -244,6 +367,8 @@ POST {endpoint}/api/hubs/myHub/groups/0~L25z~cm0/:send?api-version=2024-01-01
244367
```Http
245368
POST {endpoint}/api/hubs/{hub}/groups/{group}/:send?api-version=2024-01-01
246369
370+
Headers:
371+
Authorization: Bearer <access token>
247372
Content-Type: text/plain
248373
```
249374

@@ -270,6 +395,11 @@ socket.on('eventName', (arg1, arg2) => {
270395
```HTTP
271396
POST {endpoint}/api/hubs/myHub/groups/0~L25z~/:send?api-version=2024-01-01
272397
398+
Headers:
399+
Authorization: Bearer <access token>
400+
Content-Type: text/plain
401+
402+
Body:
273403
42/ns,["eventName","arg1","arg2"]
274404
```
275405

@@ -278,6 +408,8 @@ POST {endpoint}/api/hubs/myHub/groups/0~L25z~/:send?api-version=2024-01-01
278408
```Http
279409
POST {endpoint}/api/hubs/{hub}/groups/{group}/:send?api-version=2024-01-01
280410
411+
Headers:
412+
Authorization: Bearer <access token>
281413
Content-Type: text/plain
282414
```
283415

@@ -296,6 +428,11 @@ Disconnect socket `socketId` in namespace `/ns` in hub `myHub`.
296428
```HTTP
297429
POST {endpoint}/api/hubs/myHub/groups/0~L25z~c29ja2V0SWQ/:send?api-version=2024-01-01
298430
431+
Headers:
432+
Authorization: Bearer <access token>
433+
Content-Type: text/plain
434+
435+
Body:
299436
41/ns,
300437
```
301438

0 commit comments

Comments
 (0)