Dela via


Skydda en ASP.NET Core Blazor Web App med OpenID Connect (OIDC)

Note

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Important

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Den här artikeln beskriver hur du skyddar en Blazor Web App med OpenID Connect (OIDC) med hjälp av en exempelapp på dotnet/blazor-samples GitHub-lagringsplatsen (.NET 8 eller senare) (hur du laddar ned).

För Microsoft Entra-ID eller Azure AD B2C kan du använda AddMicrosoftIdentityWebApp från Microsoft Identity Web (Microsoft.Identity.Web NuGet-paket, API-dokumentation), som lägger till både OIDC- och Cookie autentiseringshanterare med lämpliga standardvärden. Exempelappen och vägledningen i den här artikeln använder inte Microsoft Identity Web. Vägledningen visar hur du konfigurerar OIDC-hanteraren manuellt för alla OIDC-leverantörer. Mer information om hur du implementerar Microsoft Identity Web finns i Skydda en ASP.NET Core Blazor Web App med Microsoft Entra-ID.

Den här versionen av artikeln täcker implementeringen av OIDC utan att använda Backend for Frontend (BFF) pattern med en app som använder global interaktiv auto-återgivning (server och .Client projekt). BFF-mönstret är användbart för att göra autentiserade begäranden till externa tjänster. Ändra artikelversionsväljaren till BFF-mönster om appens specifikation kräver att BFF-mönstret används.

Följande specifikation antas:

  • Blazor Web App Använder autoåtergivningsläget med global interaktivitet.
  • Tjänster för anpassade autentiseringstillståndsleverantörer används av server- och klientappar för att fånga användarens autentiseringstillstånd och överföra det mellan servern och klienten.
  • Den här appen är en startpunkt för alla OIDC-autentiseringsflöden. OIDC konfigureras manuellt i appen och förlitar sig inte på Microsoft Entra-ID eller Microsoft-webbpaketIdentity, och exempelappen kräver inte heller Microsoft Azure-värdtjänster. Exempelappen kan dock användas med Entra, Microsoft Identity Web och hanteras i Azure.
  • Automatisk icke-interaktiv tokenförnyelse.
  • Ett separat webb-API-projekt visar ett säkert webb-API-anrop för väderdata.

För en alternativ användarupplevelse med Microsoft Authentication Library för .NET, Microsoft Identity Web och Microsoft Entra ID, se Skydda en ASP.NET Core Blazor Web App med Microsoft Entra ID.

Exempellösning

Exempelappen består av följande projekt:

  • BlazorWebAppOidc: Projekt på serversidan för Blazor Web App, som innehåller ett exempel på minimal API-slutpunkt för väderdata.
  • BlazorWebAppOidc.Client: Klientsideprojektet för Blazor Web App.
  • MinimalApiJwt: Backend-webb-API med en minimal API-slutpunkt för väderdata.

Få åtkomst till exemplet i den senaste versionsmappen i Blazor-exemplarsamlingen med följande länk. Exemplet finns i BlazorWebAppOidc mappen för .NET 8 eller senare.

Starta lösningen från Aspire/Aspire.AppHost projektet.

Visa eller ladda ned exempelkod (ladda ned)

Exempel på lösningsfunktioner:

  • Automatisk förnyelse av den interaktionsfria tokenen med hjälp av en anpassad cookie förnyare (CookieOidcRefresher.cs).

  • Väderdata hanteras av en minimal API-slutpunkt (/weather-forecast) i Program filen (Program.cs) i MinimalApiJwt projektet. Slutpunkten kräver auktorisering genom att anropa RequireAuthorization. För alla kontrollanter som du lägger till i projektet lägger du till [Authorize] attributet till kontrollanten eller åtgärden. Mer information om hur du kräver auktorisering i appen via en auktoriseringsprincip och om att välja bort auktorisering vid en delmängd av offentliga slutpunkter finns i vägledningen förRazor Pages OIDC.

  • Appen anropar säkert ett webb-API för väderdata:

    • När komponenten Weather återges på servern använder komponenten ServerWeatherForecaster på servern för att hämta väderdata från webb-API:et MinimalApiJwt i projektet med hjälp av en DelegatingHandler (TokenHandler) som kopplar åtkomsttoken från HttpContext till begäran.
    • När komponenten återges på klienten, använder komponenten ClientWeatherForecaster tjänstimplementeringen som använder en förkonfigurerad HttpClient (i klientprojektets Program-fil) för att utföra ett web-API-anrop från serverprojektets ServerWeatherForecaster.
  • Klassen PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) är en serverside AuthenticationStateProvider som använder PersistentComponentState för att överföra autentiseringstillståndet till klienten, vilket sedan är fastställt för hela WebAssembly-applikationens livslängd.

Mer information om (webb)API-anrop med hjälp av en tjänstabstraktion i s finns i Blazor Web AppAnropa ett webb-API från en ASP.NET Core-appBlazor.

OIDC-providerns terminologi och vägledning

Även om du inte behöver använda Microsoft Entra (ME-ID) som OIDC-provider för att använda exempelappen och vägledningen i den här artikeln, beskriver den här artikeln inställningar för ME-ID med hjälp av namn som finns i Microsoft-dokumentationen och Azure/Entra-portalerna. OIDC-inställningar har liknande namngivning mellan OIDC-leverantörer. När du använder en OIDC-provider från tredje part använder du leverantörens dokumentation tillsammans med vägledningen i den här artikeln för registreringar av app- och webb-API:er.

Appregistreringar för Microsoft Entra-ID

Vi rekommenderar att du använder separata registreringar för appar och webb-API:er, även när apparna och webb-API:erna finns i samma lösning. Följande vägledning gäller för appen och BlazorWebAppOidc webb-API:et för MinimalApiJwt exempellösningen, men samma vägledning gäller vanligtvis för alla Entra-baserade registreringar för appar och webb-API:er.

Vägledning för app- och webb-API-registrering finns i Registrera ett program i Microsoft Entra-ID.

Registrera webb-API:et (MinimalApiJwt) först så att du sedan kan bevilja åtkomst till webb-API:et när du registrerar appen. Webb-API:ets hyresgäst-ID och klient-ID används för att konfigurera webb-API:et i filen Program. När du har registrerat webb-API:et exponerar du webb-API:et i Appregistreringar>Exponera ett API med omfångsnamnet Weather.Get. Registrera app-ID-URI:n för användning i appens konfiguration.

Registrera sedan appen (BlazorWebAppOidc/BlazorWebApOidc.Client) med en webbplattformskonfiguration och en omdirigerings-URIhttps://localhost/signin-oidc för (en port krävs inte). Appens tenant-ID och klient-ID, tillsammans med webb-API:ets basadress, app-ID-URI och väderscope-namn, används för att konfigurera appen i filen Program. Ge API-behörighet att komma åt webb-API:et iAPI-behörigheter för >. Om appens säkerhetsspecifikation anropar den kan du bevilja administratörsmedgivande för organisationen att få åtkomst till webb-API:et. Auktoriserade användare och grupper tilldelas till appens registrering i Appregistreringar>Företagsprogram.

Markera inte någon av kryssrutorna för att auktoriseringsslutpunkten ska returnera åtkomsttoken eller ID-token i appregistreringskonfigurationen för implicit beviljande och hybridflöden i Entra- eller Azure-portalen. OpenID Connect-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

Skapa en klienthemlighet i appens registrering i Entra- eller Azure-portalen (Hantera>certifikat och hemligheter>Ny klienthemlighet). Håll kvar på klienthemlighetsvärdet för användning i nästa avsnitt.

Ytterligare entra-konfigurationsvägledning för specifika inställningar finns senare i den här artikeln.

Upprätta klienthemligheten

Det här avsnittet gäller endast serverprojektet för Blazor Web App (BlazorWebAppOidc projektet).

Warning

Lagra inte apphemligheter, anslutningssträngar, autentiseringsuppgifter, lösenord, personliga ID-nummer (PIN),privat C#/.NET-kod eller privata nycklar/token i kod på klientsidan, vilket alltid är osäkert. I test-/mellanlagrings- och produktionsmiljöer bör Blazor kod på serversidan och webb-API:er använda säkra autentiseringsflöden som undviker att underhålla autentiseringsuppgifter i projektkod eller konfigurationsfiler. Förutom testning av lokal utveckling rekommenderar vi att du undviker användning av miljövariabler för att lagra känsliga data, eftersom miljövariabler inte är den säkraste metoden. För testning av lokal utveckling rekommenderas Secret Manager-verktyget för att skydda känsliga data. Mer information finns i Skyddat underhåll av känsliga data och autentiseringsuppgifter.

För testning av lokal utveckling använder du verktyget Secret Manager för att lagra Blazor serverprojektets klienthemlighet under konfigurationsnyckeln Authentication:Schemes:MicrosoftOidc:ClientSecret.

Serverprojektet Blazor har inte initierats för Secret Manager-verktyget. Använd ett kommandogränssnitt, till exempel PowerShell-kommandogränssnittet Developer i Visual Studio, för att köra följande kommando. Innan du kör kommandot ändrar du katalogen med kommandot cd till serverprojektets katalog. Kommandot upprättar en identifierare för användarhemligheter (<UserSecretsId> i serverappens projektfil):

dotnet user-secrets init

Kör följande kommando för att ange klienthemligheten. Platshållaren {SECRET} är klienthemligheten som hämtas från appens registrering:

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

Om du använder Visual Studio kan du bekräfta att hemligheten har angetts genom att högerklicka på serverprojektet i Solution Explorer och välja Hantera användarhemligheter.

MinimalApiJwt projekt

MinimalApiJwt-projektet är ett bakände-webb-API för flera frontend-projekt. Projektet konfigurerar en minimal API-slutpunkt för väderdata.

Den MinimalApiJwt.http filen kan användas för att testa väderdatabegäran. Observera att MinimalApiJwt projektet måste köras för att testa slutpunkten och att slutpunkten är hårdkodad i filen. Mer information finns i Använda .http-filer i Visual Studio 2022.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument och Swagger-användargränssnittet i utvecklingsmiljön. Mer information finns i Använda de genererade OpenAPI-dokumenten.

Projektet skapar en minimal API-slutpunkt för väderdata:

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

Konfigurera projektet i JwtBearerOptions av AddJwtBearer-anropet i projektets Program-fil.

Anger Authority auktoriteten för att göra OIDC-anrop. Vi rekommenderar att du använder en separat appregistrering för MinimalApiJwt projektet. Myndigheten matchar utfärdaren (iss) av JWT som returneras av identitetsleverantören.

jwtOptions.Authority = "{AUTHORITY}";

Formatet på auktoriteten beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett klient-ID för aaaabbbb-0000-cccc-1111-dddd2222eeee.

ME-ID exempel på hyresgästmyndighet:

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

Exempel på AAD B2C-klientorganisation:

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

Anger Audience målgruppen för en mottagen OIDC-token.

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

Note

När du använder Microsoft Entra-ID matchar du bara värdet till sökvägen till program-ID-URI:n som konfigurerats när du lägger till omfång Weather.Get under Exponera ett API i Entra- eller Azure-portalen. Ta inte med omfångsnamnet "Weather.Get" i värdet.

Målgruppens format beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett tenant-ID för contoso och ett klient-ID för 11112222-bbbb-3333-cccc-4444dddd5555.

ME-ID exempel på hyresgästs app-ID-URI:

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

Exempel på AAD B2C klientorganisations app-ID-URI:

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

Blazor Web App serverprojekt (BlazorWebAppOidc)

BlazorWebAppOidc projektet är serversideprojektet för Blazor Web App.

A DelegatingHandler (TokenHandler) hanterar att koppla en användares åtkomsttoken till utgående begäranden. Tokenhanteraren körs endast under statisk återgivning på serversidan (statisk SSR), så att använda HttpContext är säkert i det här scenariot. Mer information finns i IHttpContextAccessor/HttpContext i ASP.NET Core-appar Blazor och ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

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

I projektets Program fil registreras tokenhanteraren (TokenHandler) som en tjänst och anges som meddelandehanterare med AddHttpMessageHandler för att göra säkra begäranden till serverdelswebb-API MinimalApiJwt :et med hjälp av en namngiven HTTP-klient ("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>();

I projektets appsettings.json fil konfigurerar du den externa API-URI:n:

"ExternalApiUri": "{BASE ADDRESS}"

Example:

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

Följande OpenIdConnectOptions konfiguration finns i projektets Program-fil vid anropet till AddOpenIdConnect:

PushedAuthorizationBehavior: Kontrollerar stödet för Pushed Authorization Requests (PAR). Som standard är inställningen att använda PAR om identitetsproviderns identifieringsdokument (som vanligtvis finns på .well-known/openid-configuration) annonserar stöd för PAR. Om du vill kräva PAR-stöd för appen kan du tilldela värdet PushedAuthorizationBehavior.Require. PAR stöds inte av Microsoft Entra och det finns inga planer på att Entra någonsin ska stödja det i framtiden.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Anger det autentiseringsschema som motsvarar mellanprogrammet som ansvarar för att bevara användarens identitet efter en lyckad autentisering. OIDC-hanteraren måste använda ett inloggningsschema som kan bevara användarautentiseringsuppgifter mellan begäranden. Följande rad finns bara i demonstrationssyfte. Om det utelämnas används DefaultSignInScheme som ett återställningsvärde.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Omfång för openid och profile (Scope) (valfritt): Omfången openid och profile konfigureras också som standard eftersom de krävs för att OIDC-hanteraren ska fungera, men dessa kan behöva läggas till igen om omfången ingår i Authentication:Schemes:MicrosoftOidc:Scope konfigurationen. Allmän konfigurationsvägledning finns i Konfiguration i ASP.NET Core- och ASP.NET Core-konfigurationBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

SaveTokens: Definierar om åtkomst- och uppdateringstoken ska lagras i AuthenticationProperties efter en lyckad auktorisering. Den här egenskapen är inställd på true så att uppdateringstoken lagras för icke-interaktiv tokenuppdatering.

oidcOptions.SaveTokens = true;

Omfång för offlineåtkomst (Scope): Omfånget offline_access krävs för uppdateringstoken.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Authority och ClientId: Anger utfärdare och klient-ID för OIDC-anrop.

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

I följande exempel används ett klient-ID aaaabbbb-0000-cccc-1111-dddd2222eeee för och ett klient-ID för 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";

För flertenantappar bör den "vanliga" auktoriteten användas. Du kan också använda den "vanliga" myndigheten för appar med en enda klientorganisation, men en anpassad IssuerValidator krävs, vilket visas senare i det här avsnittet.

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

ResponseType: Konfigurerar OIDC-hanteraren för att endast utföra auktoriseringskodflödet. Implicita bidrag och hybridflöden är onödiga i det här läget. OIDC-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims och konfiguration av NameClaimType och RoleClaimType: Många OIDC-servrar använder "name" och "role" i stället för SOAP/WS-Fed standardvärden i ClaimTypes. När MapInboundClaims är inställt på falseutför hanteraren inte anspråksmappningar och anspråksnamnen från JWT används direkt av appen. I följande exempel anges rollanspråkstypen till "roles", vilket är lämpligt för Microsoft Entra ID (ME-ID). Mer information finns i din identitetsproviders dokumentation.

Note

MapInboundClaims måste anges till false för de flesta OIDC-leverantörer, vilket förhindrar att anspråk byts namn.

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

Sökvägskonfiguration: Sökvägar måste matcha omdirigerings-URI:n (återanrop för inloggning) och omdirigering efter utloggning (återanrop efter utloggning) som konfigurerats när applikationen registreras hos OIDC-leverantören. I Azure-portalen konfigureras sökvägar på bladet Autentisering för appens registrering. Både inloggnings- och utloggningssökvägarna måste registreras som omdirigerings-URI:er. Standardvärdena är /signin-oidc och /signout-callback-oidc.

CallbackPath: Begärans sökväg inom appens basväg där användaragenten skickas tillbaka.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

En port krävs inte för localhost adresser när du använder Microsoft Entra-ID. De flesta andra OIDC-leverantörer kräver rätt port.

SignedOutCallbackPath (konfigurationsnyckel: "SignedOutCallbackPath"): Begärans sökväg inom appens bassökväg som fångas upp av OIDC-hanteraren där användaragenten först returneras efter utloggning från identitetsleverantören. Exempelappen anger inte något värde för sökvägen eftersom standardvärdet "/signout-callback-oidc" används. Efter att ha uppsnappat begäran omdirigerar OIDC-hanteraren till SignedOutRedirectUri eller RedirectUri, om detta anges.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

När du använder Microsoft Entra-ID anger du sökvägen i Webbplattformskonfigurationens omdirigerings-URI-poster i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port. Om du inte lägger till URI för den utloggade återanropsvägen i appens registrering i Entra, vägrar Entra att dirigera användaren tillbaka till appen och uppmanar dem istället att bara stänga webbläsarfönstret.

RemoteSignOutPath: Begäranden som tas emot på den här sökvägen gör att hanteraren anropar utloggning med hjälp av utloggningsschemat.

I följande exempel är platshållaren {PORT} appens port:

https://localhost/signout-oidc

Note

När du använder Microsoft Entra-ID anger du url:en för utloggning via Front-kanalen i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port.

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

Exempel (standardvärden):

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

(Endast Microsoft Azure med den "vanliga" slutpunkten) TokenValidationParameters.IssuerValidator: Många OIDC-leverantörer arbetar med standardutfärdarverifieraren, men vi måste ta hänsyn till utfärdaren som parameteriseras med klientorganisations-ID :t ({TENANT ID}) som returneras av https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Mer information finns i SecurityTokenInvalidIssuerException med OpenID Connect och Azure AD:s "common"-endpunkt (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Endast för appar som använder Microsoft Entra-ID eller Azure AD B2C med den "vanliga" slutpunkten:

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

Blazor Web App klientprojekt (BlazorWebAppOidc.Client)

Detta BlazorWebAppOidc.Client projektet är klientsideprojektet för Blazor Web App.

Klienten anropar AddAuthenticationStateDeserialization för att deserialisera och använda autentiseringstillståndet som skickas av servern. Autentiseringstillståndet är fastställt under programlivslängden för WebAssembly-applikationen.

Klassen PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) är en AuthenticationStateProvider på klientsidan som avgör användarens autentiseringstillstånd genom att söka efter data som sparats på sidan när den återges på servern. Autentiseringstillståndet är fastställt under programlivslängden för WebAssembly-applikationen.

Om användaren behöver logga in eller ut, krävs det en fullständig omladdning av sidan.

Exempelappen innehåller endast ett användarnamn och e-postmeddelande i visningssyfte.

För Microsoft Entra-ID eller Azure AD B2C kan du använda AddMicrosoftIdentityWebApp från Microsoft Identity Web (Microsoft.Identity.Web NuGet-paket, API-dokumentation), som lägger till både OIDC- och Cookie autentiseringshanterare med lämpliga standardvärden. Exempelappen och vägledningen i den här artikeln använder inte Microsoft Identity Web. Vägledningen visar hur du konfigurerar OIDC-hanteraren manuellt för alla OIDC-leverantörer. Mer information om hur du implementerar Microsoft Identity Web finns i Skydda en ASP.NET Core Blazor Web App med Microsoft Entra-ID.

Den här versionen av artikeln omfattar implementering av OIDC utan att använda mönstret Serverdel för klientdel (BFF) med en app som använder global interaktiv serverrendering (enskilt projekt). BFF-mönstret är användbart för att göra autentiserade begäranden till externa tjänster. Ändra artikelversionsväljaren till BFF-mönster om appens specifikation kräver att BFF-mönstret används med global interaktiv automatisk återgivning.

Följande specifikation antas:

För en alternativ användarupplevelse med Microsoft Authentication Library för .NET, Microsoft Identity Web och Microsoft Entra ID, se Skydda en ASP.NET Core Blazor Web App med Microsoft Entra ID.

Exempellösning

Exempelappen består av följande projekt:

  • BlazorWebAppOidcServer: Blazor Web App projekt på serversidan (global interaktiv serverrendering).
  • MinimalApiJwt: Backend-webb-API med en minimal API-slutpunkt för väderdata.

Få åtkomst till exemplet i den senaste versionsmappen i Blazor-exemplarsamlingen med följande länk. Exemplet finns i BlazorWebAppOidcServer mappen för .NET 8 eller senare.

Visa eller ladda ned exempelkod (ladda ned)

Appregistreringar för Microsoft Entra-ID

Vi rekommenderar att du använder separata registreringar för appar och webb-API:er, även när apparna och webb-API:erna finns i samma lösning. Följande vägledning gäller för appen och BlazorWebAppOidcServer webb-API:et för MinimalApiJwt exempellösningen, men samma vägledning gäller vanligtvis för alla Entra-baserade registreringar för appar och webb-API:er.

Registrera webb-API:et (MinimalApiJwt) först så att du sedan kan bevilja åtkomst till webb-API:et när du registrerar appen. Webb-API:ets hyresgäst-ID och klient-ID används för att konfigurera webb-API:et i filen Program. När du har registrerat webb-API:et exponerar du webb-API:et i Appregistreringar>Exponera ett API med omfångsnamnet Weather.Get. Registrera app-ID-URI:n för användning i appens konfiguration.

Registrera sedan appen (BlazorWebAppOidcServer) med en webbplattformskonfiguration och en omdirigerings-URI av https://localhost/signin-oidc (en port krävs inte). Appens tenant-ID och klient-ID, tillsammans med webb-API:ets basadress, app-ID-URI och väderscope-namn, används för att konfigurera appen i filen Program. Ge API-behörighet att komma åt webb-API:et iAPI-behörigheter för >. Om appens säkerhetsspecifikation anropar den kan du bevilja administratörsmedgivande för organisationen att få åtkomst till webb-API:et. Auktoriserade användare och grupper tilldelas till appens registrering i Appregistreringar>Företagsprogram.

Markera inte någon av kryssrutorna för att auktoriseringsslutpunkten ska returnera åtkomsttoken eller ID-token i appregistreringskonfigurationen för implicit beviljande och hybridflöden i Entra- eller Azure-portalen. OpenID Connect-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

Skapa en klienthemlighet i appens registrering i Entra- eller Azure-portalen (Hantera>certifikat och hemligheter>Ny klienthemlighet). Håll kvar på klienthemlighetsvärdet för användning i nästa avsnitt.

Ytterligare entra-konfigurationsvägledning för specifika inställningar finns senare i den här artikeln.

Upprätta klienthemligheten

Det här avsnittet gäller endast serverprojektet för Blazor Web App (BlazorWebAppOidcServer projektet).

Warning

Lagra inte apphemligheter, anslutningssträngar, autentiseringsuppgifter, lösenord, personliga ID-nummer (PIN),privat C#/.NET-kod eller privata nycklar/token i kod på klientsidan, vilket alltid är osäkert. I test-/mellanlagrings- och produktionsmiljöer bör Blazor kod på serversidan och webb-API:er använda säkra autentiseringsflöden som undviker att underhålla autentiseringsuppgifter i projektkod eller konfigurationsfiler. Förutom testning av lokal utveckling rekommenderar vi att du undviker användning av miljövariabler för att lagra känsliga data, eftersom miljövariabler inte är den säkraste metoden. För testning av lokal utveckling rekommenderas Secret Manager-verktyget för att skydda känsliga data. Mer information finns i Skyddat underhåll av känsliga data och autentiseringsuppgifter.

För testning av lokal utveckling använder du verktyget Secret Manager för att lagra Blazor serverprojektets klienthemlighet under konfigurationsnyckeln Authentication:Schemes:MicrosoftOidc:ClientSecret.

Serverprojektet Blazor har inte initierats för Secret Manager-verktyget. Använd ett kommandogränssnitt, till exempel PowerShell-kommandogränssnittet Developer i Visual Studio, för att köra följande kommando. Innan du kör kommandot ändrar du katalogen med kommandot cd till serverprojektets katalog. Kommandot upprättar en identifierare för användarhemligheter (<UserSecretsId> i appens projektfil):

dotnet user-secrets init

Kör följande kommando för att ange klienthemligheten. Platshållaren {SECRET} är klienthemligheten som hämtas från appens registrering:

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

Om du använder Visual Studio kan du bekräfta att hemligheten har angetts genom att högerklicka på projektet i Solution Explorer och välja Hantera användarhemligheter.

MinimalApiJwt projekt

MinimalApiJwt-projektet är ett bakände-webb-API för flera frontend-projekt. Projektet konfigurerar en minimal API-slutpunkt för väderdata.

Den MinimalApiJwt.http filen kan användas för att testa väderdatabegäran. Observera att MinimalApiJwt projektet måste köras för att testa slutpunkten och att slutpunkten är hårdkodad i filen. Mer information finns i Använda .http-filer i Visual Studio 2022.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument och Swagger-användargränssnittet i utvecklingsmiljön. Mer information finns i Använda de genererade OpenAPI-dokumenten.

Projektet skapar en minimal API-slutpunkt för väderdata:

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

Konfigurera projektet i JwtBearerOptions av AddJwtBearer-anropet i projektets Program-fil.

Anger Authority auktoriteten för att göra OIDC-anrop. Vi rekommenderar att du använder en separat appregistrering för MinimalApiJwt projektet. Myndigheten matchar utfärdaren (iss) av JWT som returneras av identitetsleverantören.

jwtOptions.Authority = "{AUTHORITY}";

Formatet på auktoriteten beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett klient-ID för aaaabbbb-0000-cccc-1111-dddd2222eeee.

ME-ID exempel på hyresgästmyndighet:

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

Exempel på AAD B2C-klientorganisation:

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

Anger Audience målgruppen för en mottagen OIDC-token.

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

Note

När du använder Microsoft Entra-ID matchar du bara värdet till sökvägen till program-ID-URI:n som konfigurerats när du lägger till omfång Weather.Get under Exponera ett API i Entra- eller Azure-portalen. Ta inte med omfångsnamnet "Weather.Get" i värdet.

Målgruppens format beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett tenant-ID för contoso och ett klient-ID för 11112222-bbbb-3333-cccc-4444dddd5555.

ME-ID exempel på hyresgästs app-ID-URI:

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

Exempel på AAD B2C klientorganisations app-ID-URI:

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

BlazorWebAppOidcServer projekt

Automatisk uppdatering av icke-interaktiv token hanteras av en anpassad cookie uppdaterare (CookieOidcRefresher.cs).

A DelegatingHandler (TokenHandler) hanterar att koppla en användares åtkomsttoken till utgående begäranden. Tokenhanteraren körs endast under statisk återgivning på serversidan (statisk SSR), så att använda HttpContext är säkert i det här scenariot. Mer information finns i IHttpContextAccessor/HttpContext i ASP.NET Core-appar Blazor och ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

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

I projektets Program fil registreras tokenhanteraren (TokenHandler) som en tjänst och anges som meddelandehanterare med AddHttpMessageHandler för att göra säkra begäranden till serverdelswebb-API MinimalApiJwt :et med hjälp av en namngiven HTTP-klient ("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>();

Komponenten Weather använder attributet[Authorize] för att förhindra obehörig åtkomst. Mer information om hur du kräver auktorisering i appen via en auktoriseringsprincip och om att välja bort auktorisering vid en delmängd av offentliga slutpunkter finns i vägledningen förRazor Pages OIDC.

ExternalApi HTTP-klienten används för att göra en begäran om väderdata till det säkra webb-API:et. OnInitializedAsync I livscykelhändelsen för 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!");

I projektets appsettings.json fil konfigurerar du den externa API-URI:n:

"ExternalApiUri": "{BASE ADDRESS}"

Example:

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

Följande OpenIdConnectOptions konfiguration finns i projektets Program-fil vid anropet till AddOpenIdConnect:

PushedAuthorizationBehavior: Kontrollerar stödet för Pushed Authorization Requests (PAR). Som standard är inställningen att använda PAR om identitetsproviderns identifieringsdokument (som vanligtvis finns på .well-known/openid-configuration) annonserar stöd för PAR. Om du vill kräva PAR-stöd för appen kan du tilldela värdet PushedAuthorizationBehavior.Require. PAR stöds inte av Microsoft Entra och det finns inga planer på att Entra någonsin ska stödja det i framtiden.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Anger det autentiseringsschema som motsvarar mellanprogrammet som ansvarar för att bevara användarens identitet efter en lyckad autentisering. OIDC-hanteraren måste använda ett inloggningsschema som kan bevara användarautentiseringsuppgifter mellan begäranden. Följande rad finns bara i demonstrationssyfte. Om det utelämnas används DefaultSignInScheme som ett återställningsvärde.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Omfång för openid och profile (Scope) (valfritt): Omfången openid och profile konfigureras också som standard eftersom de krävs för att OIDC-hanteraren ska fungera, men dessa kan behöva läggas till igen om omfången ingår i Authentication:Schemes:MicrosoftOidc:Scope konfigurationen. Allmän konfigurationsvägledning finns i Konfiguration i ASP.NET Core- och ASP.NET Core-konfigurationBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

Konfigurera omfånget Weather.Get för åtkomst till det externa webb-API:et för väderdata. Följande exempel baseras på användning av Entra-ID i en ME-ID klientdomän. I följande exempel så finns platshållaren {APP ID URI} i Entra- eller Azure-portalen där webb-API:et exponeras. För alla andra identitetsleverantörer, använd lämpligt omfång.

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

Omfångets format beror på vilken typ av klientorganisation som används. I följande exempel är vistelsetdomän contoso.onmicrosoft.com, och klient-ID 11112222-bbbb-3333-cccc-4444dddd5555.

ME-ID exempel på hyresgästs app-ID-URI:

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

Exempel på AAD B2C klientorganisations app-ID-URI:

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

SaveTokens: Definierar om åtkomst- och uppdateringstoken ska lagras i AuthenticationProperties efter en lyckad auktorisering. Den här egenskapen är inställd på true så att uppdateringstoken lagras för icke-interaktiv tokenuppdatering.

oidcOptions.SaveTokens = true;

Omfång för offlineåtkomst (Scope): Omfånget offline_access krävs för uppdateringstoken.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Authority och ClientId: Anger utfärdare och klient-ID för OIDC-anrop.

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

I följande exempel används ett klient-ID aaaabbbb-0000-cccc-1111-dddd2222eeee för och ett klient-ID för 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";

För flertenantappar bör den "vanliga" auktoriteten användas. Du kan också använda den "vanliga" myndigheten för appar med en enda klientorganisation, men en anpassad IssuerValidator krävs, vilket visas senare i det här avsnittet.

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

ResponseType: Konfigurerar OIDC-hanteraren för att endast utföra auktoriseringskodflödet. Implicita bidrag och hybridflöden är onödiga i det här läget. OIDC-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims och konfiguration av NameClaimType och RoleClaimType: Många OIDC-servrar använder "name" och "role" i stället för SOAP/WS-Fed standardvärden i ClaimTypes. När MapInboundClaims är inställt på falseutför hanteraren inte anspråksmappningar och anspråksnamnen från JWT används direkt av appen. I följande exempel anges rollanspråkstypen till "roles", vilket är lämpligt för Microsoft Entra ID (ME-ID). Mer information finns i din identitetsproviders dokumentation.

Note

MapInboundClaims måste anges till false för de flesta OIDC-leverantörer, vilket förhindrar att anspråk byts namn.

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

Sökvägskonfiguration: Sökvägar måste matcha omdirigerings-URI:n (återanrop för inloggning) och omdirigering efter utloggning (återanrop efter utloggning) som konfigurerats när applikationen registreras hos OIDC-leverantören. I Azure-portalen konfigureras sökvägar på bladet Autentisering för appens registrering. Både inloggnings- och utloggningssökvägarna måste registreras som omdirigerings-URI:er. Standardvärdena är /signin-oidc och /signout-callback-oidc.

CallbackPath: Begärans sökväg inom appens basväg där användaragenten skickas tillbaka.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

En port krävs inte för localhost adresser när du använder Microsoft Entra-ID. De flesta andra OIDC-leverantörer kräver rätt port.

SignedOutCallbackPath (konfigurationsnyckel: "SignedOutCallbackPath"): Begärans sökväg inom appens bassökväg som fångas upp av OIDC-hanteraren där användaragenten först returneras efter utloggning från identitetsleverantören. Exempelappen anger inte något värde för sökvägen eftersom standardvärdet "/signout-callback-oidc" används. Efter att ha uppsnappat begäran omdirigerar OIDC-hanteraren till SignedOutRedirectUri eller RedirectUri, om detta anges.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

När du använder Microsoft Entra-ID anger du sökvägen i Webbplattformskonfigurationens omdirigerings-URI-poster i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port. Om du inte lägger till URI för den utloggade återanropsvägen i appens registrering i Entra, vägrar Entra att dirigera användaren tillbaka till appen och uppmanar dem istället att bara stänga webbläsarfönstret.

RemoteSignOutPath: Begäranden som tas emot på den här sökvägen gör att hanteraren anropar utloggning med hjälp av utloggningsschemat.

I följande exempel är platshållaren {PORT} appens port:

https://localhost/signout-oidc

Note

När du använder Microsoft Entra-ID anger du url:en för utloggning via Front-kanalen i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port.

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

Exempel (standardvärden):

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

(Endast Microsoft Azure med den "vanliga" slutpunkten) TokenValidationParameters.IssuerValidator: Många OIDC-leverantörer arbetar med standardutfärdarverifieraren, men vi måste ta hänsyn till utfärdaren som parameteriseras med klientorganisations-ID :t ({TENANT ID}) som returneras av https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Mer information finns i SecurityTokenInvalidIssuerException med OpenID Connect och Azure AD:s "common"-endpunkt (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Endast för appar som använder Microsoft Entra-ID eller Azure AD B2C med den "vanliga" slutpunkten:

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

För Microsoft Entra-ID eller Azure AD B2C kan du använda AddMicrosoftIdentityWebApp från Microsoft Identity Web (Microsoft.Identity.Web NuGet-paket, API-dokumentation), som lägger till både OIDC- och Cookie autentiseringshanterare med lämpliga standardvärden. Exempelappen och vägledningen i den här artikeln använder inte Microsoft Identity Web. Vägledningen visar hur du konfigurerar OIDC-hanteraren manuellt för alla OIDC-leverantörer. Mer information om hur du implementerar Microsoft Identity Web finns i Skydda en ASP.NET Core Blazor Web App med Microsoft Entra-ID.

Den här versionen av artikeln beskriver implementering av OIDC med mönstret Serverdel för klientdel (BFF). Om appens specifikation inte kräver att BFF-mönstret ska införas ändrar du artikelversionsväljaren till Icke-BFF-mönster (interaktiv automatisk återgivning) eller Icke-BFF-mönster (interaktiv server) (interaktiv serverrendering).

Prerequisites

.NET Aspire kräver Visual Studio version 17.10 eller senare.

Se även avsnittet Krav i Snabbstart: Skapa din första .NET Aspire app.

Exempellösning

Exempelappen består av följande projekt:

  • .NET Aspire:
    • Aspire.AppHost: Används för att hantera högnivåorkestreringsproblem för appen.
    • Aspire.ServiceDefaults: Innehåller standardkonfigurationer för .NET Aspire appar som kan utökas och anpassas efter behov.
  • MinimalApiJwt: Bakgrundswebb-API, som innehåller ett exempel på en minimal API-slutpunkt för väderdata.
  • BlazorWebAppOidc: Projektet på serversidan för Blazor Web App. Projektet använder YARP för att proxa förfrågningar till en slutpunkt för väderprognoser i serverdelswebb-API-projektet (MinimalApiJwt), med access_token lagrat i autentiseringen cookie.
  • BlazorWebAppOidc.Client: Klientsideprojektet för Blazor Web App.

Få åtkomst till exemplet i den senaste versionsmappen i Blazor-exemplarsamlingen med följande länk. Exemplet finns i BlazorWebAppOidcBff mappen för .NET 8 eller senare.

Visa eller ladda ned exempelkod (ladda ned)

Blazor Web App Använder autoåtergivningsläget med global interaktivitet.

Serverprojektet anropar AddAuthenticationStateSerialization för att lägga till en autentiseringsstatusleverantör på serversidan som använder PersistentComponentState för att överföra autentiseringsstatusen till klienten. Klienten anropar AddAuthenticationStateDeserialization för att deserialisera och använda autentiseringstillståndet som skickas av servern. Autentiseringstillståndet är fastställt under programlivslängden för WebAssembly-applikationen.

Klassen PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) är en serverside AuthenticationStateProvider som använder PersistentComponentState för att överföra autentiseringstillståndet till klienten, vilket sedan är fastställt för hela WebAssembly-applikationens livslängd.

Den här appen är en startpunkt för alla OIDC-autentiseringsflöden. OIDC konfigureras manuellt i appen och förlitar sig inte på Microsoft Entra-ID eller Microsoft-webbpaketIdentity, och exempelappen kräver inte heller Microsoft Azure-värdtjänster. Exempelappen kan dock användas med Entra, Microsoft Identity Web och hanteras i Azure.

Automatisk förnyelse av den interaktionsfria tokenen med hjälp av en anpassad cookie förnyare (CookieOidcRefresher.cs).

Mönstret Serverdel för klientdel (BFF) används .NET Aspire för tjänstidentifiering och YARP för proxybegäranden till en slutpunkt för väderprognoser i serverdelsappen.

Serverdelswebb-API:et (MinimalApiJwt) använder JWT-bärarautentisering för att verifiera JWT-tokens som sparats av Blazor Web App i samband med inloggning cookie.

Aspire förbättrar upplevelsen av att skapa .NET-molnbaserade appar. Det ger en konsekvent, åsiktsuppsättning med verktyg och mönster för att skapa och köra distribuerade appar.

YARP (Yet Another Reverse Proxy) är ett bibliotek som används för att skapa en omvänd proxyserver. MapForwarder i filen Program i serverprojektet läggs direkt vidarebefordran av HTTP-begäranden som matchar det angivna mönstret till ett specifikt mål med standardkonfigurationen för den utgående begäran, anpassade transformationer och standard-HTTP-klienten:

  • När komponenten Weather renderas på servern använder komponenten klassen ServerWeatherForecaster för att hantera begäran om väderdata med åtkomsttoken för användaren. IHttpContextAccessor.HttpContext avgör om en HttpContext är tillgänglig för användning av metoden GetWeatherForecastAsync. Mer information finns i ASP.NET Core-komponenterRazor.
  • När komponenten renderas på klienten, nyttjas implementeringen av ClientWeatherForecaster-tjänsten, som använder en förkonfigurerad HttpClient (i klientprojektets Program-fil) för att göra ett webb-API-anrop till serverprojektet. En minimal API-slutpunkt (/weather-forecast) som definierats i serverprojektets Program-fil transformerar begäran med användarens åtkomsttoken för att hämta väderdata.

För mer information om .NET Aspire finns i Allmän tillgänglighet för .NET Aspire: Förenkla .NET Cloud-Native-utveckling (maj, 2024).

Mer information om (webb)API-anrop med hjälp av en tjänstabstraktion i s finns i Blazor Web AppAnropa ett webb-API från en ASP.NET Core-appBlazor.

Appregistreringar för Microsoft Entra-ID

Vi rekommenderar att du använder separata registreringar för appar och webb-API:er, även när apparna och webb-API:erna finns i samma lösning. Följande vägledning gäller för appen och BlazorWebAppOidc webb-API:et för MinimalApiJwt exempellösningen, men samma vägledning gäller vanligtvis för alla Entra-baserade registreringar för appar och webb-API:er.

Registrera webb-API:et (MinimalApiJwt) först så att du sedan kan bevilja åtkomst till webb-API:et när du registrerar appen. Webb-API:ets hyresgäst-ID och klient-ID används för att konfigurera webb-API:et i filen Program. När du har registrerat webb-API:et exponerar du webb-API:et i Appregistreringar>Exponera ett API med omfångsnamnet Weather.Get. Registrera app-ID-URI:n för användning i appens konfiguration.

Registrera sedan appen (BlazorWebAppOidc/BlazorWebApOidc.Client) med en webbplattformskonfiguration och en omdirigerings-URIhttps://localhost/signin-oidc för (en port krävs inte). Appens tenant-ID och klient-ID, tillsammans med webb-API:ets basadress, app-ID-URI och väderscope-namn, används för att konfigurera appen i filen Program. Ge API-behörighet att komma åt webb-API:et iAPI-behörigheter för >. Om appens säkerhetsspecifikation anropar den kan du bevilja administratörsmedgivande för organisationen att få åtkomst till webb-API:et. Auktoriserade användare och grupper tilldelas till appens registrering i Appregistreringar>Företagsprogram.

Markera inte någon av kryssrutorna för att auktoriseringsslutpunkten ska returnera åtkomsttoken eller ID-token i appregistreringskonfigurationen för implicit beviljande och hybridflöden i Entra- eller Azure-portalen. OpenID Connect-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

Skapa en klienthemlighet i appens registrering i Entra- eller Azure-portalen (Hantera>certifikat och hemligheter>Ny klienthemlighet). Håll kvar på klienthemlighetsvärdet för användning i nästa avsnitt.

Ytterligare entra-konfigurationsvägledning för specifika inställningar finns senare i den här artikeln.

Upprätta klienthemligheten

Det här avsnittet gäller endast serverprojektet för Blazor Web App (BlazorWebAppOidc projektet).

Warning

Lagra inte apphemligheter, anslutningssträngar, autentiseringsuppgifter, lösenord, personliga ID-nummer (PIN),privat C#/.NET-kod eller privata nycklar/token i kod på klientsidan, vilket alltid är osäkert. I test-/mellanlagrings- och produktionsmiljöer bör Blazor kod på serversidan och webb-API:er använda säkra autentiseringsflöden som undviker att underhålla autentiseringsuppgifter i projektkod eller konfigurationsfiler. Förutom testning av lokal utveckling rekommenderar vi att du undviker användning av miljövariabler för att lagra känsliga data, eftersom miljövariabler inte är den säkraste metoden. För testning av lokal utveckling rekommenderas Secret Manager-verktyget för att skydda känsliga data. Mer information finns i Skyddat underhåll av känsliga data och autentiseringsuppgifter.

För testning av lokal utveckling använder du verktyget Secret Manager för att lagra Blazor serverprojektets klienthemlighet under konfigurationsnyckeln Authentication:Schemes:MicrosoftOidc:ClientSecret.

Serverprojektet Blazor har inte initierats för Secret Manager-verktyget. Använd ett kommandogränssnitt, till exempel PowerShell-kommandogränssnittet Developer i Visual Studio, för att köra följande kommando. Innan du kör kommandot ändrar du katalogen med kommandot cd till serverprojektets katalog. Kommandot upprättar en identifierare för användarhemligheter (<UserSecretsId> i serverappens projektfil):

dotnet user-secrets init

Kör följande kommando för att ange klienthemligheten. Platshållaren {SECRET} är klienthemligheten som hämtas från appens registrering:

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

Om du använder Visual Studio kan du bekräfta att hemligheten har angetts genom att högerklicka på serverprojektet i Solution Explorer och välja Hantera användarhemligheter.

.NET Aspire projekt

Mer information om hur du använder .NET Aspire och information om exempelappens .AppHost projekt och .ServiceDefaults finns i dokumentationen.NET Aspire.

Bekräfta att du har uppfyllt kraven för .NET Aspire. Mer information finns i avsnittet Krav i Snabbstart: Skapa din första .NET Aspire app.

Exempelappen konfigurerar endast en osäker HTTP-startprofil (http) för användning under utvecklingstestning. Mer information, inklusive ett exempel på profiler för osäkra och säkra startinställningar, finns i Tillåt osäker transport i .NET Aspire (.NET Aspire dokumentation).

MinimalApiJwt projekt

MinimalApiJwt-projektet är ett bakände-webb-API för flera frontend-projekt. Projektet konfigurerar en minimal API-slutpunkt för väderdata. Begäranden från Blazor Web App projekt på serversidan (BlazorWebAppOidc) skickas till MinimalApiJwt projektet.

Den MinimalApiJwt.http filen kan användas för att testa väderdatabegäran. Observera att MinimalApiJwt projektet måste köras för att testa slutpunkten och att slutpunkten är hårdkodad i filen. Mer information finns i Använda .http-filer i Visual Studio 2022.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument.

Projektet innehåller paket och konfiguration för att skapa OpenAPI-dokument och Swagger-användargränssnittet i utvecklingsmiljön. Mer information finns i Använda de genererade OpenAPI-dokumenten.

En dataslutpunkt för säker väderprognos finns i projektets Program fil:

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

Utökningsmetoden RequireAuthorization kräver auktorisering för routedefinitionen. För alla kontrollanter som du lägger till i projektet lägger du till [Authorize] attributet till kontrollanten eller åtgärden.

Konfigurera projektet i JwtBearerOptions av AddJwtBearer-anropet i projektets Program-fil.

Anger Authority auktoriteten för att göra OIDC-anrop. Vi rekommenderar att du använder en separat appregistrering för MinimalApiJwt projektet. Myndigheten matchar utfärdaren (iss) av JWT som returneras av identitetsleverantören.

jwtOptions.Authority = "{AUTHORITY}";

Formatet på auktoriteten beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett klient-ID för aaaabbbb-0000-cccc-1111-dddd2222eeee.

ME-ID exempel på hyresgästmyndighet:

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

Exempel på AAD B2C-klientorganisation:

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

Anger Audience målgruppen för en mottagen OIDC-token.

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

Note

När du använder Microsoft Entra-ID matchar du bara värdet till sökvägen till program-ID-URI:n som konfigurerats när du lägger till omfång Weather.Get under Exponera ett API i Entra- eller Azure-portalen. Ta inte med omfångsnamnet "Weather.Get" i värdet.

Målgruppens format beror på vilken typ av hyresgäst som används. I följande exempel för Microsoft Entra ID används ett tenant-ID för contoso och ett klient-ID för 11112222-bbbb-3333-cccc-4444dddd5555.

ME-ID exempel på hyresgästs app-ID-URI:

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

Exempel på AAD B2C klientorganisations app-ID-URI:

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

Blazor Web App projekt på serversidan (BlazorWebAppOidc)

I det här avsnittet beskrivs hur du konfigurerar projektet på serversidan Blazor .

Följande OpenIdConnectOptions konfiguration finns i projektets Program fil vid anropet till AddOpenIdConnect.

PushedAuthorizationBehavior: Kontrollerar stödet för Pushed Authorization Requests (PAR). Som standard är inställningen att använda PAR om identitetsproviderns identifieringsdokument (som vanligtvis finns på .well-known/openid-configuration) annonserar stöd för PAR. Om du vill kräva PAR-stöd för appen kan du tilldela värdet PushedAuthorizationBehavior.Require. PAR stöds inte av Microsoft Entra och det finns inga planer på att Entra någonsin ska stödja det i framtiden.

oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.UseIfAvailable;

SignInScheme: Anger det autentiseringsschema som motsvarar mellanprogrammet som ansvarar för att bevara användarens identitet efter en lyckad autentisering. OIDC-hanteraren måste använda ett inloggningsschema som kan bevara användarautentiseringsuppgifter mellan begäranden. Följande rad finns bara i demonstrationssyfte. Om det utelämnas används DefaultSignInScheme som ett återställningsvärde.

oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

Omfång för openid och profile (Scope) (valfritt): Omfången openid och profile konfigureras också som standard eftersom de krävs för att OIDC-hanteraren ska fungera, men dessa kan behöva läggas till igen om omfången ingår i Authentication:Schemes:MicrosoftOidc:Scope konfigurationen. Allmän konfigurationsvägledning finns i Konfiguration i ASP.NET Core- och ASP.NET Core-konfigurationBlazor.

oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);

SaveTokens: Definierar om åtkomst- och uppdateringstoken ska lagras i AuthenticationProperties efter en lyckad auktorisering. Värdet är inställt på true för att autentisera begäranden om väderdata från serverdelswebb-API-projektet (MinimalApiJwt).

oidcOptions.SaveTokens = true;

Omfång för offlineåtkomst (Scope): Omfånget offline_access krävs för uppdateringstoken.

oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);

Omfång för att hämta väderdata från webb-API:et (Scope): Konfigurera omfånget Weather.Get för åtkomst till det externa webb-API:et för väderdata. I följande exempel så finns platshållaren {APP ID URI} i Entra- eller Azure-portalen där webb-API:et exponeras. För alla andra identitetsleverantörer, använd lämpligt omfång.

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

Omfångets format beror på vilken typ av klientorganisation som används. I följande exempel är vistelsetdomän contoso.onmicrosoft.com, och klient-ID 11112222-bbbb-3333-cccc-4444dddd5555.

ME-ID exempel på hyresgästs app-ID-URI:

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

Exempel på AAD B2C klientorganisations app-ID-URI:

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

Authority och ClientId: Anger utfärdare och klient-ID för OIDC-anrop.

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

I följande exempel används ett klient-ID aaaabbbb-0000-cccc-1111-dddd2222eeee för och ett klient-ID för 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";

För flertenantappar bör den "vanliga" auktoriteten användas. Du kan också använda den "vanliga" myndigheten för appar med en enda klientorganisation, men en anpassad IssuerValidator krävs, vilket visas senare i det här avsnittet.

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

ResponseType: Konfigurerar OIDC-hanteraren för att endast utföra auktoriseringskodflödet. Implicita bidrag och hybridflöden är onödiga i det här läget. OIDC-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

oidcOptions.ResponseType = OpenIdConnectResponseType.Code;

MapInboundClaims och konfiguration av NameClaimType och RoleClaimType: Många OIDC-servrar använder "name" och "role" i stället för SOAP/WS-Fed standardvärden i ClaimTypes. När MapInboundClaims är inställt på falseutför hanteraren inte anspråksmappningar och anspråksnamnen från JWT används direkt av appen. I följande exempel anges rollanspråkstypen till "roles", vilket är lämpligt för Microsoft Entra ID (ME-ID). Mer information finns i din identitetsproviders dokumentation.

Note

MapInboundClaims måste anges till false för de flesta OIDC-leverantörer, vilket förhindrar att anspråk byts namn.

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

Sökvägskonfiguration: Sökvägar måste matcha omdirigerings-URI:n (återanrop för inloggning) och omdirigering efter utloggning (återanrop efter utloggning) som konfigurerats när applikationen registreras hos OIDC-leverantören. I Azure-portalen konfigureras sökvägar på bladet Autentisering för appens registrering. Både inloggnings- och utloggningssökvägarna måste registreras som omdirigerings-URI:er. Standardvärdena är /signin-oidc och /signout-callback-oidc.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

En port krävs inte för localhost adresser när du använder Microsoft Entra-ID. De flesta andra OIDC-leverantörer kräver rätt port.

SignedOutCallbackPath (konfigurationsnyckel: "SignedOutCallbackPath"): Begärans sökväg inom appens bassökväg som fångas upp av OIDC-hanteraren där användaragenten först returneras efter utloggning från identitetsleverantören. Exempelappen anger inte något värde för sökvägen eftersom standardvärdet "/signout-callback-oidc" används. Efter att ha uppsnappat begäran omdirigerar OIDC-hanteraren till SignedOutRedirectUri eller RedirectUri, om detta anges.

Konfigurera återkopplingssökvägen efter utloggning i appens OIDC-leverantörsregistrering. I följande exempel är platshållaren {PORT} appens port:

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

Note

När du använder Microsoft Entra-ID anger du sökvägen i Webbplattformskonfigurationens omdirigerings-URI-poster i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port. Om du inte lägger till URI för den utloggade återanropsvägen i appens registrering i Entra, vägrar Entra att dirigera användaren tillbaka till appen och uppmanar dem istället att bara stänga webbläsarfönstret.

RemoteSignOutPath: Begäranden som tas emot på den här sökvägen gör att hanteraren anropar utloggning med hjälp av utloggningsschemat.

I följande exempel är platshållaren {PORT} appens port:

https://localhost/signout-oidc

Note

När du använder Microsoft Entra-ID anger du url:en för utloggning via Front-kanalen i Entra- eller Azure-portalen. En port krävs inte för localhost adresser när du använder Entra. De flesta andra OIDC-leverantörer kräver rätt port.

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

Exempel (standardvärden):

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

(Endast Microsoft Azure med den "vanliga" slutpunkten) TokenValidationParameters.IssuerValidator: Många OIDC-leverantörer arbetar med standardutfärdarverifieraren, men vi måste ta hänsyn till utfärdaren som parameteriseras med klientorganisations-ID :t ({TENANT ID}) som returneras av https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Mer information finns i SecurityTokenInvalidIssuerException med OpenID Connect och Azure AD:s "common"-endpunkt (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Endast för appar som använder Microsoft Entra-ID eller Azure AD B2C med den "vanliga" slutpunkten:

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

Klientsidesprojekt Blazor Web App (BlazorWebAppOidc.Client)

Detta BlazorWebAppOidc.Client projektet är klientsideprojektet för Blazor Web App.

Klienten anropar AddAuthenticationStateDeserialization för att deserialisera och använda autentiseringstillståndet som skickas av servern. Autentiseringstillståndet är fastställt under programlivslängden för WebAssembly-applikationen.

Klassen PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) är en AuthenticationStateProvider på klientsidan som avgör användarens autentiseringstillstånd genom att söka efter data som sparats på sidan när den återges på servern. Autentiseringstillståndet är fastställt under programlivslängden för WebAssembly-applikationen.

Om användaren behöver logga in eller ut, krävs det en fullständig omladdning av sidan.

Exempelappen innehåller endast ett användarnamn och e-postmeddelande i visningssyfte.

Serialisera endast namn- och rollanspråken

Det här avsnittet gäller endast för icke-BFF-mönster (Interactive Auto) och BFF-mönster (Interactive Auto) samt deras exempelappar.

Program I filen serialiseras alla anspråk genom att ange SerializeAllClaims till true. Om du bara vill att namn- och rollanspråken ska serialiseras för CSR tar du bort alternativet eller anger det till false.

Ange konfiguration med JSON-konfigurationsprovidern (appinställningar)

Exempellösningsprojekten konfigurerar OIDC- och JWT-ägarautentisering i sina Program filer för att göra konfigurationsinställningarna identifierbara med C#-automatisk komplettering. Professionella appar använder vanligtvis en konfigurationsprovider för att konfigurera OIDC-alternativ, till exempel JSON-standardkonfigurationsprovidern. JSON-konfigurationsprovidern läser in konfigurationen från appinställningarsfiler appsettings.json/appsettings.{ENVIRONMENT}.json, där {ENVIRONMENT} platshållaren är appens körningsmiljö. Följ anvisningarna i det här avsnittet om du vill använda appinställningar för konfiguration.

Lägg till följande JSON-konfiguration i appens inställningsfil (appsettings.json) för BlazorWebAppOidc projektet eller BlazorWebAppOidcServer :

"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"
      ]
    }
  }
},

Uppdatera platshållarna i föregående konfiguration så att de matchar de värden som appen använder i Program filen:

  • {TENANT ID (BLAZOR APP)}: Tenant-ID för Blazor-appen.
  • {CLIENT ID (BLAZOR APP)}: Klient-ID för Blazor-appen.
  • {APP ID URI (WEB API)}: App-ID-URI:n för webb-API:et.

Den "vanliga" autentiseringsmyndigheten (https://login.microsoftonline.com/common/v2.0/) bör användas för appar med flera hyresgäster. För att använda den "vanliga" utfärdaren för applikationer med en enda klientorganisation, se avsnittet Använd den "vanliga" utfärdaren för applikationer med en enda klientorganisation.

Uppdatera andra värden i föregående konfiguration så att de matchar anpassade/icke-standardvärden som används i Program filen.

Konfigurationen hämtas automatiskt av autentiseringsverktyget.

Ta bort följande rader från Program filen:

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

ConfigureCookieOidc I metoden för CookieOidcServiceCollectionExtensions.cstar du bort följande rad:

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

MinimalApiJwt I projektet lägger du till följande konfiguration av appinställningar i appsettings.json filen:

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

Uppdatera platshållarna i föregående konfiguration så att de matchar de värden som appen använder i Program filen:

  • {TENANT ID (WEB API)}: Hyresgästens ID för webb-API:et.
  • {APP ID URI (WEB API)}: App-ID-URI:n för webb-API:et.

Myndighetsformat använder följande mönster:

  • ME-ID klienttyp: https://sts.windows.net/{TENANT ID}/
  • B2C-klienttyp: https://login.microsoftonline.com/{TENANT ID}/v2.0/

Målgruppsformat använder följande mönster ({CLIENT ID} är klient-ID:t för webb-API:et, {DIRECTORY NAME} är katalognamnet, till exempel contoso):

  • ME-ID klienttyp: api://{CLIENT ID}
  • B2C-klienttyp: https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}

Konfigurationen hämtas automatiskt av JWT-ägarautentiseringsverktyget.

Ta bort följande rader från Program filen:

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

Mer information om konfiguration finns i följande resurser:

Använd den "gemensamma" auktoriteten för appar med en enda hyresgäst

Du kan använda den "vanliga" auktoriteten för appar med en enda klientorganisation, men du måste vidta följande steg för att implementera en anpassad utfärdarvaliderare.

Microsoft.IdentityModel.Validators Lägg till NuGet-paketet i BlazorWebAppOidcprojektet , BlazorWebAppOidcServereller BlazorWebAppOidcBff .

Note

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

Överst i Program-filen, gör namnområdet Microsoft.IdentityModel.Validators tillgängligt.

using Microsoft.IdentityModel.Validators;

Använd följande kod i Program filen där OIDC-alternativ har konfigurerats:

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

Mer information finns i SecurityTokenInvalidIssuerException med OpenID Connect och Azure AD:s "common"-endpunkt (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

Omdirigera till startsidan vid utloggning

Komponenten LogInOrOut (Layout/LogInOrOut.razor) anger ett dolt fält för retur-URL:en (ReturnUrl) till den aktuella URL:en (currentURL). När användaren loggar ut från appen returnerar identitetsprovidern användaren till sidan som de loggade ut från. Om användaren loggar ut från en säker sida returneras de till samma säkra sida och skickas tillbaka via autentiseringsprocessen. Det här autentiseringsflödet är rimligt när användarna behöver ändra konton regelbundet.

Du kan också använda följande LogInOrOut komponent, som inte anger någon retur-URL när du loggar ut.

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>

Tokenuppdatering

Implementationen av den anpassade cookie uppdateraren (CookieOidcRefresher.cs) uppdaterar användarens uppgifter automatiskt när de upphör att gälla. Den aktuella implementeringen förväntar sig att ta emot en ID-token från tokenslutpunkten i utbyte mot uppdateringstoken. Anspråken i denna ID-token används sedan för att skriva över användarens anspråk.

Exempelimplementeringen innehåller inte kod för att begära anspråk från UserInfo-slutpunkten vid tokenuppdatering. Mer information finns i BlazorWebAppOidc AddOpenIdConnect with GetClaimsFromUserInfoEndpoint = true doesn't propogate [sic] role claims to client (dotnet/aspnetcore #58826).

Note

Vissa identitetsprovidrar returnerar bara en åtkomsttoken när du använder en uppdateringstoken. CookieOidcRefresher kan uppdateras med ytterligare logik för att fortsätta att använda den tidigare uppsättningen anspråk som lagras i autentiseringen cookie eller använda åtkomsttoken för att begära anspråk från UserInfo-slutpunkten.

Kryptografisk nonce

En nonce är ett strängvärde som associerar en klients session med en ID-token för att minimera reprisattacker.

Om du får ett nonce-fel under utveckling och testning av autentisering, använd en ny privat- eller inkognito-webbläsarsession för varje testkörning, oavsett hur liten ändringen i appen eller testanvändaren är, eftersom inaktuell cookie-data kan leda till ett nonce-fel. Mer information finns i avsnittet Cookies och webbplatsdata .

Nonce krävs inte eller används inte när en refresh-token utbyts mot en ny åtkomsttoken. I exempelappen anger CookieOidcRefresher (CookieOidcRefresher.cs) avsiktligt OpenIdConnectProtocolValidator.RequireNonce till false.

Programroller för appar som inte har registrerats med Microsoft Entra (ME-ID)

Det här avsnittet gäller appar som inte använder Microsoft Entra-ID (ME-ID) som identitetsprovider. Appar som registrerats med ME-ID finns i avsnittet Programroller för appar som registrerats med Microsoft Entra (ME-ID).

Konfigurera rollanspråkstypen (TokenValidationParameters.RoleClaimType) i OpenIdConnectOptions för Program.cs:

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

För många OIDC-identitetsleverantörer är rollanspråkstypen role. Kontrollera identitetsleverantörens dokumentation för rätt värde.

Ersätt klassen UserInfo i BlazorWebAppOidc.Client-projektet med följande klass.

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

I det här läget Razor kan komponenter anta rollbaserad och principbaserad auktorisering. Programroller visas i role-krav, ett anspråk per roll.

Programroller för appar som registrerats med Microsoft Entra (ME-ID)

Använd vägledningen i det här avsnittet för att implementera programroller, ME-ID säkerhetsgrupper och ME-ID inbyggda administratörsroller för appar som använder Microsoft Entra ID (ME-ID).

Metoden som beskrivs i det här avsnittet konfigurerar ME-ID att skicka grupper och roller i autentiseringshuvudet cookie. När användare bara är medlemmar i ett fåtal säkerhetsgrupper och roller bör följande metod fungera för de flesta värdplattformar utan att stöta på ett problem där rubriker är för långa, till exempel med IIS-värd som har en standardgräns för sidhuvudlängd på 16 KB (MaxRequestBytes). Om rubriklängden är ett problem på grund av hög grupp- eller rollmedlemskap rekommenderar vi att du inte följer riktlinjerna i det här avsnittet för att implementera Microsoft Graph för att hämta en användares grupper och roller från ME-ID separat, en metod som inte blåser upp storleken på autentiseringen cookie. Mer information finns i Felaktig begäran – Begäran för lång – IIS Server (dotnet/aspnetcore #57545).

Konfigurera rollanspråkstypen (TokenValidationParameters.RoleClaimType) i OpenIdConnectOptions för Program.cs. Ange värdet till roles:

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Även om du inte kan tilldela roller till grupper utan ett ME-ID Premium-konto kan du tilldela roller till användare och ta emot rollanspråk för användare med ett Standard Azure-konto. Vägledningen i det här avsnittet kräver inte ett ME-ID Premium-konto.

När du arbetar med standardkatalogen följer du riktlinjerna i Lägg till approller i ditt program och få dem i tokenen (ME-ID dokumentation) för att konfigurera och tilldela roller. Om du inte arbetar med standardkatalogen redigerar du appens manifest i Azure-portalen för att upprätta appens roller manuellt i appRoles posten för manifestfilen. Mer information finns i Konfigurera rollanspråket (ME-ID dokumentation).

En användares Azure-säkerhetsgrupper hanteras i groups anspråk, och en användares inbyggda ME-ID tilldelningar av administratörsroller hanteras i välkända ID-anspråk (wids). Värden för båda anspråkstyperna är GUID:er. När de tas emot av appen kan dessa anspråk användas för att upprätta roll- och principauktorisering i Razor komponenter.

I appens manifest i Azure-portalen anger du groupMembershipClaims attributet till All. Värdet All resulterar i att ME-ID skickar alla säkerhets-/distributionsgrupper (groups anspråk) och roller (wids anspråk) för den inloggade användaren. Så här anger du attributet groupMembershipClaims:

  1. Öppna appens registrering i Azure-portalen.
  2. Välj Hantera>Manifest i sidofältet.
  3. Leta upp attributet groupMembershipClaims.
  4. Ange värdet till All ("groupMembershipClaims": "All").
  5. Välj knappen Spara .

Ersätt klassen UserInfo i BlazorWebAppOidc.Client-projektet med följande klass.

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

I det här läget Razor kan komponenter anta rollbaserad och principbaserad auktorisering:

  • Programroller visas i roles-krav, ett anspråk per roll.
  • Säkerhetsgrupper visas i groups krav, ett krav per grupp. Säkerhetsgruppens GUID visas i Azure-portalen när du skapar en säkerhetsgrupp och listas när du väljer Identity>Översikt>Grupper>Visa.
  • Inbyggda ME-ID administratörsroller uttrycks i wids krav, ett krav per roll. Anspråket wids med värdet b79fbf4d-3ef9-4689-8143-76b194e85509 skickas alltid av ME-ID för konton som inte är gästkonton hos hyresgästen och refererar inte till någon administratörsroll. GUID:er för administratörsroller (rollmalls-ID:n) visas i Azure-portalen när du väljer Roller och administratörer, följt av ellipsen (...) >Beskrivning för den angivna rollen. Rollmall-ID:er visas också i de inbyggda Microsoft Entra-rollerna (Entra-dokumentation) .

Alternativ: Hantering av Duende-åtkomsttoken

I exempelappen används en anpassad cookie uppdateringsimplementering (CookieOidcRefresher.cs) för att utföra automatisk icke-interaktiv tokenuppdatering. En alternativ lösning finns i paketet med öppen källkodDuende.AccessTokenManagement.OpenIdConnect.

Duende Access Token Management tillhandahåller funktioner för automatisk hantering av åtkomsttoken för .NET Worker och ASP.NET Core-webbappar, inklusive Blazor, utan att behöva lägga till en anpassad cookie uppdatering.

När paketet har installerats tar du bort CookieOidcRefresher och lägger till åtkomsttokenhantering för den inloggade användaren i Program filen:

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

Den inskrivna HTTP-klienten (eller med namnet HTTP-klient, om den implementeras) har automatisk åtkomsttokens livslängdshantering för den inloggade användarens räkning, inklusive hantering av transparent uppdateringstoken.

Mer information finns i dokumentationen för Hantering av Duende-åtkomsttoken för Blazor.

Troubleshoot

Logging

Serverappen är en standardapp för ASP.NET Core. Se vägledningen för ASP.NET Core-loggning för att aktivera en lägre loggningsnivå i serverappen.

Information om hur du aktiverar felsökning eller spårningsloggning för Blazor WebAssembly autentisering finns i avsnittet autentiseringsloggning på klientsidani ASP.NET Core-loggning Blazor med artikelversionsväljaren inställd på ASP.NET Core i .NET 7 eller senare.

Vanliga fel

  • Debuggern avbryter på ett undantag under utloggning med Microsoft Entra External ID

    Följande undantag stoppar Visual Studio-felsökningsprogrammet vid utloggning med Microsoft Entra Externt ID:

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

    Felsökaren i Visual Studio bryter mot JavaScript-undantag under utloggning

    Undantaget genereras från Entra JavaScript-kod, så det här är inget problem med ASP.NET Core. Undantaget påverkar inte appfunktionerna i produktion, så undantaget kan ignoreras vid testning av lokal utveckling.

  • Felkonfiguration av appen eller Identity-leverantören (IP)

    De vanligaste felen orsakas av felaktig konfiguration. Följande är några exempel:

    • Beroende på kraven i scenariot förhindrar en saknad eller felaktig utfärdare, instans, klient-ID, klientdomän, klient-ID eller omdirigerings-URI en app från att autentisera klienter.
    • Felaktiga omfång för begäran hindrar klienter från att komma åt serverwebb-API-slutpunkter.
    • Felaktiga eller saknade server-API-behörigheter hindrar klienter från att komma åt serverwebb-API-slutpunkter.
    • Köra appen på en annan port än vad som har konfigurerats i omdirigerings-URI:n för IP-adressens appregistrering. Observera att en port inte krävs för Microsoft Entra-ID och en app som körs på en localhost utvecklingstestningsadress, men appens portkonfiguration och porten där appen körs måste matcha för icke-localhost adresser.

    Den här artikeln täcker exempel på korrekt konfiguration. Kontrollera noggrant konfigurationen för att hitta felkonfigurationer av appar och IP-adresser.

    Om konfigurationen verkar vara korrekt:

    • Analysera applikationsloggar.

    • Granska nätverkstrafiken mellan klientappen och IP- eller serverappen med webbläsarens utvecklarverktyg. Ofta returneras ett exakt felmeddelande eller ett meddelande med en ledtråd till vad som orsakar problemet till klienten av IP- eller serverappen efter en begäran. Vägledning för utvecklarverktyg finns i följande artiklar:

    Dokumentationsteamet svarar på feedback om dokument och buggar i artiklar (öppna ett problem från avsnittet Feedback på den här sidan ) men kan inte tillhandahålla produktsupport. Det finns flera offentliga supportforum som hjälper dig att felsöka en app. Vi rekommenderar följande:

    Föregående forum ägs eller kontrolleras inte av Microsoft.

    Skapa ett ärende med ASP.NET Core-produktgruppen för rapporter om reproducerbara ramverksfel som inte är säkerhetsrelaterade, känsliga eller konfidentiella. Öppna inte ett ärende med produktgruppen förrän du noggrant har undersökt orsaken till problemet och inte kan lösa det på egen hand eller med hjälp av communityn på ett offentligt supportforum. Produktenheten kan inte felsöka enskilda appar som har brutits på grund av enkel felkonfiguration eller användningsfall som rör tjänster från tredje part. Om en rapport är känslig eller konfidentiell eller beskriver en potentiell säkerhetsbrist i produkten som cyberattacker kan utnyttja kan du läsa Rapportera säkerhetsproblem och buggar (dotnet/aspnetcore GitHub-lagringsplats).

  • Obehörig klient för ME-ID

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] Auktoriseringen misslyckades. Dessa krav uppfylldes inte: DenyAnonymousAuthorizationRequirement: Kräver en autentiserad användare.

    Återanropsfel vid inloggning från ME-ID:

    • Fel: unauthorized_client
    • Beskrivning: AADB2C90058: The provided application is not configured to allow public clients.

    Så här löser du felet:

    1. Gå till appens manifest i Azure-portalen.
    2. Ställ in attributetallowPublicClient till null eller true.

Cookies och webbplatsdata

Cookies och webbplatsdata kan sparas mellan appuppdateringar och störa testning och felsökning. Rensa följande när du gör ändringar i appkoden, ändringar av användarkonton med providern eller konfigurationsändringar för providerappen:

  • Cookies för användarinloggning
  • Appcookies
  • Cachelagrade och lagrade webbplatsdata

En metod för att förhindra kvardröjande cookies och webbplatsdata från att störa testning och felsökning är att:

  • Konfigurera en webbläsare
    • Använd en webbläsare för testning som du kan konfigurera för att ta bort alla cookie och platsdata varje gång webbläsaren stängs.
    • Kontrollera att webbläsaren stängs manuellt eller av IDE för ändringar i appen, testanvändaren eller providerkonfigurationen.
  • Använd ett anpassat kommando för att öppna en webbläsare i InPrivate- eller Incognito-läge i Visual Studio:
    • Öppna dialogrutan Bläddra med från knappen Kör i Visual Studio.
    • Välj knappen Lägg till .
    • Ange sökvägen till webbläsaren i fältet Program . Följande sökvägar för körbara filer är typiska installationsplatser för Windows 10. Om webbläsaren är installerad på en annan plats eller om du inte använder Windows 10 anger du sökvägen till webbläsarens körbara fil.
      • 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
    • I fältet Argument anger du det kommandoradsalternativ som webbläsaren använder för att öppna i InPrivate- eller Incognito-läge. Vissa webbläsare kräver appens URL.
      • Microsoft Edge: Använd -inprivate.
      • Google Chrome: Använd --incognito --new-window {URL}, där platshållaren för {URL} är url:en som ska öppnas (till exempel https://localhost:5001).
      • Mozilla Firefox: Använd -private -url {URL}, där platshållaren {URL} är url:en som ska öppnas (till exempel https://localhost:5001).
    • Ange ett namn i fältet Eget namn . Till exempel Firefox Auth Testing.
    • Välj knappen OK .
    • Om du vill undvika att behöva välja webbläsarprofilen för varje iteration av testning med en app anger du profilen som standard med knappen Ange som standard .
    • Kontrollera att webbläsaren är stängd av IDE för alla ändringar i appen, testanvändaren eller providerkonfigurationen.

Appuppgraderingar

En fungerande app kan misslyckas omedelbart efter att ha uppgraderat .NET SDK på utvecklingsdatorn eller ändrat paketversioner i appen. I vissa fall kan osammanhängande paket skada en app vid genomförande av större uppgraderingar. De flesta av dessa problem kan åtgärdas genom att följa dessa instruktioner:

  1. Rensa det lokala systemets NuGet-paketcacheminnen genom att köra dotnet nuget locals all --clear från ett kommandogränssnitt.
  2. Ta bort projektets mappar bin och obj.
  3. Återställa och återskapa projektet.
  4. Ta bort alla filer i distributionsmappen på servern innan du distribuerar om appen.

Note

Användning av paketversioner som inte är kompatibla med appens målramverk stöds inte. Information om ett paket finns i NuGet-galleriet.

Starta lösningen från rätt projekt

Blazor Web Apps:

  • För ett av BFF-mönsterexemplen (Backend-for-Frontend) startar du lösningen från Aspire/Aspire.AppHost projektet.
  • Starta lösningen från serverprojektet för ett av de icke-BFF-mönsterexemplen.

Blazor Server:

Starta lösningen från serverprojektet.

Inspektera användaren

Följande UserClaims komponent kan användas direkt i appar eller fungera som grund för ytterligare anpassning.

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

Ytterligare resurser