Eduard Keilholz

Hi, my name is Eduard Keilholz. I'm a Microsoft developer working at 4DotNet in The Netherlands. I like to speak at conferences about all and nothing, mostly Azure (or other cloud) related topics.
LinkedIn | Twitter | Mastodon | Bsky


I received the Microsoft MVP Award for Azure

Eduard Keilholz
HexMaster's Blog
Some thoughts about software development, cloud, azure, ASP.NET Core and maybe a little bit more...

Azure Web Pubsub - Advanced Scenarios

In my previous post, I showed how Azure Web PubSub works and how to connect, send messages and receive messages. I also explained groups and how you can create and join groups. In this post, I will start from there and make life a lot easier working with groups.

Scroll down if you want to see an Azure Web PubSub demo in action.

Custom protocols

There are two sub-protocols that come out of the box with Azure Web PubSub: The JSON WebSocket subprotocol and the Protobuf WebSocket subprotocol. These protocols empower you to use the publish and subscribe pattern more efficient because no round trip to the server is required anymore.

This way, clients (front-ends) are now enabled to join and leave groups when desired. But not only that, the protocols also allow sending messages directly targetting a group, from the clients.

But hey hold on, how about permissions? Yes! Good question, those permissions are controlled at the time the connection was created. Let’s dig a little but into how connections are created.

Connecting to PubSub

When you create a connection like in the example of my previous post, a URL is generated, including a JWT Token that contains information about the connection. For example, when you connect using a a userId, the JWT Token will also contain that userId. Additionally, you can also add roles. With these roles you can control the groups that connections can join and/or send messages to. These roles are webpubsub.sendToGroup and webpubsub.joinLeaveGroup.

Using the roles names above, clients can join/leave all groups and send messages to all groups. You can also choose to control which groups in a more finegrained fashion, by adding the name of the groups like so: webpubsub.sendToGroup.group1 and webpubsub.joinLeaveGroup.group1. You can add an array of roles, as desired. If you don’t add these roles, clients will receive a Forbidden response when trying to join/leave or publish to a group.

var psClient = new WebPubSubServiceClient(
    webPubSubConnectionString,
    pubSubHubName);

var clientConnectionInformation = await psClient.GetClientAccessUriAsync(
    userId: userId,
    roles: new[]
    {
        $"webpubsub.sendToGroup.group1",
        $"webpubsub.joinLeaveGroup.group1"
    });

Connecting from the client-side

Adding the roles to the connection information, doesn’t say anything about a protocol used for the WebSocket. You set the protocol, client-side when creating the WebSocket object like so:

let ws = new WebSocket(clientConnectionInformation, "json.webpubsub.azure.v1");

Now you have enabled the JSON WebSocket subprotocol. That allows you to join and leave groups from the client, and also send messages directly to a group. The protocol allows messages in certain structures. For example, to join a group you can send a message that looks like so:

{
  "type": "joinGroup",
  "group": "group1"
}

Alternatively, for leaving a group you send a similar message but with a type of leaveGroup in stead of joinGroup. You can also request the server to send a confimation back after the commands are published successfully by generating an acknowledgement ID. This ID will be used to send a confirmation message back.

{
  "type": "joinGroup",
  "group": "group1",
  "ackId": 1
}

To send such a command, you need to convert the JSON object to a string, and send that string using the ws.send() method.

ws.send(
  JSON.stringify({
    type: "joinGroup",
    group: "group1",
    ackId: 1,
  })
);

Sending messages to a group

To send a message to a group, you use the message type sendToGroup. You can choose whether you (as a sender of the message) want to receive the message yourself, or just all the others in the group with the noEcho property.

{
    "type": "sendToGroup",
    "group": "group1",
    "ackId" : 2,
    "noEcho": true|false,
    "dataType" : "json|text|binary",
    "data": {},
}

The content of the data object, should match the data type specified in the dataType property.

Conclusion

You can now join and leave groups, and send messages to groups directly from a client. This was not possible without the sub-protocol. As mentioned in my first post about Azure Web PubSub, these functionalities are available when you use a client library. But in fact, I believe Azure Web PubSub shines when you can leave those libaries out and use JavaScript’s native WebSocket object instead.

Demonstration

As a demonstration, I created an Angular App for Planning Poker. You can start a new session and share the session code with your colleagues. Your colleagues can join using that session code. You can now start planning poker sessions. There is no backend involved except for creating client connections. The source for the backend (Azure Functions) project can be found in GitHub as well as the source for the Angular project. Want to see the project in action? -this-link-is-gone-.