Configure Event Grid Namespaces | Run the Sample |
This scenario showcases how to authenticate to Azure Event Grid via JWT authentication using MQTT 5. This scenario is identical to getting_started
in functionality.
JWT authentication is documented in Microsoft Entra JWT authentication and Azure RBAC authorization to publish or subscribe MQTT messages from Event Grid documentation.
To keep the scenario simple, a single client called "sample_client" publishes and subscribes to MQTT messages on topics shown in the table.
Client | Role | Operation | Topic/Topic Filter |
---|---|---|---|
sample_client | publisher | publish | jwt/topic1 |
sample_client | subscriber | subscribe | jwt/+ |
This sample involves configuring Event Grid per the specifications in setup, but does not require CA certificates to be configured.
Run the commands to create the "jwt" topic space, and the two permission bindings that provide publish and subscribe access to $all client group on the samples topic space.
# from folder scenarios/jwt_authentication
source ../../az.env
az resource create --id "$res_id/topicSpaces/jwt" --properties '{
"topicTemplates": ["jwt/#"]
}'
The required .env
files can be configured manually, we provide the script below as a reference to create those files, as they are ignored from git.
# from folder scenarios/jwt_authentication
source ../../az.env
host_name=$(az resource show --ids $res_id --query "properties.topicSpacesConfiguration.hostname" -o tsv)
echo "MQTT_HOST_NAME=$host_name" > .env
echo "MQTT_USERNAME=sample_client" >> .env
echo "MQTT_CLIENT_ID=sample_client" >> .env
echo "AZURE_CLIENT_ID=<your client Id>" >> .env
echo "AZURE_TENANT_ID=<your tennant Id>" >> .env
echo "AZURE_CLIENT_SECRET<your client secret>" >> .env
Event Grid namespaces supports JWT authentication for Managed Identities and Service principals only:
-
Managed Identity. You can use a Managed identity provided by many Azure services, such as Azure Container Apps, Azure Container Instances, Azure Kubernetes Services or Azure Web Apps, full list is available here.
-
Service Principal. You can create your own Service Principal by creating an Application Registration in Microsoft Entra ID.
To create the service principal and the secret using the Azure CLI:
clientId=$(az ad app create --display-name "MyMqttSamplesApp" --query appId -o tsv)
spId=$(az ad sp create --id $clientId --query id -o tsv)
az ad app credential reset --id $clientId --append
take note of the appId, password and tenant values returned from the previous command.
Note. You can use these values as environment variables for dotnet by using the launchSettings.json file
In Azure EventGrid Namespaces, assign permissions to the Microsoft Entra ID identity using the built-in roles Event Grid Topic Spaces Publisher/Subscriber
.
# from folder scenarios/jwt_authentication
source ../../az.env
az role assignment create \
--assignee $spId \
--role "EventGrid TopicSpaces Publisher" \
--scope $res_id
az role assignment create \
--assignee $spId \
--role "EventGrid TopicSpaces Subscriber" \
--scope $res_id
By assigning these roles to an Azure subscription, it allows that subscription to communicate with any Topic Space within an instance of Event Grid owned by the specified Service Principal (e.g., if these roles are assigned at a subscription level, any Topic Space of an Event Grid under the given subscription could be subscribed/published to).
An alternative to using Azure CLI is the Azure Portal:
- Locate the resource group that contains the desired instance of Event Grid.
- Navigate to
Access control (IAM)
blade. - Under
Role Assignments
, clickAdd
, and assignEvent Grid Topic Spaces Publisher/Subscriber
roles. - Assign the role to the desired Azure account, and click
Review + Assign
.
All samples are designed to be executed from the root scenario folder.
To build the dotnet sample run:
# from folder scenarios/jwt_authenticaton
dotnet build dotnet/jwt_authentication.sln
To run the dotnet sample:
dotnet/jwt_authentication/bin/Debug/net7.0/jwt_authentication
To connect using WebSockets, modify client's ConnectAsync()
call as follows:
MqttClientConnectResult connAck = await mqttClient!.ConnectAsync(new MqttClientOptionsBuilder()
.WithClientId("sample_client")
//.WithTcpServer(hostname, 8883)
.WithWebSocketServer(b => b.WithUri($"{hostname}:443/mqtt"))
.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500)
.WithAuthentication("OAUTH2-JWT", Encoding.UTF8.GetBytes(jwt.Token))
.WithTlsOptions(new MqttClientTlsOptions() { UseTls = true })
.Build());
Note that it is required to use port 443 for websocket connections. To learn more about this flow visit the documentation.