Dela via


Skydda en ASP.NET Core Blazor Web App med Microsoft Entra ID

I den här artikeln beskrivs hur du skyddar en Blazor Web App med Microsofts identitetsplattform/Microsoft Identity-webbpaket för Microsoft Entra-ID med hjälp av en exempelapp.

Följande specifikation omfattas:

  • Blazor Web App använder automatiskt återgivningsläge med global interaktivitet (InteractiveAuto).
  • Serverprojektet anropar AddAuthenticationStateSerialization för att lägga till en leverantör av autentiseringstillstånd på serversidan som använder sig av PersistentComponentState för att strömma autentiseringstillståndet till klienten. Klienten anropar AddAuthenticationStateDeserialization för att deserialisera och använda autentiseringstillståndet som skickas av servern. Autentiseringstillståndet förblir konstant under hela livslängden för WebAssembly-applikationen.
  • Appen använder Microsoft Entra-ID, baserat på Microsoft Identity Web-paket.
  • Automatisk uppdatering av icke-interaktiva token hanteras av ramverket.
  • Appen använder abstraktioner på serversidan och klientsidan för att visa genererade väderdata:
    • När komponenten Weather återges på servern för att visa väderdata, använder den komponenten ServerWeatherForecaster på servern för att direkt hämta väderdata (inte genom ett anrop via webb-API).
    • När komponenten Weather renderas på klienten använder komponenten implementeringen av ClientWeatherForecaster-tjänsten, som använder en förkonfigurerad HttpClient (i klientprojektets Program-fil) för att göra ett anrop till serverprojektets minimala API (/weather-forecast) för att hämta väderdata. Den minimala API-slutpunkten hämtar väderdata från klassen ServerWeatherForecaster och returnerar dem till klienten för återgivning av komponenten.

Exempelapp

Exempelappen består av två projekt:

  • BlazorWebAppEntra: Projekt på serversidan för Blazor Web App, som innehåller ett exempel på en Minimal API--endpoint för väderinformation.
  • BlazorWebAppEntra.Client: Projektet på klientsidan för Blazor Web App.

Få åtkomst till exempelappar via den senaste versionsmappen från lagringsplatsens rot med följande länk. Projekten finns i mappen BlazorWebAppEntra för .NET 9 eller senare.

Visa eller ladda ned exempelkod (hur du laddar ned)

Blazor Web App projekt på serversidan (BlazorWebAppEntra)

BlazorWebAppEntra-projektet är projektet på serversidan för Blazor Web App.

Den BlazorWebAppEntra.http filen kan användas för att testa väderdatabegäran. Observera att BlazorWebAppEntra 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.

Projekt på klientsidan Blazor Web App (BlazorWebAppEntra.Client)

Det BlazorWebAppEntra.Client projektet är projektet på klientsidan för Blazor Web App.

Om användaren behöver logga in eller ut vid rendering på klientsidan initieras en fullständig sidinläsning.

Konfiguration

I det här avsnittet beskrivs hur du konfigurerar exempelappen.

AddMicrosoftIdentityWebApp från Microsoft Identity Web (Microsoft.Identity.Web NuGet-paket, API-dokumentation) konfigureras av AzureAd-avsnittet i serverprojektets appsettings.json-fil.

I registreringen av appen i Entra- eller Azure-portalen använder du en Web-plattformskonfiguration med en omdirigerings-URIhttps://localhost/signin-oidc (utan att en port krävs). Bekräfta att ID-token och åtkomsttoken under Implicit beviljande och hybridflöden inte är valda. OpenID Connect-hanteraren begär automatiskt lämpliga token med hjälp av koden som returneras från auktoriseringsslutpunkten.

Konfigurera appen

I serverprojektets appinställningsfil (appsettings.json) anger du appens AzureAd avsnittskonfiguration. Hämta program-ID:t (klient-), klientdomänen (utgivaren) och katalog-ID:t (klient) från appens registrering i Entra- eller Azure-portalen:

"AzureAd": {
  "CallbackPath": "/signin-oidc",
  "ClientId": "{CLIENT ID}",
  "Domain": "{DOMAIN}",
  "Instance": "https://login.microsoftonline.com/",
  "ResponseType": "code",
  "TenantId": "{TENANT ID}"
},

Platshållare i föregående exempel:

  • {CLIENT ID}: Programmets (klient)-ID.
  • {DOMAIN}: Hyresgästdomän (utgivaren).
  • {TENANT ID}: Katalog-ID (hyresgäst).

Exempel:

"AzureAd": {
  "CallbackPath": "/signin-oidc",
  "ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "Domain": "contoso.onmicrosoft.com",
  "Instance": "https://login.microsoftonline.com/",
  "ResponseType": "code",
  "TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
},

Återanropssökvägen (CallbackPath) måste matcha den omdirigerings-URI (sökväg för återanrop för inloggning) som konfigurerades vid registreringen av programmet i Entra- eller Azure-portalen. Sökvägar konfigureras på bladet autentisering i appens registrering. Standardvärdet för CallbackPath är /signin-oidc för en registrerad omdirigerings-URI för https://localhost/signin-oidc (en port krävs inte).

SignedOutCallbackPath (konfigurationsnyckel: "SignedOutCallbackPath") är sökvägen för begäran i appens bassökväg som fångas upp av OpenID Connect-hanteraren där användaragenten först returneras efter utloggning från Entra. Exempelappen anger inte något värde för sökvägen eftersom standardvärdet "/signout-callback-oidc" används. Efter att ha avlyssnat begäran omdirigerar OpenID Connect-hanteraren till SignedOutRedirectUri eller RedirectUri, om det är angivet.

Konfigurera den utloggade motringningssökvägen i appens Entra-registrering. I Entra- eller Azure-portalen anger du sökvägen i Web-plattformskonfigurationens omdirigerings-URI poster:

https://localhost/signout-callback-oidc

Obs

En port krävs inte för localhost adresser när du använder Entra.

Om du inte lägger till URI:n för den utloggade motringningssökvägen i appens registrering i Entra vägrar Entra att omdirigera användaren tillbaka till appen och ber dem bara att stänga webbläsarfönstret.

Not

Entra omdirigerar inte en primär administratörsanvändare (rotkonto) eller extern användare tillbaka till Blazor-programmet. I stället loggar Entra ut användaren från appen och rekommenderar att de stänger alla webbläsarfönster. Mer information finns i postLogoutRedirectUri fungerar inte när utfärdar-URL:en innehåller ett klient-ID (AzureAD/microsoft-authentication-library-for-js #5783).

Varning

Lagra inte apphemligheter, anslutningssträngar, autentiseringsuppgifter, lösenord, personliga identifieringsnummer (PIN),privat C#/.NET-kod eller privata nycklar/token i kod på klientsidan, vilket är alltid osäker. 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 verktyget Secret Manager för att skydda känsliga data. Mer information finns i På ett säkert sätt underhålla känsliga data och autentiseringsuppgifter.

Upprätta klienthemligheten

Skapa en klienthemlighet i appens Entra-ID-registrering i Entra- eller Azure-portalen (Hantera>-certifikat & hemligheter>Ny klienthemlighet). Använd värde för den nya hemligheten i följande vägledning.

Använd någon av eller båda av följande metoder för att tillhandahålla klienthemligheten till appen:

  • Secret Manager-verktyget: Secret Manager-verktyget lagrar privata data på den lokala datorn och används endast under lokal utveckling.
  • Azure Key Vault-: Du kan lagra klienthemligheten i ett nyckelvalv för användning i alla miljöer, inklusive för utvecklingsmiljön när du arbetar lokalt. Vissa utvecklare föredrar att använda nyckelvalv för mellanlagrings- och produktionsdistributioner och använder verktyget Secret Manager för lokal utveckling.

Vi rekommenderar starkt att du undviker att lagra klienthemligheter i projektkod eller konfigurationsfiler. Använd säkra autentiseringsflöden, till exempel någon av eller båda metoderna i det här avsnittet.

Secret Manager-verktyget

Verktyget Secret Manager kan lagra serverappens klienthemlighet under konfigurationsnyckeln AzureAd:ClientSecret.

Exempelappen 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, som används internt av verktyget för att spåra hemligheter för appen:

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 Entra-registrering:

dotnet user-secrets set "AzureAd: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.

Azure Key Vault

Azure Key Vault- är en säker metod för att tillhandahålla appens klienthemlighet till appen.

Information om hur du skapar ett nyckelvalv och anger en klienthemlighet finns i Om Azure Key Vault-hemligheter (Azure-dokumentation), som korslänkar resurser för att komma igång med Azure Key Vault. Om du vill implementera koden i det här avsnittet registrerar du nyckelvalvets URI och det hemliga namnet från Azure när du skapar nyckelvalvet och hemligheten. När du anger åtkomstprincipen för hemligheten i Åtkomstprinciper panelen:

  • Endast behörigheten att hämta -hemligheten krävs för.
  • Välj programmet som Principal för hemligheten.

Viktig

En nyckelvalvshemlighet skapas med ett förfallodatum. Se till att spåra när en nyckelvalvshemlighet upphör att gälla och skapa en ny hemlighet för appen innan det datumet passerar.

Lägg till följande AzureHelper-klass i serverprojektet. Metoden GetKeyVaultSecret hämtar en hemlighet från ett nyckelvalv. Justera namnområdet (BlazorSample.Helpers) så att det matchar projektets namnområdesschema.

Helpers/AzureHelper.cs:

using Azure;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;

namespace BlazorSample.Helpers;

public static class AzureHelper
{
    public static string GetKeyVaultSecret(string tenantId, string vaultUri, string secretName)
    {
        DefaultAzureCredentialOptions options = new()
        {
            // Specify the tenant ID to use the dev credentials when running the app locally
            // in Visual Studio.
            VisualStudioTenantId = tenantId,
            SharedTokenCacheTenantId = tenantId
        };

        var client = new SecretClient(new Uri(vaultUri), new DefaultAzureCredential(options));
        var secret = client.GetSecretAsync(secretName).Result;

        return secret.Value.Value;
    }
}

Om tjänster registreras i serverprojektets Program-fil hämtar och tillämpar du klienthemligheten med hjälp av följande kod:

var tenantId = builder.Configuration.GetValue<string>("AzureAd:TenantId")!;
var vaultUri = builder.Configuration.GetValue<string>("AzureAd:VaultUri")!;
var secretName = builder.Configuration.GetValue<string>("AzureAd:SecretName")!;

builder.Services.Configure<MicrosoftIdentityOptions>(
    OpenIdConnectDefaults.AuthenticationScheme,
    options =>
    {
        options.ClientSecret = 
            AzureHelper.GetKeyVaultSecret(tenantId, vaultUri, secretName);
    });

Om du vill styra miljön där föregående kod fungerar, till exempel för att undvika att köra koden lokalt eftersom du har valt att använda verktyget Secret Manager för lokal utveckling, kan du omsluta koden i en villkorsstyrd instruktion som kontrollerar miljön:

if (!context.HostingEnvironment.IsDevelopment())
{
    ...
}

I avsnittet AzureAd i appsettings.jsonlägger du till följande VaultUri och SecretName konfigurationsnycklar och -värden:

"VaultUri": "{VAULT URI}",
"SecretName": "{SECRET NAME}"

I föregående exempel:

  • Platshållaren {VAULT URI} är nyckelvalvets URI. Inkludera det avslutande snedstrecket på URI:n.
  • Platshållaren {SECRET NAME} är det hemliga namnet.

Exempel:

"VaultUri": "https://contoso.vault.azure.net/",
"SecretName": "BlazorWebAppEntra"

Konfigurationen används för att underlätta tillhandahållandet av dedikerade nyckelvalv och hemliga namn baserat på appens miljökonfigurationsfiler. Du kan till exempel ange olika konfigurationsvärden för appsettings.Development.json under utveckling, appsettings.Staging.json vid mellanlagring och appsettings.Production.json för produktionsdistributionen. Mer information finns i ASP.NET Core Blazor configuration.

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 @context.User.Identity?.Name
                </button>
            </form>
        </Authorized>
        <NotAuthorized>
            <a class="nav-link" href="authentication/login">
                <span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span> 
                Login
            </a>
        </NotAuthorized>
    </AuthorizeView>
</div>

Felsöka

Skogsavverkning

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å klientsidan i ASP.NET Core Blazor loggning med artikelversionsväljaren inställd på ASP.NET Core 7.0 eller senare.

Vanliga fel

  • Felkonfiguration av appen eller Identity IP-leverantör

    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.

    Konfigurationstäckning i den här artikeln visar exempel på rätt konfiguration. Kontrollera noggrant konfigurationen för att leta efter fel i 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å dokumentationsfeedback och buggar i artiklar. Starta ett ärende från Den här sidan feedbacksektionen, men de 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.

    För rapporter om icke-säkerhetsrelaterade, icke-känsliga och icke-konfidentiella reproducerbara ramverksfel, skapa ett ärende med ASP.NET Core-produktenheten. Öppna inte ett ärende med produktgruppen förrän du noggrant har undersökt orsaken till ett problem och inte kan lösa det själv och med hjälp av communityt på ett offentligt support-forum. 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 Rapportering av 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. Ange attributet allowPublicClient 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
  • App cookies
  • Cachelagrade och lagrade platsdata

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 Visual Studio-knappen Kör.
    • Välj knappen Lägg till.
    • Ange sökvägen till webbläsaren i fältet Program. Följande körbara sökvägar ä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 Inkognitolä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 Användarvänligt 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 Core SDK på utvecklingsdatorn eller ändrat paketversioner i appen. I vissa fall kan osammanhängande paket orsaka att en app slutar fungera 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.

Obs

Användning av paketversioner som inte är kompatibla med appens målramverk stöds inte. Information om ett paket finns i NuGet Gallery eller FuGet Package Explorer.

Kör serverappen

När du testar och felsöker Blazor Web Appkontrollerar du att du kör appen 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