Dela via


Konfigurera OpenID Connect Web-autentisering (UI) i ASP.NET Core

Av Damien Bowden

Visa eller ladda ned exempelkod

Den här artikeln beskriver följande områden:

  • Vad är en konfidentiell interaktiv OpenID Connect-klient
  • Skapa en OpenID Connect-klient i ASP.NET Core
  • Exempel på OpenID Connect-klient med kodfragment
  • Använda openID Connect-providerklienter från tredje part
  • Backend för frontend (BFF) säkerhetsarkitektur
  • Avancerade funktioner, standarder, utöka en OpenID Connect-klient

En alternativ upplevelse med Microsoft Authentication Library för .NET, Microsoft Identity Web och Microsoft Entra ID finns i Snabbstart: Logga in användare och anropa Microsoft Graph API från en ASP.NET Core-webbapp (Azure-dokumentation).

Ett exempel med Microsoft Entra External ID OIDC-server finns i Logga in användare för en ASP.NET Core-webbapp i en extern klientorganisation och en ASP.NET Core-webbapp som autentiserar användare mot Microsoft Entra External ID med Microsoft Identity Web.

Vad är en konfidentiell interaktiv OpenID Connect-klient

OpenID Connect kan användas för att implementera autentisering i ASP.NET Core-program. Det rekommenderade sättet är att använda en konfidentiell OpenID Connect-klient med hjälp av kodflödet. Användning av bevisnyckeln för kodutbyte av OAuth Public Clients (PKCE) rekommenderas för den här implementeringen. Både programklienten och användaren av programmet autentiseras i det konfidentiella flödet. Programklienten använder en klienthemlighet eller en klientkontroll för att autentisera.

Offentliga OpenID Connect/OAuth-klienter rekommenderas inte längre för webbprogram.

Standardflödet fungerar som det visas i följande diagram:

Konfidentiell OIDC-kodflödesklient med PKCE

OpenID Connect finns i många varianter och alla serverimplementeringar har lite olika parametrar och krav. Vissa servrar stöder inte användarinformationsslutpunkten, vissa stöder fortfarande inte PKCE och andra kräver särskilda parametrar i tokenbegäran. Klientpåståenden kan användas i stället för klienthemligheter. Det finns också nya standarder som lägger till extra säkerhet ovanpå OpenID Connect Core, till exempel FAPI, CIBA eller DPoP för underordnade API:er.

Anmärkning

Från .NET 9 används OAuth 2.0 Pushed Authorization Requests (PAR) RFC 9126 per standard, om OpenID Connect-servern stöder detta. Det här är ett flöde i tre steg och inte ett tvåstegsflöde som visas ovan. (Begäran om användarinformation är ett valfritt steg.)

Skapa en Open ID Connect-kodflödesklient med Pages Razor

Följande avsnitt visar hur du implementerar en OpenID Connect-klient i ett tomt ASP.NET Core-sidprojekt Razor . Samma logik kan tillämpas på alla ASP.NET Core-webbprojekt där endast användargränssnittsintegrering skiljer sig.

Lägga till OpenID Connect-stöd

Microsoft.AspNetCore.Authentication.OpenIdConnect Lägg till Nuget-paketen i projektet ASP.NET Core.

Konfigurera OpenID Connect-klienten

Lägg till autentiseringen till webbapplikationen med hjälp av builder.Services i Program.cs-filen. Konfigurationen är beroende av OpenID Connect-servern. Varje OpenID Connect-server kräver små skillnader i konfigurationen.

OpenID Connect-hanteraren används för utmaningar och inloggning. cookie Används för att hantera sessionen i webbprogrammet. Standardscheman för autentiseringen kan anges efter behov.

Mer information finns i vägledningen för ASP.NET Coreauthentication-handler.

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");

    options.Authority = oidcConfig["Authority"];
    options.ClientId = oidcConfig["ClientId"];
    options.ClientSecret = oidcConfig["ClientSecret"];

    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.ResponseType = OpenIdConnectResponseType.Code;

    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    options.MapInboundClaims = false;
    options.TokenValidationParameters.NameClaimType = JwtRegisteredClaimNames.Name;
    options.TokenValidationParameters.RoleClaimType = "roles";
});

Mer information om de olika OpenID Connect-alternativen finns i Skydda en ASP.NET Core Blazor Web App med OpenID Connect (OIDC).

De olika möjligheterna för anspråksmappning finns i Mappa, anpassa och transformera anspråk i ASP.NET Core.

Anmärkning

Följande namnområden krävs:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;

Konfigurera konfigurationsegenskaperna

Lägg till OpenID Connect-klientinställningarna i programkonfigurationsegenskaperna. Inställningarna måste matcha klientkonfigurationen på OpenID Connect-servern. Inga hemligheter ska sparas i programinställningarna där de kan checkas in av misstag. Hemligheter bör lagras på en säker plats som Azure Key Vault i produktionsmiljöer eller i användarhemligheter i en utvecklingsmiljö. Mer information finns i Säker lagring av apphemligheter under utveckling i ASP.NET Core.

"OpenIDConnectSettings": {
  // OpenID Connect URL. (The base URL for the /.well-known/openid-configuration)
  "Authority": "<Authority>",
  // client ID from the OpenID Connect server
  "ClientId": "<Client ID>",
  //"ClientSecret": "--stored-in-user-secrets-or-key-vault--"
},

Konfiguration för sökväg för återuppringning vid utloggning

SignedOutCallbackPath (konfigurationsnyckeln: "SignedOutCallbackPath") är begärandesökvägen i appens bassökväg som fångas upp av OpenID Connect-hanteraren där användaragenten först returneras efter utloggning från identitetsprovidern. 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 å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

Anmärkning

När du använder Microsoft Entra ID anger du sökvägen i konfigurationen för Web-plattformens 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.

Uppdatera pipelinemetoden ASP.NET Core i programklassen.

Metoden UseRouting måste implementeras före UseAuthorization metoden.

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
// Authorization is applied for middleware after the UseAuthorization method
app.UseAuthorization();
app.MapRazorPages();

Tvinga fram auktorisering

[Authorize] Lägg till attributet till de skyddade Razor sidorna:

[Authorize]

En bättre metod är att framtvinga auktorisering för hela appen och välja bort osäkra sidor:

var requireAuthPolicy = new AuthorizationPolicyBuilder()
    .RequireAuthenticatedUser()
    .Build();

builder.Services.AddAuthorizationBuilder()
    .SetFallbackPolicy(requireAuthPolicy);

Avregistrera dig från auktorisering vid offentliga slutpunkter genom att tillämpa [AllowAnonymous] attributet på de offentliga slutpunkterna. Exempel finns i avsnitten Lägg till en ny Logout.cshtml och SignedOut.cshtmlRazor sidor i projektet och Implementera Login sida .

Lägga till en ny Logout.cshtml sida och SignedOut.cshtmlRazor sidor i projektet

En utloggning krävs för att logga ut både cookie sessionen och OpenID Connect-sessionen. Hela appen måste omdirigeras till OpenID Connect-servern för att logga ut. Efter en lyckad utloggning öppnar appen RedirectUri-rutten.

Implementera en standardutloggningssida och ändra Logout razor-sidkoden till följande:

[Authorize]
public class LogoutModel : PageModel
{
    public IActionResult OnGetAsync()
    {
        return SignOut(new AuthenticationProperties
        {
            RedirectUri = "/SignedOut"
        },
        // Clear auth cookie
        CookieAuthenticationDefaults.AuthenticationScheme,
        // Redirect to OIDC provider signout endpoint
        OpenIdConnectDefaults.AuthenticationScheme);
    }
}

Kräver SignedOut.cshtml[AllowAnonymous]-attributet:

[AllowAnonymous]
public class SignedOutModel : PageModel
{
    public void OnGet()
    {
    }
}

Implementera sidan Login

En LoginRazor sida kan också implementeras för att anropa ChallengeAsync direkt med den nödvändiga AuthProperties. Detta krävs inte om webbappen kräver autentisering och standardutmaningen används.

Sidan Login.cshtml kräver attributet[AllowAnonymous]:

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPageOidc.Pages;

[AllowAnonymous]
public class LoginModel : PageModel
{
    [BindProperty(SupportsGet = true)]
    public string? ReturnUrl { get; set; }

    public async Task OnGetAsync()
    {
        var properties = GetAuthProperties(ReturnUrl);
        await HttpContext.ChallengeAsync(properties);
    }

    private static AuthenticationProperties GetAuthProperties(string? returnUrl)
    {
        const string pathBase = "/";

        // Prevent open redirects.
        if (string.IsNullOrEmpty(returnUrl))
        {
            returnUrl = pathBase;
        }
        else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative))
        {
            returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery;
        }
        else if (returnUrl[0] != '/')
        {
            returnUrl = $"{pathBase}{returnUrl}";
        }

        return new AuthenticationProperties { RedirectUri = returnUrl };
    }
}

Lägg till en inloggnings- och utloggningsknapp för användaren

@if (Context.User.Identity!.IsAuthenticated)
{
	<li class="nav-item">
		<a class="nav-link text-dark" asp-area="" asp-page="/Logout">Logout</a>
	</li>

	<span class="nav-link text-dark">Hi @Context.User.Identity.Name</span>
}
else
{
	<li class="nav-item">
		<a class="nav-link text-dark" asp-area="" asp-page="/Index">Login</a>
	</li>
}

Exempel med kodfragment

Exempel på användning av användarinformationsslutpunkt

OpenID Connect-alternativen kan användas för att mappa anspråk, implementera hanterare eller till och med spara token i sessionen för senare användning.

Alternativet Scope kan användas för att begära olika anspråk eller en uppdateringstoken som skickas som information till OpenID Connect-servern. offline_access Begär att servern ska returnera en referenstoken som kan användas för att uppdatera sessionen utan att autentisera användaren av programmet igen.

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    var oidcConfig = builder.Configuration.GetSection("OpenIDConnectSettings");
    options.Authority = oidcConfig["IdentityProviderUrl"];
    options.ClientSecret = oidcConfig["ClientSecret"];
    options.ClientId = oidcConfig["Audience"];
    options.ResponseType = OpenIdConnectResponseType.Code;

    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("email");
    options.Scope.Add("offline_access");

    options.ClaimActions.Remove("amr");
    options.ClaimActions.MapUniqueJsonKey("website", "website");

    options.GetClaimsFromUserInfoEndpoint = true;
    options.SaveTokens = true;

    // .NET 9 feature
    options.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Require;

    options.TokenValidationParameters.NameClaimType = "name";
    options.TokenValidationParameters.RoleClaimType = "role";
});

Implementera Microsoft-identitetsleverantörer

Microsoft har flera identitetsprovidrar och OpenID Connect-implementeringar. Microsoft har olika OpenID Connect-servrar:

  • Microsoft Entra ID
  • Externt ID för Microsoft Entra
  • Azure AD B2C

Om du autentiserar med någon av Microsofts identitetsprovidrar i ASP.NET Core rekommenderar vi att du använder Nuget-paketen Microsoft.Identity.Web .

Nuget-paketen Microsoft.Identity.Web är en Microsoft-specifik klient som bygger på ASP.NET Core OpenID Connect-klienten med vissa ändringar i standardklienten.

Använda openID Connect-providerklienter från tredje part

Många OpenID Connect-serverimplementeringar skapar Nuget-paket som är optimerade för samma OpenID Connect-implementering. Dessa paket implementerar OpenID Connect-klientinformationen med de extrafunktioner som krävs av den specifika OpenID Connect-servern. Microsoft.Identity.Web är ett exempel på detta.

Om du implementerar flera OpenID Connect-klienter från olika OpenID Connect-servrar i ett enda program är det normalt bättre att återgå till standardimplementeringen ASP.NET Core eftersom de olika klienterna skriver över vissa alternativ som påverkar de andra klienterna.

OpenIddict-webbleverantörer är en klientimplementering som stöder många olika serverimplementeringar.

IdentityModel är ett .NET-standardhjälpbibliotek för anspråksbaserad identitet, OAuth 2.0 och OpenID Connect. Detta kan också användas för att hjälpa till med klientimplementeringen.

Backend för frontend-säkerhetsarkitektur (BFF)

Vi rekommenderar inte längre att du implementerar offentliga OpenID Connect-klienter för webbappar.

Mer information finns i utkastet till OAuth 2.0 för Browser-Based-program.

Om du implementerar webbprogram som inte har någon oberoende serverdel rekommenderar vi att du använder mönstersäkerhetsarkitekturen Serverdel för klientdel (BFF). Det här mönstret kan implementeras på olika sätt, men autentiseringen implementeras alltid i serverdelen och inga känsliga data skickas till webbklienten för ytterligare auktoriserings- eller autentiseringsflöden.

Avancerade funktioner, standarder, utöka OIDC-klienten

Loggning / Skogsavverkning

Det kan vara svårt att felsöka OpenID Connect-klienter. Personligt identifierbara informationsdata (PII) loggas inte som standard. Om du felsöker i utvecklingsläge kan IdentityModelEventSource.ShowPII användas för att logga känsliga personuppgifter. Distribuera inte en app med IdentityModelEventSource.ShowPII till produktiva servrar.

//using ...

using Microsoft.IdentityModel.Logging;

var builder = WebApplication.CreateBuilder(args);

//... code 

var app = builder.Build();

IdentityModelEventSource.ShowPII = true;

//... code 

app.Run();

Mer information finns i Loggning.

Anmärkning

Du kanske vill sänka den konfigurerade loggnivån för att se alla nödvändiga loggar.

OIDC- och OAuth-parameteranpassning

Alternativet OAuth- och OIDC-autentiseringshanterare (AdditionalAuthorizationParameters) tillåter anpassning av auktoriseringsmeddelandeparametrar som vanligtvis ingår som en del av omdirigeringsfrågesträngen.

Mappa krav från OpenID Connect

Mer information finns i Mappa, anpassa och transformera anspråk i ASP.NET Core.

Blazor OpenID Connect

Mer information finns i Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC).

Standarder