Konfigurieren der OpenID Connect-Webauthentifizierung (UI) in ASP.NET Core
Von Damien Bowden
Anzeigen oder Herunterladen von Beispielcode
In diesem Artikel werden die folgenden Themenbereiche behandelt:
- Was ist ein vertraulicher interaktiver OpenID Connect-Client
- Erstellen eines OpenID Connect-Clients in ASP.NET Core
- Beispiele für openID Connect-Client mit Codeausschnitten
- Verwenden von OpenID Connect-Anbieterclients von Drittanbietern
- Back-End für BFF-Sicherheitsarchitektur (Frontend)
- Erweiterte Features, Standards, Erweitern des OpenID Connect-Clients
Eine alternative Erfahrung mit der Verwendung Microsoft Authentication Library for .NET, Microsoft Identity Webund Microsoft Entra IDfinden Sie unter Schnellstart: Anmelden von Benutzern und Aufrufen der Microsoft Graph-API aus einer ASP.NET Core Web App (Azure-Dokumentation).
Ein Beispiel für die Verwendung des Microsoft Entra External ID OIDC-Servers finden Sie unter Anmelden von Benutzern für eine Beispiel-ASPNET Core-Web-App in einem externen Mandanten sowie unter einer ASP.NET Core-Web-App, die Benutzer gegen Microsoft Entra External ID mithilfe von Microsoft Identity Web-authentifiziert.
Was ist ein vertraulicher interaktiver OpenID Connect-Client
OpenID Connect kann verwendet werden, um die Authentifizierung in ASP.NET Core-Anwendungen zu implementieren. Die empfohlene Methode ist die Verwendung eines vertraulichen OpenID Connect-Clients mithilfe des Codeflusses. Die Verwendung des Proof Key für Code Exchange von OAuth Public Clients (PKCE) wird für diese Implementierung empfohlen. Sowohl der Anwendungsclient als auch der Benutzer der Anwendung werden im vertraulichen Fluss authentifiziert. Der Anwendungsclient verwendet einen geheimen Clientschlüssel oder eine Client assertion zur Authentifizierung.
Öffentliche OpenID Connect/OAuth-Clients werden für Webanwendungen nicht mehr empfohlen.
Der Standardfluss funktioniert wie im folgenden Diagramm dargestellt:
OpenID Connect kommt in vielen Variationen, und alle Serverimplementierungen weisen geringfügig unterschiedliche Parameter und Anforderungen auf. Einige Server unterstützen den Benutzerinformationsendpunkt nicht, einige unterstützen PKCE immer noch nicht, und andere erfordern spezielle Parameter in der Tokenanforderung. Client assertionen können anstelle von geheimen Clientschlüsseln verwendet werden. Darüber hinaus gibt es neue Standards, die zusätzliche Sicherheit über openID Connect Core, z. B. FAPI, CIBA oder DPoP für downstream-APIs, hinzufügen.
Hinweis
Ab .NET 9 wird OAuth 2.0 Pushed Authorization Requests (PAR) RFC 9126 standardmäßig verwendet, wenn der OpenID Connect-Server dies unterstützt. Dies ist ein dreistufiger Fluss und kein zweistufiger Fluss, wie oben dargestellt. (Die Benutzerinformationsanforderung ist ein optionaler Schritt.)
Erstellen eines Open ID Connect-Codeflussclients mithilfe von Razor Seiten
Im folgenden Abschnitt wird gezeigt, wie Sie einen OpenID Connect-Client in einem leeren ASP.NET Core-Seitenprojekt Razor implementieren. Dieselbe Logik kann auf jedes ASP.NET Core-Webprojekt angewendet werden, wobei nur die UI-Integration unterschiedlich ist.
Hinzufügen der OpenID Connect-Unterstützung
Fügen Sie dem ASP.NET Core-Projekt die Microsoft.AspNetCore.Authentication.OpenIdConnect
Nuget-Pakete hinzu.
Einrichten des OpenID Connect-Clients
Fügen Sie die Authentifizierung zur Webanwendung hinzu, indem Sie builder.Services in der Datei Program.cs
verwenden. Die Konfiguration ist vom OpenID Connect-Server abhängig. Jeder OpenID Connect-Server erfordert kleine Unterschiede beim Setup.
Der OpenID Connect-Handler wird für Herausforderungen und Anmeldungen verwendet. Dies cookie wird verwendet, um die Sitzung in der Webanwendung zu behandeln. Die Standardschemas für die Authentifizierung können nach Bedarf angegeben werden.
Weitere Informationen finden Sie in den Anleitungen zu 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";
});
Ausführliche Informationen zu den verschiedenen OpenID Connect-Optionen finden Sie unter Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC).
Die verschiedenen Anspruchszuordnungsmöglichkeiten finden Sie unter Zuordnung, Anpassen und Transformieren von Ansprüchen in ASP.NET Core.
Hinweis
Die folgenden Namespaces sind erforderlich:
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
Einrichten der Konfigurationseigenschaften
Fügen Sie die OpenID Connect-Clienteinstellungen zu den Anwendungskonfigurationseigenschaften hinzu. Die Einstellungen müssen mit der Clientkonfiguration auf dem OpenID Connect-Server übereinstimmen. In den Anwendungseinstellungen sollten keine Geheimnisse beibehalten werden, da sie möglicherweise versehentlich eingecheckt werden könnten. Geheime Schlüssel sollten an einem sicheren Ort wie Azure Key Vault in Produktionsumgebungen oder in geheimen Benutzerschlüsseln in einer Entwicklungsumgebung gespeichert werden. Weitere Informationen finden Sie unter Sichere Speicherung von App-Geheimnissen in der Entwicklung in 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 des Rückrufpfads für die Abmeldung
Der SignedOutCallbackPath (Konfigurationsschlüssel: „SignedOutCallbackPath
“) ist der Anforderungspfad innerhalb des vom OpenID Connect-Handler abgefangenen Basispfads der App, in dem der Benutzer-Agent nach der Abmeldung vom Identitätsanbieter zuerst zurückgegeben wird. Die Beispiel-App legt keinen Wert für den Pfad fest, da der Standardwert von "/signout-callback-oidc
" verwendet wird. Nach dem Abfangen der Anforderung wird sie vom OpenID Connect-Handler, falls angegeben, an SignedOutRedirectUri oder RedirectUri umgeleitet.
Konfigurieren Sie den Rückrufpfad für die Abmeldung in der OIDC-Anbieterregistrierung der App. Im folgenden Beispiel ist der {PORT}
Platzhalter der Port der App:
https://localhost:{PORT}/signout-callback-oidc
Hinweis
Legen Sie bei Verwendung der Microsoft Entra-ID den Pfad in den Redirect URI-Konfigurationseinträgen der Web-Plattform im Entra- oder Azure-Portal fest. Bei Verwendung von Entra ist kein Port für localhost
Adressen erforderlich. Die meisten anderen OIDC-Anbieter benötigen den richtigen Port. Wenn Sie den Rückrufpfad-URI für abgemeldete Benutzer nicht zur Registrierung der App bei Entra hinzufügen, lehnt Entra die Weiterleitung des Benutzers an die App ab und fordert ihn lediglich auf, das Browserfenster zu schließen.
Aktualisieren Sie die ASP.NET Core-Pipelinemethode in der Programmklasse.
Die UseRouting
-Methode muss vor der UseAuthorization
-Methode implementiert werden.
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
// Authorization is applied for middleware after the UseAuthorization method
app.UseAuthorization();
app.MapRazorPages();
Erzwingen der Autorisierung
Fügen Sie das [Authorize]
Attribut den geschützten Razor Seiten hinzu:
[Authorize]
Ein besserer Ansatz besteht darin, die Autorisierung für die gesamte App zu erzwingen und unsichere Seiten zu deaktivieren:
var requireAuthPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
builder.Services.AddAuthorizationBuilder()
.SetFallbackPolicy(requireAuthPolicy);
Hinzufügen einer neuen Logout.cshtml
und SignedOut.cshtml
Razor Seiten zum Projekt
Um sowohl die cookie-Sitzung als auch die OpenID Connect-Sitzung abzumelden, ist ein Logout erforderlich. Die gesamte App muss zum Abmelden an den OpenID Connect-Server umgeleitet werden. Nach einer erfolgreichen Abmeldung öffnet die App die RedirectUri
Route.
Implementieren Sie eine Standard-Abmeldeseite und ändern Sie den Logout
Razor-Seitencode auf die folgende Weise:
[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);
}
}
Für die SignedOut.cshtml
ist das [AllowAnonymous]
Attributerforderlich:
[AllowAnonymous]
public class SignedOutModel : PageModel
{
public void OnGet()
{
}
}
Seite Login
implementieren
Sie können auch eine Login
Razor-Seite implementieren, um ChallengeAsync
direkt mit den erforderlichen AuthProperties
aufzurufen. Dies ist nicht erforderlich, wenn die Web-App Authentifizierung erfordert und die Standardabfrage verwendet wird.
Für die Login.cshtml
Seite ist das [AllowAnonymous]
Attributerforderlich:
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 };
}
}
Hinzufügen einer Anmelde- und Abmeldeschaltfläche für den Benutzer
@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>
}
Beispiele mit Codeausschnitten
Beispiel für die Verwendung des Benutzerinformationsendpunkts
Die OpenID Connect-Optionen können verwendet werden, um Ansprüche zuzuordnen, Handler zu implementieren oder sogar die Token in der Sitzung zur späteren Verwendung zu speichern.
Die option Scope
kann verwendet werden, um unterschiedliche Ansprüche oder ein Aktualisierungstoken anzufordern, das als Informationen an den OpenID Connect-Server gesendet wird. Beim Anfordern der offline_access
wird der Server aufgefordert, ein Referenztoken zurückzugeben, mit dem die Sitzung aktualisiert werden kann, ohne den Benutzer der Anwendung erneut authentifizieren zu müssen.
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";
});
Implementieren von Microsoft-Identitätsanbietern
Microsoft verfügt über mehrere Identitätsanbieter und OpenID Connect-Implementierungen. Microsoft verfügt über unterschiedliche OpenID Connect-Server:
- Microsoft Entra ID
- Microsoft Entra External ID
- Azure AD B2C
Wenn die Authentifizierung mit einem der Microsoft-Identitätsanbieter in ASP.NET Core erfolgt, empfiehlt es sich, die Microsoft.Identity.Web
Nuget-Pakete zu verwenden.
Die Microsoft.Identity.Web
Nuget-Pakete sind ein microsoftspezifischer Client, der auf dem ASP.NET Core OpenID Connect-Client mit einigen Änderungen am Standardclient basiert.
Verwenden von OpenID Connect-Anbieterclients von Drittanbietern
Viele OpenID Connect-Serverimplementierungen erstellen Nuget-Pakete, die für dieselbe OpenID Connect-Implementierung optimiert sind. Diese Pakete implementieren die OpenID Connect-Clientspezifischen mit den extras, die vom spezifischen OpenID Connect-Server benötigt werden. Microsoft.Identity.Web
ist ein Beispiel dafür.
Wenn Sie mehrere OpenID Connect-Clients von verschiedenen OpenID Connect-Servern in einer einzigen Anwendung implementieren, ist es normalerweise besser, zur Standardimplementierung von ASP.NET Core zurückzukehren, da die verschiedenen Clients einige Optionen überschreiben, die sich auf die anderen Clients auswirken.
OpenIddict-Webanbieter sind eine Clientimplementierung , die viele verschiedene Serverimplementierungen unterstützt.
IdentityModel
ist eine .NET-Standardhilfsbibliothek für anspruchsbasierte Identität, OAuth 2.0 und OpenID Connect. Dies kann auch zur Unterstützung bei der Clientimplementierung verwendet werden.
Back-End für BFF-Sicherheitsarchitektur (Frontend)
Es wird nicht mehr empfohlen, öffentliche OpenID Connect-Clients für beliebige Web-Apps zu implementieren.
Weitere Informationen finden Sie im Entwurf zu OAuth 2.0 für browserbasierte Anwendungen.
Wenn Sie Web- Anwendungen ohne unabhängiges Back-End implementieren, empfehlen wir die Verwendung des Back-End-Musters für Frontend (BFF) Sicherheitsarchitektur. Dieses Muster kann auf unterschiedliche Weise implementiert werden, die Authentifizierung wird jedoch immer im Back-End implementiert, und für weitere Autorisierungs- oder Authentifizierungsflüsse werden keine vertraulichen Daten an den Webclient gesendet.
Erweiterte Features, Standards, Erweitern des OIDC-Clients
Logging
Das Debuggen von OpenID Connect-Clients kann schwierig sein. Personenbezogene Informationen (PII)-Daten werden standardmäßig nicht protokolliert. Wenn das Debuggen im Entwicklungsmodus erfolgt, kann die IdentityModelEventSource.ShowPII
zum Protokollieren vertraulicher personenbezogener Daten verwendet werden. Stellen Sie keine App mit IdentityModelEventSource.ShowPII
für produktive Server bereit.
//using ...
using Microsoft.IdentityModel.Logging;
var builder = WebApplication.CreateBuilder(args);
//... code
var app = builder.Build();
IdentityModelEventSource.ShowPII = true;
//... code
app.Run();
Weitere Informationen finden Sie unter Protokollierung.
Hinweis
Möglicherweise möchten Sie die konfigurierte Protokollebene verringern, um alle erforderlichen Protokolle anzuzeigen.
Anpassung der OIDC- und OAuth-Parameter
Die OAuth- und OIDC-Authentifizierungshandler (AdditionalAuthorizationParameters) ermöglichen die Anpassung von Autorisierungsmeldungsparametern, die in der Regel als Teil der Umleitungsabfragezeichenfolge enthalten sind.
Zuordnen von Ansprüchen aus OpenID Connect
Weitere Informationen finden Sie unter Zuordnung, Anpassen und Transformieren von Ansprüchen in ASP.NET Core.
Blazor OpenID Connect
Weitere Informationen finden Sie unter Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC).