-
Notifications
You must be signed in to change notification settings - Fork 29
Sample with JWT #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
patilsnr
wants to merge
10
commits into
main
Choose a base branch
from
npatilsen/aadSample
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Sample with JWT #68
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
f96d5a1
jwt rbac outline
patilsnr 90cd1e0
jwt sample running
patilsnr 96651f7
cleanup
patilsnr 3200f94
Update README.md
patilsnr 48127c9
Update README.md
patilsnr f5a7c98
Update README.md
patilsnr b07f784
comments
patilsnr a18c16c
misc
patilsnr d111358
Merge branch 'main' into npatilsen/aadSample
patilsnr d6bdf0b
Update README.md with websocket info
patilsnr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| # :point_right: JWT Authentication to Event Grid | ||
|
|
||
| | [Create the Client Certificate](#lock-create-the-client-certificate) | [Configure Event Grid Namespaces](#triangular_ruler-configure-event-grid-namespaces) | [Configure Mosquitto](#fly-configure-mosquitto) | [Run the Sample](#game_die-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. | ||
|
|
||
| The sample provides step by step instructions on how to perform following tasks: | ||
|
|
||
| - Create the resources including client, topic spaces, permission bindings | ||
| - Use $all client group, which is the default client group with all the clients in a namespace, to authorize publish and subscribe access in permission bindings | ||
| - Create a custom role assignment on the Azure Portal to access Event Grid via Json Web Token (JWT) authentication. | ||
| - Create a JWT, which is used to authenticate to Event Grid. | ||
| - Connect with MQTT 5.0.0 | ||
| - Configure connection settings such as KeepAlive and CleanSession | ||
| - Publish messages to a topic | ||
| - Subscribe to a topic to receive messages | ||
|
|
||
| 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|sample/topic1| | ||
| |sample_client|subscriber|subscribe|sample/+| | ||
|
|
||
| ## Prerequisites | ||
| This sample involves configuring Event Grid per the specifications in [getting_started](../getting_started). If that sample has not already been set up and run, it should be done before moving onto this one. | ||
|
|
||
| ## :lock: Configure the Json Web Token and AAD Role Assignments | ||
|
|
||
| 1. Modify the following JSON snippet by adding an Azure subscription Id: | ||
|
|
||
| ```json | ||
| { | ||
| "properties": { | ||
| "roleName": "Event Grid Pub-Sub", | ||
| "description": "communicate with Event Grid.", | ||
| "assignableScopes": [ | ||
| "/subscriptions/<YOUR SUBSCRIPTION ID HERE>" | ||
| ], | ||
| "permissions": [ | ||
| { | ||
| "actions": [], | ||
| "notActions": [], | ||
| "dataActions": [ | ||
| "Microsoft.EventGrid/*" | ||
| ], | ||
| "notDataActions": [] | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
| 2. Copy the modified snippet and save it locally. | ||
| 3. In the Azure portal, go to your Resource Group that contains Event Grid and open the Access control (IAM) page. | ||
| 4. Click Add and then click Add custom role. This opens the custom roles editor. | ||
| 5. On the `Basics` tab, select `Start from JSON`, and upload the modified JSON file you saved locally. | ||
| 6. Select the `Review and Create` tab and then `Create`. | ||
| 7. **NOTE:** It is possible that your Azure account may not have room for more custom role assignments. In this instance the current workaround is to create a free Azure account and complete this process while logged in from there. | ||
|
|
||
| ## :triangular_ruler: Configure Event Grid Namespaces (Skip if [getting_started](../getting_started) has already been properly configured) | ||
|
|
||
| Ensure to create an Event Grid namespace by following the steps in [setup](../setup). Event Grid namespace requires registering the client, and the topic spaces to authorize the publish/subscribe permissions. | ||
|
|
||
| ### Create the Client (Skip if [getting_started](../getting_started) has already been properly configured) | ||
|
|
||
| We will use the SubjectMatchesAuthenticationName validation scheme for `sample_client`. Instructions for how to do this can be found in [getting_started](../getting_started). If this has already been done once, it does not have to be done again (unless using a different Azure account). | ||
|
|
||
| ### Create topic spaces and permission bindings | ||
| Run the commands to create the "samples" topic space, and the two permission bindings that provide publish and subscribe access to $all client group on the samples topic space. As for above, the instructions to do this are part of [getting_started](../getting_started) and do not have to be repeated if they have already been done in the Azure account being used to run this sample. | ||
|
|
||
| ## :game_die: Run the Sample | ||
|
|
||
| All samples are designed to be executed from the root scenario folder. | ||
|
|
||
| ### dotnet | ||
|
|
||
| To build the dotnet sample run: | ||
|
|
||
| ```bash | ||
| # from folder scenarios/jwt_authenticaton | ||
| dotnet build dotnet/jwt_authentication.sln | ||
| ``` | ||
|
|
||
| To run the dotnet sample: | ||
|
|
||
| ```bash | ||
| dotnet/jwt_authentication/bin/Debug/net7.0/jwt_authentication | ||
| ``` | ||
|
|
||
| ## Connecting over WebSocket | ||
| To connect using WebSockets, modify client's `ConnectAsync()` call as follows: | ||
| ```csharp | ||
| 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](https://learn.microsoft.com/azure/event-grid/mqtt-support#connection-flow). |
25 changes: 25 additions & 0 deletions
25
scenarios/jwt_authentication/dotnet/jwt_authentication.sln
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.0.31903.59 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "jwt_authentication", "jwt_authentication\jwt_authentication.csproj", "{64CD6647-A322-4F5C-AFD1-3B657CE65FA5}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {64CD6647-A322-4F5C-AFD1-3B657CE65FA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {64CD6647-A322-4F5C-AFD1-3B657CE65FA5}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {64CD6647-A322-4F5C-AFD1-3B657CE65FA5}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {64CD6647-A322-4F5C-AFD1-3B657CE65FA5}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ExtensibilityGlobals) = postSolution | ||
| SolutionGuid = {7A2246F6-BDDC-4173-AD14-FD2DC0F879D0} | ||
| EndGlobalSection | ||
| EndGlobal |
39 changes: 39 additions & 0 deletions
39
scenarios/jwt_authentication/dotnet/jwt_authentication/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| using MQTTnet; | ||
| using MQTTnet.Client; | ||
| using MQTTnet.Client.Extensions; | ||
| using System.Text; | ||
| using Azure.Identity; | ||
| using Azure.Core; | ||
|
|
||
| // Create client | ||
| IMqttClient mqttClient = new MqttFactory().CreateMqttClient(MqttNetTraceLogger.CreateTraceLogger()); | ||
| string hostname = "<Event Grid Mqtt Hostname Here>"; | ||
|
|
||
| // Create JWT | ||
| var defaultCredential = new DefaultAzureCredential(); | ||
|
|
||
| // Sets the audience field of the JWT to Event Grid | ||
| var tokenRequestContext = new TokenRequestContext(new string[] { "https://eventgrid.azure.net/" }); | ||
| AccessToken jwt = defaultCredential.GetToken(tokenRequestContext); | ||
|
|
||
| // Required to use port 8883: https://learn.microsoft.com/azure/event-grid/mqtt-support | ||
| MqttClientConnectResult connAck = await mqttClient!.ConnectAsync(new MqttClientOptionsBuilder() | ||
| .WithClientId("sample_client") | ||
| .WithTcpServer(hostname, 8883) | ||
| .WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V500) | ||
| .WithAuthentication("OAUTH2-JWT", Encoding.UTF8.GetBytes(jwt.Token)) | ||
| .WithTlsOptions(new MqttClientTlsOptions() { UseTls = true }) | ||
| .Build()); | ||
|
|
||
| Console.WriteLine($"Client Connected: {mqttClient.IsConnected} with CONNACK: {connAck.ResultCode}"); | ||
|
|
||
| mqttClient.ApplicationMessageReceivedAsync += async m => await Console.Out.WriteAsync( | ||
| $"Received message on topic: '{m.ApplicationMessage.Topic}' with content: '{m.ApplicationMessage.ConvertPayloadToString()}'\n\n"); | ||
|
|
||
| MqttClientSubscribeResult suback = await mqttClient.SubscribeAsync("sample/+", MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); | ||
| suback.Items.ToList().ForEach(s => Console.WriteLine($"subscribed to '{s.TopicFilter.Topic}' with '{s.ResultCode}'")); | ||
|
|
||
| MqttClientPublishResult puback = await mqttClient.PublishStringAsync("sample/topic1", "hello world!", MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce); | ||
| Console.WriteLine(puback.ReasonString); | ||
|
|
||
| Console.ReadLine(); | ||
21 changes: 21 additions & 0 deletions
21
scenarios/jwt_authentication/dotnet/jwt_authentication/jwt_authentication.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net7.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Azure.Identity" Version="1.10.1" /> | ||
| <PackageReference Include="MQTTnet" Version="4.3.1.873" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <Reference Include="MQTTnet.Client.Extensions"> | ||
| <HintPath>..\..\..\..\mqttclients\dotnet\MQTTnet.Client.Extensions\bin\Debug\net7.0\MQTTnet.Client.Extensions.dll</HintPath> | ||
| </Reference> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.