Поделиться через


Защита веб-приложения ASP.NET Core Blazor с помощью OpenID Подключение (OIDC)

В этой статье описывается, как защитить Blazor веб-приложение с помощью OpenID Подключение (OIDC) с помощью примера приложения вdotnet/blazor-samplesрепозитории GitHub (.NET 8 или более поздней версии) (как скачать).

Эта версия статьи охватывает реализацию OIDC без внедрения шаблона Серверной части для внешнего интерфейса (BFF). Шаблон BFF полезен для выполнения аутентифицированных запросов к внешним службам. Измените селектор версии статьи на OIDC с шаблоном BFF, если спецификация приложения вызывает внедрение шаблона BFF.

Рассматривается следующая спецификация:

  • Blazor Веб-приложение использует режим автоматической отрисовки с глобальным взаимодействием.
  • Пользовательские службы поставщика состояний проверки подлинности используются сервером и клиентскими приложениями для записи состояния проверки подлинности пользователя и потока между сервером и клиентом.
  • Это приложение является отправной точкой для любого потока проверки подлинности OIDC. OIDC настраивается вручную в приложении и не зависит от идентификатора Microsoft Entra или веб-пакетов МайкрософтIdentity, а также не требует размещения Microsoft Azure. Однако пример приложения может использоваться с Entra, Microsoft Identity Web и размещенным в Azure.
  • Автоматическое обновление неинтерактивного маркера.
  • Безопасно вызывает (веб-) API в серверном проекте для данных.

Пример приложения

Пример приложения состоит из двух проектов:

  • BlazorWebAppOidc: серверный проект веб-приложения, содержащий пример минимальной конечной Blazor точки API для данных о погоде.
  • BlazorWebAppOidc.Client: клиентский Blazor проект веб-приложения.

Перейдите к примеру приложений через последнюю папку версии из корневого каталога репозитория, используя следующую ссылку. Проекты находятся в папке BlazorWebAppOidc для .NET 8 или более поздней версии.

Просмотреть или скачать образец кода (описание загрузки)

Проект веб-приложения на стороне Blazor сервера (BlazorWebAppOidc)

Проект BlazorWebAppOidc — это серверный проект Blazor веб-приложения.

Файл BlazorWebAppOidc.http можно использовать для тестирования запроса данных о погоде. Обратите внимание, что BlazorWebAppOidc проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".

Примечание.

Серверный проект используется, но никогда не используется IHttpContextAccessor/HttpContextдля интерактивных отрисованных компонентов. Дополнительные сведения см. в руководстве по устранению угроз для интерактивной отрисовки на стороне сервера ASP.NET CoreBlazor.

Настройка

В этом разделе объясняется, как настроить пример приложения.

Примечание.

Для идентификатора Microsoft Entra и Azure AD B2C можно использовать AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web пакет NuGet, документация по API), которая добавляет обработчики OIDC и Cookie проверки подлинности с соответствующими значениями по умолчанию. Пример приложения и руководство в этом разделе не используют Microsoft Identity Web. В руководстве показано, как настроить обработчик OIDC вручную для любого поставщика OIDC. Дополнительные сведения о реализации Microsoft Identity Web см. в связанных ресурсах.

Следующая OpenIdConnectOptions конфигурация найдена в файле проекта Program по вызову AddOpenIdConnect:

  • SignInScheme: задает схему проверки подлинности, соответствующую ПО промежуточного слоя, ответственному за сохранение удостоверения пользователя после успешной проверки подлинности. Обработчик OIDC должен использовать схему входа, которая может сохранять учетные данные пользователя в запросах. Следующая строка представлена лишь для демонстрационных целей. Если опущено, DefaultSignInScheme используется в качестве резервного значения.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Области для и () (необязательно): profileopenid область также настраиваются по умолчанию, так как они необходимы для работы обработчика OIDC, но их может потребоваться повторно добавить, если область включены в Authentication:Schemes:MicrosoftOidc:Scope конфигурацию.Scopeprofileopenid Общие рекомендации по настройке см. в разделе "Конфигурация" в ASP.NET Core и конфигурации ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: определяет, следует ли хранить маркеры доступа и обновления в AuthenticationProperties после успешной авторизации. Это свойство устанавливается false по умолчанию, чтобы уменьшить размер окончательной проверки подлинности cookie.

    oidcOptions.SaveTokens = false;
    
  • Область автономного доступа (Scope): offline_access для маркера обновления требуется область.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Authority и ClientId: задает идентификатор центра и клиента для вызовов OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Пример:

    • Центр (): https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/ ({AUTHORITY}использует идентификатор a3942615-d115-4eb7-bc84-9974abcf5064клиента)
    • Идентификатор клиента ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
    oidcOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/";
    oidcOptions.ClientId = "4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
    

    Пример для центра "common" Microsoft Azure:

    Центр "common" должен использоваться для мультитенантных приложений. Вы также можете использовать центр "common" для однотенантных приложений, но это IssuerValidator необходимо, как показано далее в этом разделе.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ClientSecret: секрет клиента OIDC.

    Следующий пример предназначен только для тестирования и демонстрации. Не сохраняйте секрет клиента в сборке приложения или проверка секрет в систему управления версиями. Сохраните секрет клиента в секретах пользователей, Azure Key Vault или переменной среды.

    Конфигурация схемы проверки подлинности автоматически считывается, где builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]{SCHEME NAME} заполнитель — это схема, которая по MicrosoftOidc умолчанию. Так как конфигурация предварительно настроена, секрет клиента можно автоматически считывать с помощью Authentication:Schemes:MicrosoftOidc:ClientSecret ключа конфигурации. На сервере с помощью переменных среды назовите переменную Authentication__Schemes__MicrosoftOidc__ClientSecretсреды:

    set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET}
    

    Только для демонстрации и тестированияClientSecret можно задать напрямую. Не устанавливайте значение непосредственно для развернутых рабочих приложений. Для немного улучшенной безопасности условно компилируйте строку с символом DEBUG :

    #if DEBUG
    oidcOptions.ClientSecret = "{CLIENT SECRET}";
    #endif
    

    Пример:

    Секрет клиента (): 463471c8c4...f90d674bc9 ({CLIENT SECRET}сокращен для отображения)

    #if DEBUG
    oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9";
    #endif
    
  • ResponseType: настраивает обработчик OIDC только для выполнения потока кода авторизации. Неявные гранты и гибридные потоки являются ненужными в этом режиме.

    В конфигурации регистрации приложений неявного предоставления или портал Azure портал Azure не выбирайте флажок проверка box для конечной точки авторизации, чтобы вернуть маркеры доступа или маркеры идентификатора. Обработчик OIDC автоматически запрашивает соответствующие маркеры с помощью кода, возвращаемого из конечной точки авторизации.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimsи настройка NameClaimTypeRoleClaimTypeи: многие серверы ClaimTypesOIDC используют "" и "namerole" вместо значений по умолчанию SOAP/WS-Fed. Если MapInboundClaims задано значение false, обработчик не выполняет сопоставления утверждений, а имена утверждений из JWT используются непосредственно приложением. В следующем примере вручную сопоставляется утверждения имени и роли:

Примечание.

MapInboundClaims Необходимо задать значение false для большинства поставщиков OIDC, что предотвращает переименование утверждений.

oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
oidcOptions.TokenValidationParameters.RoleClaimType = "role";
  • Конфигурация пути. Пути должны соответствовать URI перенаправления (путь обратного вызова для входа) и пути перенаправления после выхода (путь обратного вызова со знаком выхода), настроенные при регистрации приложения в поставщике OIDC. В портал Azure пути настраиваются в колонке проверки подлинности регистрации приложения. Пути входа и выхода должны быть зарегистрированы как URI перенаправления. Значения по умолчанию: /signin-oidc и /signout-callback-oidc.

    • CallbackPath: Путь запроса в базовом пути приложения, в котором возвращается агент пользователя.

      В записи или портал Azure задайте путь в URI перенаправления веб-платформы:

      https://localhost/signin-oidc

      Примечание.

      Порт не требуется для localhost адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков OIDC требуется правильный порт.

    • SignedOutCallbackPath: Путь запроса в базовом пути приложения, в котором агент пользователя возвращается после выхода из поставщика удостоверений.

      В записи или портал Azure задайте путь в URI перенаправления веб-платформы:

      https://localhost/signout-callback-oidc

      Примечание.

      Порт не требуется для localhost адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков OIDC требуется правильный порт.

      Примечание.

      При использовании Microsoft Identity Web поставщик в настоящее время перенаправляется только в том SignedOutCallbackPath случае, если microsoftonline.com используется центр (https://login.microsoftonline.com/{TENANT ID}/v2.0/). Это ограничение не существует, если вы можете использовать центр "common" с Microsoft Identity Web. Дополнительные сведения см. в разделе postLogoutRedirectUri, если URL-адрес центра содержит идентификатор клиента (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: запросы, полученные по этому пути, приводят к вызову обработчика выхода с помощью схемы выхода.

      В записи или портал Azure задайте URL-адрес выхода front-channel:

      https://localhost/signout-oidc

      Примечание.

      Порт не требуется для localhost адресов при использовании идентификатора Microsoft Entra. Большинству других поставщиков 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}) возвращенный https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException с помощью OpenID Подключение и конечной точки Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet#1731).

    Только для приложений с помощью идентификатора Microsoft Entra или Azure AD B2C с конечной точкой common:

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Пример кода приложения

Проверьте пример приложения для следующих функций:

  • Автоматическое обновление неинтерактивного маркера с помощью пользовательского cookie средства обновления (CookieOidcRefresher.cs).
  • Класс PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) — это серверная сторона AuthenticationStateProvider , которая используется PersistentComponentState для потока состояния проверки подлинности клиенту, который затем фиксируется в течение времени существования приложения WebAssembly.
  • Пример запросов к веб-приложению Blazor для данных о погоде обрабатывается минимальной конечной точкой API (/weather-forecast) в Program файле (Program.cs). Для конечной точки требуется авторизация путем вызова RequireAuthorization. Для всех контроллеров, добавляющихся в проект, добавьте [Authorize] атрибут в контроллер или действие.
  • Приложение безопасно вызывает (веб-) API в проекте сервера для погодных данных:
    • При отрисовке Weather компонента на сервере компонент используется ServerWeatherForecaster на сервере для получения данных о погоде напрямую (а не через вызов веб-API).
    • При отрисовке компонента на клиенте компонент использует ClientWeatherForecaster реализацию службы, которая использует предварительно настроенный HttpClient (в файле клиентского проекта Program ) вызов веб-API к проекту сервера. Минимальная конечная точка API (/weather-forecast), определенная в файле проекта Program сервера, получает данные о погоде из ServerWeatherForecaster клиента и возвращает данные клиенту.

Дополнительные сведения о вызовах API (веб-) с помощью абстракций служб в веб-приложения см. в Blazor разделе "Вызов веб-API" из приложения ASP.NET CoreBlazor.

Проект веб-приложения на стороне Blazor клиента (BlazorWebAppOidc.Client)

Проект BlazorWebAppOidc.Client — это клиентский проект Blazor веб-приложения.

Класс PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) — это клиентская сторона AuthenticationStateProvider , которая определяет состояние проверки подлинности пользователя путем поиска данных, сохраненных на странице при отрисовке на сервере. Состояние проверки подлинности исправлено для времени существования приложения WebAssembly.

Если пользователю нужно войти или выйти, требуется полная перезагрузка страницы.

Пример приложения предоставляет только имя пользователя и электронную почту в целях отображения. Он не включает маркеры, прошедшие проверку подлинности на сервере при выполнении последующих запросов, которые работают отдельно с помощью cookie включенного в HttpClient запросы к серверу.

Эта версия статьи охватывает реализацию OIDC с шаблоном Серверной части для frontend (BFF). Измените селектор версий статьи на OIDC без шаблона BFF, если спецификация приложения не вызывает внедрения шаблона BFF.

Рассматривается следующая спецификация:

  • Blazor Веб-приложение использует режим автоматической отрисовки с глобальным взаимодействием.
  • Пользовательские службы поставщика состояний проверки подлинности используются сервером и клиентскими приложениями для записи состояния проверки подлинности пользователя и потока между сервером и клиентом.
  • Это приложение является отправной точкой для любого потока проверки подлинности OIDC. OIDC настраивается вручную в приложении и не зависит от идентификатора Microsoft Entra или веб-пакетов МайкрософтIdentity, а также не требует размещения Microsoft Azure. Однако пример приложения может использоваться с Entra, Microsoft Identity Web и размещенным в Azure.
  • Автоматическое обновление неинтерактивного маркера.
  • Шаблон серверной части внешнего интерфейса (BFF) используется с помощью .NET Aspire для обнаружения служб и YARP для прокси-запросов к конечной точке прогноза погоды в серверном приложении.
    • Внутренний веб-API использует проверку подлинности носителя JWT для проверки маркеров JWT, сохраненных Blazor веб-приложением в входе cookie.
    • Aspire улучшает возможности создания облачных приложений .NET. Он предоставляет согласованный набор средств и шаблонов для создания и запуска распределенных приложений.
    • YARP (еще один обратный прокси-сервер) — это библиотека, используемая для создания обратного прокси-сервера.

Дополнительные сведения о .NET Aspire см. в статье "Общая доступность .NET Aspire: упрощение разработки в .NET Cloud-Native (май 2024 г.)".

Необходимые условия

Для .NET Aspire требуется Visual Studio версии 17.10 или более поздней.

Пример приложения

Пример приложения состоит из пяти проектов:

  • .NET Aspire:
    • Aspire.AppHost: используется для управления проблемами оркестрации высокого уровня приложения.
    • Aspire.ServiceDefaults: содержит конфигурации приложений .NET Aspire по умолчанию, которые можно расширить и настроить по мере необходимости.
  • MinimalApiJwt: внутренний веб-API, содержащий пример конечной точки Минимального API для данных о погоде.
  • BlazorWebAppOidc: серверный проект Blazor веб-приложения.
  • BlazorWebAppOidc.Client: клиентский Blazor проект веб-приложения.

Перейдите к примеру приложений через последнюю папку версии из корневого каталога репозитория, используя следующую ссылку. Проекты находятся в папке BlazorWebAppOidcBff для .NET 8 или более поздней версии.

Просмотреть или скачать образец кода (описание загрузки)

Проекты .NET Aspire

Дополнительные сведения об использовании .NET Aspire и .AppHost.ServiceDefaults проектах примера приложения см. в документации по .NET Aspire.

Убедитесь, что вы выполнили необходимые условия для .NET Aspire. Дополнительные сведения см. в разделе "Предварительные требования" краткого руководства. Создание первого приложения .NET Aspire.

Пример приложения настраивает только небезопасный профиль запуска HTTP (http) для использования во время тестирования разработки. Дополнительные сведения, включая пример небезопасных и безопасных параметров запуска, см. в разделе "Разрешить небезопасный транспорт" в документации по .NET Aspire (.NET Aspire).

Проект веб-приложения на стороне Blazor сервера (BlazorWebAppOidc)

Проект BlazorWebAppOidc — это серверный проект Blazor веб-приложения. Проект использует YARP для прокси-запросов к конечной точке прогноза погоды в проекте внутреннего веб-API (MinimalApiJwt) с access_token сохраненным в проверке подлинности cookie.

Файл BlazorWebAppOidc.http можно использовать для тестирования запроса данных о погоде. Обратите внимание, что BlazorWebAppOidc проект должен выполняться для тестирования конечной точки, а конечная точка жестко закодирована в файл. Дополнительные сведения см. в статье "Использование HTTP-файлов в Visual Studio 2022".

Примечание.

Серверный проект используется, но никогда не используется IHttpContextAccessor/HttpContextдля интерактивных отрисованных компонентов. Дополнительные сведения см. в руководстве по устранению угроз для интерактивной отрисовки на стороне сервера ASP.NET CoreBlazor.

Настройка

В этом разделе объясняется, как настроить пример приложения.

Примечание.

Для идентификатора Microsoft Entra и Azure AD B2C можно использовать AddMicrosoftIdentityWebApp из Microsoft Identity Web (Microsoft.Identity.Web пакет NuGet, документация по API), которая добавляет обработчики OIDC и Cookie проверки подлинности с соответствующими значениями по умолчанию. Пример приложения и руководство в этом разделе не используют Microsoft Identity Web. В руководстве показано, как настроить обработчик OIDC вручную для любого поставщика OIDC. Дополнительные сведения о реализации Microsoft Identity Web см. в связанных ресурсах.

Следующая OpenIdConnectOptions конфигурация найдена в файле проекта Program по вызову AddOpenIdConnect:

  • SignInScheme: задает схему проверки подлинности, соответствующую ПО промежуточного слоя, ответственному за сохранение удостоверения пользователя после успешной проверки подлинности. Обработчик OIDC должен использовать схему входа, которая может сохранять учетные данные пользователя в запросах. Следующая строка представлена лишь для демонстрационных целей. Если опущено, DefaultSignInScheme используется в качестве резервного значения.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Области для и () (необязательно): profileopenid область также настраиваются по умолчанию, так как они необходимы для работы обработчика OIDC, но их может потребоваться повторно добавить, если область включены в Authentication:Schemes:MicrosoftOidc:Scope конфигурацию.Scopeprofileopenid Общие рекомендации по настройке см. в разделе "Конфигурация" в ASP.NET Core и конфигурации ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: определяет, следует ли хранить маркеры доступа и обновления в AuthenticationProperties после успешной авторизации. Для проверки подлинности запросов о погоде из проектаMinimalApiJwt веб-API серверной части задано true значение.

    oidcOptions.SaveTokens = true;
    
  • Область автономного доступа (Scope): offline_access для маркера обновления требуется область.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Области получения данных о погоде из веб-API (Scope): Weather.Get область настраивается на портале Azure или Entra в разделе "Предоставление API". Это необходимо для проекта веб-API серверной части (MinimalApiJwt) для проверки маркера доступа с помощью носителя JWT.

    oidcOptions.Scope.Add("{APP ID URI}/{API NAME}");
    

    Пример:

    • URI идентификатора приложения ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
      • Имя каталога ({DIRECTORY NAME}): contoso
      • Идентификатор приложения (клиента) ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
    • Область, настроенная для данных о погоде (MinimalApiJwt{API NAME}):Weather.Get
    oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f/Weather.Get");
    

    В предыдущем примере относится приложение, зарегистрированное в клиенте с типом клиента AAD B2C. Если приложение зарегистрировано в клиенте ME-ID, URI идентификатора приложения отличается, поэтому область отличается.

    Пример:

    • URI идентификатора приложения ({APP ID URI}): api://{CLIENT ID} с идентификатором приложения (клиентом) ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
    • Область, настроенная для данных о погоде (MinimalApiJwt{API NAME}):Weather.Get
    oidcOptions.Scope.Add("api://4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f/Weather.Get");
    
  • Authority и ClientId: задает идентификатор центра и клиента для вызовов OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Пример:

    • Центр (): https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/ ({AUTHORITY}использует идентификатор a3942615-d115-4eb7-bc84-9974abcf5064клиента)
    • Идентификатор клиента ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
    oidcOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/";
    oidcOptions.ClientId = "4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
    

    Пример для центра "common" Microsoft Azure:

    Центр "common" должен использоваться для мультитенантных приложений. Вы также можете использовать центр "common" для однотенантных приложений, но это IssuerValidator необходимо, как показано далее в этом разделе.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ClientSecret: секрет клиента OIDC.

    Следующий пример предназначен только для тестирования и демонстрации. Не сохраняйте секрет клиента в сборке приложения или проверка секрет в систему управления версиями. Сохраните секрет клиента в секретах пользователей, Azure Key Vault или переменной среды.

    Конфигурация схемы проверки подлинности автоматически считывается, где builder.Configuration["Authentication:Schemes:{SCHEME NAME}:{PropertyName}"]{SCHEME NAME} заполнитель — это схема, которая по MicrosoftOidc умолчанию. Так как конфигурация предварительно настроена, секрет клиента можно автоматически считывать с помощью Authentication:Schemes:MicrosoftOidc:ClientSecret ключа конфигурации. На сервере с помощью переменных среды назовите переменную Authentication__Schemes__MicrosoftOidc__ClientSecretсреды:

    set Authentication__Schemes__MicrosoftOidc__ClientSecret={CLIENT SECRET}
    

    Только для демонстрации и тестированияClientSecret можно задать напрямую. Не устанавливайте значение непосредственно для развернутых рабочих приложений. Для немного улучшенной безопасности условно компилируйте строку с символом DEBUG :

    #if DEBUG
    oidcOptions.ClientSecret = "{CLIENT SECRET}";
    #endif
    

    Пример:

    Секрет клиента (): 463471c8c4...f90d674bc9 ({CLIENT SECRET}сокращен для отображения)

    #if DEBUG
    oidcOptions.ClientSecret = "463471c8c4...137f90d674bc9";
    #endif
    
  • ResponseType: настраивает обработчик OIDC только для выполнения потока кода авторизации. Неявные гранты и гибридные потоки являются ненужными в этом режиме.

    В конфигурации регистрации приложений неявного предоставления или портал Azure портал Azure не выбирайте флажок проверка box для конечной точки авторизации, чтобы вернуть маркеры доступа или маркеры идентификатора. Обработчик OIDC автоматически запрашивает соответствующие маркеры с помощью кода, возвращаемого из конечной точки авторизации.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaimsи настройка NameClaimTypeRoleClaimTypeи: многие серверы ClaimTypesOIDC используют "" и "namerole" вместо значений по умолчанию SOAP/WS-Fed. Если MapInboundClaims задано значение false, обработчик не выполняет сопоставления утверждений, а имена утверждений из JWT используются непосредственно приложением. В следующем примере вручную сопоставляется утверждения имени и роли:

Примечание.

MapInboundClaims Необходимо задать значение false для большинства поставщиков OIDC, что предотвращает переименование утверждений.

oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
oidcOptions.TokenValidationParameters.RoleClaimType = "role";
  • Конфигурация пути. Пути должны соответствовать URI перенаправления (путь обратного вызова для входа) и пути перенаправления после выхода (путь обратного вызова со знаком выхода), настроенные при регистрации приложения в поставщике OIDC. В портал Azure пути настраиваются в колонке проверки подлинности регистрации приложения. Пути входа и выхода должны быть зарегистрированы как URI перенаправления. Значения по умолчанию: /signin-oidc и /signout-callback-oidc.

    • CallbackPath: Путь запроса в базовом пути приложения, в котором возвращается агент пользователя.

      В записи или портал Azure задайте путь в URI перенаправления веб-платформы:

      https://localhost/signin-oidc

      Примечание.

      Порт не требуется для localhost адресов.

    • SignedOutCallbackPath: Путь запроса в базовом пути приложения, в котором агент пользователя возвращается после выхода из поставщика удостоверений.

      В записи или портал Azure задайте путь в URI перенаправления веб-платформы:

      https://localhost/signout-callback-oidc

      Примечание.

      Порт не требуется для localhost адресов.

      Примечание.

      При использовании Microsoft Identity Web поставщик в настоящее время перенаправляется только в том SignedOutCallbackPath случае, если microsoftonline.com используется центр (https://login.microsoftonline.com/{TENANT ID}/v2.0/). Это ограничение не существует, если вы можете использовать центр "common" с Microsoft Identity Web. Дополнительные сведения см. в разделе postLogoutRedirectUri, если URL-адрес центра содержит идентификатор клиента (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: запросы, полученные по этому пути, приводят к вызову обработчика выхода с помощью схемы выхода.

      В записи или портал Azure задайте URL-адрес выхода front-channel:

      https://localhost/signout-oidc

      Примечание.

      Порт не требуется для localhost адресов.

    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}) возвращенный https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Дополнительные сведения см. в статье SecurityTokenInvalidIssuerException с помощью OpenID Подключение и конечной точки Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet#1731).

    Только для приложений с помощью идентификатора Microsoft Entra или Azure AD B2C с конечной точкой common:

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Пример кода приложения

Проверьте пример приложения для следующих функций:

  • Автоматическое обновление неинтерактивного маркера с помощью пользовательского cookie средства обновления (CookieOidcRefresher.cs).
  • Класс PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) — это серверная сторона AuthenticationStateProvider , которая используется PersistentComponentState для потока состояния проверки подлинности клиенту, который затем фиксируется в течение времени существования приложения WebAssembly.
  • Запросы к Blazor веб-приложению являются прокси-серверным проектом веб-API (MinimalApiJwt). MapForwarderProgram В файле добавляется прямая пересылка HTTP-запросов, которые соответствуют указанному шаблону определенному назначению, используя конфигурацию по умолчанию для исходящего запроса, настраиваемые преобразования и HTTP-клиент по умолчанию:
    • При отрисовке Weather компонента на сервере компонент используется ServerWeatherForecaster для прокси-запроса на данные погоды с маркером доступа пользователя.
    • При отрисовке компонента на клиенте компонент использует ClientWeatherForecaster реализацию службы, которая использует предварительно настроенный HttpClient (в файле клиентского проекта Program ) вызов веб-API к проекту сервера. Минимальная конечная точка API (/weather-forecast), определенная в файле проекта Program сервера, преобразует запрос с маркером доступа пользователя для получения данных о погоде.

Дополнительные сведения о вызовах API (веб-) с помощью абстракций служб в веб-приложения см. в Blazor разделе "Вызов веб-API" из приложения ASP.NET CoreBlazor.

Проект веб-приложения на стороне Blazor клиента (BlazorWebAppOidc.Client)

Проект BlazorWebAppOidc.Client — это клиентский проект Blazor веб-приложения.

Класс PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) — это клиентская сторона AuthenticationStateProvider , которая определяет состояние проверки подлинности пользователя путем поиска данных, сохраненных на странице при отрисовке на сервере. Состояние проверки подлинности исправлено для времени существования приложения WebAssembly.

Если пользователю нужно войти или выйти, требуется полная перезагрузка страницы.

Пример приложения предоставляет только имя пользователя и электронную почту в целях отображения. Он не включает маркеры, прошедшие проверку подлинности на сервере при выполнении последующих запросов, которые работают отдельно с помощью cookie включенного в HttpClient запросы к серверу.

Проект веб-API серверной части (MinimalApiJwt)

Проект MinimalApiJwt — это внутренний веб-API для нескольких интерфейсных проектов. Проект настраивает минимальную конечную точку API для данных о погоде. Запросы из проекта на стороне Blazor сервера веб-приложения (BlazorWebAppOidc) используются в MinimalApiJwt проекте.

Настройка

Настройте проект в вызове в JwtBearerOptionsAddJwtBearer файле проекта Program :

  • Audience: задает аудиторию для любого полученного токена OpenID Подключение.

    На портале Azure или Entra: соответствует значению только путь к URI идентификатора приложения, настроенного при добавлении Weather.Get область в разделе "Предоставление API":

    jwtOptions.Audience = "{APP ID URI}";
    

    Пример:

    URI идентификатора приложения ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}

    • Имя каталога ({DIRECTORY NAME}): contoso
    • Идентификатор приложения (клиента) ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f
    jwtOptions.Audience = "https://contoso.onmicrosoft.com/4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
    

    В предыдущем примере относится приложение, зарегистрированное в клиенте с типом клиента AAD B2C. Если приложение зарегистрировано в клиенте ME-ID, URI идентификатора приложения отличается, поэтому аудитория отличается.

    Пример:

    URI идентификатора приложения ({APP ID URI}): api://{CLIENT ID} с идентификатором приложения (клиентом) ({CLIENT ID}): 4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f

    jwtOptions.Audience = "api://4ba4de56-9cef-45d9-83fa-a4c18f9f5f0f";
    
  • Authority: задает центр для выполнения вызовов OpenID Подключение. Соответствует значению центра, настроенного для обработчика OIDC в BlazorWebAppOidc/Program.cs:

    jwtOptions.Authority = "{AUTHORITY}";
    

    Пример:

    Центр (): https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/ ({AUTHORITY}использует идентификатор a3942615-d115-4eb7-bc84-9974abcf5064клиента)

    jwtOptions.Authority = "https://login.microsoftonline.com/a3942615-d115-4eb7-bc84-9974abcf5064/v2.0/";
    

    В предыдущем примере относится приложение, зарегистрированное в клиенте с типом клиента AAD B2C. Если приложение зарегистрировано в клиенте ME-ID, центр должен соответствовать issurer (iss) JWT, возвращаемого поставщиком удостоверений:

    jwtOptions.Authority = "https://sts.windows.net/a3942615-d115-4eb7-bc84-9974abcf5064/";
    

Минимальный API для данных о погоде

Безопасная конечная точка данных прогноза 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] атрибут в контроллер или действие.

Перенаправление на домашнюю страницу при выходе

Когда пользователь перемещается по приложению, компонент (Layout/LogInOrOut.razor) задает скрытое поле для возвращаемого URL-адреса (ReturnUrl) значение текущего URL-адреса (currentURL).LogInOrOut Когда пользователь выходит из приложения, поставщик удостоверений возвращает их на страницу, из которой они вышли.

Если пользователь выходит из безопасной страницы, он возвращается обратно на ту же безопасную страницу после выхода только для отправки через процесс проверки подлинности. Это поведение хорошо, если пользователям нужно часто переключать учетные записи. Однако альтернативная спецификация приложения может вызвать возвращение пользователя на домашнюю страницу приложения или на другую страницу после выхода. В следующем примере показано, как задать домашнюю страницу приложения в качестве URL-адреса возврата для операций выхода.

Важные изменения LogInOrOut компонента показаны в следующем примере. Скрытое value поле для этого ReturnUrl поля устанавливается на домашнюю страницу./ IDisposable больше не реализуется. Больше NavigationManager не внедряется. Весь @code блок удаляется.

Layout/LogInOrOut.razor:

@using Microsoft.AspNetCore.Authorization

<div class="nav-item px-3">
    <AuthorizeView>
        <Authorized>
            <form action="authentication/logout" method="post">
                <AntiforgeryToken />
                <input type="hidden" name="ReturnUrl" value="/" />
                <button type="submit" class="nav-link">
                    <span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
                    </span> Logout @context.User.Identity?.Name
                </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>

Криптографический nonce

Nonce — это строковое значение, которое связывает сеанс клиента с маркером идентификатора для устранения атак воспроизведения.

Если во время разработки и тестирования проверки подлинности возникает ошибка, используйте новый сеанс браузера InPrivate/incognito для каждого тестового запуска, независимо от того, насколько мало внесенных изменений в приложение или тестового пользователя, так как устаревшие cookie данные могут привести к ошибке nonce. Дополнительные сведения см. в Cookieразделе данных сайта и s.

Не требуется или используется, если маркер обновления обменивается на новый маркер доступа. В примере приложения CookieOidcRefresher () намеренно задает значение OpenIdConnectProtocolValidator.RequireNoncefalse.CookieOidcRefresher.cs

Устранение неполадок

Ведение журнала

Серверное приложение — это стандартное приложение ASP.NET Core. Ознакомьтесь с руководством по ведению журнала ASP.NET Core, чтобы включить более низкий уровень ведения журнала в серверном приложении.

Чтобы включить ведение журнала отладки или трассировки для Blazor WebAssembly проверки подлинности, см. раздел Blazor ведения журнала проверки подлинности на стороне клиента ASP.NET Core с селектором версий статьи, установленным для ASP.NET Core 7.0 или более поздней версии.

Распространенные ошибки

  • Неправильная настройка приложения или поставщика Identity (IP)

    Наиболее частые ошибки вызваны неправильной настройкой. Ниже приводятся несколько примеров.

    • В зависимости от требований сценария, отсутствующие или неправильные элементы, такие как центр сертификации, экземпляр, идентификатор арендатора, домен арендатора, идентификатор клиента или URI перенаправления, не позволяют приложению осуществлять проверку подлинности клиентов.
    • Неверные область запросов не позволяют клиентам получать доступ к конечным точкам веб-API сервера.
    • Неправильные или отсутствующие разрешения API сервера не позволяют клиентам получить доступ к конечным точкам веб-API сервера.
    • Запуск приложения на порте, отличном от настроенного в URI перенаправления регистрации приложения IP-адреса. Обратите внимание, что порт не требуется для идентификатора Microsoft Entra и приложения, работающего на localhost адресе тестирования разработки, но конфигурация порта приложения и порт, на котором выполняется приложение, должно соответствовать не-адресамlocalhost .

    Покрытие конфигурации в этой статье показывает примеры правильной конфигурации. Тщательно проверка конфигурацию, в ходе поиска неправильной настройки приложений и IP-адресов.

    Если конфигурация верна, выполните приведенные ниже действия.

    • Проанализируйте журналы приложений.

    • Изучите трафик между клиентским приложением и серверным приложением или приложением поставщика удостоверений с помощью инструментов разработчика браузера. Зачастую точное сообщение об ошибке или сообщение с указанием на то, что вызывает проблему, возвращается клиенту с помощью серверного приложения или приложения поставщика удостоверений после выполнения запроса. Руководство по инструментам разработчика можно найти в следующих статьях:

    Команда разработчиков документации реагирует на отзывы о документах и ошибки в статьях (откройте запрос в разделе отзывов на этой странице), но не может предоставить поддержку продукта. Помощь в устранении неполадок в приложении предоставляют несколько общественных форумов поддержки. Мы рекомендуем следующее:

    Указанные выше форумы не принадлежат корпорации Майкрософт и не управляются ею.

    Чтобы сообщить об ошибках с воспроизведением платформы, которые не связаны с безопасностью и конфиденциальностью, откройте запрос с единицей продукта ASP.NET Core. Не открывайте запрос с единицей продукта, пока вы тщательно не изучите причину проблемы и не попытаетесь решить ее самостоятельно или с помощью сообщества на общедоступном форуме поддержки. Единица продукта не способна устранять неполадки отдельных приложений, которые не работают из-за неправильной конфигурации или вариантов использования с участием сторонних служб. Если отчет является конфиденциальным или конфиденциальным в природе или описывает потенциальный недостаток безопасности в продукте, который злоумышленники могут использовать, см. статью "Отчеты о проблемах безопасности и ошибках" (dotnet/aspnetcoreрепозиторий 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.

    Чтобы устранить эту ошибку, сделайте следующее:

    1. На портале Azure перейдите к манифесту приложения.
    2. Задайте для атрибута 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
    • В поле "Аргументы" укажите параметр командной строки, который браузер использует для открытия в режиме 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).
    • Введите имя в поле Понятное имя. Например, Firefox Auth Testing.
    • Выберите кнопку ОК.
    • Чтобы не выбирать профиль браузера для каждой операции тестирования с помощью приложения, задайте профиль по умолчанию с помощью кнопки По умолчанию.
    • Убедитесь, что при любых изменениях в приложении, в данных тестового пользователя или в конфигурации поставщика закрытие браузера выполняется интегрированной средой разработки.

Обновление приложений

Приложения-функции могут перестать работать сразу после обновления пакета SDK для .NET Core на компьютере разработки или обновления версии пакетов в самом приложении. В некоторых случаях в результате важного обновления несогласованные версии пакетов могут привести к нарушению работы приложения. Большинство этих проблем можно исправить следующим образом:

  1. Очистите кэши пакетов NuGet локальных систем, выполнив команду dotnet nuget locals all --clear из командной оболочки.
  2. Удалите папки bin и obj проекта.
  3. Восстановите и перестройте проект.
  4. Удалите все файлы из папки развертывания на сервере, прежде чем повторно развернуть приложение.

Примечание.

Использование версий пакета, несовместимых с требуемой платформой приложения, не поддерживается. Дополнительные сведения о пакете см. на странице коллекций NuGet или обозревателя пакетов FuGet.

Запуск серверного приложения

При тестировании и устранении Blazor неполадок веб-приложения убедитесь, что приложение выполняется из серверного проекта.

Проверка пользователя

Следующий 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.Count() > 0)
{
    <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;
    }
}

Дополнительные ресурсы