Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Примечание.
Это не последняя версия этой статьи. В текущей версии см. версию .NET 9 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущей версии см. версию .NET 9 этой статьи.
В этой статье описывается, как защитить Blazor Web Appприложение OpenID Connect (OIDC) с помощью примера приложения в dotnet/blazor-samples
репозитории GitHub (.NET 8 или более поздней версии) (как скачать).
Для идентификатора Microsoft Entra или Azure AD B2C можно использовать AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web
пакет NuGet, документация по API), которая добавляет обработчики OIDC и Cookie проверки подлинности с соответствующими значениями по умолчанию. Пример приложения и инструкции, приведенные в этой статье, не используют Microsoft Identity Web. В руководстве показано, как настроить обработчик OIDC вручную для любого поставщика OIDC. Дополнительные сведения о реализации Microsoft Identity Web см. в статье "Защита ASP.NET Core Blazor Web App с помощью идентификатора Microsoft Entra".
Эта версия статьи охватывает реализацию OIDC без использования шаблона 'Backend for Frontend' (BFF) с приложением, которое использует глобальный интерактивный автоматический рендеринг (сервер и проекты). Шаблон BFF полезен для выполнения аутентифицированных запросов к внешним службам. Измените селектор версии статьи на шаблон BFF , если спецификация приложения вызывает внедрение шаблона BFF.
Используется следующая спецификация:
- Элемент Blazor Web App использует режим автоматической отрисовки с глобальной интерактивностью.
- Пользовательские службы, предоставляющие состояние аутентификации, используются сервером и клиентскими приложениями для фиксации состояния аутентификации пользователя и передачи между сервером и клиентом.
- Это приложение является отправной точкой для любого потока проверки подлинности OIDC. OIDC настраивается вручную в приложении и не зависит от идентификатора Microsoft Entra или пакетов Microsoft Identity Web, а также примерное приложение не требует размещения на Microsoft Azure. Однако пример приложения можно использовать с Entra, Microsoft Identity Web и размещать в Azure.
- Автоматическое обновление неинтерактивного токена.
- Отдельный проект веб-API демонстрирует безопасный вызов веб-API для погодных данных.
Для получения альтернативного опыта работы с библиотекой аутентификации Microsoft для .NET, Microsoft Web, и Microsoft Entra ID, см. статью "Защита ASP.NET Core с помощью Microsoft Entra ID".
Образец решения
Пример приложения состоит из следующих проектов:
-
BlazorWebAppOidc
: серверный проект объекта Blazor Web App, содержащий пример минимальной конечной точки API для данных погоды. -
BlazorWebAppOidc.Client
: клиентская часть проекта Blazor Web App. -
MinimalApiJwt
: внутренний веб-API с минимальной конечной точкой API для данных о погоде.
Получить доступ к образцу из папки последней версии в репозитории примеров Blazor по следующей ссылке. Пример находится в папке BlazorWebAppOidc
для .NET 8 или более поздней версии.
Запустите решение из Aspire/Aspire.AppHost
проекта.
Просмотр или скачивание примера кода (как скачать)
Примеры функций решения:
Автоматическое обновление токена без взаимодействия пользователя с помощью настраиваемого cookie средства обновления (
CookieOidcRefresher.cs
).Данные о погоде обрабатываются минимальной конечной точкой API (
/weather-forecast
) вProgram
файле (Program.cs
)MinimalApiJwt
проекта. Для конечной точки требуется авторизация путем вызова RequireAuthorization. Для всех контроллеров, добавляющихся в проект, добавьте[Authorize]
атрибут в контроллер или действие. Дополнительные сведения о необходимости авторизации в приложении с помощью политики авторизации и исключении авторизации для подмножества общедоступных конечных точек см. в Razor руководстве по OIDC Pages.Приложение безопасно вызывает веб-API для погодных данных:
- При отрисовке
Weather
компонента на сервере компонент используетServerWeatherForecaster
на сервере для получения данных о погоде из веб-API вMinimalApiJwt
проекте с помощью DelegatingHandler (TokenHandler
), который присоединяет маркер доступа к запросу из HttpContext. - При отрисовке компонента на клиенте компонент использует
ClientWeatherForecaster
реализацию службы, использующую предварительно настроенный HttpClient (в файле клиентского проектаProgram
), для вызова веб-API изServerWeatherForecaster
проекта сервера.
- При отрисовке
- Серверный проект вызывает AddAuthenticationStateSerialization, чтобы добавить поставщика состояния проверки подлинности на стороне сервера, который используется PersistentComponentState для передачи состояния проверки подлинности клиенту. Клиент вызывает AddAuthenticationStateDeserialization для десериализации и использования состояния аутентификации, переданного сервером. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
- Класс
PersistingAuthenticationStateProvider
(PersistingAuthenticationStateProvider.cs
) — это серверный компонент AuthenticationStateProvider, который использует PersistentComponentState для передачи состояния проверки подлинности клиенту, который затем устанавливается на время существования приложения WebAssembly.
Дополнительные сведения о вызовах веб-API с использованием абстракций служб см. в статье Blazor Web App.
Регистрация приложений Microsoft Entra ID
Мы рекомендуем использовать отдельные регистрации для приложений и веб-API, даже если приложения и веб-API находятся в одном решении. Представленные рекомендации предназначены для BlazorWebAppOidc
приложения и MinimalApiJwt
веб-API примерного решения, но те же рекомендации также применяются к любым Entra-базированным регистрациям для приложений и веб-API.
Сначала зарегистрируйте веб-API,MinimalApiJwt
чтобы предоставить доступ к веб-API при регистрации приложения. Идентификатор арендатора и идентификатор клиента веб-API используются для настройки веб-API в файле Program
. После регистрации веб-API откройте веб-API в регистрациях приложений>Expose an API с именем области Weather.Get
. Запишите URI идентификатора приложения для использования в конфигурации приложения.
Затем зарегистрируйте приложение (BlazorWebAppOidc
/BlazorWebApOidc.Client
) с конфигурацией веб-платформы и URI перенаправления (порт не требуется). Идентификатор арендатора и идентификатор клиента приложения, а также базовый адрес веб-API, URI идентификатора приложения и имя области видимости погоды используются для настройки приложения в файле Program
. Предоставьте разрешение API для доступа к веб-API в Регистрация приложений>разрешениях API. Если спецификация безопасности приложения вызывает ее, вы можете предоставить согласие администратора для организации для доступа к веб-API. Авторизованные пользователи и группы назначаются на регистрацию приложения в Регистрация приложений>Корпоративные приложения.
В конфигурации регистрации приложений на портале Entra или Azure в разделе неявного предоставления и гибридного потоков не устанавливайте флажки ни для конечной точки авторизации, возвращающей токены доступа или токены идентификатора. Обработчик OpenID Connect автоматически запрашивает соответствующие маркеры с помощью кода, возвращенного из конечной точки авторизации.
Создайте секрет клиента в регистрации приложения на портале Entra или Azure (управление>сертификатами и секретами>нового секрета клиента). Сохраните значение секрета клиента для использования в следующем разделе.
Дополнительные рекомендации по настройке Entra для определенных параметров приведены далее в этой статье.
Создайте секрет клиента
Этот раздел применяется только к серверному проекту Blazor Web App (BlazorWebAppOidc
проект).
Предупреждение
Не сохраняйте секреты приложений, строки подключения, учетные данные, пароли, личные идентификационные номера (ПИН-коды), частный код C#/.NET или закрытые ключи и токены в клиентском коде, который всегда небезопасн. В тестовых, промежуточных и рабочих средах код на стороне Blazor сервера и веб-API должен использовать безопасные методы аутентификации, которые избегают хранения учетных данных в коде проекта или конфигурационных файлах. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. в разделе "Безопасное обслуживание конфиденциальных данных и учетных данных".
При локальном тестировании разработки используйте средство Secret Manager для хранения секрета клиента проекта сервера под конфигурационным ключом Blazor.
Серверный Blazor проект не инициализирован для средства Диспетчера секретов. Используйте командную оболочку, например командную оболочку PowerShell разработчика в Visual Studio, чтобы выполнить следующую команду. Перед выполнением команды с помощью команды cd
измените каталог на директорию проекта сервера. Команда устанавливает идентификатор секретов пользователя (<UserSecretsId>
в файле проекта приложения сервера):
dotnet user-secrets init
Выполните следующую команду, чтобы задать секрет клиента. Заполнитель {SECRET}
представляет собой секретный ключ клиента, полученный при регистрации приложения.
dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"
При использовании Visual Studio можно подтвердить, что секрет задан, щелкнув правой кнопкой мыши проект сервера в обозревателе решений и выбрав пункт "Управление секретами пользователей".
MinimalApiJwt
проект
Проект MinimalApiJwt
— это внутренний веб-API для нескольких интерфейсных проектов. Проект настраивает минимальную конечную точку API для данных о погоде.
Файл MinimalApiJwt.http
можно использовать для тестирования запроса данных о погоде. Обратите внимание, что MinimalApiJwt
проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".
Проект включает пакеты и конфигурацию для создания документов OpenAPI и пользовательского интерфейса Swagger в среде разработки. Дополнительные сведения см. в статье "Использование созданных документов OpenAPI".
Проект создает минимальную конечную точку API для данных погоды:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
Настройте проект в JwtBearerOptions вызове в файле проекта AddJwtBearerProgram
.
Задает Authority уполномоченный орган для вызовов OIDC. Рекомендуется использовать отдельную регистрацию приложения для MinimalApiJwt
проекта. Орган соответствует эмитенту (iss
) JWT, возвращаемого поставщиком удостоверений.
jwtOptions.Authority = "{AUTHORITY}";
Формат органа управления зависит от типа арендатора в использовании. В следующих примерах для Microsoft Entra ID используется Tenant ID aaaabbbb-0000-cccc-1111-dddd2222eeee
.
пример полномочий арендатора ME-ID:
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
Пример центра клиента AAD B2C:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
Задает Audience аудиторию для любого полученного токена OIDC.
jwtOptions.Audience = "{APP ID URI}";
Примечание.
При использовании Microsoft Entra ID, сопоставьте значение только с путем URI идентификатора приложения, настроенного при добавлении области в разделе «Предоставление API» на портале Entra или Azure. Не включайте имя области "Weather.Get
" в значение.
Формат аудитории зависит от типа используемого арендатора. В следующих примерах для Microsoft Entra ID используется Tenant ID contoso
и Client ID 11112222-bbbb-3333-cccc-4444dddd5555
.
пример URI идентификатора приложения клиента ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Пример URI идентификатора приложения клиента AAD B2C:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
Blazor Web App серверный проект (BlazorWebAppOidc
)
Проект BlazorWebAppOidc
является серверным проектом Blazor Web App.
A DelegatingHandler (TokenHandler
) присоединяет токен доступа пользователя к исходящему запросу. Обработчик маркеров выполняется только во время статического рендеринга на стороне сервера, поэтому использование HttpContext безопасно в этом сценарии. Подробности см. в разделе IHttpContextAccessor/HttpContext в приложениях ASP.NET Core Blazor и на Blazor Web App.
TokenHandler.cs
:
public class TokenHandler(IHttpContextAccessor httpContextAccessor) :
DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (httpContextAccessor.HttpContext is null)
{
throw new Exception("HttpContext not available");
}
var accessToken = await httpContextAccessor.HttpContext
.GetTokenAsync("access_token");
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
return await base.SendAsync(request, cancellationToken);
}
}
В файле проекта
builder.Services.AddScoped<TokenHandler>();
builder.Services.AddHttpClient("ExternalApi",
client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ??
throw new Exception("Missing base address!")))
.AddHttpMessageHandler<TokenHandler>();
В файле проекта appsettings.json
настройте URI внешнего API:
"ExternalApiUri": "{BASE ADDRESS}"
Пример:
"ExternalApiUri": "https://localhost:7277"
Следующая OpenIdConnectOptions конфигурация найдена в файле проекта Program
при вызове AddOpenIdConnect:
PushedAuthorizationBehavior: контролирует поддержку push-запросов авторизации (PAR). По умолчанию параметр использует PAR, если документ обнаружения поставщика удостоверений, обычно найденный по адресу .well-known/openid-configuration
, заявляет о поддержке PAR. Если требуется поддержка PAR для приложения, можно назначить значение PushedAuthorizationBehavior.Require
. PAR не поддерживается Microsoft Entra, и не планируется поддержка в будущем.
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;
SignInScheme. Задает схему проверки подлинности, соответствующую ПО промежуточного слоя, ответственному за сохранение удостоверения пользователя после успешной проверки подлинности. Обработчик OIDC должен использовать схему входа, которая может сохранять учетные данные пользователя в запросах. Следующая строка представлена лишь для демонстрационных целей. Если опущено, DefaultSignInScheme используется в качестве резервного значения.
oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
Области для openid
и profile
(Scope) (необязательно): области openid
и profile
также настраиваются по умолчанию, так как они необходимы для работы обработчика OIDC, но их может потребоваться повторно добавить, если области включены в конфигурацию Authentication:Schemes:MicrosoftOidc:Scope
. Для общих рекомендаций по настройке смотрите Конфигурация в ASP.NET Core и ASP.NET Core Blazor конфигурация.
oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
SaveTokens: определяет, следует ли хранить маркеры доступа и обновления в AuthenticationProperties после успешной авторизации. Это свойство имеет значение true
, поэтому токен обновления сохраняется для неинтерактивного обновления токенов.
oidcOptions.SaveTokens = true;
Область для офлайн-доступа (Scope): Область offline_access
необходима для получения маркера обновления.
oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
Authority и ClientId: задает уровень полномочий и идентификатор клиента для вызовов OIDC.
oidcOptions.Authority = "{AUTHORITY}";
oidcOptions.ClientId = "{CLIENT ID}";
В следующем примере используется идентификатор арендатора aaaabbbb-0000-cccc-1111-dddd2222eeee
и идентификатор клиента 00001111-aaaa-2222-bbbb-3333cccc4444
.
oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
Для мультитенантных приложений следует использовать орган "common". Вы также можете использовать полномочия "common" для однотенантных приложений, но требуется настраиваемый IssuerValidator, как показано далее в этом разделе.
oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
ResponseType: настраивает обработчик OIDC только для выполнения потока кода авторизации. Неявные гранты и гибридные потоки являются ненужными в этом режиме. Обработчик OIDC автоматически запрашивает соответствующие маркеры с помощью кода, возвращаемого из конечной точки авторизации.
oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
MapInboundClaims и настройка NameClaimType и RoleClaimType: многие серверы name
OIDC используют "name
" и "ClaimTypes" вместо значений по умолчанию SOAP/WS-Fed. Если MapInboundClaims задано значение false
, обработчик не выполняет сопоставления утверждений, а имена утверждений из JWT используются непосредственно приложением. В следующем примере для типа утверждения роли задано значение "roles
", которое подходит для идентификатора Microsoft Entra (ME-ID). Дополнительные сведения см. в документации поставщика удостоверений.
Примечание.
MapInboundClaims Необходимо задать значение false
для большинства поставщиков OIDC, что предотвращает переименование утверждений.
oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
Конфигурация пути: Пути должны соответствовать URI перенаправления (путь обратного вызова для входа) и пути перенаправления после выхода (путь обратного вызова после выхода), которые были настроены при регистрации приложения у поставщика OIDC. На портале Azure пути настраиваются в колонке проверки подлинности регистрации приложения. Пути входа и выхода должны быть зарегистрированы как URI перенаправления. Значения по умолчанию: /signin-oidc
и /signout-callback-oidc
.
CallbackPath: Путь запроса в пределах базового пути приложения, где возвращается агент пользователя.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signin-oidc
Примечание.
Порт не требуется для localhost
адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков OIDC требуется правильный порт.
SignedOutCallbackPath (ключ конфигурации: "SignedOutCallbackPath
"): путь запроса в рамках базового пути приложения, перехваченный обработчиком OIDC, куда агент пользователя сначала возвращается после выхода из поставщика удостоверений. Пример приложения не задает значение для пути, так как используется значение по умолчанию "/signout-callback-oidc
". После перехвата запроса обработчик OIDC перенаправляет на SignedOutRedirectUri или RedirectUri, если указано.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signout-callback-oidc
Примечание.
При использовании идентификатора Microsoft Entra укажите путь в записях веб-платформы раздела URI перенаправления на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт. Если вы не добавите URI пути обратного вызова после выхода из системы в регистрацию приложения в Entra, Entra откажется перенаправить пользователя обратно в приложение и просто попросит его закрыть окно браузера.
RemoteSignOutPath: запросы, полученные по этому пути, приводят к тому, что обработчик вызывает выход, используя схему выхода.
В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost/signout-oidc
Примечание.
При использовании Microsoft Entra ID настройте URL front-channel для выхода на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт.
oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
Примеры (значения по умолчанию):
oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
(Microsoft Azure только с "общей" конечной точкой) TokenValidationParameters.IssuerValidator: многие провайдеры OIDC работают с проверкой издателя по умолчанию, но нам нужно учитывать издателя, параметризованного с использованием идентификатора клиента (Tenant ID) ({TENANT ID}
), возвращаемого https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
. Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException при работе с OpenID Connect и конечной точкой "common" Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731).
Только для приложений, использующих Microsoft Entra ID или Azure AD B2C с конечной точкой «common»:
var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
Blazor Web App клиентский проект (BlazorWebAppOidc.Client
)
Проект BlazorWebAppOidc.Client
— это клиентский проект Blazor Web App.
Клиент вызывает AddAuthenticationStateDeserialization для десериализации и использования состояния аутентификации, переданного сервером. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
Класс PersistentAuthenticationStateProvider
(PersistentAuthenticationStateProvider.cs
) — это клиентский элемент AuthenticationStateProvider, который определяет состояние аутентификации пользователя путем поиска данных, сохранённых на странице после её отрисовки на сервере. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
Если пользователю нужно войти или выйти, требуется полная перезагрузка страницы.
Пример приложения предоставляет только имя пользователя и электронную почту в целях отображения.
Для идентификатора Microsoft Entra или Azure AD B2C можно использовать AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web
пакет NuGet, документация по API), которая добавляет обработчики OIDC и Cookie проверки подлинности с соответствующими значениями по умолчанию. Пример приложения и инструкции, приведенные в этой статье, не используют Microsoft Identity Web. В руководстве показано, как настроить обработчик OIDC вручную для любого поставщика OIDC. Дополнительные сведения о реализации Microsoft Identity Web см. в статье "Защита ASP.NET Core Blazor Web App с помощью идентификатора Microsoft Entra".
Эта версия статьи охватывает реализацию OIDC без использования шаблона BFF (Backend for Frontend) с приложением, которое использует глобальное рендеринг интерактивного сервера (в рамках одного проекта). Шаблон BFF полезен для выполнения аутентифицированных запросов к внешним службам. Измените селектор версии статьи на шаблон BFF, если спецификация приложения требует внедрения шаблона BFF с глобальной интерактивной отрисовкой.
Используется следующая спецификация:
- В Blazor Web App используется режим серверной отрисовки с глобальным взаимодействием.
- Это приложение является отправной точкой для любого потока проверки подлинности OIDC. OIDC настраивается вручную в приложении и не зависит от идентификатора Microsoft Entra или пакетов Microsoft Identity Web, а также примерное приложение не требует размещения на Microsoft Azure. Однако пример приложения можно использовать с Entra, Microsoft Identity Web и размещать в Azure.
- Автоматическое обновление неинтерактивного токена.
- Отдельный проект веб-API демонстрирует безопасный вызов веб-API для погодных данных.
Для получения альтернативного опыта работы с библиотекой аутентификации Microsoft для .NET, Microsoft Web, и Microsoft Entra ID, см. статью "Защита ASP.NET Core с помощью Microsoft Entra ID".
Образец решения
Пример приложения состоит из следующих проектов:
-
BlazorWebAppOidcServer
: Blazor Web App серверный проект (глобальный интерактивный серверный рендеринг). -
MinimalApiJwt
: внутренний веб-API с минимальной конечной точкой API для данных о погоде.
Получить доступ к образцу из папки последней версии в репозитории примеров Blazor по следующей ссылке. Пример находится в папке BlazorWebAppOidcServer
для .NET 8 или более поздней версии.
Просмотр или скачивание примера кода (как скачать)
Регистрация приложений Microsoft Entra ID
Мы рекомендуем использовать отдельные регистрации для приложений и веб-API, даже если приложения и веб-API находятся в одном решении. Представленные рекомендации предназначены для BlazorWebAppOidcServer
приложения и MinimalApiJwt
веб-API примерного решения, но те же рекомендации также применяются к любым Entra-базированным регистрациям для приложений и веб-API.
Сначала зарегистрируйте веб-API,MinimalApiJwt
чтобы предоставить доступ к веб-API при регистрации приложения. Идентификатор арендатора и идентификатор клиента веб-API используются для настройки веб-API в файле Program
. После регистрации веб-API откройте веб-API в регистрациях приложений>Expose an API с именем области Weather.Get
. Запишите URI идентификатора приложения для использования в конфигурации приложения.
Затем зарегистрируйте приложение (BlazorWebAppOidcServer
) с конфигурацией веб-платформы и URI перенаправления (порт не требуется). Идентификатор арендатора и идентификатор клиента приложения, а также базовый адрес веб-API, URI идентификатора приложения и имя области видимости погоды используются для настройки приложения в файле Program
. Предоставьте разрешение API для доступа к веб-API в Регистрация приложений>разрешениях API. Если спецификация безопасности приложения вызывает ее, вы можете предоставить согласие администратора для организации для доступа к веб-API. Авторизованные пользователи и группы назначаются на регистрацию приложения в Регистрация приложений>Корпоративные приложения.
В конфигурации регистрации приложений на портале Entra или Azure в разделе неявного предоставления и гибридного потоков не устанавливайте флажки ни для конечной точки авторизации, возвращающей токены доступа или токены идентификатора. Обработчик OpenID Connect автоматически запрашивает соответствующие маркеры с помощью кода, возвращенного из конечной точки авторизации.
Создайте секрет клиента в регистрации приложения на портале Entra или Azure (управление>сертификатами и секретами>нового секрета клиента). Сохраните значение секрета клиента для использования в следующем разделе.
Дополнительные рекомендации по настройке Entra для определенных параметров приведены далее в этой статье.
Создайте секрет клиента
Этот раздел применяется только к серверному проекту Blazor Web App (BlazorWebAppOidcServer
проект).
Предупреждение
Не сохраняйте секреты приложений, строки подключения, учетные данные, пароли, личные идентификационные номера (ПИН-коды), частный код C#/.NET или закрытые ключи и токены в клиентском коде, который всегда небезопасн. В тестовых, промежуточных и рабочих средах код на стороне Blazor сервера и веб-API должен использовать безопасные методы аутентификации, которые избегают хранения учетных данных в коде проекта или конфигурационных файлах. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. в разделе "Безопасное обслуживание конфиденциальных данных и учетных данных".
При локальном тестировании разработки используйте средство Secret Manager для хранения секрета клиента проекта сервера под конфигурационным ключом Blazor.
Серверный Blazor проект не инициализирован для средства Диспетчера секретов. Используйте командную оболочку, например командную оболочку PowerShell разработчика в Visual Studio, чтобы выполнить следующую команду. Перед выполнением команды с помощью команды cd
измените каталог на директорию проекта сервера. Команда устанавливает идентификатор секретов пользователя (<UserSecretsId>
в файле проекта приложения):
dotnet user-secrets init
Выполните следующую команду, чтобы задать секрет клиента. Заполнитель {SECRET}
представляет собой секретный ключ клиента, полученный при регистрации приложения.
dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"
При использовании Visual Studio можно подтвердить, что секрет задан, щелкнув правой кнопкой мыши проект в обозревателе решений и выбрав пункт "Управление секретами пользователей".
MinimalApiJwt
проект
Проект MinimalApiJwt
— это внутренний веб-API для нескольких интерфейсных проектов. Проект настраивает минимальную конечную точку API для данных о погоде.
Файл MinimalApiJwt.http
можно использовать для тестирования запроса данных о погоде. Обратите внимание, что MinimalApiJwt
проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".
Проект включает пакеты и конфигурацию для создания документов OpenAPI и пользовательского интерфейса Swagger в среде разработки. Дополнительные сведения см. в статье "Использование созданных документов OpenAPI".
Проект создает минимальную конечную точку API для данных погоды:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
Настройте проект в JwtBearerOptions вызове в файле проекта AddJwtBearerProgram
.
Задает Authority уполномоченный орган для вызовов OIDC. Рекомендуется использовать отдельную регистрацию приложения для MinimalApiJwt
проекта. Орган соответствует эмитенту (iss
) JWT, возвращаемого поставщиком удостоверений.
jwtOptions.Authority = "{AUTHORITY}";
Формат органа управления зависит от типа арендатора в использовании. В следующих примерах для Microsoft Entra ID используется Tenant ID aaaabbbb-0000-cccc-1111-dddd2222eeee
.
пример полномочий арендатора ME-ID:
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
Пример центра клиента AAD B2C:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
Задает Audience аудиторию для любого полученного токена OIDC.
jwtOptions.Audience = "{APP ID URI}";
Примечание.
При использовании Microsoft Entra ID, сопоставьте значение только с путем URI идентификатора приложения, настроенного при добавлении области в разделе «Предоставление API» на портале Entra или Azure. Не включайте имя области "Weather.Get
" в значение.
Формат аудитории зависит от типа используемого арендатора. В следующих примерах для Microsoft Entra ID используется Tenant ID contoso
и Client ID 11112222-bbbb-3333-cccc-4444dddd5555
.
пример URI идентификатора приложения клиента ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Пример URI идентификатора приложения клиента AAD B2C:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
BlazorWebAppOidcServer
проект
Автоматическое обновление неинтерактивного маркера управляется пользовательским cookie обновлением (CookieOidcRefresher.cs
).
A DelegatingHandler (TokenHandler
) присоединяет токен доступа пользователя к исходящему запросу. Обработчик маркеров выполняется только во время статического рендеринга на стороне сервера, поэтому использование HttpContext безопасно в этом сценарии. Подробности см. в разделе IHttpContextAccessor/HttpContext в приложениях ASP.NET Core Blazor и на Blazor Web App.
TokenHandler.cs
:
public class TokenHandler(IHttpContextAccessor httpContextAccessor) :
DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (httpContextAccessor.HttpContext is null)
{
throw new Exception("HttpContext not available");
}
var accessToken = await httpContextAccessor.HttpContext
.GetTokenAsync("access_token");
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
return await base.SendAsync(request, cancellationToken);
}
}
В файле проекта
builder.Services.AddScoped<TokenHandler>();
builder.Services.AddHttpClient("ExternalApi",
client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ??
throw new Exception("Missing base address!")))
.AddHttpMessageHandler<TokenHandler>();
Компонент Weather
использует [Authorize]
атрибут для предотвращения несанкционированного доступа. Дополнительные сведения о необходимости авторизации в приложении с помощью политики авторизации и исключении авторизации для подмножества общедоступных конечных точек см. в Razor руководстве по OIDC Pages.
ExternalApi
HTTP-клиент используется для отправки запроса на данные о погоде к безопасному веб-API. В событии жизненного циклаOnInitializedAsync
Weather.razor
:
using var request = new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
var client = ClientFactory.CreateClient("ExternalApi");
using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
forecasts = await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
throw new IOException("No weather forecast!");
В файле проекта appsettings.json
настройте URI внешнего API:
"ExternalApiUri": "{BASE ADDRESS}"
Пример:
"ExternalApiUri": "https://localhost:7277"
Следующая OpenIdConnectOptions конфигурация найдена в файле проекта Program
при вызове AddOpenIdConnect:
PushedAuthorizationBehavior: контролирует поддержку push-запросов авторизации (PAR). По умолчанию параметр использует PAR, если документ обнаружения поставщика удостоверений, обычно найденный по адресу .well-known/openid-configuration
, заявляет о поддержке PAR. Если требуется поддержка PAR для приложения, можно назначить значение PushedAuthorizationBehavior.Require
. PAR не поддерживается Microsoft Entra, и не планируется поддержка в будущем.
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;
SignInScheme. Задает схему проверки подлинности, соответствующую ПО промежуточного слоя, ответственному за сохранение удостоверения пользователя после успешной проверки подлинности. Обработчик OIDC должен использовать схему входа, которая может сохранять учетные данные пользователя в запросах. Следующая строка представлена лишь для демонстрационных целей. Если опущено, DefaultSignInScheme используется в качестве резервного значения.
oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
Области для openid
и profile
(Scope) (необязательно): области openid
и profile
также настраиваются по умолчанию, так как они необходимы для работы обработчика OIDC, но их может потребоваться повторно добавить, если области включены в конфигурацию Authentication:Schemes:MicrosoftOidc:Scope
. Для общих рекомендаций по настройке смотрите Конфигурация в ASP.NET Core и ASP.NET Core Blazor конфигурация.
oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
Weather.Get
Настройте область доступа к внешнему веб-API для данных о погоде. Следующий пример основан на использовании идентификатора Entra в домене клиента ME-ID. В следующем примере заполнитель {APP ID URI}
найден на портале Entra или Azure, где размещён веб-API. Для любого другого поставщика удостоверений используйте соответствующую сферу применения.
oidcOptions.Scope.Add("{APP ID URI}/Weather.Get");
Формат области зависит от типа используемого арендатора. В следующих примерах домен арендатора — это contoso.onmicrosoft.com
, а идентификатор клиента — это 11112222-bbbb-3333-cccc-4444dddd5555
.
пример URI идентификатора приложения клиента ME-ID:
oidcOptions.Scope.Add("api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");
Пример URI идентификатора приложения клиента AAD B2C:
oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");
SaveTokens: определяет, следует ли хранить маркеры доступа и обновления в AuthenticationProperties после успешной авторизации. Это свойство имеет значение true
, поэтому токен обновления сохраняется для неинтерактивного обновления токенов.
oidcOptions.SaveTokens = true;
Область для офлайн-доступа (Scope): Область offline_access
необходима для получения маркера обновления.
oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
Authority и ClientId: задает уровень полномочий и идентификатор клиента для вызовов OIDC.
oidcOptions.Authority = "{AUTHORITY}";
oidcOptions.ClientId = "{CLIENT ID}";
В следующем примере используется идентификатор арендатора aaaabbbb-0000-cccc-1111-dddd2222eeee
и идентификатор клиента 00001111-aaaa-2222-bbbb-3333cccc4444
.
oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
Для мультитенантных приложений следует использовать орган "common". Вы также можете использовать полномочия "common" для однотенантных приложений, но требуется настраиваемый IssuerValidator, как показано далее в этом разделе.
oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
ResponseType: настраивает обработчик OIDC только для выполнения потока кода авторизации. Неявные гранты и гибридные потоки являются ненужными в этом режиме. Обработчик OIDC автоматически запрашивает соответствующие маркеры с помощью кода, возвращаемого из конечной точки авторизации.
oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
MapInboundClaims и настройка NameClaimType и RoleClaimType: многие серверы name
OIDC используют "name
" и "ClaimTypes" вместо значений по умолчанию SOAP/WS-Fed. Если MapInboundClaims задано значение false
, обработчик не выполняет сопоставления утверждений, а имена утверждений из JWT используются непосредственно приложением. В следующем примере для типа утверждения роли задано значение "roles
", которое подходит для идентификатора Microsoft Entra (ME-ID). Дополнительные сведения см. в документации поставщика удостоверений.
Примечание.
MapInboundClaims Необходимо задать значение false
для большинства поставщиков OIDC, что предотвращает переименование утверждений.
oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
Конфигурация пути: Пути должны соответствовать URI перенаправления (путь обратного вызова для входа) и пути перенаправления после выхода (путь обратного вызова после выхода), которые были настроены при регистрации приложения у поставщика OIDC. На портале Azure пути настраиваются в колонке проверки подлинности регистрации приложения. Пути входа и выхода должны быть зарегистрированы как URI перенаправления. Значения по умолчанию: /signin-oidc
и /signout-callback-oidc
.
CallbackPath: Путь запроса в пределах базового пути приложения, где возвращается агент пользователя.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signin-oidc
Примечание.
Порт не требуется для localhost
адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков OIDC требуется правильный порт.
SignedOutCallbackPath (ключ конфигурации: "SignedOutCallbackPath
"): путь запроса в рамках базового пути приложения, перехваченный обработчиком OIDC, куда агент пользователя сначала возвращается после выхода из поставщика удостоверений. Пример приложения не задает значение для пути, так как используется значение по умолчанию "/signout-callback-oidc
". После перехвата запроса обработчик OIDC перенаправляет на SignedOutRedirectUri или RedirectUri, если указано.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signout-callback-oidc
Примечание.
При использовании идентификатора Microsoft Entra укажите путь в записях веб-платформы раздела URI перенаправления на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт. Если вы не добавите URI пути обратного вызова после выхода из системы в регистрацию приложения в Entra, Entra откажется перенаправить пользователя обратно в приложение и просто попросит его закрыть окно браузера.
RemoteSignOutPath: запросы, полученные по этому пути, приводят к тому, что обработчик вызывает выход, используя схему выхода.
В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost/signout-oidc
Примечание.
При использовании Microsoft Entra ID настройте URL front-channel для выхода на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт.
oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
Примеры (значения по умолчанию):
oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
(Microsoft Azure только с "общей" конечной точкой) TokenValidationParameters.IssuerValidator: многие провайдеры OIDC работают с проверкой издателя по умолчанию, но нам нужно учитывать издателя, параметризованного с использованием идентификатора клиента (Tenant ID) ({TENANT ID}
), возвращаемого https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
. Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException при работе с OpenID Connect и конечной точкой "common" Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731).
Только для приложений, использующих Microsoft Entra ID или Azure AD B2C с конечной точкой «common»:
var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
Для идентификатора Microsoft Entra или Azure AD B2C можно использовать AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web
пакет NuGet, документация по API), которая добавляет обработчики OIDC и Cookie проверки подлинности с соответствующими значениями по умолчанию. Пример приложения и инструкции, приведенные в этой статье, не используют Microsoft Identity Web. В руководстве показано, как настроить обработчик OIDC вручную для любого поставщика OIDC. Дополнительные сведения о реализации Microsoft Identity Web см. в статье "Защита ASP.NET Core Blazor Web App с помощью идентификатора Microsoft Entra".
Эта версия статьи рассматривает реализацию OIDC с шаблоном Backend для Frontend (BFF). Если спецификация приложения не предусматривает внедрение шаблона BFF, измените селектор версии статьи на шаблон без BFF (интерактивная отрисовка авто) или шаблон без BFF (интерактивная серверная отрисовка).
Предпосылки
.NET Aspire требуется Visual Studio версии 17.10 или более поздней.
Кроме того, см. раздел "Предварительные требования"краткого руководства. Создание первого .NET Aspire приложения.
Образец решения
Пример приложения состоит из следующих проектов:
-
.NET Aspire:
-
Aspire.AppHost
: Используется для управления высокоуровневыми аспектами оркестрации приложения. -
Aspire.ServiceDefaults
: содержит конфигурации приложений по умолчанию .NET Aspire , которые можно расширить и настроить по мере необходимости.
-
-
MinimalApiJwt
: серверный веб API, содержащий пример конечной точки минимального API для данных о погоде. -
BlazorWebAppOidc
: серверный проект объекта Blazor Web App. Проект использует YARP для прокси-запросов к конечной точке прогноза погоды в проекте внутреннего веб-API (MinimalApiJwt
) сaccess_token
сохраненным в проверке подлинности cookie. -
BlazorWebAppOidc.Client
: клиентская часть проекта Blazor Web App.
Получить доступ к образцу из папки последней версии в репозитории примеров Blazor по следующей ссылке. Пример находится в папке BlazorWebAppOidcBff
для .NET 8 или более поздней версии.
Просмотр или скачивание примера кода (как скачать)
Элемент Blazor Web App использует режим автоматической отрисовки с глобальной интерактивностью.
Серверный проект вызывает AddAuthenticationStateSerialization, чтобы добавить поставщика состояния проверки подлинности на стороне сервера, который используется PersistentComponentState для передачи состояния проверки подлинности клиенту. Клиент вызывает AddAuthenticationStateDeserialization для десериализации и использования состояния аутентификации, переданного сервером. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
Класс PersistingAuthenticationStateProvider
(PersistingAuthenticationStateProvider.cs
) — это серверный компонент AuthenticationStateProvider, который использует PersistentComponentState для передачи состояния проверки подлинности клиенту, который затем устанавливается на время существования приложения WebAssembly.
Это приложение является отправной точкой для любого потока проверки подлинности OIDC. OIDC настраивается вручную в приложении и не зависит от идентификатора Microsoft Entra или пакетов Microsoft Identity Web, а также примерное приложение не требует размещения на Microsoft Azure. Однако пример приложения можно использовать с Entra, Microsoft Identity Web и размещать в Azure.
Автоматическое обновление токена без взаимодействия пользователя с помощью настраиваемого cookie средства обновления (CookieOidcRefresher.cs
).
Шаблон серверной части внешнего интерфейса (BFF) используется .NET Aspire для обнаружения служб и YARP для прокси-запросов к конечной точке прогноза погоды в серверном приложении.
Серверная часть веб-API (MinimalApiJwt
) использует аутентификацию JWT-носителя для проверки токенов JWT, сохранённых Blazor Web App в процессе входа cookie.
Aspire улучшает возможности создания облачных приложений .NET. Он предоставляет согласованный набор средств и шаблонов для создания и запуска распределенных приложений.
YARP (еще один обратный прокси-сервер) — это библиотека, используемая для создания обратного прокси-сервера.
MapForwarder
в файле проекта сервера Program
добавляет прямую передачу HTTP-запросов, которые соответствуют указанному шаблону, к определенному назначению, используя конфигурацию по умолчанию для исходящего запроса, настраиваемые преобразования и HTTP-клиент по умолчанию:
- При обработке компонента
Weather
на сервере, компонент использует классServerWeatherForecaster
для посредничества в запросе данных о погоде с использованием маркера доступа пользователя. IHttpContextAccessor.HttpContext определяет, доступен ли HttpContext для использования методомGetWeatherForecastAsync
. Дополнительные сведения см. в разделе ASP.NET Основные Razor компоненты. - При отрисовке компонента на клиенте компонент использует
ClientWeatherForecaster
реализацию службы, которая использует предустановленный HttpClient (в файле клиентского проектаProgram
) для выполнения вызова веб-API в серверном проекте. Минимальный API-эндпоинт (/weather-forecast
), определенный в файлеProgram
серверного проекта, преобразует запрос, используя маркер доступа пользователя, чтобы получить данные о погоде.
Для получения дополнительной информации о .NET Aspire, смотрите Общедоступность .NET Aspire: упрощение разработки .NET Cloud-Native (май 2024 г.).
Дополнительные сведения о вызовах веб-API с использованием абстракций служб см. в статье Blazor Web App.
Регистрация приложений Microsoft Entra ID
Мы рекомендуем использовать отдельные регистрации для приложений и веб-API, даже если приложения и веб-API находятся в одном решении. Представленные рекомендации предназначены для BlazorWebAppOidc
приложения и MinimalApiJwt
веб-API примерного решения, но те же рекомендации также применяются к любым Entra-базированным регистрациям для приложений и веб-API.
Сначала зарегистрируйте веб-API,MinimalApiJwt
чтобы предоставить доступ к веб-API при регистрации приложения. Идентификатор арендатора и идентификатор клиента веб-API используются для настройки веб-API в файле Program
. После регистрации веб-API откройте веб-API в регистрациях приложений>Expose an API с именем области Weather.Get
. Запишите URI идентификатора приложения для использования в конфигурации приложения.
Затем зарегистрируйте приложение (BlazorWebAppOidc
/BlazorWebApOidc.Client
) с конфигурацией веб-платформы и URI перенаправления (порт не требуется). Идентификатор арендатора и идентификатор клиента приложения, а также базовый адрес веб-API, URI идентификатора приложения и имя области видимости погоды используются для настройки приложения в файле Program
. Предоставьте разрешение API для доступа к веб-API в Регистрация приложений>разрешениях API. Если спецификация безопасности приложения вызывает ее, вы можете предоставить согласие администратора для организации для доступа к веб-API. Авторизованные пользователи и группы назначаются на регистрацию приложения в Регистрация приложений>Корпоративные приложения.
В конфигурации регистрации приложений на портале Entra или Azure в разделе неявного предоставления и гибридного потоков не устанавливайте флажки ни для конечной точки авторизации, возвращающей токены доступа или токены идентификатора. Обработчик OpenID Connect автоматически запрашивает соответствующие маркеры с помощью кода, возвращенного из конечной точки авторизации.
Создайте секрет клиента в регистрации приложения на портале Entra или Azure (управление>сертификатами и секретами>нового секрета клиента). Сохраните значение секрета клиента для использования в следующем разделе.
Дополнительные рекомендации по настройке Entra для определенных параметров приведены далее в этой статье.
Создайте секрет клиента
Этот раздел применяется только к серверному проекту Blazor Web App (BlazorWebAppOidc
проект).
Предупреждение
Не сохраняйте секреты приложений, строки подключения, учетные данные, пароли, личные идентификационные номера (ПИН-коды), частный код C#/.NET или закрытые ключи и токены в клиентском коде, который всегда небезопасн. В тестовых, промежуточных и рабочих средах код на стороне Blazor сервера и веб-API должен использовать безопасные методы аутентификации, которые избегают хранения учетных данных в коде проекта или конфигурационных файлах. Вне локального тестирования разработки рекомендуется избегать использования переменных среды для хранения конфиденциальных данных, так как переменные среды не являются наиболее безопасным подходом. Для локального тестирования разработки средство Secret Manager рекомендуется для защиты конфиденциальных данных. Дополнительные сведения см. в разделе "Безопасное обслуживание конфиденциальных данных и учетных данных".
При локальном тестировании разработки используйте средство Secret Manager для хранения секрета клиента проекта сервера под конфигурационным ключом Blazor.
Серверный Blazor проект не инициализирован для средства Диспетчера секретов. Используйте командную оболочку, например командную оболочку PowerShell разработчика в Visual Studio, чтобы выполнить следующую команду. Перед выполнением команды с помощью команды cd
измените каталог на директорию проекта сервера. Команда устанавливает идентификатор секретов пользователя (<UserSecretsId>
в файле проекта приложения сервера):
dotnet user-secrets init
Выполните следующую команду, чтобы задать секрет клиента. Заполнитель {SECRET}
представляет собой секретный ключ клиента, полученный при регистрации приложения.
dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"
При использовании Visual Studio можно подтвердить, что секрет задан, щелкнув правой кнопкой мыши проект сервера в обозревателе решений и выбрав пункт "Управление секретами пользователей".
.NET Aspire проектов
Дополнительные сведения об использовании .NET Aspire, а также о проектах .AppHost
и .ServiceDefaults
примера приложения см. в .NET Aspire документации.
Убедитесь, что вы выполнили предварительные условия для .NET Aspire. Дополнительные сведения см. в разделе "Предварительные требования " краткого руководства. Создание первого .NET Aspire приложения.
Пример приложения настраивает только небезопасный профиль запуска HTTP (http
) для использования во время тестирования разработки. Дополнительные сведения, включая пример небезопасных и безопасных профилей параметров запуска, см. в разделе "Разрешить небезопасный транспорт" (.NET Aspire.NET Aspireдокументация).
MinimalApiJwt
проект
Проект MinimalApiJwt
— это внутренний веб-API для нескольких интерфейсных проектов. Проект настраивает минимальную конечную точку API для данных о погоде. Запросы из Blazor Web App серверного проекта (BlazorWebAppOidc
) перенаправляются через прокси на проект MinimalApiJwt
.
Файл MinimalApiJwt.http
можно использовать для тестирования запроса данных о погоде. Обратите внимание, что MinimalApiJwt
проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".
Проект включает пакеты и конфигурацию для создания документов OpenAPI и пользовательского интерфейса Swagger в среде разработки. Дополнительные сведения см. в статье "Использование созданных документов OpenAPI".
Конечная точка данных для защищенного прогноза погоды находится в файле проекта Program
.
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
Метод RequireAuthorization расширения требует авторизации для определения маршрута. Для всех контроллеров, добавляющихся в проект, добавьте [Authorize]
атрибут в контроллер или действие.
Настройте проект в JwtBearerOptions вызове в файле проекта AddJwtBearerProgram
.
Задает Authority уполномоченный орган для вызовов OIDC. Рекомендуется использовать отдельную регистрацию приложения для MinimalApiJwt
проекта. Орган соответствует эмитенту (iss
) JWT, возвращаемого поставщиком удостоверений.
jwtOptions.Authority = "{AUTHORITY}";
Формат органа управления зависит от типа арендатора в использовании. В следующих примерах для Microsoft Entra ID используется Tenant ID aaaabbbb-0000-cccc-1111-dddd2222eeee
.
пример полномочий арендатора ME-ID:
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
Пример центра клиента AAD B2C:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
Задает Audience аудиторию для любого полученного токена OIDC.
jwtOptions.Audience = "{APP ID URI}";
Примечание.
При использовании Microsoft Entra ID, сопоставьте значение только с путем URI идентификатора приложения, настроенного при добавлении области в разделе «Предоставление API» на портале Entra или Azure. Не включайте имя области "Weather.Get
" в значение.
Формат аудитории зависит от типа используемого арендатора. В следующих примерах для Microsoft Entra ID используется Tenant ID contoso
и Client ID 11112222-bbbb-3333-cccc-4444dddd5555
.
пример URI идентификатора приложения клиента ME-ID:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Пример URI идентификатора приложения клиента AAD B2C:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
Серверный Blazor Web App проект (BlazorWebAppOidc
)
В этом разделе объясняется, как настроить серверный Blazor проект.
Следующая конфигурация OpenIdConnectOptions находится в файле проекта Program
по вызову AddOpenIdConnect.
PushedAuthorizationBehavior: контролирует поддержку push-запросов авторизации (PAR). По умолчанию параметр использует PAR, если документ обнаружения поставщика удостоверений, обычно найденный по адресу .well-known/openid-configuration
, заявляет о поддержке PAR. Если требуется поддержка PAR для приложения, можно назначить значение PushedAuthorizationBehavior.Require
. PAR не поддерживается Microsoft Entra, и не планируется поддержка в будущем.
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;
SignInScheme. Задает схему проверки подлинности, соответствующую ПО промежуточного слоя, ответственному за сохранение удостоверения пользователя после успешной проверки подлинности. Обработчик OIDC должен использовать схему входа, которая может сохранять учетные данные пользователя в запросах. Следующая строка представлена лишь для демонстрационных целей. Если опущено, DefaultSignInScheme используется в качестве резервного значения.
oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
Области для openid
и profile
(Scope) (необязательно): области openid
и profile
также настраиваются по умолчанию, так как они необходимы для работы обработчика OIDC, но их может потребоваться повторно добавить, если области включены в конфигурацию Authentication:Schemes:MicrosoftOidc:Scope
. Для общих рекомендаций по настройке смотрите Конфигурация в ASP.NET Core и ASP.NET Core Blazor конфигурация.
oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
SaveTokens: определяет, следует ли хранить маркеры доступа и обновления в AuthenticationProperties после успешной авторизации. Для проверки подлинности запросов на данные о погоде из проекта веб-API серверной части установлено значение true
, равное MinimalApiJwt
.
oidcOptions.SaveTokens = true;
Область для офлайн-доступа (Scope): Область offline_access
необходима для получения маркера обновления.
oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
Области получения данных о погоде из веб-API (Scope): настройте Weather.Get
область доступа к внешнему веб-API для данных о погоде. В следующем примере заполнитель {APP ID URI}
найден на портале Entra или Azure, где размещён веб-API. Для любого другого поставщика удостоверений используйте соответствующую сферу применения.
oidcOptions.Scope.Add("{APP ID URI}/Weather.Get");
Формат области зависит от типа используемого арендатора. В следующих примерах домен арендатора — это contoso.onmicrosoft.com
, а идентификатор клиента — это 11112222-bbbb-3333-cccc-4444dddd5555
.
пример URI идентификатора приложения клиента ME-ID:
oidcOptions.Scope.Add("api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");
Пример URI идентификатора приложения клиента AAD B2C:
oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");
Authority и ClientId: задает уровень полномочий и идентификатор клиента для вызовов OIDC.
oidcOptions.Authority = "{AUTHORITY}";
oidcOptions.ClientId = "{CLIENT ID}";
В следующем примере используется идентификатор арендатора aaaabbbb-0000-cccc-1111-dddd2222eeee
и идентификатор клиента 00001111-aaaa-2222-bbbb-3333cccc4444
.
oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
Для мультитенантных приложений следует использовать орган "common". Вы также можете использовать полномочия "common" для однотенантных приложений, но требуется настраиваемый IssuerValidator, как показано далее в этом разделе.
oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
ResponseType: настраивает обработчик OIDC только для выполнения потока кода авторизации. Неявные гранты и гибридные потоки являются ненужными в этом режиме. Обработчик OIDC автоматически запрашивает соответствующие маркеры с помощью кода, возвращаемого из конечной точки авторизации.
oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
MapInboundClaims и настройка NameClaimType и RoleClaimType: многие серверы name
OIDC используют "name
" и "ClaimTypes" вместо значений по умолчанию SOAP/WS-Fed. Если MapInboundClaims задано значение false
, обработчик не выполняет сопоставления утверждений, а имена утверждений из JWT используются непосредственно приложением. В следующем примере для типа утверждения роли задано значение "roles
", которое подходит для идентификатора Microsoft Entra (ME-ID). Дополнительные сведения см. в документации поставщика удостоверений.
Примечание.
MapInboundClaims Необходимо задать значение false
для большинства поставщиков OIDC, что предотвращает переименование утверждений.
oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
Конфигурация пути: Пути должны соответствовать URI перенаправления (путь обратного вызова для входа) и пути перенаправления после выхода (путь обратного вызова после выхода), которые были настроены при регистрации приложения у поставщика OIDC. На портале Azure пути настраиваются в колонке проверки подлинности регистрации приложения. Пути входа и выхода должны быть зарегистрированы как URI перенаправления. Значения по умолчанию: /signin-oidc
и /signout-callback-oidc
.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signin-oidc
Примечание.
Порт не требуется для localhost
адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков OIDC требуется правильный порт.
SignedOutCallbackPath (ключ конфигурации: "SignedOutCallbackPath
"): путь запроса в рамках базового пути приложения, перехваченный обработчиком OIDC, куда агент пользователя сначала возвращается после выхода из поставщика удостоверений. Пример приложения не задает значение для пути, так как используется значение по умолчанию "/signout-callback-oidc
". После перехвата запроса обработчик OIDC перенаправляет на SignedOutRedirectUri или RedirectUri, если указано.
Настройте путь обратного вызова для выхода из системы в настройках провайдера OIDC приложения. В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost:{PORT}/signout-callback-oidc
Примечание.
При использовании идентификатора Microsoft Entra укажите путь в записях веб-платформы раздела URI перенаправления на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт. Если вы не добавите URI пути обратного вызова после выхода из системы в регистрацию приложения в Entra, Entra откажется перенаправить пользователя обратно в приложение и просто попросит его закрыть окно браузера.
RemoteSignOutPath: запросы, полученные по этому пути, приводят к тому, что обработчик вызывает выход, используя схему выхода.
В следующем примере заполнитель {PORT}
является портом приложения:
https://localhost/signout-oidc
Примечание.
При использовании Microsoft Entra ID настройте URL front-channel для выхода на портале Entra или Azure. Порт не требуется при использовании Entra для адресов "localhost
". Большинству других поставщиков OIDC требуется правильный порт.
oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
Примеры (значения по умолчанию):
oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
(Microsoft Azure только с "общей" конечной точкой) TokenValidationParameters.IssuerValidator: многие провайдеры OIDC работают с проверкой издателя по умолчанию, но нам нужно учитывать издателя, параметризованного с использованием идентификатора клиента (Tenant ID) ({TENANT ID}
), возвращаемого https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
. Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException при работе с OpenID Connect и конечной точкой "common" Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731).
Только для приложений, использующих Microsoft Entra ID или Azure AD B2C с конечной точкой «common»:
var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
Клиентский Blazor Web App проект (BlazorWebAppOidc.Client
)
Проект BlazorWebAppOidc.Client
— это клиентский проект Blazor Web App.
Клиент вызывает AddAuthenticationStateDeserialization для десериализации и использования состояния аутентификации, переданного сервером. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
Класс PersistentAuthenticationStateProvider
(PersistentAuthenticationStateProvider.cs
) — это клиентский элемент AuthenticationStateProvider, который определяет состояние аутентификации пользователя путем поиска данных, сохранённых на странице после её отрисовки на сервере. Состояние аутентификации зафиксировано на все время существования приложения WebAssembly.
Если пользователю нужно войти или выйти, требуется полная перезагрузка страницы.
Пример приложения предоставляет только имя пользователя и электронную почту в целях отображения.
Сериализуйте только утверждения о имени и роли.
Этот раздел относится только к шаблону, отличному от BFF (интерактивное авто) и шаблону BFF (интерактивное авто) и их примерам приложений.
В файле Program
все утверждения сериализуются путём установки SerializeAllClaims в true
. Если вы хотите сериализовать для CSR только имя и заявки о роли, удалите параметр или задайте для него значение false
.
Укажите конфигурацию с помощью поставщика конфигурации JSON (параметры приложения)
Примеры проектов решений настраивают проверку подлинности носителя OIDC и JWT в своих Program
файлах для обнаружения параметров конфигурации с помощью автозаполнения C#. Профессиональные приложения обычно используют поставщика конфигурации для настройки OIDC параметров, таких как поставщик конфигурации JSON по умолчанию. Поставщик конфигурации JSON загружает конфигурацию из файлов appsettings.json
/appsettings.{ENVIRONMENT}.json
параметров приложения, где {ENVIRONMENT}
заполнитель — среда выполнения приложения. Следуйте инструкциям в этом разделе, чтобы использовать файлы параметров приложения для настройки.
В файле настроек приложения (appsettings.json
) проекта BlazorWebAppOidc
или BlazorWebAppOidcServer
добавьте следующую конфигурацию JSON:
"Authentication": {
"Schemes": {
"MicrosoftOidc": {
"Authority": "https://login.microsoftonline.com/{TENANT ID (BLAZOR APP)}/v2.0/",
"ClientId": "{CLIENT ID (BLAZOR APP)}",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath": "/signout-callback-oidc",
"RemoteSignOutPath": "/signout-oidc",
"SignedOutRedirectUri": "/",
"Scope": [
"openid",
"profile",
"offline_access",
"{APP ID URI (WEB API)}/Weather.Get"
]
}
}
},
Обновите заполнители в предыдущей конфигурации, чтобы соответствовать значениям, которые приложение использует в Program
файле:
-
{TENANT ID (BLAZOR APP)}
: идентификатор арендатора приложения Blazor. -
{CLIENT ID (BLAZOR APP)}
: идентификатор Blazor клиента приложения. -
{APP ID URI (WEB API)}
: URI идентификатора веб-приложения API.
Для приложений с несколькими арендаторами следует использовать "common" (https://login.microsoftonline.com/common/v2.0/
) авторизацию. Чтобы использовать "common" Орган для однопользовательских приложений, см. раздел Использование "common" Органа для однопользовательских приложений.
Обновите любые другие значения в предыдущей конфигурации, чтобы соответствовать пользовательским или не по умолчанию значениям, используемым в Program
файле.
Конфигурация автоматически выбирается конструктором аутентификации.
Удалите следующие строки из Program
файла:
- oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
- oidcOptions.Scope.Add("...");
- oidcOptions.CallbackPath = new PathString("...");
- oidcOptions.SignedOutCallbackPath = new PathString("...");
- oidcOptions.RemoteSignOutPath = new PathString("...");
- oidcOptions.Authority = "...";
- oidcOptions.ClientId = "...";
В методе ConfigureCookieOidc
CookieOidcServiceCollectionExtensions.cs
, удалите следующую строку:
- oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
В проекте MinimalApiJwt
добавьте следующую конфигурацию параметров приложения в файл appsettings.json
.
"Authentication": {
"Schemes": {
"Bearer": {
"Authority": "https://sts.windows.net/{TENANT ID (WEB API)}/",
"ValidAudiences": [ "{APP ID URI (WEB API)}" ]
}
}
},
Обновите заполнители в предыдущей конфигурации, чтобы соответствовать значениям, которые приложение использует в Program
файле:
-
{TENANT ID (WEB API)}
: идентификатор арендатора веб-API. -
{APP ID URI (WEB API)}
: URI идентификатора веб-приложения API.
Форматы власти принимают следующие шаблоны:
- тип арендатора ME-ID:
https://sts.windows.net/{TENANT ID}/
- Тип клиента B2C:
https://login.microsoftonline.com/{TENANT ID}/v2.0/
Форматы аудитории принимают следующие шаблоны ({CLIENT ID}
является идентификатором клиента веб-API; {DIRECTORY NAME}
это имя каталога, например contoso
):
- тип арендатора ME-ID:
api://{CLIENT ID}
- Тип клиента B2C:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
Конфигурация автоматически выбирается построителем проверки подлинности носителя JWT.
Удалите следующие строки из Program
файла:
- jwtOptions.Authority = "...";
- jwtOptions.Audience = "...";
Дополнительные сведения о конфигурации см. в следующих ресурсах:
- Конфигурация в ASP.NET Core
- Конфигурация Blazor в ASP.NET Core
Используйте "common" авторизацию для одноклиентских приложений
Вы можете использовать "common" Authority для приложений для одного арендатора, но для реализации пользовательского валидатора издателя необходимо выполнить следующие действия.
Добавьте Microsoft.IdentityModel.Validators
пакет NuGet в проект BlazorWebAppOidc
, BlazorWebAppOidcServer
, или BlazorWebAppOidcBff
.
Примечание.
Рекомендации по добавлению пакетов в приложения .NET см. в статьях в разделе "Установка пакетов и управление пакетами" в рабочем процессе потребления пакетов (документация NuGet). Проверьте правильность версий пакета на сайте NuGet.org.
В верхней части файла Program
обеспечьте доступность пространства имен Microsoft.IdentityModel.Validators.
using Microsoft.IdentityModel.Validators;
Используйте следующий код в файле, в Program
котором настроены параметры OIDC:
var microsoftIssuerValidator =
AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
oidcOptions.TokenValidationParameters.IssuerValidator =
microsoftIssuerValidator.Validate;
Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException при работе с OpenID Connect и конечной точкой "common" Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet
#1731).
Перенаправление на домашнюю страницу при выходе
Компонент LogInOrOut
(Layout/LogInOrOut.razor
) задает скрытое поле для возвращаемого URL-адреса (ReturnUrl
) для текущего URL-адреса (currentURL
). Когда пользователь выходит из приложения, поставщик удостоверений возвращает пользователя на страницу, из которой они выошли. Если пользователь выходит из безопасной страницы, он возвращается на ту же безопасную страницу и отправляется обратно через процесс проверки подлинности. Этот поток проверки подлинности является разумным, если пользователям нужно регулярно изменять учетные записи.
В качестве альтернативы используйте следующий компонент LogInOrOut
, который не предоставляет возвращаемый URL-адрес при выходе.
Layout/LogInOrOut.razor
:
<div class="nav-item px-3">
<AuthorizeView>
<Authorized>
<form action="authentication/logout" method="post">
<AntiforgeryToken />
<button type="submit" class="nav-link">
<span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
</span> Logout
</button>
</form>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">
<span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span>
Login
</a>
</NotAuthorized>
</AuthorizeView>
</div>
Обновление токена
Реализация пользовательского cookie обновления (CookieOidcRefresher.cs
) автоматически обновляет утверждения пользователя при истечении их срока действия. Текущая реализация ожидает получения ID токена с точки окончания токенов в обмен на маркер обновления. Затем утверждения в этом токене идентификатора используются для замены утверждений пользователя.
Пример реализации не содержит код для запроса к конечной точке UserInfo при обновлении токена. Дополнительные сведения см. в разделе BlazorWebAppOidc AddOpenIdConnect with GetClaimsFromUserInfoEndpoint = true doesn't propogate [sic] role claims to client
(dotnet/aspnetcore
#58826).
Примечание.
Некоторые поставщики удостоверений возвращают токен доступа только при использовании токена обновления.
CookieOidcRefresher
можно обновить, добавив дополнительную логику, чтобы и дальше использовать предыдущий набор утверждений, сохранённых в системе аутентификации cookie, или использовать токен доступа для запроса утверждений из API точки UserInfo.
Криптографический элемент nonce
Nonce — это строковое значение, которое связывает сеанс клиента с идентификационным токеном, чтобы предотвратить атаки повторного воспроизведения.
Если при разработке и тестировании аутентификации возникает ошибка одноразового токена (nonce error), используйте новый сеанс браузера в режиме InPrivate/инкогнито для каждого прогона теста, независимо от того, насколько незначительны изменения в приложении или учетной записи тестировщика, так как устаревшие cookie данные могут привести к ошибке одноразового токена. Дополнительные сведения см. в разделе "Файлы cookie" и "Данные сайта ".
Нонc не требуется и не используется, когда маркер обновления обменивается на новый маркер доступа. В примере приложения CookieOidcRefresher
(CookieOidcRefresher.cs
) намеренно задает значение OpenIdConnectProtocolValidator.RequireNonce для false
.
Роли приложений для программ, не зарегистрированных в Microsoft Entra (ME-ID)
Этот раздел относится к приложениям, которые не используют идентификатор Microsoft Entra (ME-ID) в качестве поставщика удостоверений. Сведения о приложениях, зарегистрированных с помощью ME-ID, см. в разделе " Роли приложения" для приложений, зарегистрированных в Microsoft Entra (ME-ID) .
Настройте тип утверждения роли (TokenValidationParameters.RoleClaimType) в OpenIdConnectOptionsProgram.cs
:
oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";
Для многих поставщиков удостоверений OIDC тип атрибута роли role
. Проверьте документацию удостоверяющего центра для корректного значения.
Замените UserInfo
класс в BlazorWebAppOidc.Client
проекте следующим классом.
UserInfo.cs
:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;
namespace BlazorWebAppOidc.Client;
// Add properties to this class and update the server and client
// AuthenticationStateProviders to expose more information about
// the authenticated user to the client.
public sealed class UserInfo
{
public required string UserId { get; init; }
public required string Name { get; init; }
public required string[] Roles { get; init; }
public const string UserIdClaimType = "sub";
public const string NameClaimType = "name";
private const string RoleClaimType = "role";
public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
new()
{
UserId = GetRequiredClaim(principal, UserIdClaimType),
Name = GetRequiredClaim(principal, NameClaimType),
Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
.ToArray(),
};
public ClaimsPrincipal ToClaimsPrincipal() =>
new(new ClaimsIdentity(
Roles.Select(role => new Claim(RoleClaimType, role))
.Concat([
new Claim(UserIdClaimType, UserId),
new Claim(NameClaimType, Name),
]),
authenticationType: nameof(UserInfo),
nameType: NameClaimType,
roleType: RoleClaimType));
private static string GetRequiredClaim(ClaimsPrincipal principal,
string claimType) =>
principal.FindFirst(claimType)?.Value ??
throw new InvalidOperationException(
$"Could not find required '{claimType}' claim.");
}
На этом этапе Razor компоненты могут принимать авторизацию на основе ролей и политик. Роли приложения отображаются в role
утверждениях, по одному утверждению для каждой роли.
Роли приложений для программ, зарегистрированных в Microsoft Entra (ME-ID)
Используйте инструкции в этом разделе для реализации ролей приложений, групп безопасности ME-ID и ME-ID встроенных ролей администратора для приложений с помощью идентификатора Microsoft Entra (ME-ID).
Описанный в этом разделе подход настраивает ME-ID для отправки групп и ролей в заголовке аутентификации cookie. Если пользователи входят только в несколько групп безопасности и ролей, предложенный ниже подход должен работать для большинства хостинговых платформ без возникновения проблемы слишком длинных заголовков, например, при использовании хостинга IIS с ограничением длины заголовка по умолчанию 16 КБ (MaxRequestBytes
). Если длина заголовка является проблемой из-за высокого уровня членства в группе или роли, мы рекомендуем не следовать инструкциям в этом разделе в пользу реализации Microsoft Graph для получения групп и ролей пользователя из ME-ID отдельно, подход, который не расширяет размер проверки подлинности cookie. Дополнительные сведения см. в разделе "Недопустимый запрос — слишком длинный запрос — сервер IIS" (dotnet/aspnetcore
#57545).
Настройте тип утверждения роли (TokenValidationParameters.RoleClaimType) в OpenIdConnectOptionsProgram.cs
. Задайте для параметра значение roles
:
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
Хотя вы не можете назначать роли группам без учетной записи ME-ID Premium, вы можете назначать роли пользователям и получать утверждения ролей для пользователей со стандартной учетной записью Azure. Для использования рекомендаций в этом разделе не нужна учетная запись ME-ID Premium.
При работе с каталогом по умолчанию следуйте рекомендациям в статье «Добавьте роли приложения в ваше приложение и получайте их в токене (ME-ID документация)» для настройки и назначения ролей. Если вы не работаете с каталогом по умолчанию, измените манифест приложения в портале Azure, чтобы вручную установить роли приложения в записи манифеста appRoles
. Дополнительные сведения см. в "Настройка утверждения роли" (документацияME-ID).
Группы безопасности Azure пользователя приходят в
В манифесте приложения на портале Azure установите значение атрибута groupMembershipClaims
на All
. Значение All
приводит к тому, что ME-ID отправляет все группы безопасности и распределения (groups
утверждения) и роли (wids
утверждения) вошедшего в систему пользователя. Чтобы задать groupMembershipClaims
атрибут, выполните следующие действия.
- Откройте регистрацию приложения в портал Azure.
- Выберите Управление>Манифест на боковой панели.
- Найдите атрибут
groupMembershipClaims
. - Установите значение на
All
("groupMembershipClaims": "All"
). - Нажмите кнопку "Сохранить ".
Замените UserInfo
класс в BlazorWebAppOidc.Client
проекте следующим классом.
UserInfo.cs
:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;
namespace BlazorWebAppOidc.Client;
// Add properties to this class and update the server and client
// AuthenticationStateProviders to expose more information about
// the authenticated user to the client.
public sealed class UserInfo
{
public required string UserId { get; init; }
public required string Name { get; init; }
public required string[] Roles { get; init; }
public required string[] Groups { get; init; }
public required string[] Wids { get; init; }
public const string UserIdClaimType = "sub";
public const string NameClaimType = "name";
private const string RoleClaimType = "roles";
private const string GroupsClaimType = "groups";
private const string WidsClaimType = "wids";
public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
new()
{
UserId = GetRequiredClaim(principal, UserIdClaimType),
Name = GetRequiredClaim(principal, NameClaimType),
Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
.ToArray(),
Groups = principal.FindAll(GroupsClaimType).Select(c => c.Value)
.ToArray(),
Wids = principal.FindAll(WidsClaimType).Select(c => c.Value)
.ToArray(),
};
public ClaimsPrincipal ToClaimsPrincipal() =>
new(new ClaimsIdentity(
Roles.Select(role => new Claim(RoleClaimType, role))
.Concat(Groups.Select(role => new Claim(GroupsClaimType, role)))
.Concat(Wids.Select(role => new Claim(WidsClaimType, role)))
.Concat([
new Claim(UserIdClaimType, UserId),
new Claim(NameClaimType, Name),
]),
authenticationType: nameof(UserInfo),
nameType: NameClaimType,
roleType: RoleClaimType));
private static string GetRequiredClaim(ClaimsPrincipal principal,
string claimType) =>
principal.FindFirst(claimType)?.Value ??
throw new InvalidOperationException(
$"Could not find required '{claimType}' claim.");
}
На этом этапе Razor компоненты могут принимать авторизацию на основе ролей и политик:
- Роли приложения отображаются в
roles
утверждениях, по одному утверждению для каждой роли. - Группы безопасности отображаются в
groups
утверждениях, по одному утверждению для каждой группы. Идентификаторы GUID группы безопасности отображаются на портале Azure при создании группы безопасности и перечисляются при выборе Identity>Обзор>Группы>Просмотр. - Встроенные роли администратора ME-ID отображаются в утверждениях
wids
, по одному утверждению на каждую роль. Утверждениеwids
со значениемb79fbf4d-3ef9-4689-8143-76b194e85509
всегда отправляется ME-ID для негостевых учетных записей арендатора и не ссылается на роль администратора. Идентификаторы ролей администратора (идентификаторы ролей-шаблонов) отображаются в портале Azure при выборе Роли и администраторы, а затем многоточия (>) Описание для указанной роли. Идентификаторы шаблонов ролей также перечислены в встроенных ролях Microsoft Entra (документация по Entra).
Устранение неполадок
Логирование
Серверное приложение — это стандартное приложение ASP.NET Core. Ознакомьтесь с руководством по ведению журнала ASP.NET Core , чтобы включить более низкий уровень ведения журнала в серверном приложении.
Чтобы включить ведение журнала отладки или трассировки для Blazor WebAssembly проверки подлинности, см. раздел Blazor ASP.NET Core с селектором версий статьи, установленным для ASP.NET Core в .NET 7 или более поздней версии.
Распространенные ошибки
Отладчик останавливается на исключении во время выхода из системы с Microsoft Entra External ID
Следующее исключение останавливает отладчик Visual Studio во время выхода из системы с Microsoft Entra External ID:
Uncaught TypeError TypeError: Failed to execute 'postMessage' on 'Window': The provided value cannot be converted to a sequence.
Исключение выбрасывается из кода Entra JavaScript, поэтому это не связано с ASP.NET Core. Исключение не влияет на функциональные возможности приложений в рабочей среде, поэтому исключение можно игнорировать во время локального тестирования разработки.
Неправильная настройка приложения или поставщика Identity (IP)
Наиболее частые ошибки вызваны неправильной настройкой. Ниже приводятся несколько примеров.
- В зависимости от требований сценария, отсутствие или неправильные значения таких элементов, как авторитет, экземпляр, идентификатор арендатора, домен арендатора, идентификатор клиента или URI перенаправления, не позволяют приложению аутентифицировать клиентов.
- Неверные области запросов не позволяют клиентам получать доступ к конечным точкам веб-API сервера.
- Неправильные или отсутствующие разрешения API сервера не позволяют клиентам получить доступ к конечным точкам веб-API сервера.
- Запуск приложения на порте, отличающемся от того, который настроен в URI перенаправления в настройках регистрации приложения для IP. Обратите внимание, что порт не требуется для идентификатора Microsoft Entra и приложения, работающего на
localhost
адресе тестирования разработки, но конфигурация порта приложения и порт, на котором оно выполняется, должны совпадать для других адресовlocalhost
.
Освещение конфигурации в этой статье приводит примеры правильной конфигурации. Тщательно проверьте конфигурацию, исключите неправильные настройки приложения и IP-адреса.
Если конфигурация верна, выполните приведенные ниже действия.
Проанализируйте журналы приложений.
Изучите сетевой трафик между клиентским приложением и IP или серверным приложением с помощью инструментов разработчика браузера. Зачастую точное сообщение об ошибке или сообщение с указанием на то, что вызывает проблему, возвращается клиенту серверным приложением или приложением IP после выполнения запроса. Руководство по инструментам разработчика можно найти в следующих статьях:
- Google Chrome (документация По Google)
- Microsoft Edge
- Mozilla Firefox (документация mozilla)
Команда документации отвечает на отзывы о документе и ошибки в статьях (откройте проблему из раздела отзывов этой страницы ), но не может предоставить поддержку продукта. Помощь в устранении неполадок в приложении предоставляют несколько общественных форумов поддержки. Мы рекомендуем следующее:
Предыдущие форумы не принадлежат или управляются корпорацией Майкрософт.
Для отчетов об ошибках платформы, которые не относятся к безопасности, не являются конфиденциальными и не являются тайными, откройте задачу в подразделении продукта ASP.NET Core. Не открывайте запрос с продуктовой командой, пока вы тщательно не изучите причину проблемы и не сможете решить её самостоятельно или с помощью сообщества на общедоступном форуме поддержки. Единица продукта не способна устранять неполадки отдельных приложений, которые не работают из-за неправильной конфигурации или вариантов использования с участием сторонних служб. Если отчет имеет деликатный или конфиденциальный характер или описывает потенциальную уязвимость безопасности в продукте, которую могут использовать злоумышленники, см. раздел "Отчеты о проблемах безопасности и ошибках" (
репозиторий GitHub). Несанкционированный клиент для ME-ID
info: Авторизация не удалась Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]. Эти требования не выполнены: DenyAnonymousAuthorizationRequirement: требуется прошедший проверку подлинности пользователь.
Ошибка обратного вызова при входе из ME-ID:
- Ошибка:
unauthorized_client
- Описание:
AADB2C90058: The provided application is not configured to allow public clients.
Чтобы устранить эту ошибку, сделайте следующее:
- На портале Azure перейдите к манифесту приложения.
- Установите атрибут
allowPublicClient
наnull
илиtrue
.
- Ошибка:
Файлы cookie и данные сайта
Файлы cookie и данные сайта могут сохраняться в разных обновлениях приложений и повлиять на тестирование и устранение неполадок. При внесении изменений в код приложения, изменений в учетную запись пользователя у поставщика или изменений конфигурации приложения поставщика очистите следующее:
- файлы cookie входа пользователей;
- файлы cookie приложения;
- кэшированные и сохраненные данные сайта.
Один из подходов, позволяющих предотвратить влияние устаревших файлов cookie и данных сайта на тестирование и устранение неполадок заключается в следующем:
- Настройка браузера
- Для тестирования используйте браузер, в котором можно настроить удаление всех файлов cookie и данных сайта при каждом закрытии браузера.
- Убедитесь, что при любых изменениях в приложении, в данных тестового пользователя или в конфигурации поставщика закрытие браузера выполняется вручную или интегрированной средой разработки.
- Используйте пользовательскую команду, чтобы открыть браузер в режиме InPrivate или Incognito в Visual Studio:
- Откройте диалоговое окно "Обзор с помощью" через кнопку «Запуск» в Visual Studio.
- Нажмите кнопку "Добавить ".
- Укажите путь к браузеру в поле "Программа ". Следующие пути к исполняемым файлам являются типичными расположениями установки для Windows 10. Если браузер установлен в другом расположении или вы используете операционную систему, отличную от Windows 10, укажите путь к исполняемому файлу браузера.
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
- Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
- Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- В поле "Аргументы" укажите параметр командной строки, который браузер использует для открытия в режиме InPrivate или Incognito. Для некоторых браузеров требуется URL-адрес приложения.
- Microsoft Edge: используйте
-inprivate
. - Google Chrome: используйте
--incognito --new-window {URL}
, где в качестве{URL}
укажите URL-адрес для открытия (например,https://localhost:5001
). - Mozilla Firefox: используйте
-private -url {URL}
, где{URL}
представляет собой URL-адрес для открытия (например,https://localhost:5001
).
- Microsoft Edge: используйте
- Укажите имя в поле «Понятное имя». Например,
Firefox Auth Testing
. - Нажмите кнопку "ОК ".
- Чтобы избежать необходимости выбирать профиль браузера для каждого итерации тестирования с приложением, задайте профиль в качестве значения по умолчанию с кнопкой "Задать как значение по умолчанию ".
- Убедитесь, что при любых изменениях в приложении, в данных тестового пользователя или в конфигурации поставщика закрытие браузера выполняется интегрированной средой разработки.
Обновление приложений
Работающее приложение может перестать работать сразу после обновления .NET Core SDK на машине разработки или изменения версий пакетов в самой программе. В некоторых случаях при выполнении крупных обновлений несогласованные пакеты могут нарушить работу приложения. Большинство этих проблем можно исправить следующим образом:
- Очистите кэши пакетов NuGet локальных систем, выполнив команду
dotnet nuget locals all --clear
из командной оболочки. - Удалите папки
bin
иobj
проекта. - Восстановите и перестройте проект.
- Удалите все файлы из папки развертывания на сервере, прежде чем повторно развернуть приложение.
Примечание.
Использование версий пакета, несовместимых с требуемой платформой приложения, не поддерживается. Для получения сведений о пакете используйте NuGet Gallery.
Начните работу над решением из подходящего проекта
Blazor Web Apps:
- Для одного из примеров шаблона Backend for-Frontend (BFF) запустите решение из
Aspire/Aspire.AppHost
проекта. - Для одного из примеров шаблонов, отличных от BFF, запустите решение из серверного проекта.
Blazor Server:
Запустите решение из серверного проекта.
Проверка пользователя
Следующий UserClaims
компонент можно использовать непосредственно в приложениях или служить основой для дальнейшей настройки.
UserClaims.razor
:
@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li><b>@claim.Type:</b> @claim.Value</li>
}
</ul>
}
@code {
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState == null)
{
return;
}
var authState = await AuthState;
claims = authState.User.Claims;
}
}
Дополнительные ресурсы
-
AzureAD/microsoft-identity-web
Репозиторий GitHub: Полезное руководство по реализации Microsoft Identity Web для Microsoft Entra ID и Azure Active Directory B2C для приложений ASP.NET Core, включая ссылки на примеры приложений и связанную документацию по Azure. В настоящее время Blazor Web App не упоминаются прямо в документации Azure, но настройка и конфигурация Blazor Web App для ME-ID и размещения Azure такая же, как для любого веб-приложения ASP.NET Core. -
AuthenticationStateProvider
служба - Управление состоянием проверки подлинности в Blazor Web Apps
-
Токен обновления во время HTTP-запроса в Blazor интерактивном сервере с OIDC (
dotnet/aspnetcore
#55213) - Защита данных в Blazor Web Apps с помощью интерактивного автоматического рендеринга
-
Как получить доступ к объекту
AuthenticationStateProvider
изDelegatingHandler
ASP.NET Core