Skip to content

Commit 5550fd6

Browse files
committed
Add wildcard group permission
1 parent f32c9dc commit 5550fd6

8 files changed

Lines changed: 221 additions & 21 deletions

articles/azure-web-pubsub/concept-client-protocols.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: This article presents an overview of the client protocols for Azure
44
author: vicancy
55
ms.author: lianwei
66
ms.service: azure-web-pubsub
7-
ms.topic: conceptual
7+
ms.topic: conceptual
88
ms.date: 11/08/2021
99
ms.custom: sfi-ropc-nochange
1010
---
@@ -42,13 +42,13 @@ You could also configure properties for the client connection when generating th
4242

4343
You could also add custom claims into the access token, and these values are preserved as the `claims` property in [connect upstream request body](./reference-cloud-events.md#system-connect-event).
4444

45-
[Server SDKs](./howto-generate-client-access-url.md#generate-from-service-sdk) provides APIs to generate the access token for the clients.
45+
[Server SDKs](./howto-generate-client-access-url.md#generate-from-service-sdk) provides APIs to generate the access token for the clients.
4646

4747
<a name="simple_client"></a>
4848

4949
## The simple WebSocket client
5050

51-
A **simple WebSocket client**, as the naming indicates, is a simple WebSocket connection. It can also have its own custom subprotocol.
51+
A **simple WebSocket client**, as the naming indicates, is a simple WebSocket connection. It can also have its own custom subprotocol.
5252

5353
For example, in JavaScript, you can create a simple WebSocket client by using the following code:
5454

@@ -62,7 +62,7 @@ var client2 = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', '
6262

6363
Simple WebSocket client has two modes: `sendEvent` and `sendToGroup`. The mode is determined once the connection is established and cannot be changed later.
6464

65-
`sendEvent` is the default mode for the simple WebSocket client. In `sendEvent` mode, every WebSocket frame the client sent is considered as a `message` event. Users can configure [event handlers](./concept-service-internals.md#event-handler) or [event listeners](./concept-service-internals.md#event-listener) to handle these `message` events.
65+
`sendEvent` is the default mode for the simple WebSocket client. In `sendEvent` mode, every WebSocket frame the client sent is considered as a `message` event. Users can configure [event handlers](./concept-service-internals.md#event-handler) or [event listeners](./concept-service-internals.md#event-listener) to handle these `message` events.
6666

6767
```javascript
6868
// Every data frame is considered as a `message` event
@@ -102,7 +102,7 @@ var pubsubClient = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub
102102

103103
```js
104104
let ackId = 0;
105-
pubsubClient.send(
105+
pubsubClient.send(
106106
JSON.stringify({
107107
type: 'joinGroup',
108108
group: 'group1',
@@ -114,7 +114,7 @@ pubsubClient.send(
114114

115115
```js
116116
let ackId = 0;
117-
pubsubClient.send(
117+
pubsubClient.send(
118118
JSON.stringify({
119119
type: 'sendToGroup',
120120
group: 'group1',
@@ -191,6 +191,8 @@ As you likely noticed in the earlier PubSub WebSocket client description, a clie
191191
| `webpubsub.sendToGroup` | The client can publish messages to any group. |
192192
| `webpubsub.joinLeaveGroup.<group>` | The client can join or leave group `<group>`. |
193193
| `webpubsub.sendToGroup.<group>` | The client can publish messages to group `<group>`. |
194+
| `webpubsub.joinLeaveGroups.<pattern>` | The client can join/leave any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)). |
195+
| `webpubsub.sendToGroups.<pattern>` | The client can publish messages to any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)). |
194196
| | |
195197

196198
The permission of a client can be granted in several ways:
@@ -199,7 +201,7 @@ The permission of a client can be granted in several ways:
199201

200202
Client can connect to the service using a JWT. The token payload can carry information such as the `role` of the client. When signing the JWT to the client, you can grant permissions to the client by giving the client specific roles.
201203

202-
For example, let's sign a JWT that has the permission to send messages to `group1` and `group2`:
204+
For example, let's sign a JWT that has the permission to send messages to `group1` and `group2`:
203205

204206
```js
205207
let token = await serviceClient.getClientAccessToken({

articles/azure-web-pubsub/concept-service-internals.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ A client can publish to other clients only when it's _authorized_ to. The `role`
212212
| `webpubsub.sendToGroup` | The client can publish messages to any group. |
213213
| `webpubsub.joinLeaveGroup.<group>` | The client can join/leave group `<group>`. |
214214
| `webpubsub.sendToGroup.<group>` | The client can publish messages to group `<group>`. |
215+
| `webpubsub.joinLeaveGroups.<pattern>` | The client can join/leave any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)).
216+
| `webpubsub.sendToGroups.<pattern>` | The client can publish messages to any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)).
215217
216218
The server-side can also grant or revoke permissions of the client dynamically through [server protocol](#connection-manager) as to be illustrated in a later section.
217219
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
---
2+
title: Use wildcard group role patterns
3+
description: Learn how to grant Azure Web PubSub clients permissions to many groups using wildcard role patterns.
4+
author: kevinguo-ed
5+
ms.author: kevinguo
6+
ms.service: azure-web-pubsub
7+
ms.topic: conceptual
8+
ms.date: 10/14/2025
9+
ms.custom:
10+
---
11+
12+
# Use wildcard group role patterns
13+
14+
Azure Web PubSub now supports wildcard pattern matching in client "group" roles so you can authorize a client for many related groups with a single role string. This reduces token size, simplifies permission management, and improves performance versus enumerating many concrete group roles.
15+
16+
You can continue to use the existing literal roles:
17+
18+
- `webpubsub.sendToGroup.{groupName}`
19+
- `webpubsub.joinLeaveGroup.{groupName}`
20+
21+
But you can now also use the new pattern roles:
22+
23+
- `webpubsub.sendToGroups.{pattern}`
24+
- `webpubsub.joinLeaveGroups.{pattern}`
25+
26+
Where `{pattern}` follows the wildcard syntax below.
27+
28+
## When to use pattern roles
29+
30+
Use pattern roles when:
31+
32+
- A user or device must access a large but bounded dynamic set of groups (for example: all groups for a specific tenant or project)
33+
- You want to keep access tokens small (avoid listing dozens or hundreds of explicit group roles)
34+
35+
Avoid over-broad patterns (like `**`) unless absolutely required; follow the principle of least privilege.
36+
37+
## Pattern syntax
38+
39+
| Symbol | Meaning |
40+
| ------ | ------- |
41+
| `?` | Matches exactly one character except `/` |
42+
| `*` | Matches zero or more characters except `/` |
43+
| `**` | Matches zero or more characters including `/` (crosses path boundaries) |
44+
| `\` | Escape character for `\`, `*`, `?` |
45+
46+
Additional rules:
47+
48+
- `/` acts as a path separator and is never matched by `?` or `*` (only by `**`).
49+
- Use `**` sparingly; prefer narrower patterns (`clientA/*/chat`).
50+
- Up to five total `*` characters (including those forming `**`) are allowed in a single pattern.
51+
52+
### Examples
53+
54+
| Pattern | Matches | Does not match |
55+
| ------- | ------- | -------------- |
56+
| `chat-*` | `chat-1`, `chat-room` | `chat/1`, `xchat-1` |
57+
| `clientA/*` | `clientA/alpha`, `clientA/1` | `clientA/alpha/room1`, `clientB/alpha` |
58+
| `clientA/**` | `clientA/alpha`, `clientA/alpha/room1` | `clientB/anything` |
59+
| `clientA/rooms/?1` | `clientA/rooms/a1`, `clientA/rooms/11` | `clientA/rooms/1`, `clientA/rooms/a/1` |
60+
| `literal\*star` | `literal*star` | `literalXstar` |
61+
62+
### Escaping
63+
64+
Prefix `*`, `?`, or `\` with `\` to match the literal character. Example: `project\*123` matches only `project*123`.
65+
66+
## Using pattern roles in code
67+
68+
Add the pattern role to the `roles` collection when generating a client access token. The client then automatically has the implied permissions for matching groups.
69+
70+
## Code samples
71+
72+
# [JavaScript](#tab/javascript)
73+
74+
```js
75+
const token = await serviceClient.getClientAccessToken({
76+
roles: [
77+
// Can send to all groups under clientA/
78+
'webpubsub.sendToGroups.clientA/**',
79+
// Can join/leave any direct child group under clientA/public/
80+
'webpubsub.joinLeaveGroups.clientA/public/*'
81+
]
82+
});
83+
```
84+
85+
# [C#](#tab/csharp)
86+
87+
```csharp
88+
var url = service.GetClientAccessUri(roles: new [] {
89+
"webpubsub.sendToGroups.clientA/**",
90+
"webpubsub.joinLeaveGroups.clientA/public/*"
91+
});
92+
```
93+
94+
# [Python](#tab/python)
95+
96+
```python
97+
token = service.get_client_access_token(roles=[
98+
"webpubsub.sendToGroups.clientA/**",
99+
"webpubsub.joinLeaveGroups.clientA/public/*"
100+
])
101+
```
102+
103+
# [Java](#tab/java)
104+
105+
```java
106+
GetClientAccessTokenOptions opt = new GetClientAccessTokenOptions();
107+
opt.addRole("webpubsub.sendToGroups.clientA/**");
108+
opt.addRole("webpubsub.joinLeaveGroups.clientA/public/*");
109+
WebPubSubClientAccessToken token = service.getClientAccessToken(opt);
110+
```
111+
112+
---
113+
114+
## Security guidance
115+
116+
- Prefer the narrowest pattern that satisfies the scenario.
117+
118+
## Frequently asked questions
119+
120+
**Q: Can I mix literal and pattern roles?**
121+
Yes. A literal role always applies exactly; patterns add broader coverage.
122+
123+
124+
## Next steps
125+
126+
> [!div class="nextstepaction"]
127+
> [Generate client access URL and use roles](howto-generate-client-access-url.md)
128+
129+
> [!div class="nextstepaction"]
130+
> [Authorize access with Microsoft Entra ID](concept-azure-ad-authorization.md)

articles/azure-web-pubsub/howto-connect-mqtt-websocket-client.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ A client can publish to other clients only when it's *authorized* to do so. A cl
4343
| `webpubsub.sendToGroup` | The client can publish messages to any group. |
4444
| `webpubsub.joinLeaveGroup.<group>` | The client can join or leave group `<group>`. |
4545
| `webpubsub.sendToGroup.<group>` | The client can publish messages to group `<group>`. |
46+
| `webpubsub.joinLeaveGroups.<pattern>` | The client can join/leave any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)). |
47+
| `webpubsub.sendToGroups.<pattern>` | The client can publish messages to any group whose name matches `<pattern>` (see [Wildcard group role patterns](./concept-wildcard-group-roles.md)). |
4648
| | |
4749

4850
## Authentication and authorization

articles/azure-web-pubsub/howto-generate-client-access-url.md

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
8080
});
8181
```
8282

83+
- Configure pattern roles to cover many groups
84+
85+
```js
86+
let token = await serviceClient.getClientAccessToken({
87+
roles: [
88+
// send to any group under clientA/
89+
"webpubsub.sendToGroups.clientA/**",
90+
// join/leave any direct child of clientA/public/
91+
"webpubsub.joinLeaveGroups.clientA/public/*"
92+
]
93+
});
94+
```
95+
8396
- Configure a group `group1` that the client joins once it connects using this Client Access URL
8497

8598
```js
@@ -99,7 +112,7 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
99112
```csharp
100113
// for web pubsub native clients
101114
var url = service.GetClientAccessUri();
102-
115+
103116
// for mqtt clients
104117
var url = service.GetClientAccessUri(clientProtocol: WebPubSubClientProtocol.Mqtt);
105118
```
@@ -128,6 +141,15 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
128141
var url = service.GetClientAccessUri(roles: new string[] { "webpubsub.sendToGroup.group1" });
129142
```
130143

144+
- Configure pattern roles to cover many groups
145+
146+
```csharp
147+
var url = service.GetClientAccessUri(roles: new [] {
148+
"webpubsub.sendToGroups.clientA/**",
149+
"webpubsub.joinLeaveGroups.clientA/public/*"
150+
});
151+
```
152+
131153
- Configure a group `group1` that the client joins once it connects using this Client Access URL
132154

133155
```csharp
@@ -145,7 +167,7 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
145167
```python
146168
# for web pubsub native clients
147169
token = service.get_client_access_token();
148-
170+
149171
# for mqtt clients
150172
token = service.get_client_access_token(client_protocol="MQTT")
151173
```
@@ -174,6 +196,15 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
174196
token = service.get_client_access_token(roles=["webpubsub.sendToGroup.group1"])
175197
```
176198

199+
- Configure pattern roles to cover many groups
200+
201+
```python
202+
token = service.get_client_access_token(roles=[
203+
"webpubsub.sendToGroups.clientA/**",
204+
"webpubsub.joinLeaveGroups.clientA/public/*"
205+
])
206+
```
207+
177208
- Configure a group `group1` that the client joins once it connects using this Client Access URL
178209

179210
```python
@@ -233,6 +264,15 @@ The same Client Access URL can be generated by using the Web PubSub server SDK.
233264
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
234265
```
235266

267+
- Configure pattern roles to cover many groups
268+
269+
```java
270+
GetClientAccessTokenOptions option = new GetClientAccessTokenOptions();
271+
option.addRole("webpubsub.sendToGroups.clientA/**");
272+
option.addRole("webpubsub.joinLeaveGroups.clientA/public/*");
273+
WebPubSubClientAccessToken token = service.getClientAccessToken(option);
274+
```
275+
236276
- Configure a group `group1` that the client joins once it connects using this Client Access URL
237277

238278
```java
@@ -258,15 +298,15 @@ You could also use Microsoft Entra ID and generate the token by invoking [Genera
258298
1. Use the Microsoft Entra token to invoke `:generateToken`.
259299

260300
1. Gather the following information:
261-
301+
262302
| Value name | How to get the value |
263303
| --- | --- |
264304
| TenantId | TenantId is the value of **Directory (tenant) ID** on the **Overview** pane of the application you registered. |
265305
| ClientId | ClientId is the value of **Application (client) ID** from the **Overview** pane of the application you registered. |
266306
| ClientSecret | ClientSecret is the value of the client secret you just added in step #1 |
267-
307+
268308
1. Get the Microsoft Entra ID token from Microsoft identity platform
269-
309+
270310
We use [CURL](https://curl.se/) tool to show how to invoke the REST APIs. The tool is bundled into Windows 10/11, and you could install the tool following [Install CURL](https://curl.se/download.html).
271311

272312
```bash
@@ -316,3 +356,6 @@ You could also use Microsoft Entra ID and generate the token by invoking [Genera
316356
"token": "ABCDEFG.ABC.ABC"
317357
}
318358
```
359+
360+
> [!TIP]
361+
> See [Wildcard group role patterns](concept-wildcard-group-roles.md) for syntax, escaping, and security guidance.

articles/azure-web-pubsub/includes/reference-permission.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
author: vicancy
33
ms.author: lianwei
44
ms.service: azure-web-pubsub
5-
ms.topic: include
6-
ms.date: 01/24/2023
5+
ms.topic: include
6+
ms.date: 10/14/2025
77
---
88

99
## Permissions
@@ -17,5 +17,7 @@ A PubSub WebSocket client can only publish to other clients when it's authorized
1717
| `webpubsub.sendToGroup` | The client can publish messages to any group.
1818
| `webpubsub.joinLeaveGroup.<group>` | The client can join/leave the group `<group>`.
1919
| `webpubsub.sendToGroup.<group>` | The client can publish messages to the group `<group>`.
20+
| `webpubsub.joinLeaveGroups.<pattern>` | The client can join/leave any group whose name matches `<pattern>` (see [Wildcard group role patterns](../concept-wildcard-group-roles.md)).
21+
| `webpubsub.sendToGroups.<pattern>` | The client can publish messages to any group whose name matches `<pattern>` (see [Wildcard group role patterns](../concept-wildcard-group-roles.md)).
2022

2123
The server can dynamically grant or revoke client permissions through REST APIs or server SDKs.

articles/azure-web-pubsub/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@
251251
href: concept-billing-model.md
252252
- name: Microsoft Entra Authorization
253253
href: concept-azure-ad-authorization.md
254+
- name: Wildcard group role patterns
255+
href: concept-wildcard-group-roles.md
254256
- name: Metrics
255257
href: concept-metrics.md
256258
- name: Security

0 commit comments

Comments
 (0)