@@ -5,7 +5,7 @@ description: Learn how to secure a Blazor Web App with Windows Authentication.
5
5
monikerRange : ' >= aspnetcore-9.0'
6
6
ms.author : wpickett
7
7
ms.custom : mvc
8
- ms.date : 03/25 /2025
8
+ ms.date : 09/11 /2025
9
9
uid : blazor/security/blazor-web-app-windows-authentication
10
10
---
11
11
# Secure an ASP.NET Core Blazor Web App with Windows Authentication
@@ -88,32 +88,48 @@ The authorization policy is enforced by the `LocalAccountOnly` component.
88
88
</p>
89
89
```
90
90
91
- The ` UserClaims ` component lists the user's claims, which includes the user's Windows security identifiers (SIDs).
91
+ The ` UserClaims ` component lists the user's claims and roles, including the user's Windows security identifiers (SIDs) with SID translations .
92
92
93
93
` Components/Pages/UserClaims.razor ` :
94
94
95
95
``` razor
96
96
@page "/user-claims"
97
97
@using System.Security.Claims
98
- @using Microsoft.AspNetCore.Authorization
99
- @attribute [Authorize]
98
+ @using System.Security.Principal
99
+ @using Microsoft.AspNetCore.Components.QuickGrid
100
+
101
+ <PageTitle>User Claims & Roles</PageTitle>
102
+
103
+ <h1>User Claims & Roles</h1>
100
104
101
- <PageTitle>User Claims</PageTitle>
105
+ <QuickGrid Items="claims" Pagination="pagination">
106
+ <Paginator State="pagination" />
107
+ <PropertyColumn Property="@(p => p.Type)" Sortable="true" />
108
+ <PropertyColumn Property="@(p => p.Value)" Sortable="true" />
109
+ <PropertyColumn Property="@(p => GetClaimAsHumanReadable(p))" Sortable="true" Title="Translation" />
110
+ <PropertyColumn Property="@(p => p.Issuer)" Sortable="true" />
111
+ </QuickGrid>
102
112
103
- <h1>User Claims </h1>
113
+ <h1>User Roles </h1>
104
114
105
- @if (claims .Any())
115
+ @if (roles .Any())
106
116
{
107
117
<ul>
108
- @foreach (var claim in claims )
118
+ @foreach (var role in roles )
109
119
{
110
- <li><b>@claim.Type:</b> @claim.Value </li>
120
+ <li>@role </li>
111
121
}
112
122
</ul>
113
123
}
124
+ else
125
+ {
126
+ <p>No roles available.</p>
127
+ }
114
128
115
129
@code {
116
- private IEnumerable<Claim> claims = [];
130
+ private IQueryable<Claim> claims = Enumerable.Empty<Claim>().AsQueryable();
131
+ private IEnumerable<string> roles = Enumerable.Empty<string>();
132
+ PaginationState pagination = new PaginationState { ItemsPerPage = 10 };
117
133
118
134
[CascadingParameter]
119
135
private Task<AuthenticationState>? AuthState { get; set; }
@@ -126,7 +142,38 @@ The `UserClaims` component lists the user's claims, which includes the user's Wi
126
142
}
127
143
128
144
var authState = await AuthState;
129
- claims = authState.User.Claims;
145
+
146
+ claims = authState.User.Claims.AsQueryable();
147
+
148
+ roles = authState.User.Claims
149
+ .Where(claim => claim.Type == ClaimTypes.Role)
150
+ .Select(claim => claim.Value);
151
+ }
152
+
153
+ private string GetClaimAsHumanReadable(Claim claim)
154
+ {
155
+ if (!OperatingSystem.IsWindows() ||
156
+ claim.Type is not (ClaimTypes.PrimarySid or ClaimTypes.PrimaryGroupSid
157
+ or ClaimTypes.GroupSid))
158
+ {
159
+ // We're either not on Windows or not dealing with a SID Claim that
160
+ // can be translated
161
+ return string.Empty;
162
+ }
163
+
164
+ SecurityIdentifier sid = new SecurityIdentifier(claim.Value);
165
+
166
+ try
167
+ {
168
+ // Throw an exception if the SID can't be translated
169
+ var account = sid.Translate(typeof(NTAccount));
170
+
171
+ return account.ToString();
172
+ }
173
+ catch (IdentityNotMappedException)
174
+ {
175
+ return "Could not be mapped";
176
+ }
130
177
}
131
178
}
132
179
```
0 commit comments