Группы Microsoft Entra (ME-ID), роли администратора и роли приложения
В этой статье объясняется, как настроить использование Blazor WebAssembly групп и ролей и ролей Microsoft Entra ID (ME-ID).
ME-ID предоставляет несколько подходов авторизации, которые можно объединить с ASP.NET Core Identity:
- Группы
- Безопасность
- Microsoft 365
- Распределение
- Роли
- Встроенные роли администратора me-ID
- Роли приложения
Руководство, описанное в этой статье, относится к Blazor WebAssembly сценариям развертывания ME-ID, описанным в следующих статьях:
Примеры, приведенные в этой статье, используют новые функции .NET/C#. При использовании примеров с .NET 7 или более ранней версией требуются незначительные изменения. Однако примеры текста и кода, относящиеся к взаимодействию с ME-ID и Microsoft Graph, одинаковы для всех версий ASP.NET Core.
Пример приложения
Перейдите к примеру приложения с именем BlazorWebAssemblyEntraGroupsAndRoles
, используя последнюю папку версии из корневого каталога репозитория, используя следующую ссылку. Пример предоставляется для .NET 8 или более поздней версии. Сведения о том, как запустить приложение, см. в файле примера приложения README
.
Пример приложения включает UserClaims
компонент для отображения утверждений пользователя. Компонент UserData
отображает основные свойства учетной записи пользователя.
Просмотреть или скачать образец кода (описание загрузки)
Предварительные требования
В этой статье описано, как реализовать API Microsoft Graph для каждого руководства по пакету SDK Graph в руководстве по использованию API Graph с ASP.NET Core Blazor WebAssembly. Следуйте инструкциям по реализации пакета SDK Graph, чтобы настроить приложение и проверить его, чтобы убедиться, что приложение может получить данные API Graph для тестовой учетной записи пользователя. Кроме того, ознакомьтесь со статьей по безопасности API Graph, чтобы ознакомиться с концепциями безопасности Microsoft Graph.
При локальном тестировании с помощью пакета SDK Graph рекомендуется использовать новый сеанс браузера in-private/incognito для каждого теста, чтобы предотвратить мешающие тесты файлам cookie. Дополнительные сведения см. в статье "Защита автономного приложения ASP.NET Core Blazor WebAssembly с помощью идентификатора Microsoft Entra.
Средства регистрации приложений ME-ID в Интернете
Эта статья ссылается на портал Azure на протяжении всего времени при появлении запроса на настройку регистрации приложения ME-ID приложения, но Центр администрирования Microsoft Entra также является жизнеспособным вариантом для управления регистрацией приложений ME-ID. Любой интерфейс можно использовать, но руководство в этой статье специально охватывает жесты для портал Azure.
Области
Разрешения и области означают то же самое и используются взаимозаменяемо в документации по безопасности и портал Azure. Если текст не ссылается на портал Azure, в этой статье используются /области областей при обращении к разрешениям Graph.
Области являются нечувствительными к регистру, поэтому User.Read
они совпадают user.read
. Вы можете использовать любой формат, но мы рекомендуем согласованный выбор в коде приложения.
Чтобы разрешить вызовы API Microsoft Graph для профиля пользователя, назначения ролей и членства в группах, приложение настраивается с делегированной User.Read
областью () в портал Azure поскольку доступ к данным пользователя определяется областями, предоставленными (https://graph.microsoft.com/User.Read
делегированными) отдельным пользователям. Эта область требуется в дополнение к областям, необходимым в сценариях развертывания ME-ID, описанных в статьях, перечисленных ранее (автономный с учетными записями Майкрософт или автономной с me-ID).
К дополнительным обязательным областям относятся:
- Делегированная
RoleManagement.Read.Directory
область (https://graph.microsoft.com/RoleManagement.Read.Directory
): позволяет приложению считывать параметры управления доступом на основе ролей (RBAC) для каталога вашей компании от имени вошедшего пользователя. Это включает чтение шаблонов ролей каталога, ролей каталогов и членства. Членство в роли каталога используется для созданияdirectoryRole
утверждений в приложении для встроенных ролей администратора ME-ID. Требуется согласие администратора. - Делегированная
AdministrativeUnit.Read.All
область (https://graph.microsoft.com/AdministrativeUnit.Read.All
): позволяет приложению читать административные единицы и членство в административной единице от имени пользователя, вошедшего в систему. Эти членства используются для созданияadministrativeUnit
утверждений в приложении. Требуется согласие администратора.
Дополнительные сведения см. в разделе "Обзор разрешений и согласия" на платформе Майкрософт identity и обзор разрешений Microsoft Graph.
Настраиваемая учетная запись пользователя
Назначьте пользователей группам безопасности ME-ID и ролям администратора ME-ID в портал Azure.
Примеры в этой статье:
- Предположим, что пользователю назначена роль администратора выставления счетов ME-ID в клиенте портал Azure ME-ID для авторизации доступа к данным API сервера.
- Используйте политики авторизации для управления доступом в приложении.
Расширение RemoteUserAccount для включения свойств для:
Roles
: массив ролей приложений ME-ID (в разделе "Роли приложений ")Oid
: неизменяемое утверждение идентификатора объекта () (oid
однозначно идентифицирует пользователя внутри и между клиентами)
CustomUserAccount.cs
:
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
namespace BlazorWebAssemblyEntraGroupsAndRoles;
public class CustomUserAccount : RemoteUserAccount
{
[JsonPropertyName("roles")]
public List<string>? Roles { get; set; }
[JsonPropertyName("oid")]
public string? Oid { get; set; }
}
Добавьте ссылку на пакет для приложения Microsoft.Graph
.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
Добавьте служебные классы и конфигурацию пакета SDK Graph в руководство по использованию API Graph с ASP.NET Основной Blazor WebAssemblyстатьей. User.Read
Укажите и RoleManagement.Read.Directory
AdministrativeUnit.Read.All
области для маркера доступа, как показано в статье в примере wwwroot/appsettings.json
файла.
Добавьте в приложение следующую фабрику пользовательских учетных записей. Эта фабрика используется для установки:
Утверждения роли приложения () (
role
рассматриваются в разделе " Роли приложений ").Пример утверждений данных профиля пользователя для номера мобильного телефона пользователя (
mobilePhone
) и расположения офиса (officeLocation
).Утверждения роли администратора ME-ID (
directoryRole
).Утверждения административной единицы ME-ID (
administrativeUnit
).Утверждения группы ME-ID (
directoryGroup
).logger
(ILogger) для удобства в случае, если вы хотите регистрировать сведения или ошибки.
CustomAccountFactory.cs
:
using System.Security.Claims;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
using Microsoft.Graph;
using Microsoft.Kiota.Abstractions.Authentication;
namespace BlazorWebAssemblyEntraGroupsAndRoles;
public class CustomAccountFactory(IAccessTokenProviderAccessor accessor,
IServiceProvider serviceProvider, ILogger<CustomAccountFactory> logger,
IConfiguration config)
: AccountClaimsPrincipalFactory<CustomUserAccount>(accessor)
{
private readonly ILogger<CustomAccountFactory> logger = logger;
private readonly IServiceProvider serviceProvider = serviceProvider;
private readonly string? baseUrl = string.Join("/",
config.GetSection("MicrosoftGraph")["BaseUrl"],
config.GetSection("MicrosoftGraph")["Version"]);
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account,
RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity is not null &&
initialUser.Identity.IsAuthenticated)
{
var userIdentity = initialUser.Identity as ClaimsIdentity;
if (userIdentity is not null && !string.IsNullOrEmpty(baseUrl) &&
account.Oid is not null)
{
account?.Roles?.ForEach((role) =>
{
userIdentity.AddClaim(new Claim("role", role));
});
try
{
var client = new GraphServiceClient(
new HttpClient(),
serviceProvider
.GetRequiredService<IAuthenticationProvider>(),
baseUrl);
var user = await client.Me.GetAsync();
if (user is not null)
{
userIdentity.AddClaim(new Claim("mobilephone",
user.MobilePhone ?? "(000) 000-0000"));
userIdentity.AddClaim(new Claim("officelocation",
user.OfficeLocation ?? "Not set"));
}
var memberOf = client.Users[account?.Oid].MemberOf;
var graphDirectoryRoles = await memberOf.GraphDirectoryRole.GetAsync();
if (graphDirectoryRoles?.Value is not null)
{
foreach (var entry in graphDirectoryRoles.Value)
{
if (entry.RoleTemplateId is not null)
{
userIdentity.AddClaim(
new Claim("directoryRole", entry.RoleTemplateId));
}
}
}
var graphAdministrativeUnits = await memberOf.GraphAdministrativeUnit.GetAsync();
if (graphAdministrativeUnits?.Value is not null)
{
foreach (var entry in graphAdministrativeUnits.Value)
{
if (entry.Id is not null)
{
userIdentity.AddClaim(
new Claim("administrativeUnit", entry.Id));
}
}
}
var graphGroups = await memberOf.GraphGroup.GetAsync();
if (graphGroups?.Value is not null)
{
foreach (var entry in graphGroups.Value)
{
if (entry.Id is not null)
{
userIdentity.AddClaim(
new Claim("directoryGroup", entry.Id));
}
}
}
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
return initialUser;
}
}
Предыдущий код:
- Не включает транзитивное членство. Если приложению требуются прямые и транзитивные утверждения членства в группах, замените свойство
MemberOf
(IUserMemberOfCollectionWithReferencesRequestBuilder
) наTransitiveMemberOf
(IUserTransitiveMemberOfCollectionWithReferencesRequestBuilder
). - Задает значения GUID в
directoryRole
утверждениях— идентификаторы шаблонов ролей администратора ME-ID (Microsoft.Graph.Models.DirectoryRole.RoleTemplateId
). Идентификаторы шаблонов — это стабильные идентификаторы для создания политик авторизации пользователей в приложениях, описанных далее в этой статье. Не используйтеentry.Id
для значений утверждений роли каталога, так как они не стабильны для клиентов.
Затем настройте проверку подлинности MSAL для использования фабрики пользовательских учетных записей пользователей.
Убедитесь, что Program
файл использует Microsoft.AspNetCore.Components.WebAssembly.Authentication пространство имен:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
AddMsalAuthentication Обновите вызов следующим образом. Обратите внимание, что Blazor платформа RemoteUserAccount заменена приложением CustomUserAccount
для проверки подлинности MSAL и фабрики утверждений учетной записи:
builder.Services.AddMsalAuthentication<RemoteAuthenticationState,
CustomUserAccount>(options =>
{
builder.Configuration.Bind("AzureAd",
options.ProviderOptions.Authentication);
options.UserOptions.RoleClaim = "role";
})
.AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount,
CustomAccountFactory>();
Убедитесь, что код пакета SDK Graph в файле, описанном Program
API Use Graph, см. в статье ASP.NET CoreBlazor WebAssembly:
var baseUrl =
string.Join("/",
builder.Configuration.GetSection("MicrosoftGraph")["BaseUrl"] ??
"https://graph.microsoft.com",
builder.Configuration.GetSection("MicrosoftGraph")["Version"] ??
"v1.0");
var scopes = builder.Configuration.GetSection("MicrosoftGraph:Scopes")
.Get<List<string>>() ?? [ "user.read" ];
builder.Services.AddGraphClient(baseUrl, scopes);
Внимание
Убедитесь в регистрации приложения в портал Azure, что предоставлены следующие разрешения:
User.Read
RoleManagement.Read.Directory
(Требуется согласие администратора)AdministrativeUnit.Read.All
(Требуется согласие администратора)
Убедитесь, что wwwroot/appsettings.json
конфигурация правильна для руководства по пакету SDK Graph.
wwwroot/appsettings.json
:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/{TENANT ID}",
"ClientId": "{CLIENT ID}",
"ValidateAuthority": true
},
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com",
"Version": "v1.0",
"Scopes": [
"User.Read",
"RoleManagement.Read.Directory",
"AdministrativeUnit.Read.All"
]
}
}
Укажите значения для следующих заполнителей из регистрации ME-ID приложения в портал Azure:
{TENANT ID}
: значение GUID идентификатора каталога (клиента).{CLIENT ID}
: значение GUID идентификатора приложения (клиента).
Настройка авторизации
Создайте политику для каждой роли приложения (по имени роли), встроенной роли администратора ME-ID (по идентификатору шаблона роли или GUID) или группе безопасности (по идентификатору объекта или GUID) в Program
файле. В следующем примере создается политика для встроенной роли администратора выставления счетов me-ID:
builder.Services.AddAuthorizationCore(options =>
{
options.AddPolicy("BillingAdministrator", policy =>
policy.RequireClaim("directoryRole",
"b0f54661-2d74-4c50-afa3-1ec803f12efe"));
});
Полный список идентификаторов (GUID) для ролей администратора ME-ID см. в документации по идентификаторам шаблонов ролей. Сведения о безопасности Azure или идентификаторе группы O365 (GUID) см. в идентификаторе объекта для группы в области портал Azure Групп регистрации приложения. Дополнительные сведения о политиках авторизации см. в статье Авторизация на основе политик в ASP.NET Core.
В следующих примерах приложение использует предыдущую политику для авторизации пользователя.
С политикой работает компонентAuthorizeView
:
<AuthorizeView Policy="BillingAdministrator">
<Authorized>
<p>
The user is in the 'Billing Administrator' ME-ID Administrator Role
and can see this content.
</p>
</Authorized>
<NotAuthorized>
<p>
The user is NOT in the 'Billing Administrator' role and sees this
content.
</p>
</NotAuthorized>
</AuthorizeView>
Доступ ко всему компоненту может основываться на политике, использующей директиву атрибута [Authorize]
(AuthorizeAttribute):
@page "/"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "BillingAdministrator")]
Если пользователь не авторизован, он перенаправляется на страницу входа ME-ID.
Проверку политики можно также выполнять в коде с помощью процедурной логики.
CheckPolicy.razor
:
@page "/checkpolicy"
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
<h1>Check Policy</h1>
<p>This component checks a policy in code.</p>
<button @onclick="CheckPolicy">Check 'BillingAdministrator' policy</button>
<p>Policy Message: @policyMessage</p>
@code {
private string policyMessage = "Check hasn't been made yet.";
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
private async Task CheckPolicy()
{
var user = (await authenticationStateTask).User;
if ((await AuthorizationService.AuthorizeAsync(user,
"BillingAdministrator")).Succeeded)
{
policyMessage = "Yes! The 'BillingAdministrator' policy is met.";
}
else
{
policyMessage = "No! 'BillingAdministrator' policy is NOT met.";
}
}
}
Используя предыдущие подходы, вы также можете создать доступ на основе политик для групп безопасности, где GUID, используемый для политики, соответствует
Роли приложения
Чтобы настроить приложение в портал Azure для предоставления утверждений о членстве в ролях приложений, см. статью "Добавление ролей приложения в приложение" и их получение в маркере в документации по ME-ID.
В следующем примере предполагается, что приложение настроено с двумя ролями, а роли назначаются тестового пользователя:
Admin
Developer
Хотя вы не можете назначать роли группам без учетной записи ME-ID Premium, вы можете назначать роли пользователям и получать утверждения ролей для пользователей со стандартной учетной записью Azure. В этом разделе не требуется учетная запись ME-ID Premium.
Используйте любой из следующих подходов, чтобы добавить роли приложения в ME-ID:
При работе с каталогом по умолчанию следуйте инструкциям в статье "Добавление ролей приложения в приложение" и их получение в маркере для создания ролей ME-ID.
Если вы не работаете с каталогом по умолчанию, измените манифест приложения в портал Azure, чтобы вручную установить роли приложения в
appRoles
записи файла манифеста. Ниже приведен примерappRoles
записи, которая создаетAdmin
иDeveloper
роли. Эти примеры ролей используются позже на уровне компонента для реализации ограничений доступа:Внимание
Следующий подход рекомендуется использовать только для приложений, которые не зарегистрированы в каталоге по умолчанию учетной записи Azure. Сведения о приложениях, зарегистрированных в каталоге по умолчанию, см. в предыдущем маркере этого списка.
"appRoles": [ { "allowedMemberTypes": [ "User" ], "description": "Administrators manage developers.", "displayName": "Admin", "id": "{ADMIN GUID}", "isEnabled": true, "lang": null, "origin": "Application", "value": "Admin" }, { "allowedMemberTypes": [ "User" ], "description": "Developers write code.", "displayName": "Developer", "id": "{DEVELOPER GUID}", "isEnabled": true, "lang": null, "origin": "Application", "value": "Developer" } ],
{ADMIN GUID}
{DEVELOPER GUID}
Для заполнителей, приведенных в предыдущем примере, можно создать идентификаторы GUID с помощью генератора GUID в Интернете (результат поиска Google для "генератор guid") .
Чтобы назначить роль пользователю (или группе, если у вас есть учетная запись уровня "Премиум"):
- Перейдите к корпоративным приложениям в области "ME-ID" портал Azure.
- Выберите приложение. Выберите "Управление пользователями и группами>" на боковой панели.
- Установите флажок для одной или нескольких учетных записей пользователей.
- В меню над списком пользователей выберите "Изменить назначение".
- Для записи "Выбор роли" выберите "Нет".
- Выберите роль из списка и нажмите кнопку "Выбрать ", чтобы выбрать ее.
- Нажмите кнопку "Назначить " в нижней части экрана, чтобы назначить роль.
На портале Azure назначается несколько ролей путем повторного добавления пользователей для каждого дополнительного назначения роли. Нажмите кнопку "Добавить пользователя или группу " в верхней части списка пользователей, чтобы повторно добавить пользователя. Используйте описанные выше действия, чтобы назначить пользователю другую роль. Этот процесс можно повторять столько раз, сколько необходимо для добавления дополнительных ролей пользователю (или группе).
CustomAccountFactory
, как показано в разделе Настраиваемая учетная запись пользователя, настраивается для работы в утверждении role
с использованием значения массива JSON. Добавьте и зарегистрируйте CustomAccountFactory
приложение, как показано в разделе пользовательской учетной записи пользователя. Нет необходимости предоставлять код для удаления исходного утверждения role
, поскольку оно автоматически удаляется платформой.
В файле добавьте или подтвердите Program
утверждение с именем "role
" в качестве утверждения роли для ClaimsPrincipal.IsInRole проверок:
builder.Services.AddMsalAuthentication(options =>
{
...
options.UserOptions.RoleClaim = "role";
});
Примечание.
Если вы предпочитаете directoryRoles
использовать утверждение (роли администратора ME-ID), назначьте "directoryRoles
" параметру RemoteAuthenticationUserOptions.RoleClaim.
После выполнения описанных выше действий по созданию и назначению ролей пользователям (или группам, если у вас есть учетная запись Azure уровня "Премиум") и реализован CustomAccountFactory
пакет SDK Graph, как описано ранее в этой статье, и в разделе "Использование API Graph с ASP.NET Core Blazor WebAssembly", должно появиться role
утверждение для каждой назначенной роли, назначаемой пользователем (или ролям, назначенным группам, в которых они являются членами). Запустите приложение с тестовой пользователем, чтобы убедиться, что утверждения присутствуют должным образом. При локальном тестировании с помощью пакета SDK Graph рекомендуется использовать новый сеанс браузера in-private/incognito для каждого теста, чтобы предотвратить мешающие тесты файлам cookie. Дополнительные сведения см. в статье "Защита автономного приложения ASP.NET Core Blazor WebAssembly с помощью идентификатора Microsoft Entra.
На этом этапе можно применять подходы с авторизацией компонентов. Любой из механизмов авторизации в компонентах приложения может использовать Admin
роль для авторизации пользователя:
-
<AuthorizeView Roles="Admin">
Директива атрибута
[Authorize]
(AuthorizeAttribute)@attribute [Authorize(Roles = "Admin")]
-
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); var user = authState.User; if (user.IsInRole("Admin")) { ... }
Поддерживается тестирование с использованием нескольких ролей:
Требовать, чтобы пользователь имел одну из ролей:
Admin
илиDeveloper
при использовании компонентаAuthorizeView
:<AuthorizeView Roles="Admin, Developer"> ... </AuthorizeView>
Требовать, чтобы пользователь имел обе роли:
Admin
иDeveloper
при использовании компонентаAuthorizeView
:<AuthorizeView Roles="Admin"> <AuthorizeView Roles="Developer" Context="innerContext"> ... </AuthorizeView> </AuthorizeView>
Дополнительные сведения о внутренней AuthorizeViewсреде см. в
Context
разделе ASP.NET Проверка подлинности и авторизация CoreBlazor.Требовать, чтобы пользователь имел одну из ролей:
Admin
илиDeveloper
при использовании атрибута[Authorize]
:@attribute [Authorize(Roles = "Admin, Developer")]
Требовать, чтобы пользователь имел обе роли:
Admin
иDeveloper
при использовании атрибута[Authorize]
:@attribute [Authorize(Roles = "Admin")] @attribute [Authorize(Roles = "Developer")]
Требовать, чтобы пользователь имел одну из ролей:
Admin
илиDeveloper
при использовании процедурного кода:@code { private async Task DoSomething() { var authState = await AuthenticationStateProvider .GetAuthenticationStateAsync(); var user = authState.User; if (user.IsInRole("Admin") || user.IsInRole("Developer")) { ... } else { ... } } }
Требовать, чтобы пользователь имел обе роли:
Admin
иDeveloper
при использовании процедурного кода, изменив условное ИЛИ (||
) на условное И (&&
) в предыдущем примере:if (user.IsInRole("Admin") && user.IsInRole("Developer"))
Поддерживается тестирование с использованием нескольких ролей:
Требовать, чтобы пользователь имел одну из ролей:
Admin
илиDeveloper
при использовании атрибута[Authorize]
:[Authorize(Roles = "Admin, Developer")]
Требовать, чтобы пользователь имел обе роли:
Admin
иDeveloper
при использовании атрибута[Authorize]
:[Authorize(Roles = "Admin")] [Authorize(Roles = "Developer")]
Требовать, чтобы пользователь имел одну из ролей:
Admin
илиDeveloper
при использовании процедурного кода:static readonly string[] scopeRequiredByApi = new string[] { "API.Access" }; ... [HttpGet] public IEnumerable<ReturnType> Get() { HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); if (User.IsInRole("Admin") || User.IsInRole("Developer")) { ... } else { ... } return ... }
Требовать, чтобы пользователь имел обе роли:
Admin
иDeveloper
при использовании процедурного кода, изменив условное ИЛИ (||
) на условное И (&&
) в предыдущем примере:if (User.IsInRole("Admin") && User.IsInRole("Developer"))
Так как сравнения строк .NET чувствительны к регистру, соответствующие имена ролей также учитывает регистр. Например, (верхний регистрA
) не рассматривается как та же роль, Admin
что admin
и (строчная).a
Регистр Pascal обычно используется для имен ролей (например, BillingAdministrator
), но использование регистра Pascal не является строгим требованием. Разрешены различные схемы регистра, такие как верблюдьи случаи, кебаб и змеиный случай. Использование пробелов в именах ролей также является необычным, но разрешенным. Например, billing administrator
это необычный формат имени роли в приложениях .NET, но допустимый.
Дополнительные ресурсы
- Идентификаторы шаблонов ролей (документация по ME-ID)
groupMembershipClaims
атрибут (документация по ME-ID)- Добавьте роли приложения в приложение и получите их в маркере (документация по ME-ID)
- Роли приложения (документация по Azure)
- Авторизация на основе утверждений в ASP.NET Core
- Авторизация на основе ролей в ASP.NET Core
- Проверка подлинности и авторизация в Blazor ASP.NET Core
ASP.NET Core