Udostępnij za pomocą


Zabezpieczanie ASP.NET Core Blazor Web App za pomocą technologii OpenID Connect (OIDC)

Note

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.

W tym artykule opisano, jak zabezpieczyć Blazor Web App za pomocą protokołu OpenID Connect (OIDC), korzystając z przykładowej aplikacji znajdującej się w dotnet/blazor-samples repozytorium GitHub (.NET 8 lub nowszym) (jak pobrać).

W przypadku identyfikatora Entra firmy Microsoft lub Azure AD B2C, można użyć AddMicrosoftIdentityWebApp ze strony Microsoft Identity Web (Microsoft.Identity.Web pakiet NuGet, dokumentacja interfejsu API), który dodaje zarówno obsługę OIDC, jak i Cookie moduły uwierzytelniania z odpowiednimi wartościami domyślnymi. Przykładowa aplikacja i wskazówki zawarte w tym artykule nie korzystają z witryny Microsoft Identity Web. Wskazówki pokazują, jak ręcznie skonfigurować procedurę obsługi OIDC dla dowolnego dostawcy OIDC. Aby uzyskać więcej informacji na temat wdrażania Microsoft Identity Web, zobacz Zabezpieczanie ASP.NET Core Blazor Web App przy użyciu identyfikatora Entra firmy Microsoft.

W tej wersji artykułu omówiono implementację OIDC bez stosowania wzorca Backend dla Frontendu (BFF) w aplikacji, która używa globalnego automatycznego renderowania interaktywnego (projekt serwera i .Client). Wzorzec BFF jest przydatny do podejmowania uwierzytelnionych żądań do usług zewnętrznych. Zmień selektor wersji artykułu na wzorzec BFF , jeśli specyfikacja aplikacji wywołuje wdrożenie wzorca BFF.

Przyjęto następującą specyfikację:

  • Funkcja Blazor Web App używa trybu automatycznego renderowania z globalną interakcyjnością.
  • Niestandardowe usługi dostawcy stanu uwierzytelniania są używane przez serwer i aplikacje klienckie do przechwytywania stanu uwierzytelniania użytkownika i przepływu go między serwerem a klientem.
  • Ta aplikacja jest punktem wyjścia dla dowolnego przepływu uwierzytelniania OIDC. OIDC jest konfigurowany ręcznie w aplikacji i nie opiera się na pakietach Microsoft Entra ID ani Microsoft Identity Web, nie wymaga również hostingu na platformie Microsoft Azure. Jednak przykładowa aplikacja może być używana z aplikacją Entra, Microsoft Identity Web i hostowaną na platformie Azure.
  • Automatyczne odświeżanie tokenu nieinterakcyjnego.
  • Oddzielny projekt internetowego interfejsu API demonstruje bezpieczne wywołanie internetowego interfejsu API dla danych pogodowych.

Aby uzyskać alternatywne środowisko korzystania z biblioteki Microsoft Authentication Library for .NET, Microsoft Identity Web i Microsoft Entra ID, zobacz Secure an ASP.NET Core with Microsoft Entra ID (Zabezpieczanie ASP.NET Core Blazor Web App przy użyciu identyfikatora Entra firmy Microsoft).

Przykładowe rozwiązanie

Przykładowa aplikacja składa się z następujących projektów:

  • BlazorWebAppOidc: Projekt po stronie serwera Blazor Web App, zawierający przykładowy końcowy punkt Minimalnego API dla danych pogodowych.
  • BlazorWebAppOidc.Client: implementacja po stronie klienta komponentu Blazor Web App.
  • MinimalApiJwt: webowe API backendowe z Minimal API jako końcowym punktem dostępu dla danych pogodowych.

Dostęp do przykładu za pośrednictwem najnowszego folderu wersji w repozytorium przykładów Blazor za pomocą następującego linku. Przykład znajduje się w folderze BlazorWebAppOidc dla platformy .NET 8 lub nowszej.

Uruchom rozwiązanie z Aspire/Aspire.AppHost projektu.

Wyświetlanie lub pobieranie przykładowego kodu (jak pobrać)

Przykładowe funkcje rozwiązania:

  • Automatyczne odświeżanie tokena bez interakcji przy pomocy niestandardowego cookie odświeżacza (CookieOidcRefresher.cs).

  • Dane pogodowe są obsługiwane przez minimalny punkt dostępu API (/weather-forecast) w pliku Program (Program.cs) projektu MinimalApiJwt. Punkt końcowy wymaga autoryzacji przez wywołanie metody RequireAuthorization. W przypadku wszystkich kontrolerów dodanych do projektu dodaj [Authorize] atrybut do kontrolera lub akcji. Aby uzyskać więcej informacji na temat wymagania autoryzacji w całej aplikacji zgodnie z polityką autoryzacji oraz wyłączenia autoryzacji w pewnych publicznych punktach końcowych, zobacz Razor wskazówki dotyczące OIDC Pages.

  • Aplikacja bezpiecznie wywołuje internetowy interfejs API dla danych pogodowych:

    • Podczas renderowania komponentu Weather na serwerze, komponent ten używa ServerWeatherForecaster na serwerze do pobierania danych pogodowych z internetowego API w projekcie MinimalApiJwt za pomocą DelegatingHandler (TokenHandler), która dołącza token dostępu z HttpContext do żądania.
    • Gdy składnik jest renderowany na kliencie, używa on implementacji usługi ClientWeatherForecaster, która korzysta z wstępnie skonfigurowanego HttpClient (w pliku projektu klienta Program), aby wywołać internetowy interfejs API z projektu ServerWeatherForecaster serwera.
  • Klasa PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) jest elementem po stronie AuthenticationStateProvider serwera, który używa PersistentComponentState do przesyłania stanu uwierzytelniania do klienta, który jest następnie ustalany na cały czas istnienia aplikacji WebAssembly.

Aby uzyskać więcej informacji na temat wywołań interfejsu API sieci Web przy użyciu abstrakcji usługi w Blazor Web Appprogramie s, zobacz Wywoływanie internetowego interfejsu API z aplikacji ASP.NET CoreBlazor.

Terminologia i wskazówki dotyczące dostawcy OIDC

Mimo że nie musisz wdrażać usługi Microsoft Entra (ME-ID) jako dostawcy OIDC do korzystania z przykładowej aplikacji i wskazówek w tym artykule, w tym artykule opisano ustawienia ME-ID przy użyciu nazw znalezionych w dokumentacji firmy Microsoft i portalach Azure/Entra. Ustawienia OIDC mają podobne nazwy dla dostawców OIDC. W przypadku korzystania z dostawcy OIDC innej firmy skorzystaj z dokumentacji dostawcy w połączeniu ze wskazówkami w tym artykule dotyczącymi rejestracji aplikacji i internetowego interfejsu API.

Rejestracje aplikacji Microsoft Entra ID

Zalecamy używanie oddzielnych rejestracji dla aplikacji i internetowych interfejsów API, nawet jeśli aplikacje i internetowe interfejsy API znajdują się w tym samym rozwiązaniu. Poniższe wskazówki dotyczą BlazorWebAppOidc aplikacji i MinimalApiJwt webowego interfejsu API przykładowego rozwiązania, ale te same wskazówki dotyczą wszystkich rejestracji opartych na usłudze Entra dla aplikacji i webowych interfejsów API.

Aby uzyskać wskazówki dotyczące rejestracji aplikacji i internetowego interfejsu API, zobacz Rejestrowanie aplikacji w usłudze Microsoft Entra ID.

Najpierw zarejestruj internetowy interfejs API (MinimalApiJwt), aby można było udzielić dostępu do internetowego interfejsu API podczas rejestrowania aplikacji. Identyfikator dzierżawy i identyfikator klienta służą do konfigurowania interfejsu API w jego pliku Program. Po zarejestrowaniu internetowego interfejsu API, uwidocznij go w sekcji Rejestracje aplikacji>Uwidacznianie interfejsu API przy użyciu nazwy zakresu Weather.Get. Zapisz identyfikator URI aplikacji do użycia w konfiguracji aplikacji.

Następnie zarejestruj aplikację (BlazorWebAppOidc/BlazorWebApOidc.Client) przy użyciu konfiguracji platformy webowej i jako URI przekierowania (nie jest wymagany port). Identyfikator dzierżawcy aplikacji i identyfikator klienta, wraz z podstawowym adresem internetowego interfejsu API, identyfikatorem URI aplikacji i nazwą zakresu funkcji pogodowych, są używane do konfigurowania aplikacji w pliku Program. Udziel uprawnień dostępu do interfejsu web API w obszarze Rejestracja aplikacji>Uprawnienia interfejsu API. Jeśli specyfikacja zabezpieczeń aplikacji wywołuje to żądanie, możesz udzielić organizacji zgody administratora w celu uzyskania dostępu do internetowego interfejsu API. Autoryzowani użytkownicy i grupy są przypisywani do rejestracji aplikacji w aplikacjach> dlaprzedsiębiorstw.

W konfiguracji rejestracji aplikacji w portalu Entra lub Azure, w sekcji niejawne przydzielenie i przepływy hybrydowe, nie zaznaczaj pola wyboru dla punktu końcowego autoryzacji w celu zwrócenia tokenów dostępu lub tokenów ID. Procedura obsługi OpenID Connect automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

Utwórz tajny klienta w rejestracji aplikacji w portalu Entra lub Azure (Zarządzaj>Certyfikatami i tajnymi>Nowy tajny klienta). Zachowaj tajny klucz klienta Value do wykorzystania w następnej sekcji.

Dodatkowe wskazówki dotyczące konfiguracji entra dla określonych ustawień podano w dalszej części tego artykułu.

Ustal tajny klucz klienta

Ta sekcja dotyczy tylko projektu serwera Blazor Web App (BlazorWebAppOidc projektu).

Warning

Nie przechowuj sekretów aplikacji, parametrów połączenia, poświadczeń, haseł, osobistych numerów identyfikacyjnych (PIN), prywatnego kodu C#/.NET lub kluczy prywatnych/tokenów w kodzie po stronie klienta, który jest zawsze niezabezpieczony. W środowiskach testowych/przejściowych i produkcyjnych kod po stronie Blazor serwera i internetowe interfejsy API powinny używać bezpiecznych przepływów uwierzytelniania, które unikają utrzymywania poświadczeń w kodzie projektu lub plikach konfiguracji. Poza lokalnymi testami programistycznymi zalecamy unikanie używania zmiennych środowiskowych do przechowywania poufnych danych, ponieważ zmienne środowiskowe nie są najbezpieczniejszym podejściem. W przypadku lokalnego testowania programistycznego narzędzie Secret Manager jest zalecane do zabezpieczania poufnych danych. Aby uzyskać więcej informacji, zobacz Bezpieczne utrzymywanie poufnych danych i poświadczeń.

W przypadku lokalnego testowania programistycznego użyj narzędzia Secret Manager do przechowywania tajnego klucza klienta projektu serwera pod kluczem Blazorkonfiguracji.

Projekt Blazor serwera nie został zainicjowany dla narzędzia Secret Manager. Użyj skorupki poleceń, takiej jak skorupka PowerShell dla deweloperów w programie Visual Studio, aby wykonać następujące polecenie. Przed wykonaniem polecenia zmień katalog na katalog projektu serwera za pomocą polecenia cd. Polecenie ustawia identyfikator sekretów użytkownika (<UserSecretsId> w pliku projektu aplikacji serwera):

dotnet user-secrets init

Wykonaj następujące polecenie, aby ustawić klucz tajny klienta. Symbol zastępczy {SECRET} to tajny klucz klienta uzyskany z rejestracji aplikacji.

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Jeśli używasz programu Visual Studio, możesz potwierdzić, że wpis tajny został ustawiony, klikając prawym przyciskiem myszy projekt serwera w Eksploratorze rozwiązań i wybierając polecenie Zarządzaj wpisami tajnymi użytkownika.

MinimalApiJwt projekt

Projekt MinimalApiJwt jest backendowym API dla wielu projektów frontendowych. Projekt konfiguruje minimalny punkt końcowy interfejsu API dla danych pogodowych.

Plik MinimalApiJwt.http może służyć do testowania żądania danych pogodowych. Należy pamiętać, że MinimalApiJwt projekt musi być uruchomiony, aby przetestować punkt końcowy, a punkt końcowy jest zakodowany w pliku. Aby uzyskać więcej informacji, zobacz Use .http files in Visual Studio 2022 (Używanie plików HTTP w programie Visual Studio 2022).

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI.

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI i interfejsu użytkownika struktury Swagger w środowisku deweloperów. Aby uzyskać więcej informacji, zobacz Use the generated OpenAPI documents (Używanie wygenerowanych dokumentów OpenAPI).

Projekt tworzy minimalny punkt końcowy interfejsu API dla danych pogodowych:

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();

Skonfiguruj projekt w JwtBearerOptions wywołania AddJwtBearer w pliku projektu Program.

Authority ustawia serwer autoryzacji do wykonywania wywołań OIDC. Zalecamy użycie oddzielnej rejestracji aplikacji dla MinimalApiJwt projektu. Urząd jest zgodny z parametrem issurer (iss) JWT zwróconym przez dostawcę tożsamości.

jwtOptions.Authority = "{AUTHORITY}";

Format urzędu zależy od typu używanej dzierżawy. W poniższych przykładach dla identyfikatora Microsoft Entra użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee.

przykład organu najemcy ME-ID:

jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee";

Przykład urzędu dzierżawy usługi AAD B2C:

jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";

Audience określa odbiorców dla każdego odebranego tokenu OIDC.

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

Note

W przypadku korzystania z Microsoft Entra ID, dopasuj wartość tylko do ścieżki URI identyfikatora aplikacji skonfigurowanego podczas dodawania zakresu Weather.Get w obszarze Eksponuj interfejs API w portalu Entra lub Azure. Nie uwzględniaj nazwy zakresu "Weather.Get" w wartości.

Format grupy odbiorców zależy od typu używanej dzierżawy. W poniższych przykładach dla Microsoft Entra ID użyto identyfikatora dzierżawy contoso i identyfikatora klienta 11112222-bbbb-3333-cccc-4444dddd5555.

przykład URI identyfikatora aplikacji dzierżawcy ME-ID:

jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";

Przykład identyfikatora URI aplikacji dzierżawy usługi AAD B2C:

jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";

Blazor Web App projekt serwera (BlazorWebAppOidc)

Projekt BlazorWebAppOidc jest projektem po stronie serwera programu Blazor Web App.

A DelegatingHandler (TokenHandler) zarządza dołączaniem tokenu dostępu użytkownika do żądań wychodzących. Procedura obsługi tokenów jest wykonywana tylko podczas statycznego renderowania po stronie serwera (statycznego SSR), więc użycie HttpContext jest bezpieczne w tym scenariuszu. Aby uzyskać więcej informacji, zobacz IHttpContextAccessor/HttpContext w aplikacjach ASP.NET Core Blazor i ASP.NET Core po stronie serwera i Blazor Web App dodatkowych scenariuszach zabezpieczeń.

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);
    }
}

W pliku projektu Program program obsługi tokenów (TokenHandler) jest zarejestrowany jako usługa i określony jako program obsługi komunikatów AddHttpMessageHandler do tworzenia bezpiecznych żądań do webowe API zaplecza MinimalApiJwt przy użyciu nazwanego klienta HTTP ("ExternalApi").

builder.Services.AddScoped<TokenHandler>();

builder.Services.AddHttpClient("ExternalApi",
      client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ?? 
          throw new Exception("Missing base address!")))
      .AddHttpMessageHandler<TokenHandler>();

W pliku projektu appsettings.json skonfiguruj zewnętrzny URI API.

"ExternalApiUri": "{BASE ADDRESS}"

Example:

"ExternalApiUri": "https://localhost:7277"

Następująca OpenIdConnectOptions konfiguracja znajduje się w pliku projektu Program podczas wywołania AddOpenIdConnect:

PushedAuthorizationBehavior: Kontroluje obsługę wypychanych żądań autoryzacji (PAR). Domyślnie ustawienie to użycie PAR, jeśli dokument odkrycia dostawcy tożsamości (zwykle znaleziony w .well-known/openid-configuration) informuje o obsłudze PAR. Jeśli chcesz zażądać obsługi PAR dla aplikacji, możesz przypisać wartość PushedAuthorizationBehavior.Require. Par nie jest obsługiwany przez firmę Microsoft Entra i nie ma planów, aby Entra kiedykolwiek go obsługiwać w przyszłości.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Ustawia schemat uwierzytelniania odpowiadający oprogramowaniu pośredniczącemu odpowiedzialnemu za przechowywanie tożsamości użytkownika po pomyślnym uwierzytelnieniu. Obsługiwacz OIDC musi używać mechanizmu logowania, który może utrwalać poświadczenia użytkownika między żądaniami. Poniższy wiersz jest obecny jedynie na potrzeby demonstracji. W przypadku pominięcia DefaultSignInScheme parametr jest używany jako wartość rezerwowa.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Zakresy dla openid i profile (Scope) (opcjonalnie): Zakresy openid i profile są również konfigurowane domyślnie, ponieważ są one wymagane, aby program obsługi OIDC działał, ale może być konieczne ponowne dodanie tych zakresów, jeśli są one uwzględnione w konfiguracji Authentication:Schemes:MicrosoftOidc:Scope. Aby uzyskać ogólne wskazówki dotyczące konfiguracji, zobacz Konfiguracja w ASP.NET Core oraz Konfiguracja ASP.NET CoreBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

SaveTokens: Określa, czy tokeny dostępu i odświeżania powinny być przechowywane w AuthenticationProperties po pomyślnej autoryzacji. Ta właściwość jest ustawiona na true, aby token odświeżania był przechowywany na potrzeby nieinterakcyjnego odświeżania tokenu.

oidcOptions.SaveTokens = true;

Zakres dostępu offline (Scope): Zakres offline_access jest wymagany dla tokena odświeżenia.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Authority i ClientId: Ustawia autorytet i identyfikator klienta dla zapytań OIDC.

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

W poniższym przykładzie użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee i identyfikatora klienta :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";

W przypadku aplikacji wielodostępnych należy użyć wspólnego punktu autoryzacji. Możesz również użyć "ogólnego" autorytetu dla aplikacji jednotenantowych, ale konieczne jest zastosowanie niestandardowego IssuerValidator, jak pokazano w dalszej części tej sekcji.

oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0";

ResponseType: Konfiguruje procedurę obsługi OIDC tak, aby wykonywała tylko przepływ kodu autoryzacji. Niejawne dotacje i przepływy hybrydowe są niepotrzebne w tym trybie. Procedura obsługi OIDC automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims i konfiguracja NameClaimType i RoleClaimType: Wiele serwerów OIDC używa "name" i "role" zamiast domyślnych ustawień SOAP/WS-Fed w ClaimTypes. Gdy MapInboundClaims jest ustawiona wartość false, program obsługi nie wykonuje mapowań roszczeń, a nazwy roszczeń pochodzące z JWT są używane bezpośrednio przez aplikację. Poniższy przykład ustawia typ oświadczenia roli na "roles", który jest odpowiedni dla identyfikatora Entra firmy Microsoft (ME-ID). Aby uzyskać więcej informacji, zapoznaj się z dokumentacją dostawcy tożsamości.

Note

MapInboundClaims musi być ustawione na false dla większości dostawców OIDC, co uniemożliwia zmianę nazw oświadczeń.

oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Konfiguracja ścieżki: Ścieżki muszą być zgodne z identyfikatorem URI przekierowania (ścieżką powrotu logowania) oraz ścieżką przekierowania po wylogowaniu (ścieżką powrotu po wylogowaniu), które zostały skonfigurowane podczas rejestrowania aplikacji u dostawcy OIDC. W witrynie Azure Portal ścieżki są konfigurowane w bloku Uwierzytelnianie rejestracji aplikacji. Zarówno ścieżki logowania, jak i wylogowania muszą być zarejestrowane jako URI przekierowania. Wartości domyślne to /signin-oidc i /signout-callback-oidc.

CallbackPath: ścieżka zapytania w ścieżce podstawowej aplikacji, gdzie zwracany jest agent użytkownika.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signin-oidc

Note

Port nie jest wymagany dla localhost adresów w przypadku korzystania z identyfikatora Entra firmy Microsoft. Większość innych dostawców OIDC wymaga poprawnego portu.

SignedOutCallbackPath (klucz konfiguracji: "SignedOutCallbackPath"): ścieżka żądania w ścieżce podstawowej aplikacji, przechwytywana przez program obsługi OIDC, gdzie agent użytkownika jest najpierw zwracany po wylogowaniu się z dostawcy tożsamości. Przykładowa aplikacja nie ustawia wartości dla ścieżki, ponieważ jest używana domyślna wartość "/signout-callback-oidc". Po przechwyceniu żądania, handler OIDC przekierowuje do SignedOutRedirectUri lub RedirectUri, jeśli określono.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signout-callback-oidc

Note

Używając Microsoft Entra ID, ustaw ścieżkę w wpisach identyfikatora URI przekierowania w konfiguracji platformy Web w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu. Jeśli nie dodasz identyfikatora URI ścieżki wywołania zwrotnego wylogowania do rejestracji aplikacji w Entra, Entra odmówi przekierowania użytkownika z powrotem do aplikacji i jedynie poprosi ich o zamknięcie okna przeglądarki.

RemoteSignOutPath: Żądania odebrane na tej ścieżce powodują, że program obsługi wywołuje wylogowywanie przy użyciu schematu wylogowywania.

W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost/signout-oidc

Note

W przypadku korzystania z Microsoft Entra ID ustaw adres URL wylogowania frontu w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu.

oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");

Przykłady (wartości domyślne):

oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");

(Microsoft Azure tylko z "wspólnym" punktem końcowym): TokenValidationParameters.IssuerValidatorWielu dostawców OIDC współpracuje z domyślnym walidatorem wystawcy, ale powinniśmy uwzględnić wystawcę sparametryzowanego przy użyciu identyfikatora dzierżawy ({TENANT ID}) zwróconego przez https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Aby uzyskać więcej informacji, zobacz SecurityTokenInvalidIssuerException w ramach OpenID Connect i punkt końcowy „common” Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Tylko w przypadku aplikacji korzystających z identyfikatora Entra firmy Microsoft lub usługi Azure AD B2C z "wspólnym" punktem końcowym:

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

Blazor Web App projekt klienta (BlazorWebAppOidc.Client)

Projekt BlazorWebAppOidc.Client jest projektem po stronie klienta programu Blazor Web App.

Klient wywołuje AddAuthenticationStateDeserialization w celu deserializacji i użycia stanu uwierzytelniania przekazanego przez serwer. Stan uwierzytelniania jest stały dla okresu istnienia aplikacji WebAssembly.

Klasa PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) działa po stronie klienta i określa stan uwierzytelniania użytkownika, wyszukując dane zapisane na stronie podczas jej renderowania na serwerze. Stan uwierzytelniania jest stały dla okresu istnienia aplikacji WebAssembly.

Jeśli użytkownik musi się zalogować lub wylogować, wymagane jest ponowne załadowanie pełnej strony.

Przykładowa aplikacja udostępnia tylko nazwę użytkownika i adres e-mail do celów wyświetlania.

W przypadku identyfikatora Entra firmy Microsoft lub Azure AD B2C, można użyć AddMicrosoftIdentityWebApp ze strony Microsoft Identity Web (Microsoft.Identity.Web pakiet NuGet, dokumentacja interfejsu API), który dodaje zarówno obsługę OIDC, jak i Cookie moduły uwierzytelniania z odpowiednimi wartościami domyślnymi. Przykładowa aplikacja i wskazówki zawarte w tym artykule nie korzystają z witryny Microsoft Identity Web. Wskazówki pokazują, jak ręcznie skonfigurować procedurę obsługi OIDC dla dowolnego dostawcy OIDC. Aby uzyskać więcej informacji na temat wdrażania Microsoft Identity Web, zobacz Zabezpieczanie ASP.NET Core Blazor Web App przy użyciu identyfikatora Entra firmy Microsoft.

W tej wersji artykułu opisano implementację OIDC bez stosowania wzorca Backend for Frontend (BFF) z aplikacją, która korzysta z globalnego interaktywnego renderowania serwera (jeden projekt). Wzorzec BFF jest przydatny do podejmowania uwierzytelnionych żądań do usług zewnętrznych. Zmień selektor wersji artykułu na wzorzec BFF , jeśli specyfikacja aplikacji przewiduje przyjęcie wzorca BFF z globalnym renderowaniem Interactive Auto.

Przyjęto następującą specyfikację:

  • Funkcja Blazor Web App używa trybu renderowania serwera z globalną interakcyjnością.
  • Ta aplikacja jest punktem wyjścia dla dowolnego przepływu uwierzytelniania OIDC. OIDC jest konfigurowany ręcznie w aplikacji i nie opiera się na pakietach Microsoft Entra ID ani Microsoft Identity Web, nie wymaga również hostingu na platformie Microsoft Azure. Jednak przykładowa aplikacja może być używana z aplikacją Entra, Microsoft Identity Web i hostowaną na platformie Azure.
  • Automatyczne odświeżanie tokenu nieinterakcyjnego.
  • Oddzielny projekt internetowego interfejsu API demonstruje bezpieczne wywołanie internetowego interfejsu API dla danych pogodowych.

Aby uzyskać alternatywne środowisko korzystania z biblioteki Microsoft Authentication Library for .NET, Microsoft Identity Web i Microsoft Entra ID, zobacz Secure an ASP.NET Core with Microsoft Entra ID (Zabezpieczanie ASP.NET Core Blazor Web App przy użyciu identyfikatora Entra firmy Microsoft).

Przykładowe rozwiązanie

Przykładowa aplikacja składa się z następujących projektów:

  • BlazorWebAppOidcServer: Blazor Web App projekt po stronie serwera (globalne renderowanie interakcyjnego serwera).
  • MinimalApiJwt: webowe API backendowe z Minimal API jako końcowym punktem dostępu dla danych pogodowych.

Dostęp do przykładu za pośrednictwem najnowszego folderu wersji w repozytorium przykładów Blazor za pomocą następującego linku. Przykład znajduje się w folderze BlazorWebAppOidcServer dla platformy .NET 8 lub nowszej.

Wyświetlanie lub pobieranie przykładowego kodu (jak pobrać)

Rejestracje aplikacji Microsoft Entra ID

Zalecamy używanie oddzielnych rejestracji dla aplikacji i internetowych interfejsów API, nawet jeśli aplikacje i internetowe interfejsy API znajdują się w tym samym rozwiązaniu. Poniższe wskazówki dotyczą BlazorWebAppOidcServer aplikacji i MinimalApiJwt webowego interfejsu API przykładowego rozwiązania, ale te same wskazówki dotyczą wszystkich rejestracji opartych na usłudze Entra dla aplikacji i webowych interfejsów API.

Najpierw zarejestruj internetowy interfejs API (MinimalApiJwt), aby można było udzielić dostępu do internetowego interfejsu API podczas rejestrowania aplikacji. Identyfikator dzierżawy i identyfikator klienta służą do konfigurowania interfejsu API w jego pliku Program. Po zarejestrowaniu internetowego interfejsu API, uwidocznij go w sekcji Rejestracje aplikacji>Uwidacznianie interfejsu API przy użyciu nazwy zakresu Weather.Get. Zapisz identyfikator URI aplikacji do użycia w konfiguracji aplikacji.

Następnie zarejestruj aplikację (BlazorWebAppOidcServer) przy użyciu konfiguracji platformy internetowej i identyfikatora URI przekierowania (port nie jest wymagany). Identyfikator dzierżawcy aplikacji i identyfikator klienta, wraz z podstawowym adresem internetowego interfejsu API, identyfikatorem URI aplikacji i nazwą zakresu funkcji pogodowych, są używane do konfigurowania aplikacji w pliku Program. Udziel uprawnień dostępu do interfejsu web API w obszarze Rejestracja aplikacji>Uprawnienia interfejsu API. Jeśli specyfikacja zabezpieczeń aplikacji wywołuje to żądanie, możesz udzielić organizacji zgody administratora w celu uzyskania dostępu do internetowego interfejsu API. Autoryzowani użytkownicy i grupy są przypisywani do rejestracji aplikacji w aplikacjach> dlaprzedsiębiorstw.

W konfiguracji rejestracji aplikacji w portalu Entra lub Azure, w sekcji niejawne przydzielenie i przepływy hybrydowe, nie zaznaczaj pola wyboru dla punktu końcowego autoryzacji w celu zwrócenia tokenów dostępu lub tokenów ID. Procedura obsługi OpenID Connect automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

Utwórz tajny klienta w rejestracji aplikacji w portalu Entra lub Azure (Zarządzaj>Certyfikatami i tajnymi>Nowy tajny klienta). Zachowaj tajny klucz klienta Value do wykorzystania w następnej sekcji.

Dodatkowe wskazówki dotyczące konfiguracji entra dla określonych ustawień podano w dalszej części tego artykułu.

Ustal tajny klucz klienta

Ta sekcja dotyczy tylko projektu serwera Blazor Web App (BlazorWebAppOidcServer projektu).

Warning

Nie przechowuj sekretów aplikacji, parametrów połączenia, poświadczeń, haseł, osobistych numerów identyfikacyjnych (PIN), prywatnego kodu C#/.NET lub kluczy prywatnych/tokenów w kodzie po stronie klienta, który jest zawsze niezabezpieczony. W środowiskach testowych/przejściowych i produkcyjnych kod po stronie Blazor serwera i internetowe interfejsy API powinny używać bezpiecznych przepływów uwierzytelniania, które unikają utrzymywania poświadczeń w kodzie projektu lub plikach konfiguracji. Poza lokalnymi testami programistycznymi zalecamy unikanie używania zmiennych środowiskowych do przechowywania poufnych danych, ponieważ zmienne środowiskowe nie są najbezpieczniejszym podejściem. W przypadku lokalnego testowania programistycznego narzędzie Secret Manager jest zalecane do zabezpieczania poufnych danych. Aby uzyskać więcej informacji, zobacz Bezpieczne utrzymywanie poufnych danych i poświadczeń.

W przypadku lokalnego testowania programistycznego użyj narzędzia Secret Manager do przechowywania tajnego klucza klienta projektu serwera pod kluczem Blazorkonfiguracji.

Projekt Blazor serwera nie został zainicjowany dla narzędzia Secret Manager. Użyj skorupki poleceń, takiej jak skorupka PowerShell dla deweloperów w programie Visual Studio, aby wykonać następujące polecenie. Przed wykonaniem polecenia zmień katalog na katalog projektu serwera za pomocą polecenia cd. Polecenie ustanawia identyfikator tajnych danych użytkownika w pliku projektu aplikacji (<UserSecretsId>):

dotnet user-secrets init

Wykonaj następujące polecenie, aby ustawić klucz tajny klienta. Symbol zastępczy {SECRET} to tajny klucz klienta uzyskany z rejestracji aplikacji.

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Jeśli używasz programu Visual Studio, możesz potwierdzić, że wpis tajny został ustawiony, klikając prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierając polecenie Zarządzaj wpisami tajnymi użytkownika.

MinimalApiJwt projekt

Projekt MinimalApiJwt jest backendowym API dla wielu projektów frontendowych. Projekt konfiguruje minimalny punkt końcowy interfejsu API dla danych pogodowych.

Plik MinimalApiJwt.http może służyć do testowania żądania danych pogodowych. Należy pamiętać, że MinimalApiJwt projekt musi być uruchomiony, aby przetestować punkt końcowy, a punkt końcowy jest zakodowany w pliku. Aby uzyskać więcej informacji, zobacz Use .http files in Visual Studio 2022 (Używanie plików HTTP w programie Visual Studio 2022).

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI.

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI i interfejsu użytkownika struktury Swagger w środowisku deweloperów. Aby uzyskać więcej informacji, zobacz Use the generated OpenAPI documents (Używanie wygenerowanych dokumentów OpenAPI).

Projekt tworzy minimalny punkt końcowy interfejsu API dla danych pogodowych:

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();

Skonfiguruj projekt w JwtBearerOptions wywołania AddJwtBearer w pliku projektu Program.

Authority ustawia serwer autoryzacji do wykonywania wywołań OIDC. Zalecamy użycie oddzielnej rejestracji aplikacji dla MinimalApiJwt projektu. Urząd jest zgodny z parametrem issurer (iss) JWT zwróconym przez dostawcę tożsamości.

jwtOptions.Authority = "{AUTHORITY}";

Format urzędu zależy od typu używanej dzierżawy. W poniższych przykładach dla identyfikatora Microsoft Entra użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee.

przykład organu najemcy ME-ID:

jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee";

Przykład urzędu dzierżawy usługi AAD B2C:

jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";

Audience określa odbiorców dla każdego odebranego tokenu OIDC.

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

Note

W przypadku korzystania z Microsoft Entra ID, dopasuj wartość tylko do ścieżki URI identyfikatora aplikacji skonfigurowanego podczas dodawania zakresu Weather.Get w obszarze Eksponuj interfejs API w portalu Entra lub Azure. Nie uwzględniaj nazwy zakresu "Weather.Get" w wartości.

Format grupy odbiorców zależy od typu używanej dzierżawy. W poniższych przykładach dla Microsoft Entra ID użyto identyfikatora dzierżawy contoso i identyfikatora klienta 11112222-bbbb-3333-cccc-4444dddd5555.

przykład URI identyfikatora aplikacji dzierżawcy ME-ID:

jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";

Przykład identyfikatora URI aplikacji dzierżawy usługi AAD B2C:

jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";

BlazorWebAppOidcServer projekt

Automatyczne odświeżanie tokenu nieinterakcyjnego jest zarządzane przez niestandardowy cookie moduł odświeżania (CookieOidcRefresher.cs).

A DelegatingHandler (TokenHandler) zarządza dołączaniem tokenu dostępu użytkownika do żądań wychodzących. Procedura obsługi tokenów jest wykonywana tylko podczas statycznego renderowania po stronie serwera (statycznego SSR), więc użycie HttpContext jest bezpieczne w tym scenariuszu. Aby uzyskać więcej informacji, zobacz IHttpContextAccessor/HttpContext w aplikacjach ASP.NET Core Blazor i ASP.NET Core po stronie serwera i Blazor Web App dodatkowych scenariuszach zabezpieczeń.

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);
    }
}

W pliku projektu Program program obsługi tokenów (TokenHandler) jest zarejestrowany jako usługa i określony jako program obsługi komunikatów AddHttpMessageHandler do tworzenia bezpiecznych żądań do webowe API zaplecza MinimalApiJwt przy użyciu nazwanego klienta HTTP ("ExternalApi").

builder.Services.AddScoped<TokenHandler>();

builder.Services.AddHttpClient("ExternalApi",
      client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ?? 
          throw new Exception("Missing base address!")))
      .AddHttpMessageHandler<TokenHandler>();

Składnik Weather używa atrybutu[Authorize] , aby zapobiec nieautoryzowanemu dostępowi. Aby uzyskać więcej informacji na temat wymagania autoryzacji w całej aplikacji zgodnie z polityką autoryzacji oraz wyłączenia autoryzacji w pewnych publicznych punktach końcowych, zobacz Razor wskazówki dotyczące OIDC Pages.

Klient ExternalApi HTTP służy do żądania danych pogodowych do bezpiecznego internetowego interfejsu API. OnInitializedAsync W przypadku zdarzenia cyklu życia programu 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!");

W pliku projektu appsettings.json skonfiguruj zewnętrzny URI API.

"ExternalApiUri": "{BASE ADDRESS}"

Example:

"ExternalApiUri": "https://localhost:7277"

Następująca OpenIdConnectOptions konfiguracja znajduje się w pliku projektu Program podczas wywołania AddOpenIdConnect:

PushedAuthorizationBehavior: Kontroluje obsługę wypychanych żądań autoryzacji (PAR). Domyślnie ustawienie to użycie PAR, jeśli dokument odkrycia dostawcy tożsamości (zwykle znaleziony w .well-known/openid-configuration) informuje o obsłudze PAR. Jeśli chcesz zażądać obsługi PAR dla aplikacji, możesz przypisać wartość PushedAuthorizationBehavior.Require. Par nie jest obsługiwany przez firmę Microsoft Entra i nie ma planów, aby Entra kiedykolwiek go obsługiwać w przyszłości.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Ustawia schemat uwierzytelniania odpowiadający oprogramowaniu pośredniczącemu odpowiedzialnemu za przechowywanie tożsamości użytkownika po pomyślnym uwierzytelnieniu. Obsługiwacz OIDC musi używać mechanizmu logowania, który może utrwalać poświadczenia użytkownika między żądaniami. Poniższy wiersz jest obecny jedynie na potrzeby demonstracji. W przypadku pominięcia DefaultSignInScheme parametr jest używany jako wartość rezerwowa.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Zakresy dla openid i profile (Scope) (opcjonalnie): Zakresy openid i profile są również konfigurowane domyślnie, ponieważ są one wymagane, aby program obsługi OIDC działał, ale może być konieczne ponowne dodanie tych zakresów, jeśli są one uwzględnione w konfiguracji Authentication:Schemes:MicrosoftOidc:Scope. Aby uzyskać ogólne wskazówki dotyczące konfiguracji, zobacz Konfiguracja w ASP.NET Core oraz Konfiguracja ASP.NET CoreBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

Skonfiguruj zakres dostępu Weather.Get do zewnętrznego internetowego interfejsu API danych o pogodzie. Poniższy przykład opiera się na użyciu identyfikatora Entra w domenie dzierżawy ME-ID. W poniższym przykładzie symbol zastępczy {APP ID URI} znajduje się w portalu Entra lub Azure, gdzie uwidoczniono web API. W przypadku dowolnego innego dostawcy tożsamości użyj odpowiedniego zakresu.

oidcOptions.Scope.Add("{APP ID URI}/Weather.Get");

Format zakresu zależy od typu używanej dzierżawy. W poniższych przykładach domena dzierżawy to contoso.onmicrosoft.com, a identyfikator klienta to 11112222-bbbb-3333-cccc-4444dddd5555.

przykład URI identyfikatora aplikacji dzierżawcy ME-ID:

oidcOptions.Scope.Add("api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");

Przykład identyfikatora URI aplikacji dzierżawy usługi AAD B2C:

oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");

SaveTokens: Określa, czy tokeny dostępu i odświeżania powinny być przechowywane w AuthenticationProperties po pomyślnej autoryzacji. Ta właściwość jest ustawiona na true, aby token odświeżania był przechowywany na potrzeby nieinterakcyjnego odświeżania tokenu.

oidcOptions.SaveTokens = true;

Zakres dostępu offline (Scope): Zakres offline_access jest wymagany dla tokena odświeżenia.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Authority i ClientId: Ustawia autorytet i identyfikator klienta dla zapytań OIDC.

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

W poniższym przykładzie użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee i identyfikatora klienta :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";

W przypadku aplikacji wielodostępnych należy użyć wspólnego punktu autoryzacji. Możesz również użyć "ogólnego" autorytetu dla aplikacji jednotenantowych, ale konieczne jest zastosowanie niestandardowego IssuerValidator, jak pokazano w dalszej części tej sekcji.

oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0";

ResponseType: Konfiguruje procedurę obsługi OIDC tak, aby wykonywała tylko przepływ kodu autoryzacji. Niejawne dotacje i przepływy hybrydowe są niepotrzebne w tym trybie. Procedura obsługi OIDC automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims i konfiguracja NameClaimType i RoleClaimType: Wiele serwerów OIDC używa "name" i "role" zamiast domyślnych ustawień SOAP/WS-Fed w ClaimTypes. Gdy MapInboundClaims jest ustawiona wartość false, program obsługi nie wykonuje mapowań roszczeń, a nazwy roszczeń pochodzące z JWT są używane bezpośrednio przez aplikację. Poniższy przykład ustawia typ oświadczenia roli na "roles", który jest odpowiedni dla identyfikatora Entra firmy Microsoft (ME-ID). Aby uzyskać więcej informacji, zapoznaj się z dokumentacją dostawcy tożsamości.

Note

MapInboundClaims musi być ustawione na false dla większości dostawców OIDC, co uniemożliwia zmianę nazw oświadczeń.

oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Konfiguracja ścieżki: Ścieżki muszą być zgodne z identyfikatorem URI przekierowania (ścieżką powrotu logowania) oraz ścieżką przekierowania po wylogowaniu (ścieżką powrotu po wylogowaniu), które zostały skonfigurowane podczas rejestrowania aplikacji u dostawcy OIDC. W witrynie Azure Portal ścieżki są konfigurowane w bloku Uwierzytelnianie rejestracji aplikacji. Zarówno ścieżki logowania, jak i wylogowania muszą być zarejestrowane jako URI przekierowania. Wartości domyślne to /signin-oidc i /signout-callback-oidc.

CallbackPath: ścieżka zapytania w ścieżce podstawowej aplikacji, gdzie zwracany jest agent użytkownika.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signin-oidc

Note

Port nie jest wymagany dla localhost adresów w przypadku korzystania z identyfikatora Entra firmy Microsoft. Większość innych dostawców OIDC wymaga poprawnego portu.

SignedOutCallbackPath (klucz konfiguracji: "SignedOutCallbackPath"): ścieżka żądania w ścieżce podstawowej aplikacji, przechwytywana przez program obsługi OIDC, gdzie agent użytkownika jest najpierw zwracany po wylogowaniu się z dostawcy tożsamości. Przykładowa aplikacja nie ustawia wartości dla ścieżki, ponieważ jest używana domyślna wartość "/signout-callback-oidc". Po przechwyceniu żądania, handler OIDC przekierowuje do SignedOutRedirectUri lub RedirectUri, jeśli określono.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signout-callback-oidc

Note

Używając Microsoft Entra ID, ustaw ścieżkę w wpisach identyfikatora URI przekierowania w konfiguracji platformy Web w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu. Jeśli nie dodasz identyfikatora URI ścieżki wywołania zwrotnego wylogowania do rejestracji aplikacji w Entra, Entra odmówi przekierowania użytkownika z powrotem do aplikacji i jedynie poprosi ich o zamknięcie okna przeglądarki.

RemoteSignOutPath: Żądania odebrane na tej ścieżce powodują, że program obsługi wywołuje wylogowywanie przy użyciu schematu wylogowywania.

W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost/signout-oidc

Note

W przypadku korzystania z Microsoft Entra ID ustaw adres URL wylogowania frontu w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu.

oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");

Przykłady (wartości domyślne):

oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");

(Microsoft Azure tylko z "wspólnym" punktem końcowym): TokenValidationParameters.IssuerValidatorWielu dostawców OIDC współpracuje z domyślnym walidatorem wystawcy, ale powinniśmy uwzględnić wystawcę sparametryzowanego przy użyciu identyfikatora dzierżawy ({TENANT ID}) zwróconego przez https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Aby uzyskać więcej informacji, zobacz SecurityTokenInvalidIssuerException w ramach OpenID Connect i punkt końcowy „common” Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Tylko w przypadku aplikacji korzystających z identyfikatora Entra firmy Microsoft lub usługi Azure AD B2C z "wspólnym" punktem końcowym:

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

W przypadku identyfikatora Entra firmy Microsoft lub Azure AD B2C, można użyć AddMicrosoftIdentityWebApp ze strony Microsoft Identity Web (Microsoft.Identity.Web pakiet NuGet, dokumentacja interfejsu API), który dodaje zarówno obsługę OIDC, jak i Cookie moduły uwierzytelniania z odpowiednimi wartościami domyślnymi. Przykładowa aplikacja i wskazówki zawarte w tym artykule nie korzystają z witryny Microsoft Identity Web. Wskazówki pokazują, jak ręcznie skonfigurować procedurę obsługi OIDC dla dowolnego dostawcy OIDC. Aby uzyskać więcej informacji na temat wdrażania Microsoft Identity Web, zobacz Zabezpieczanie ASP.NET Core Blazor Web App przy użyciu identyfikatora Entra firmy Microsoft.

W tej wersji artykułu opisano implementację OIDC z wykorzystaniem wzorca Backend for Frontend (BFF). Jeśli specyfikacja aplikacji nie wymaga zastosowania wzorca BFF, zmień selektor wersji artykułu na wzorzec inny niż BFF (Interactive Auto) (renderowanie interaktywne Auto) lub wzorzec inny niż BFF (Interactive Server) (renderowanie interaktywne Serwer).

Prerequisites

Aspire program Wymaga programu Visual Studio w wersji 17.10 lub nowszej.

Zobacz również sekcję Wymagania wstępne w przewodniku Szybki start: tworzenie pierwszego Aspire rozwiązania.

Przykładowe rozwiązanie

Przykładowa aplikacja składa się z następujących projektów:

  • Aspire:
    • Aspire.AppHost: służy do zarządzania ogólnymi problemami dotyczącymi aranżacji aplikacji.
    • Aspire.ServiceDefaults: zawiera domyślne Aspire konfiguracje aplikacji, które można rozszerzyć i dostosować zgodnie z potrzebami.
  • MinimalApiJwt: internetowy interfejs API zaplecza zawierający przykładowy minimalny punkt końcowy interfejsu API dla danych pogodowych.
  • BlazorWebAppOidc: Projekt po stronie serwera programu Blazor Web App. Projekt używa YARP do pośredniczenia w żądaniach do punktu docelowego prognozy pogody w projekcie webowego API zaplecza (MinimalApiJwt) z access_token przechowywanym w cookie autoryzacji.
  • BlazorWebAppOidc.Client: implementacja po stronie klienta komponentu Blazor Web App.

Dostęp do przykładu za pośrednictwem najnowszego folderu wersji w repozytorium przykładów Blazor za pomocą następującego linku. Przykład znajduje się w folderze BlazorWebAppOidcBff dla platformy .NET 8 lub nowszej.

Wyświetlanie lub pobieranie przykładowego kodu (jak pobrać)

Funkcja Blazor Web App używa trybu automatycznego renderowania z globalną interakcyjnością.

Projekt serwera wywołuje AddAuthenticationStateSerialization, aby dodać dostawcę stanu uwierzytelniania po stronie serwera, który używa PersistentComponentState do przesyłania stanu uwierzytelniania do klienta. Klient wywołuje AddAuthenticationStateDeserialization w celu deserializacji i użycia stanu uwierzytelniania przekazanego przez serwer. Stan uwierzytelniania jest stały dla okresu istnienia aplikacji WebAssembly.

Klasa PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) jest elementem po stronie AuthenticationStateProvider serwera, który używa PersistentComponentState do przesyłania stanu uwierzytelniania do klienta, który jest następnie ustalany na cały czas istnienia aplikacji WebAssembly.

Ta aplikacja jest punktem wyjścia dla dowolnego przepływu uwierzytelniania OIDC. OIDC jest konfigurowany ręcznie w aplikacji i nie opiera się na pakietach Microsoft Entra ID ani Microsoft Identity Web, nie wymaga również hostingu na platformie Microsoft Azure. Jednak przykładowa aplikacja może być używana z aplikacją Entra, Microsoft Identity Web i hostowaną na platformie Azure.

Automatyczne odświeżanie tokena bez interakcji przy pomocy niestandardowego cookie odświeżacza (CookieOidcRefresher.cs).

Wzorzec Backend for Frontend (BFF) jest używany do Aspire odkrywania usług i YARP do proxy żądań do punktu końcowego prognozy pogody w aplikacji backendowej.

Internetowy interfejs API zaplecza (MinimalApiJwt) używa uwierzytelniania przy pomocy JWT-bearer do weryfikacji tokenów JWT zapisanych w Blazor Web App podczas procesu logowania cookie.

Aspire usprawnia tworzenie aplikacji natywnych dla chmury platformy .NET. Zapewnia spójny, opiniowany zestaw narzędzi i wzorców do tworzenia i uruchamiania aplikacji rozproszonych.

YARP (Jeszcze inny zwrotny serwer proxy) to biblioteka używana do tworzenia zwrotnego serwera proxy. MapForwarder Program w pliku projektu serwera dodaje bezpośrednie przekazywanie żądań HTTP, które pasują do określonego wzorca do określonego miejsca docelowego przy użyciu konfiguracji domyślnej dla żądania wychodzącego, dostosowanych przekształceń i domyślnego klienta HTTP:

  • Podczas renderowania składnika Weather na serwerze składnik używa klasy ServerWeatherForecaster jako pośrednika na żądanie danych pogodowych przy użyciu tokenu dostępu użytkownika. IHttpContextAccessor.HttpContext określa, czy HttpContext jest dostępny do użycia przez metodę GetWeatherForecastAsync. Aby uzyskać więcej informacji, zobacz składniki ASP.NET CoreRazor.
  • Gdy składnik jest renderowany na kliencie, używa implementacji usługi ClientWeatherForecaster, która korzysta z wstępnie skonfigurowanego HttpClient (w pliku projektu klienta Program), aby nawiązać połączenie z internetowym interfejsem API w projekcie serwera. Minimalny punkt końcowy interfejsu API (/weather-forecast) zdefiniowany w pliku projektu Program serwera przekształca żądanie przy użyciu tokenu dostępu użytkownika w celu uzyskania danych pogodowych.

Aby uzyskać więcej informacji na temat wywołań interfejsu API sieci Web przy użyciu abstrakcji usługi w Blazor Web Appprogramie s, zobacz Wywoływanie internetowego interfejsu API z aplikacji ASP.NET CoreBlazor.

Rejestracje aplikacji Microsoft Entra ID

Zalecamy używanie oddzielnych rejestracji dla aplikacji i internetowych interfejsów API, nawet jeśli aplikacje i internetowe interfejsy API znajdują się w tym samym rozwiązaniu. Poniższe wskazówki dotyczą BlazorWebAppOidc aplikacji i MinimalApiJwt webowego interfejsu API przykładowego rozwiązania, ale te same wskazówki dotyczą wszystkich rejestracji opartych na usłudze Entra dla aplikacji i webowych interfejsów API.

Najpierw zarejestruj internetowy interfejs API (MinimalApiJwt), aby można było udzielić dostępu do internetowego interfejsu API podczas rejestrowania aplikacji. Identyfikator dzierżawy i identyfikator klienta służą do konfigurowania interfejsu API w jego pliku Program. Po zarejestrowaniu internetowego interfejsu API, uwidocznij go w sekcji Rejestracje aplikacji>Uwidacznianie interfejsu API przy użyciu nazwy zakresu Weather.Get. Zapisz identyfikator URI aplikacji do użycia w konfiguracji aplikacji.

Następnie zarejestruj aplikację (BlazorWebAppOidc/BlazorWebApOidc.Client) przy użyciu konfiguracji platformy webowej i jako URI przekierowania (nie jest wymagany port). Identyfikator dzierżawcy aplikacji i identyfikator klienta, wraz z podstawowym adresem internetowego interfejsu API, identyfikatorem URI aplikacji i nazwą zakresu funkcji pogodowych, są używane do konfigurowania aplikacji w pliku Program. Udziel uprawnień dostępu do interfejsu web API w obszarze Rejestracja aplikacji>Uprawnienia interfejsu API. Jeśli specyfikacja zabezpieczeń aplikacji wywołuje to żądanie, możesz udzielić organizacji zgody administratora w celu uzyskania dostępu do internetowego interfejsu API. Autoryzowani użytkownicy i grupy są przypisywani do rejestracji aplikacji w aplikacjach> dlaprzedsiębiorstw.

W konfiguracji rejestracji aplikacji w portalu Entra lub Azure, w sekcji niejawne przydzielenie i przepływy hybrydowe, nie zaznaczaj pola wyboru dla punktu końcowego autoryzacji w celu zwrócenia tokenów dostępu lub tokenów ID. Procedura obsługi OpenID Connect automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

Utwórz tajny klienta w rejestracji aplikacji w portalu Entra lub Azure (Zarządzaj>Certyfikatami i tajnymi>Nowy tajny klienta). Zachowaj tajny klucz klienta Value do wykorzystania w następnej sekcji.

Dodatkowe wskazówki dotyczące konfiguracji entra dla określonych ustawień podano w dalszej części tego artykułu.

Ustal tajny klucz klienta

Ta sekcja dotyczy tylko projektu serwera Blazor Web App (BlazorWebAppOidc projektu).

Warning

Nie przechowuj sekretów aplikacji, parametrów połączenia, poświadczeń, haseł, osobistych numerów identyfikacyjnych (PIN), prywatnego kodu C#/.NET lub kluczy prywatnych/tokenów w kodzie po stronie klienta, który jest zawsze niezabezpieczony. W środowiskach testowych/przejściowych i produkcyjnych kod po stronie Blazor serwera i internetowe interfejsy API powinny używać bezpiecznych przepływów uwierzytelniania, które unikają utrzymywania poświadczeń w kodzie projektu lub plikach konfiguracji. Poza lokalnymi testami programistycznymi zalecamy unikanie używania zmiennych środowiskowych do przechowywania poufnych danych, ponieważ zmienne środowiskowe nie są najbezpieczniejszym podejściem. W przypadku lokalnego testowania programistycznego narzędzie Secret Manager jest zalecane do zabezpieczania poufnych danych. Aby uzyskać więcej informacji, zobacz Bezpieczne utrzymywanie poufnych danych i poświadczeń.

W przypadku lokalnego testowania programistycznego użyj narzędzia Secret Manager do przechowywania tajnego klucza klienta projektu serwera pod kluczem Blazorkonfiguracji.

Projekt Blazor serwera nie został zainicjowany dla narzędzia Secret Manager. Użyj skorupki poleceń, takiej jak skorupka PowerShell dla deweloperów w programie Visual Studio, aby wykonać następujące polecenie. Przed wykonaniem polecenia zmień katalog na katalog projektu serwera za pomocą polecenia cd. Polecenie ustawia identyfikator sekretów użytkownika (<UserSecretsId> w pliku projektu aplikacji serwera):

dotnet user-secrets init

Wykonaj następujące polecenie, aby ustawić klucz tajny klienta. Symbol zastępczy {SECRET} to tajny klucz klienta uzyskany z rejestracji aplikacji.

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Jeśli używasz programu Visual Studio, możesz potwierdzić, że wpis tajny został ustawiony, klikając prawym przyciskiem myszy projekt serwera w Eksploratorze rozwiązań i wybierając polecenie Zarządzaj wpisami tajnymi użytkownika.

Projekty: Aspire

Aby uzyskać więcej informacji na temat korzystania z Aspire oraz szczegóły dotyczące projektów .AppHost i .ServiceDefaults w przykładowej aplikacji, zobacz dokumentację Aspire.

Upewnij się, że zostały spełnione wymagania wstępne dotyczące programu Aspire. Aby uzyskać więcej informacji, zobacz sekcję Wymagania wstępne przewodnika Szybki start: tworzenie pierwszego Aspire rozwiązania.

Przykładowa aplikacja konfiguruje tylko niezabezpieczony profil uruchamiania HTTP (http) do użycia podczas testowania programistycznego. Aby uzyskać więcej informacji, w tym przykład niezabezpieczonych i bezpiecznych profilów ustawień uruchamiania, zobacz Zezwalanie na niezabezpieczony transport w Aspire (Aspire dokumentacja).

MinimalApiJwt projekt

Projekt MinimalApiJwt jest backendowym API dla wielu projektów frontendowych. Projekt konfiguruje minimalny punkt końcowy interfejsu API dla danych pogodowych. Żądania z Blazor Web App projektu po stronie serwera (BlazorWebAppOidc) są kierowane do MinimalApiJwt projektu.

Plik MinimalApiJwt.http może służyć do testowania żądania danych pogodowych. Należy pamiętać, że MinimalApiJwt projekt musi być uruchomiony, aby przetestować punkt końcowy, a punkt końcowy jest zakodowany w pliku. Aby uzyskać więcej informacji, zobacz Use .http files in Visual Studio 2022 (Używanie plików HTTP w programie Visual Studio 2022).

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI.

Projekt zawiera pakiety i konfigurację do tworzenia dokumentów OpenAPI i interfejsu użytkownika struktury Swagger w środowisku deweloperów. Aby uzyskać więcej informacji, zobacz Use the generated OpenAPI documents (Używanie wygenerowanych dokumentów OpenAPI).

Bezpieczny punkt końcowy danych prognozy pogody znajduje się w pliku projektu 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();

Metoda RequireAuthorization rozszerzenia wymaga autoryzacji dla definicji trasy. W przypadku wszystkich kontrolerów dodanych do projektu dodaj [Authorize] atrybut do kontrolera lub akcji.

Skonfiguruj projekt w JwtBearerOptions wywołania AddJwtBearer w pliku projektu Program.

Authority ustawia serwer autoryzacji do wykonywania wywołań OIDC. Zalecamy użycie oddzielnej rejestracji aplikacji dla MinimalApiJwt projektu. Urząd jest zgodny z parametrem issurer (iss) JWT zwróconym przez dostawcę tożsamości.

jwtOptions.Authority = "{AUTHORITY}";

Format urzędu zależy od typu używanej dzierżawy. W poniższych przykładach dla identyfikatora Microsoft Entra użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee.

przykład organu najemcy ME-ID:

jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee";

Przykład urzędu dzierżawy usługi AAD B2C:

jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";

Audience określa odbiorców dla każdego odebranego tokenu OIDC.

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

Note

W przypadku korzystania z Microsoft Entra ID, dopasuj wartość tylko do ścieżki URI identyfikatora aplikacji skonfigurowanego podczas dodawania zakresu Weather.Get w obszarze Eksponuj interfejs API w portalu Entra lub Azure. Nie uwzględniaj nazwy zakresu "Weather.Get" w wartości.

Format grupy odbiorców zależy od typu używanej dzierżawy. W poniższych przykładach dla Microsoft Entra ID użyto identyfikatora dzierżawy contoso i identyfikatora klienta 11112222-bbbb-3333-cccc-4444dddd5555.

przykład URI identyfikatora aplikacji dzierżawcy ME-ID:

jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";

Przykład identyfikatora URI aplikacji dzierżawy usługi AAD B2C:

jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";

Projekt serwerowy Blazor Web App (BlazorWebAppOidc)

W tej sekcji opisano sposób konfigurowania projektu po stronie Blazor serwera.

Następująca OpenIdConnectOptions konfiguracja znajduje się w pliku projektu Program podczas wywołania AddOpenIdConnect.

PushedAuthorizationBehavior: Kontroluje obsługę wypychanych żądań autoryzacji (PAR). Domyślnie ustawienie to użycie PAR, jeśli dokument odkrycia dostawcy tożsamości (zwykle znaleziony w .well-known/openid-configuration) informuje o obsłudze PAR. Jeśli chcesz zażądać obsługi PAR dla aplikacji, możesz przypisać wartość PushedAuthorizationBehavior.Require. Par nie jest obsługiwany przez firmę Microsoft Entra i nie ma planów, aby Entra kiedykolwiek go obsługiwać w przyszłości.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Ustawia schemat uwierzytelniania odpowiadający oprogramowaniu pośredniczącemu odpowiedzialnemu za przechowywanie tożsamości użytkownika po pomyślnym uwierzytelnieniu. Obsługiwacz OIDC musi używać mechanizmu logowania, który może utrwalać poświadczenia użytkownika między żądaniami. Poniższy wiersz jest obecny jedynie na potrzeby demonstracji. W przypadku pominięcia DefaultSignInScheme parametr jest używany jako wartość rezerwowa.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Zakresy dla openid i profile (Scope) (opcjonalnie): Zakresy openid i profile są również konfigurowane domyślnie, ponieważ są one wymagane, aby program obsługi OIDC działał, ale może być konieczne ponowne dodanie tych zakresów, jeśli są one uwzględnione w konfiguracji Authentication:Schemes:MicrosoftOidc:Scope. Aby uzyskać ogólne wskazówki dotyczące konfiguracji, zobacz Konfiguracja w ASP.NET Core oraz Konfiguracja ASP.NET CoreBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

SaveTokens: Określa, czy tokeny dostępu i odświeżania powinny być przechowywane w AuthenticationProperties po pomyślnej autoryzacji. Wartość jest ustawiona na true, aby uwierzytelniać żądania dotyczące danych pogodowych z projektu webowego interfejsu API zaplecza (MinimalApiJwt).

oidcOptions.SaveTokens = true;

Zakres dostępu offline (Scope): Zakres offline_access jest wymagany dla tokena odświeżenia.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Zakresy uzyskiwania danych pogodowych z internetowego interfejsu API (Scope): konfigurowanie Weather.Get zakresu uzyskiwania dostępu do zewnętrznego internetowego interfejsu API na potrzeby danych pogodowych. W poniższym przykładzie symbol zastępczy {APP ID URI} znajduje się w portalu Entra lub Azure, gdzie uwidoczniono web API. W przypadku dowolnego innego dostawcy tożsamości użyj odpowiedniego zakresu.

oidcOptions.Scope.Add("{APP ID URI}/Weather.Get");

Format zakresu zależy od typu używanej dzierżawy. W poniższych przykładach domena dzierżawy to contoso.onmicrosoft.com, a identyfikator klienta to 11112222-bbbb-3333-cccc-4444dddd5555.

przykład URI identyfikatora aplikacji dzierżawcy ME-ID:

oidcOptions.Scope.Add("api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");

Przykład identyfikatora URI aplikacji dzierżawy usługi AAD B2C:

oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get");

Authority i ClientId: Ustawia autorytet i identyfikator klienta dla zapytań OIDC.

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

W poniższym przykładzie użyto identyfikatora dzierżawy aaaabbbb-0000-cccc-1111-dddd2222eeee i identyfikatora klienta :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";

W przypadku aplikacji wielodostępnych należy użyć wspólnego punktu autoryzacji. Możesz również użyć "ogólnego" autorytetu dla aplikacji jednotenantowych, ale konieczne jest zastosowanie niestandardowego IssuerValidator, jak pokazano w dalszej części tej sekcji.

oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0";

ResponseType: Konfiguruje procedurę obsługi OIDC tak, aby wykonywała tylko przepływ kodu autoryzacji. Niejawne dotacje i przepływy hybrydowe są niepotrzebne w tym trybie. Procedura obsługi OIDC automatycznie żąda odpowiednich tokenów przy użyciu kodu zwróconego z punktu końcowego autoryzacji.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims i konfiguracja NameClaimType i RoleClaimType: Wiele serwerów OIDC używa "name" i "role" zamiast domyślnych ustawień SOAP/WS-Fed w ClaimTypes. Kiedy MapInboundClaims jest ustawiony na false, mechanizm nie wykonuje mapowania roszczeń, a nazwy roszczeń z zestawu JWT są używane bezpośrednio przez aplikację. Poniższy przykład ustawia typ oświadczenia roli na "roles", który jest odpowiedni dla identyfikatora Entra firmy Microsoft (ME-ID). Aby uzyskać więcej informacji, zapoznaj się z dokumentacją dostawcy tożsamości.

Note

MapInboundClaims musi być ustawione na false dla większości dostawców OIDC, co uniemożliwia zmianę nazw oświadczeń.

oidcOptions.MapInboundClaims = false;
oidcOptions.TokenValidationParameters.NameClaimType = "name";
oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Konfiguracja ścieżki: Ścieżki muszą być zgodne z identyfikatorem URI przekierowania (ścieżką powrotu logowania) oraz ścieżką przekierowania po wylogowaniu (ścieżką powrotu po wylogowaniu), które zostały skonfigurowane podczas rejestrowania aplikacji u dostawcy OIDC. W witrynie Azure Portal ścieżki są konfigurowane w bloku Uwierzytelnianie rejestracji aplikacji. Zarówno ścieżki logowania, jak i wylogowania muszą być zarejestrowane jako URI przekierowania. Wartości domyślne to /signin-oidc i /signout-callback-oidc.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signin-oidc

Note

Port nie jest wymagany dla localhost adresów w przypadku korzystania z identyfikatora Entra firmy Microsoft. Większość innych dostawców OIDC wymaga poprawnego portu.

SignedOutCallbackPath (klucz konfiguracji: "SignedOutCallbackPath"): ścieżka żądania w ścieżce podstawowej aplikacji, przechwytywana przez program obsługi OIDC, gdzie agent użytkownika jest najpierw zwracany po wylogowaniu się z dostawcy tożsamości. Przykładowa aplikacja nie ustawia wartości dla ścieżki, ponieważ jest używana domyślna wartość "/signout-callback-oidc". Po przechwyceniu żądania, handler OIDC przekierowuje do SignedOutRedirectUri lub RedirectUri, jeśli określono.

Skonfiguruj ścieżkę wywołania zwrotnego po wylogowaniu w rejestracji dostawcy OIDC aplikacji. W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost:{PORT}/signout-callback-oidc

Note

Używając Microsoft Entra ID, ustaw ścieżkę w wpisach identyfikatora URI przekierowania w konfiguracji platformy Web w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu. Jeśli nie dodasz identyfikatora URI ścieżki wywołania zwrotnego wylogowania do rejestracji aplikacji w Entra, Entra odmówi przekierowania użytkownika z powrotem do aplikacji i jedynie poprosi ich o zamknięcie okna przeglądarki.

RemoteSignOutPath: Żądania odebrane na tej ścieżce powodują, że program obsługi wywołuje wylogowywanie przy użyciu schematu wylogowywania.

W poniższym przykładzie symbol zastępczy {PORT} jest portem aplikacji:

https://localhost/signout-oidc

Note

W przypadku korzystania z Microsoft Entra ID ustaw adres URL wylogowania frontu w portalu Entra lub Azure. Port nie jest wymagany dla adresów localhost w przypadku korzystania z usługi Entra. Większość innych dostawców OIDC wymaga poprawnego portu.

oidcOptions.CallbackPath = new PathString("{PATH}");
oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
oidcOptions.RemoteSignOutPath = new PathString("{PATH}");

Przykłady (wartości domyślne):

oidcOptions.CallbackPath = new PathString("/signin-oidc");
oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");

(Microsoft Azure tylko z "wspólnym" punktem końcowym): TokenValidationParameters.IssuerValidatorWielu dostawców OIDC współpracuje z domyślnym walidatorem wystawcy, ale powinniśmy uwzględnić wystawcę sparametryzowanego przy użyciu identyfikatora dzierżawy ({TENANT ID}) zwróconego przez https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Aby uzyskać więcej informacji, zobacz SecurityTokenInvalidIssuerException w ramach OpenID Connect i punkt końcowy „common” Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Tylko w przypadku aplikacji korzystających z identyfikatora Entra firmy Microsoft lub usługi Azure AD B2C z "wspólnym" punktem końcowym:

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

Projekt po stronie klienta Blazor Web AppBlazorWebAppOidc.Client

Projekt BlazorWebAppOidc.Client jest projektem po stronie klienta programu Blazor Web App.

Klient wywołuje AddAuthenticationStateDeserialization w celu deserializacji i użycia stanu uwierzytelniania przekazanego przez serwer. Stan uwierzytelniania jest stały dla okresu istnienia aplikacji WebAssembly.

Klasa PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) działa po stronie klienta i określa stan uwierzytelniania użytkownika, wyszukując dane zapisane na stronie podczas jej renderowania na serwerze. Stan uwierzytelniania jest stały dla okresu istnienia aplikacji WebAssembly.

Jeśli użytkownik musi się zalogować lub wylogować, wymagane jest ponowne załadowanie pełnej strony.

Przykładowa aplikacja udostępnia tylko nazwę użytkownika i adres e-mail do celów wyświetlania.

Serializacja tylko nazw i twierdzeń dotyczących roli

Ta sekcja dotyczy tylko wzorca innego niż BFF (Interactive Auto) i wzorca BFF (Interactive Auto) i ich przykładowych aplikacji.

Program W pliku wszystkie oświadczenia są serializowane przez ustawienie SerializeAllClaims na true. Jeśli chcesz, aby dla żądania CSR były serializowane tylko nazwa i oświadczenia dotyczące roli, usuń opcję lub ustaw to na false.

Podaj konfigurację za pomocą dostawcy konfiguracji JSON (ustawienia aplikacyjne)

Przykładowe projekty rozwiązań konfigurują uwierzytelnianie elementu nośnego OIDC i JWT w swoich Program plikach w celu umożliwienia odnajdywania ustawień konfiguracji przy użyciu autouzupełniania języka C#. Aplikacje profesjonalne zwykle używają dostawcy konfiguracji do konfigurowania opcji OIDC, takich jak domyślny dostawca konfiguracji JSON. Dostawca konfiguracji JSON ładuje konfigurację z plików ustawień aplikacji appsettings.json/appsettings.{ENVIRONMENT}.json, gdzie placeholder {ENVIRONMENT} to środowisko uruchomieniowe aplikacji. Postępuj zgodnie ze wskazówkami w tej sekcji, aby użyć plików ustawień aplikacji do konfiguracji.

W pliku ustawień aplikacji (appsettings.json) BlazorWebAppOidc projektu lub BlazorWebAppOidcServer dodaj następującą konfigurację 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"
      ]
    }
  }
},

Zaktualizuj symbole zastępcze w poprzedniej konfiguracji, aby odpowiadały wartościom, których aplikacja używa w pliku Program.

  • {TENANT ID (BLAZOR APP)}: Identyfikator klienta aplikacji Blazor.
  • {CLIENT ID (BLAZOR APP)}: identyfikator Blazor klienta aplikacji.
  • {APP ID URI (WEB API)}: Identyfikator URI interfejsu API aplikacji sieciowej.

"Autorytet „wspólny” (https://login.microsoftonline.com/common/v2.0) powinien być używany dla aplikacji wielodzierżawczych." Aby użyć "wspólnego" autorytetu dla aplikacji jednostanowych, zobacz sekcję Używanie "wspólnego" autorytetu dla aplikacji jednostanowych.

Zaktualizuj wszystkie inne wartości w poprzedniej konfiguracji, aby odpowiadały wartościom niestandardowym/innym niż domyślne używane w Program pliku.

Konfiguracja jest automatycznie pobierana przez konstruktora uwierzytelniania.

Usuń następujące wiersze z Program pliku:

- oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
- oidcOptions.Scope.Add("...");
- oidcOptions.CallbackPath = new PathString("...");
- oidcOptions.SignedOutCallbackPath = new PathString("...");
- oidcOptions.RemoteSignOutPath = new PathString("...");
- oidcOptions.Authority = "...";
- oidcOptions.ClientId = "...";

W metodzie ConfigureCookieOidcCookieOidcServiceCollectionExtensions.cs usuń następujący wiersz:

- oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

W projekcie MinimalApiJwt dodaj następującą konfigurację ustawień aplikacji do appsettings.json pliku:

"Authentication": {
  "Schemes": {
    "Bearer": {
      "Authority": "https://sts.windows.net/{TENANT ID (WEB API)}",
      "ValidAudiences": [ "{APP ID URI (WEB API)}" ]
    }
  }
},

Zaktualizuj symbole zastępcze w poprzedniej konfiguracji, aby odpowiadały wartościom, których aplikacja używa w pliku Program.

  • {TENANT ID (WEB API)}: identyfikator Tenant Id interfejsu API.
  • {APP ID URI (WEB API)}: Identyfikator URI interfejsu API aplikacji sieciowej.

Formaty autorytetu przyjmują następujące wzorce:

  • ME-ID typ dzierżawy: https://sts.windows.net/{TENANT ID}
  • Identyfikator zewnętrzny firmy Microsoft: https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0
  • Typ dzierżawy B2C: https://login.microsoftonline.com/{TENANT ID}/v2.0

Formaty odbiorców przyjmują następujące wzorce ({CLIENT ID} to identyfikator klienta internetowego interfejsu API; {DIRECTORY NAME} to nazwa katalogu, na przykład contoso):

  • ME-ID typ dzierżawy: api://{CLIENT ID}
  • Identyfikator zewnętrzny firmy Microsoft: {CLIENT ID}
  • Typ dzierżawy B2C: https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}

Konfiguracja jest automatycznie pobierana przez konstruktora uwierzytelniania elementu nośnego JWT.

Usuń następujące wiersze z Program pliku:

- jwtOptions.Authority = "...";
- jwtOptions.Audience = "...";

Aby uzyskać więcej informacji na temat konfiguracji, zobacz następujące zasoby:

Użyj "wspólnego" autorytetu dla aplikacji jednokrotnego najemcy

Możesz użyć "wspólnego" autorytetu dla aplikacji jednodzierżawowych, ale trzeba wykonać następujące kroki, aby zaimplementować niestandardowy walidator wydawcy.

Microsoft.IdentityModel.Validators Dodaj pakiet NuGet do BlazorWebAppOidcprojektu , BlazorWebAppOidcServerlub BlazorWebAppOidcBff .

Note

Aby uzyskać wskazówki dotyczące dodawania pakietów do aplikacji .NET, zobacz artykuły w Instalowanie i zarządzanie pakietami oraz w proces korzystania z pakietów (dokumentacja NuGet). Sprawdź prawidłowe wersje pakietów pod adresem NuGet.org.

Na górze pliku Program udostępnij przestrzeń nazw Microsoft.IdentityModel.Validators.

using Microsoft.IdentityModel.Validators;

Użyj następującego Program kodu w pliku, w którym są skonfigurowane opcje OIDC:

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

Aby uzyskać więcej informacji, zobacz SecurityTokenInvalidIssuerException w ramach OpenID Connect i punkt końcowy „common” Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Przekieruj do strony głównej po wylogowaniu

Składnik LogInOrOut (Layout/LogInOrOut.razor) ustawia ukryte pole dla zwracanego adresu URL (ReturnUrl) na bieżący adres URL (currentURL). Gdy użytkownik wyloguje się z aplikacji, dostawca tożsamości zwraca użytkownika do strony, z której się wylogował. Jeśli użytkownik wyloguje się z bezpiecznej strony, zostanie zwrócony do tej samej bezpiecznej strony i odesłany przez proces uwierzytelniania. Ten przepływ uwierzytelniania jest rozsądny, gdy użytkownicy muszą regularnie zmieniać konta.

Alternatywnie użyj następującego składnika LogInOrOut, który nie dostarcza adresu URL zwrotnego podczas wylogowywania.

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>

Odświeżanie tokenu

Implementacja niestandardowego modułu odświeżania cookie (CookieOidcRefresher.cs) automatycznie aktualizuje roszczenia użytkownika, gdy wygasną. Bieżąca implementacja oczekuje otrzymania tokenu ID w zamian za token odświeżający z punktu końcowego tokenu. Oświadczenia w tym tokenie identyfikatora są następnie używane do zastępowania oświadczeń użytkownika.

Przykładowa implementacja nie zawiera kodu do żądania oświadczeń z punktu końcowego UserInfo podczas odświeżania tokenu. Aby uzyskać więcej informacji, zobacz BlazorWebAppOidc AddOpenIdConnect with GetClaimsFromUserInfoEndpoint = true doesn't propogate [sic] role claims to client (dotnet/aspnetcore #58826).

Note

Niektórzy dostawcy tożsamości zwracają token dostępu tylko wtedy, gdy używany jest token odświeżania. CookieOidcRefresher można zaktualizować za pomocą dodatkowej logiki, aby można było dalej korzystać z wcześniejszego zestawu roszczeń przechowywanych w autoryzacji cookie lub użyć tokenu dostępu do żądania roszczeń z punktu końcowego UserInfo.

Kryptograficzne spoza

Nonce to wartość ciągu, która wiąże sesję klienta z tokenem ID w celu ograniczenia ataków powtórzeń.

Jeśli podczas opracowywania i testowania uwierzytelniania wystąpi błąd nonca, użyj nowej sesji przeglądarki InPrivate/incognito dla każdego przebiegu testowego, niezależnie od tego, jak mała zmiana została wprowadzona w aplikacji lub na koncie użytkownika testowego, ponieważ nieaktualne dane cookie mogą prowadzić do błędu nonca. Aby uzyskać więcej informacji, zobacz sekcję Pliki cookie i dane witryny .

Nonce nie jest wymagany ani używany, gdy token odświeżania jest wymieniany na nowy token dostępu. W przykładowej aplikacji CookieOidcRefresher (CookieOidcRefresher.cs) celowo ustawia OpenIdConnectProtocolValidator.RequireNonce na false.

Role dla aplikacji, które nie zostały zarejestrowane w usłudze Microsoft Entra (ME-ID)

Ta sekcja dotyczy aplikacji, które nie używają identyfikatora Entra firmy Microsoft (ME-ID) jako dostawcy tożsamości. W przypadku aplikacji zarejestrowanych przy użyciu identyfikatora ME zobacz sekcję Role aplikacji dla aplikacji zarejestrowanych w usłudze Microsoft Entra (ME-ID).

Skonfiguruj typ oświadczenia roli (TokenValidationParameters.RoleClaimType) w elemencie OpenIdConnectOptions:Program.cs

oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";

W przypadku wielu dostawców tożsamości OIDC typ atrybutu roli to role. Sprawdź dokumentację dostawcy tożsamości, aby znaleźć poprawną wartość.

Zastąp klasę UserInfo w projekcie BlazorWebAppOidc.Client następującą klasą.

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.");
}

W tym momencie Razor składniki mogą przyjąć autoryzację opartą na rolach i opartą na zasadach. Role aplikacji pojawiają się w role roszczeniach, jedno roszczenie na rolę.

Role aplikacji dla aplikacji zarejestrowanych w usłudze Microsoft Entra (ME-ID)

Skorzystaj ze wskazówek w tej sekcji, aby zaimplementować role aplikacji, ME-ID grupy zabezpieczeń i ME-ID wbudowane role administratora dla aplikacji przy użyciu identyfikatora Entra firmy Microsoft (ME-ID).

Podejście opisane w tej sekcji konfiguruje ME-ID w celu wysyłania grup i ról w nagłówku uwierzytelniania cookie. Jeśli użytkownicy są tylko członkami kilku grup zabezpieczeń i ról, poniższe podejście powinno działać w przypadku większości platform hostingu bez wystąpienia problemu, w którym nagłówki są zbyt długie, na przykład w przypadku hostingu usług IIS, który ma domyślny limit długości nagłówka 16 KB (MaxRequestBytes). Jeśli długość nagłówka jest problemem z powodu członkostwa w wielu grupach lub rolach, zalecamy, aby nie przestrzegać wskazówek w tej sekcji, lecz zamiast tego zaimplementować Microsoft Graph, aby uzyskać grupy i role użytkownika z ME-ID oddzielnie, co nie zwiększa rozmiaru tokenu uwierzytelniania. Aby uzyskać więcej informacji, zobacz Nieprawidłowe żądanie — zbyt długie żądanie — serwer IIS (dotnet/aspnetcore #57545).

Skonfiguruj typ żądania roli (TokenValidationParameters.RoleClaimType) w OpenIdConnectOptionsProgram.cs. Ustaw wartość na roles:

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Chociaż nie można przypisywać ról do grup bez konta ME-ID Premium, możesz przypisywać role użytkownikom i odbierać oświadczenia ról dla użytkowników przy użyciu standardowego konta platformy Azure. Wskazówki w tej sekcji nie wymagają konta Premium z identyfikatorem ME.ID.

Podczas pracy z katalogiem domyślnym postępuj zgodnie ze wskazówkami w temacie Dodawanie ról aplikacji do aplikacji i odbieranie ich w tokenie (ME-ID dokumentacji), aby skonfigurować i przypisać role. Jeśli nie pracujesz z katalogiem domyślnym, zmodyfikuj manifest aplikacji w witrynie Azure Portal, aby ręcznie ustanowić role aplikacji we appRoles wpisie pliku manifestu. Aby uzyskać więcej informacji, zobacz Konfigurowanie oświadczenia roli (dokumentacjaME-ID).

Grupy zabezpieczeń platformy Azure użytkownika pojawiają się w oświadczeniach groups, a wbudowane przypisania ról administratora ME-ID użytkownika pojawiają się w powszechnie znanych identyfikatorach (wids) oświadczeń. Wartości obu typów roszczeń to identyfikatory GUID. Po odebraniu przez aplikację te oświadczenia mogą służyć do ustanawiania autoryzacji roli i zasad w Razor składnikach.

W manifeście aplikacji w portalu Azure ustaw atrybut na . Wartość All powoduje, że identyfikator ME-ID wysyła wszystkie grupy zabezpieczeń/dystrybucji (groups roszczeń) i ról (wids roszczeń) zalogowanego użytkownika. Aby ustawić groupMembershipClaims atrybut:

  1. Otwórz rejestrację aplikacji w witrynie Azure Portal.
  2. Wybierz pozycję Zarządzaj>manifestem na pasku bocznym.
  3. Znajdź groupMembershipClaims atrybut.
  4. Ustaw wartość na All ("groupMembershipClaims": "All").
  5. Wybierz przycisk Zapisz .

Zastąp klasę UserInfo w projekcie BlazorWebAppOidc.Client następującą klasą.

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.");
}

Na tym etapie Razor składniki mogą przyjąć autoryzację opartą na rolach i opartą na zasadach:

  • Role aplikacji pojawiają się w roles roszczeniach, jedno roszczenie na rolę.
  • Grupy zabezpieczeń pojawiają się w groups roszczeniach, jedno roszczenie na grupę. Identyfikatory GUID grupy zabezpieczeń pojawiają się w portalu Azure podczas tworzenia grupy zabezpieczeń i są wymienione podczas wybierania Identity>Przegląd>Grupy>Widok.
  • Wbudowane role administratora ME-ID pojawiają się w wids oświadczeniach, a każda rola ma własne oświadczenie. Oświadczenie wids z wartością b79fbf4d-3ef9-4689-8143-76b194e85509 jest zawsze wysyłane przez ME-ID dla kont dzierżawcy innych niż gość i nie odnosi się do roli administratora. Identyfikatory GUID ról administratora (identyfikatory szablonów ról) są wyświetlane w portalu Azure po wybraniu Ról i administratorów, a następnie trzykropka (...) >Opis opisującego wymienioną rolę. Identyfikatory szablonów ról są również wymienione we Wbudowanych Rolach Microsoft Entra (Dokumentacja Entra).

Alternatywa: Duende Access Token Management

W przykładowej aplikacji implementacja niestandardowego cookie modułu odświeżania (CookieOidcRefresher.cs) służy do automatycznego odświeżania tokenu nieinterakcyjnego. Alternatywne rozwiązanie można znaleźć w pakiecie open sourceDuende.AccessTokenManagement.OpenIdConnect.

Usługa Duende Access Token Management zapewnia funkcje automatycznego zarządzania tokenami dostępu dla procesów roboczych platformy .NET i aplikacji internetowych platformy ASP.NET Core, w tym Blazor, bez konieczności dodawania niestandardowego cookie modułu odświeżania.

Po zainstalowaniu pakietu usuń narzędzie CookieOidcRefresher i dodaj zarządzanie tokenami dostępu dla aktualnie zalogowanego użytkownika w Program pliku:

// Add services for token management
builder.Services.AddOpenIdConnectAccessTokenManagement();

// Register a typed HTTP client with token management support
builder.Services.AddHttpClient<InvoiceClient>(client =>
    {
        client.BaseAddress = new Uri("https://api.example.com/invoices/");
    })
    .AddUserAccessTokenHandler();

Typowany klient HTTP (lub nazwany klient HTTP, jeśli zaimplementowano) ma automatyczne zarządzanie okresem istnienia tokenu dostępu w imieniu aktualnie zalogowanego użytkownika, w tym zarządzanie tokenami przezroczystego odświeżania.

Aby uzyskać więcej informacji, zobacz dokumentację usługi Duende Access Token Management dla programu Blazor.

Troubleshoot

Logging

Aplikacja serwera jest standardową aplikacją ASP.NET Core. Zobacz wskazówki dotyczące rejestrowania ASP.NET Core , aby włączyć niższy poziom rejestrowania w aplikacji serwera.

Aby włączyć rejestrowanie debugowania lub śledzenia na potrzeby Blazor WebAssembly uwierzytelniania, zobacz sekcję Rejestrowanie uwierzytelniania po stronie klienta ASP.NET Core Blazor z selektorem wersji artykułu ustawionym na ASP.NET Core na platformie .NET 7 lub nowszym.

Typowe błędy

  • Debugger zatrzymuje się na wyjątku podczas wylogowywania z Microsoft Entra External ID.

    Następujący wyjątek zatrzymuje debuger programu Visual Studio podczas wylogowywania się z zewnętrznego identyfikatora Microsoft Entra:

    Uncaught TypeError TypeError: Failed to execute 'postMessage' on 'Window': The provided value cannot be converted to a sequence.

    Przerwanie debugera Visual Studio przy wyjątku JavaScript podczas wylogowywania

    Wyjątek jest zgłaszany z kodu Entra JavaScript, więc nie jest to problem z ASP.NET Core. Wyjątek nie ma wpływu na funkcjonalność aplikacji w środowisku produkcyjnym, więc wyjątek można zignorować podczas lokalnego testowania programistycznego.

  • Błędna konfiguracja aplikacji lub Identity dostawcy (IP)

    Najczęstsze błędy są spowodowane nieprawidłową konfiguracją. Poniżej przedstawiono kilka przykładów:

    • W zależności od wymagań scenariusza brakujący lub niepoprawny autorytet, instancja, identyfikator dzierżawy, domena dzierżawy, identyfikator klienta lub URI przekierowania uniemożliwia aplikacji uwierzytelnianie klientów.
    • Nieprawidłowe zakresy żądań uniemożliwiają klientom uzyskiwanie dostępu do punktów końcowych internetowego interfejsu API serwera.
    • Nieprawidłowe lub brakujące uprawnienia interfejsu API serwera uniemożliwiają klientom uzyskiwanie dostępu do punktów końcowych internetowego interfejsu API serwera.
    • Uruchamianie aplikacji na innym porcie niż ten skonfigurowany w URI przekierowania podczas rejestracji aplikacji dla adresu IP. Należy pamiętać, że port nie jest wymagany dla Microsoft Entra ID i aplikacji działającej na localhost adresie testowania deweloperskiego, ale konfiguracja portu aplikacji i port, na którym działa aplikacja, musi być zgodna z innymi adresami niż localhost.

    Omówienie konfiguracji w tym artykule przedstawia przykłady prawidłowej konfiguracji. Dokładnie sprawdź konfigurację wyszukując błędną konfigurację aplikacji i adresu IP.

    Jeśli konfiguracja jest poprawna:

    • Analizowanie dzienników aplikacji.

    • Sprawdź ruch sieciowy między aplikacją kliencka a adresem IP lub aplikacją serwera przy użyciu narzędzi deweloperskich przeglądarki. Często dokładny komunikat o błędzie lub komunikat zawierający wskazówki dotyczące przyczyn problemu jest zwracany do klienta przez adres IP lub aplikację serwera po wykonaniu żądania. Wskazówki dotyczące narzędzi programistycznych znajdują się w następujących artykułach.

    Zespół dokumentacji odpowiada na opinie dotyczące dokumentów i usterek w artykułach (otwórz problem z sekcji Ta strona opinii), ale nie może zapewnić pomocy technicznej dotyczącej produktów. Dostępnych jest kilka publicznych forów pomocy technicznej, które ułatwiają rozwiązywanie problemów z aplikacją. Zalecamy:

    Poprzednie fora nie należą do firmy Microsoft ani nie są kontrolowane przez firmę Microsoft.

    W przypadku raportów o usterkach frameworka, które nie dotyczą zabezpieczeń, nie zawierają wrażliwych informacji i nie są poufne, otwórz zgłoszenie w jednostce produktu ASP.NET Core. Nie otwieraj problemu z jednostką produktu, dopóki nie zbadasz dokładnie przyczyny problemu i nie możesz go rozwiązać samodzielnie i z pomocą społeczności na publicznym forum pomocy technicznej. Jednostka produktu nie może rozwiązywać problemów z poszczególnymi aplikacjami, które są uszkodzone z powodu prostej błędnej konfiguracji lub przypadków użycia obejmujących usługi innych firm. Jeśli raport jest poufny lub poufny lub opisuje potencjalną lukę w zabezpieczeniach produktu, którą mogą wykorzystać cyberataki, zobacz Raportowanie problemów z zabezpieczeniami i usterek (dotnet/aspnetcorerepozytorium GitHub).

  • Nieautoryzowany klient dla ME-ID

    info: Autoryzacja Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] nie powiodła się. Te wymagania nie zostały spełnione: DenyAnonymousAuthorizationRequirement: Wymaga uwierzytelnionego użytkownika.

    Wystąpił błąd podczas logowania z ME-ID.

    • Błąd: unauthorized_client
    • Opis: AADB2C90058: The provided application is not configured to allow public clients.

    Aby naprawić ten błąd:

    1. W witrynie Azure Portal uzyskaj dostęp do manifestu aplikacji.
    2. allowPublicClient Ustaw atrybut na null lub true.

Pliki cookie i dane witryn

Pliki cookie i dane witryn mogą być utrwalane w aktualizacjach aplikacji i zakłócać testowanie i rozwiązywanie problemów. Wyczyść następujące informacje podczas wprowadzania zmian w kodzie aplikacji, zmiany konta użytkownika w dostawcy lub zmiany konfiguracji aplikacji dostawcy:

  • Pliki cookie logowania użytkownika
  • Pliki cookie aplikacji
  • Buforowane i przechowywane dane lokacji

Jedną z metod zapobiegania zakłócaniu testowania i rozwiązywania problemów przez utrzymujące się pliki cookie i dane witryny jest:

  • Konfigurowanie przeglądarki
    • Użyj przeglądarki do testowania, którą można skonfigurować, aby usuwać wszystkie cookie i dane witryny za każdym razem, gdy zamykasz przeglądarkę.
    • Upewnij się, że przeglądarka jest zamknięta ręcznie lub przez środowisko IDE w celu zmiany konfiguracji aplikacji, użytkownika testowego lub dostawcy.
  • Użyj polecenia niestandardowego, aby otworzyć przeglądarkę w trybie InPrivate lub Incognito w programie Visual Studio:
    • Otwórz okno dialogowe Przeglądaj za pomocą z przycisku Uruchom programu Visual Studio.
    • Wybierz przycisk Dodaj .
    • Podaj ścieżkę do przeglądarki w polu Program . Następujące ścieżki wykonywalne to typowe lokalizacje instalacji systemu Windows 10. Jeśli przeglądarka jest zainstalowana w innej lokalizacji lub nie używasz systemu Windows 10, podaj ścieżkę do pliku wykonywalnego przeglądarki.
      • 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
    • W polu Argumenty podaj opcję wiersza polecenia używaną przez przeglądarkę do otwierania w trybie InPrivate lub Incognito. Niektóre przeglądarki wymagają adresu URL aplikacji.
      • Microsoft Edge: użyj -inprivate.
      • Google Chrome: użyj --incognito --new-window {URL}, gdzie {URL} jest symbolem zastępczym oznaczającym adres URL do otwarcia (na przykład https://localhost:5001).
      • Mozilla Firefox: użyj -private -url {URL}, gdzie element zastępczy {URL} to adres URL do otwarcia (na przykład https://localhost:5001).
    • Podaj nazwę w polu Przyjazna nazwa . Na przykład Firefox Auth Testing.
    • Wybierz przycisk OK .
    • Aby uniknąć konieczności wybierania profilu przeglądarki dla każdej iteracji testowania za pomocą aplikacji, ustaw profil jako domyślny przy użyciu przycisku Ustaw jako domyślny .
    • Upewnij się, że przeglądarka jest zamknięta przez środowisko IDE w celu zmiany konfiguracji aplikacji, użytkownika testowego lub dostawcy.

Uaktualnienia aplikacji

Działająca aplikacja może zakończyć się niepowodzeniem natychmiast po uaktualnieniu zestawu .NET SDK na komputerze deweloperskim lub zmianie wersji pakietów w aplikacji. W niektórych przypadkach niespójne pakiety mogą spowodować przerwanie aplikacji podczas przeprowadzania głównych uaktualnień. Większość z tych problemów można rozwiązać, wykonując następujące instrukcje:

  1. Wyczyść pamięć podręczną pakietów NuGet systemu lokalnego, wykonując polecenie dotnet nuget locals all --clear z wiersza poleceń.
  2. Usuń foldery bin i obj projektu.
  3. Przywróć i odbuduj projekt.
  4. Usuń wszystkie pliki w folderze wdrażania na serwerze przed ponownym wdrożeniem aplikacji.

Note

Korzystanie z wersji pakietów niezgodnych z platformą docelową aplikacji nie jest obsługiwane. Aby uzyskać informacje na temat pakietu, użyj galerii NuGet.

Uruchamianie rozwiązania z prawidłowego projektu

Blazor Web Apps:

  • W przypadku jednego z przykładów wzorca Backend-for-Frontend (BFF) uruchom rozwiązanie z Aspire/Aspire.AppHost projektu.
  • W przypadku jednego z przykładów wzorców innych niż BFF uruchom rozwiązanie z projektu serwera.

Blazor Server:

Uruchom rozwiązanie z projektu serwera.

Sprawdzanie użytkownika

Poniższy UserClaims składnik może być używany bezpośrednio w aplikacjach lub służyć jako podstawa dalszego dostosowywania.

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;
    }
}

Dodatkowe zasoby