Skip to content

Commit 9f80ebe

Browse files
authored
Merge pull request #244442 from henrymbuguakiarie/ciam-dotnet-maui-rbac
[CIAM] Add app roles to .NET MAUI app and receive them in the ID token (ADO-124246)
2 parents b95c3d9 + 1cadb0b commit 9f80ebe

File tree

5 files changed

+194
-40
lines changed

5 files changed

+194
-40
lines changed

articles/active-directory/external-identities/customers/toc.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ items:
202202
href: tutorial-desktop-app-maui-sign-in-prepare-app.md
203203
- name: Sign in and sign out
204204
href: tutorial-desktop-app-maui-sign-in-sign-out.md
205+
- name: Use role-based access control
206+
href: tutorial-desktop-maui-role-based-access-control.md
205207
- name: .NET WPF
206208
items:
207209
- name: Prepare tenant
@@ -219,6 +221,8 @@ items:
219221
href: tutorial-mobile-app-maui-sign-in-prepare-app.md
220222
- name: Sign in and sign out
221223
href: tutorial-mobile-app-maui-sign-in-sign-out.md
224+
- name: Use role-based access control
225+
href: tutorial-mobile-maui-role-based-access-control.md
222226
- name: Command-line interface (CLI) app
223227
items:
224228
- name: Node.js - sign in users

articles/active-directory/external-identities/customers/tutorial-desktop-app-maui-sign-in-sign-out.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ The next steps will organize our code so that the `main view` is defined.
4747
1. Select **Add**.
4848
1. The _MainView.xaml_ file will open in a new document tab, displaying all of the XAML markup that represents the UI of the page. Replace the XAML markup with the following markup:
4949

50-
5150
:::code language="xaml" source="~/ms-identity-ciam-dotnet-tutorial/1-Authentication/2-sign-in-maui/Views/MainView.xaml" :::
5251

5352
1. Save the file.
@@ -69,7 +68,7 @@ The next step is to add the code for the button's `Clicked` event.
6968

7069
:::code language="csharp" source="~/ms-identity-ciam-dotnet-tutorial/1-Authentication/2-sign-in-maui/Views/MainView.xaml.cs" :::
7170

72-
The `MainView` class is a content page responsible for displaying the main view of the app. In the constructor, it retrieves the cached user account using the `MSALClientHelper` from the `PublicClientSingleton` instance and enables the sign-in button, if no cached user account is found.
71+
The `MainView` class is a content page responsible for displaying the main view of the app. In the constructor, it retrieves the cached user account using the `MSALClientHelper` from the `PublicClientSingleton` instance and enables the sign-in button, if no cached user account is found.
7372

7473
When the sign-in button is clicked, it calls the `AcquireTokenSilentAsync` method to acquire a token silently and navigates to the `claimsview` page using the `Shell.Current.GoToAsync` method. Additionally, the `OnBackButtonPressed` method is overridden to return true, indicating that the back button is disabled for this view.
7574

@@ -84,14 +83,13 @@ The next steps will organize the code so that `ClaimsView` page is defined. The
8483
1. Select **Add**.
8584
1. The _ClaimsView.xaml_ file will open in a new document tab, displaying all of the XAML markup that represents the UI of the page. Replace the XAML markup with the following markup:
8685

87-
8886
:::code language="xaml" source="~/ms-identity-ciam-dotnet-tutorial/1-Authentication/2-sign-in-maui/Views/ClaimsView.xaml" :::
8987

90-
This XAML markup code represents the UI layout for a claim view in a .NET MAUI app. It starts by defining the `ContentPage` with a title and disabling the back button behavior.
91-
92-
Inside a `VerticalStackLayout`, there are several `Label` elements displaying static text, followed by a `ListView` named `Claims` that binds to a collection called `IdTokenClaims` to display the claims found in the ID token. Each claim is rendered within a `ViewCell` using a `DataTemplate` and displayed as a centered `Label` within a Grid.
93-
94-
Lastly, there's a `Sign Out` button centered at the bottom of the layout, which triggers the `SignOutButton_Clicked` event handler when clicked.
88+
This XAML markup code represents the UI layout for a claim view in a .NET MAUI app. It starts by defining the `ContentPage` with a title and disabling the back button behavior.
89+
90+
Inside a `VerticalStackLayout`, there are several `Label` elements displaying static text, followed by a `ListView` named `Claims` that binds to a collection called `IdTokenClaims` to display the claims found in the ID token. Each claim is rendered within a `ViewCell` using a `DataTemplate` and displayed as a centered `Label` within a Grid.
91+
92+
Lastly, there's a `Sign Out` button centered at the bottom of the layout, which triggers the `SignOutButton_Clicked` event handler when clicked.
9593

9694
#### Handle the ClaimsView data
9795

@@ -101,7 +99,7 @@ The next step is to add the code to handle `ClaimsView` data.
10199

102100
:::code language="csharp" source="~/ms-identity-ciam-dotnet-tutorial/1-Authentication/2-sign-in-maui/Views/ClaimsView.xaml.cs" :::
103101

104-
The _ClaimsView.xaml.cs_ code represents the code-behind for a claim view in a .NET MAUI app. It starts by importing the necessary namespaces and defining the `ClaimsView` class, which extends `ContentPage`. The `IdTokenClaims` property is an enumerable of strings, initially set to a single string indicating no claims found.
102+
The _ClaimsView.xaml.cs_ code represents the code-behind for a claim view in a .NET MAUI app. It starts by importing the necessary namespaces and defining the `ClaimsView` class, which extends `ContentPage`. The `IdTokenClaims` property is an enumerable of strings, initially set to a single string indicating no claims found.
105103

106104
The `ClaimsView` constructor sets the binding context to the current instance, initializes the view components, and calls the `SetViewDataAsync` method asynchronously. The `SetViewDataAsync` method attempts to acquire a token silently, retrieves the claims from the authentication result, and sets the `IdTokenClaims` property to display them in the `ListView` named `Claims`. If a `MsalUiRequiredException` occurs, indicating that user interaction is needed for authentication, the app navigates to the claims view.
107105

@@ -161,7 +159,7 @@ To create `appsettings.json`, follow these steps:
161159
Set the **Debug Target** in the Visual Studio toolbar to the device you want to debug and test with. The following steps demonstrate setting the **Debug Target** to _Windows_:
162160

163161
1. Select **Debug Target** drop-down.
164-
1. Select **Framework**
162+
1. Select **Framework**
165163
1. Select **net7.0-windows...**
166164

167165
Run the app by pressing _F5_ or select the _play button_ at the top of Visual Studio.
@@ -180,5 +178,5 @@ Run the app by pressing _F5_ or select the _play button_ at the top of Visual St
180178

181179
## Next Steps
182180

183-
- [Customize the default branding](how-to-customize-branding-customers.md).
184-
- [Configure sign-in with Google](how-to-google-federation-customers.md).
181+
> [!div class="nextstepaction"]
182+
> [Tutorial: Add app roles to .NET MAUI app and receive them in the ID token](tutorial-desktop-maui-role-based-access-control.md)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
title: "Tutorial: Use role-based access control in your .NET MAUI"
3+
description: This tutorial demonstrates how to add app roles to .NET Multi-platform App UI (.NET MAUI) shell and receive them in the ID token.
4+
author: henrymbuguakiarie
5+
manager: mwongerapk
6+
7+
ms.author: henrymbugua
8+
ms.service: active-directory
9+
ms.topic: tutorial
10+
ms.subservice: ciam
11+
ms.date: 07/17/2023
12+
---
13+
14+
# Tutorial: Use role-based access control in your .NET MAUI
15+
16+
This tutorial demonstrates how to add app roles to .NET Multi-platform App UI (.NET MAUI) and receive them in the ID token.
17+
18+
In this tutorial, you learn how to:
19+
20+
> [!div class="checklist"]
21+
>
22+
> - Access the roles in the ID token.
23+
24+
## Prerequisites
25+
26+
- [Tutorial: Sign in users in .NET MAUI shell app](tutorial-desktop-app-maui-sign-in-sign-out.md)
27+
- [Using role-based access control for applications](how-to-use-app-roles-customers.md)
28+
29+
## Receive groups and roles claims in .NET MAUI
30+
31+
Once you configure your customer's tenant, you can retrieve your roles and groups claims in your client app. The roles and groups claims are both present in the ID token and the access token. Access tokens are only validated in the web APIs for which they were acquired by a client. The client shouldn't validate access tokens.
32+
33+
The .NET MAUI needs to check for the app roles claims in the ID token to implement authorization in the client side.
34+
35+
In this tutorial series, you created a .NET MAUI app where you developed the [_ClaimsView.xaml.cs_](tutorial-desktop-app-maui-sign-in-sign-out.md#handle-the-claimsview-data) to handle `ClaimsView` data. In this file, we inspect the contents of ID tokens. The value of the roles claim is checked in the following code snippet:
36+
37+
To access the role claim, you can modify the code snippet as follows:
38+
39+
```csharp
40+
var idToken = PublicClientSingleton.Instance.MSALClientHelper.AuthResult.IdToken;
41+
var handler = new JwtSecurityTokenHandler();
42+
var token = handler.ReadJwtToken(idToken);
43+
// Get the role claim value
44+
var roleClaim = token.Claims.FirstOrDefault(c => c.Type == "roles")?.Value;
45+
46+
if (!string.IsNullOrEmpty(roleClaim))
47+
{
48+
// If the role claim exists, add it to the IdTokenClaims
49+
IdTokenClaims = new List<string> { roleClaim };
50+
}
51+
else
52+
{
53+
// If the role claim doesn't exist, add a message indicating that no role claim was found
54+
IdTokenClaims = new List<string> { "No role claim found in ID token" };
55+
}
56+
57+
Claims.ItemsSource = IdTokenClaims;
58+
```
59+
60+
> [!NOTE]
61+
> To read the ID token, you must install the `System.IdentityModel.Tokens.Jwt` package.
62+
63+
If you assign a user to multiple roles, the roles string contains all roles separated by a comma, such as `Orders.Manager, Store.Manager,...`. Make sure you build your application to handle the following conditions:
64+
65+
- Absence of roles claims in the token
66+
- User hasn't been assigned to any role
67+
- Multiple values in the roles claim when you assign a user to multiple roles
68+
69+
When you define app roles for your app, it is your responsibility to implement authorization logic for those roles.
70+
71+
## Next steps
72+
73+
For more information about group claims and making informed decisions regarding the usage of app roles or groups, see:
74+
75+
- [Configuring group claims and app roles in tokens](/security/zero-trust/develop/configure-tokens-group-claims-app-roles)
76+
- [Choose an approach](../../develop/custom-rbac-for-developers.md#choose-an-approach)

0 commit comments

Comments
 (0)