Zuordnen, Anpassen und Transformieren von Ansprüchen in ASP.NET Core
Von Damien Bowden
Ansprüche können anhand beliebiger Benutzerdaten oder Daten der identity erstellt werden, die über einen vertrauenswürdigen identitysanbieter oder eine ASP.NET Core-Identität ausgegeben werden können.identity Ein Anspruch ist ein Name-Wert-Paar, das den Antragsteller repräsentiert, nicht jedoch die Aufgaben, die dieser ausführen kann. In diesem Artikel werden die folgenden Themenbereiche behandelt:
- Konfigurieren und Zuordnen von Ansprüchen mit einem OpenID Connect-Client
- Festlegen von Namens- und Rollenanspruch
- Zurücksetzen der Anspruchsnamespaces
- Anpassen und Erweitern der Ansprüche mit TransformAsync
Die Profilansprüche können im id_token
zurückgegeben werden, das nach einer erfolgreichen Authentifizierung zurückgegeben wird. Die ASP.NET Core-Client-App benötigt nur den Profilbereich. Wenn Sie das id_token
für Ansprüche verwenden, ist keine zusätzliche Anspruchszuordnung erforderlich.
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Für den obigen Code benötigen Sie das NuGet-Paket Microsoft.AspNetCore.Authentication.OpenIdConnect.
Eine andere Möglichkeit zum Abrufen der Benutzeransprüche besteht darin, die OpenID Connect-API für Benutzerinformationen zu verwenden. Die ASP.NET Core-Client-App verwendet die Eigenschaft GetClaimsFromUserInfoEndpoint
, um dies zu konfigurieren. Ein wichtiger Unterschied gegenüber den ersten Einstellungen besteht darin, dass Sie die benötigten Ansprüche mit der MapUniqueJsonKey
-Methode angeben müssen, da sonst nur die Standardansprüche name
, given_name
und email
in der Client-App verfügbar sind. Die im id_token
enthaltenen Ansprüche werden standardmäßig zugeordnet. Dies ist der Hauptunterschied gegenüber der ersten Option. Sie müssen einige der von Ihnen benötigten Ansprüche explizit definieren.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapUniqueJsonKey("preferred_username",
"preferred_username");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
});
var app = builder.Build();
// Code removed for brevity.
Hinweis
Der standardmäßige Open ID Connect-Handler verwendet Pushed Authorization Requests (PAR), wenn im Ermittlungsdokument des Identitätsanbieters Unterstützung für PAR angeboten wird. Das Ermittlungsdokument des identitysanbieters befindet sich in der Regel unter .well-known/openid-configuration
. Wenn Sie PAR nicht in der Clientkonfiguration für den identitysanbieter verwenden können, kann PAR mithilfe der Option PushedAuthorizationBehavior deaktiviert werden.
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("oidc", oidcOptions =>
{
// Other provider-specific configuration goes here.
// The default value is PushedAuthorizationBehavior.UseIfAvailable.
// 'OpenIdConnectOptions' does not contain a definition for 'PushedAuthorizationBehavior'
// and no accessible extension method 'PushedAuthorizationBehavior' accepting a first argument
// of type 'OpenIdConnectOptions' could be found
oidcOptions.PushedAuthorizationBehavior = PushedAuthorizationBehavior.Disable;
});
Um sicherzustellen, dass die Authentifizierung nur bei Verwendung von PAR erfolgreich ist, verwenden Sie stattdessen PushedAuthorizationBehavior.Require. Diese Änderung führt auch ein neues OnPushAuthorization-Ereignis in OpenIdConnectEvents ein, mit dem die Push-Autorisierungsanforderung angepasst oder manuell bearbeitet werden kann. Weitere Informationen finden Sie im API-Vorschlag.
Der Name-Anspruch und der Role-Anspruch werden Standardeigenschaften im ASP.NET Core HTTP-Kontext zugewiesen. Mitunter müssen unterschiedliche Ansprüche für die Standardeigenschaften verwendet werden, oder der Namens- und der Rollenanspruch entsprechen nicht den Standardwerten. Die Ansprüche können über die TokenValidationParameters-Eigenschaft zugeordnet und bei Bedarf auf einen beliebigen Anspruch festgelegt werden. Die Werte aus den Ansprüchen können direkt in der HttpContext-Eigenschaft User.Identity.Name und in den Rollen verwendet werden.
Wenn User.Identity.Name
keinen Wert aufweist oder die Rollen fehlen, überprüfen Sie die Werte in den zurückgegebenen Ansprüchen, und legen Sie die Werte NameClaimType
und RoleClaimType
fest. Die von der Clientauthentifizierung zurückgegebenen Ansprüche können im HTTP-Kontext angezeigt werden.
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// Other options...
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "email"
//, RoleClaimType = "role"
};
});
ASP.NET Core fügt einigen bekannten Ansprüchen Standardnamespaces hinzu, die in der App möglicherweise nicht benötigt werden. Sie können diese hinzugefügten Namespaces optional deaktivieren und genau die Ansprüche verwenden, die der OpenID Connect-Server erstellt hat.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
Wenn Sie die Namespaces pro Schema und nicht global deaktivieren müssen, können Sie die Option MapInboundClaims = false verwenden.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.MapInboundClaims = false;
options.Scope.Add("profile");
options.SaveTokens = true;
});
var app = builder.Build();
// Code removed for brevity.
Mithilfe der Schnittstelle IClaimsTransformation können Sie der ClaimsPrincipal-Klasse zusätzliche Ansprüche hinzufügen. Die Schnittstelle erfordert eine einzige TransformAsync-Methode. Diese Methode wird möglicherweise mehrmals aufgerufen. Fügen Sie nur dann einen neuen Anspruch hinzu, wenn er nicht bereits im ClaimsPrincipal
vorhanden ist. Eine ClaimsIdentity
wird erstellt, um die neuen Ansprüche hinzuzufügen, und diese kann dem ClaimsPrincipal
hinzugefügt werden.
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;
public class MyClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
var claimType = "myNewClaim";
if (!principal.HasClaim(claim => claim.Type == claimType))
{
claimsIdentity.AddClaim(new Claim(claimType, "myClaimValue"));
}
principal.AddIdentity(claimsIdentity);
return Task.FromResult(principal);
}
}
Die IClaimsTransformation-Schnittstelle und die MyClaimsTransformation
-Klasse können als Dienst registriert werden:
builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
Weitere Informationen finden Sie im folgenden Dokument:
Speichern zusätzlicher Ansprüche und Token externer Anbieter in ASP.NET Core
Ansprüche können anhand beliebiger Benutzerdaten oder Daten der identity erstellt werden, die über einen vertrauenswürdigen identitysanbieter oder eine ASP.NET Core-Identität ausgegeben werden können.identity Ein Anspruch ist ein Name-Wert-Paar, das den Antragsteller repräsentiert, nicht jedoch die Aufgaben, die dieser ausführen kann. In diesem Artikel werden die folgenden Themenbereiche behandelt:
- Konfigurieren und Zuordnen von Ansprüchen mit einem OpenID Connect-Client
- Festlegen von Namens- und Rollenanspruch
- Zurücksetzen der Anspruchsnamespaces
- Anpassen und Erweitern der Ansprüche mit TransformAsync
Die Profilansprüche können im id_token
zurückgegeben werden, das nach einer erfolgreichen Authentifizierung zurückgegeben wird. Die ASP.NET Core-Client-App benötigt nur den Profilbereich. Wenn Sie das id_token
für Ansprüche verwenden, ist keine zusätzliche Anspruchszuordnung erforderlich.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
});
Eine andere Möglichkeit zum Abrufen der Benutzeransprüche besteht darin, die OpenID Connect-API für Benutzerinformationen zu verwenden. Die ASP.NET Core-Clientanwendung verwendet die Eigenschaft GetClaimsFromUserInfoEndpoint
, um dies zu konfigurieren. Ein wichtiger Unterschied gegenüber den ersten Einstellungen besteht darin, dass Sie die benötigten Ansprüche mit der MapUniqueJsonKey
-Methode angeben müssen, da sonst nur die Standardansprüche name
, given_name
und email
in der Clientanwendung verfügbar sind. Die im id_token
enthaltenen Ansprüche werden standardmäßig zugeordnet. Dies ist der Hauptunterschied gegenüber der ersten Option. Sie müssen einige der von Ihnen benötigten Ansprüche explizit definieren.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "-your-identity-provider-";
options.RequireHttpsMetadata = true;
options.ClientId = "-your-clientid-";
options.ClientSecret = "-your-client-secret-from-user-secrets-or-keyvault";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("profile");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.MapUniqueJsonKey("preferred_username", "preferred_username");
options.ClaimActions.MapUniqueJsonKey("gender", "gender");
});
Der Name-Anspruch und der Role-Anspruch werden Standardeigenschaften im ASP.NET Core HTTP-Kontext zugewiesen. Mitunter müssen unterschiedliche Ansprüche für die Standardeigenschaften verwendet werden, oder der Namens- und der Rollenanspruch entsprechen nicht den Standardwerten. Die Ansprüche können über die TokenValidationParameters-Eigenschaft zugeordnet und bei Bedarf auf einen beliebigen Anspruch festgelegt werden. Die Werte aus den Ansprüchen können direkt in der HttpContext-Eigenschaft User.Identity.Name und in den Rollen verwendet werden.
Wenn User.Identity.Name
keinen Wert aufweist oder die Rollen fehlen, überprüfen Sie die Werte in den zurückgegebenen Ansprüchen, und legen Sie die Werte NameClaimType
und RoleClaimType
fest. Die von der Clientauthentifizierung zurückgegebenen Ansprüche können im HTTP-Kontext angezeigt werden.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
// other options...
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "email",
// RoleClaimType = "role"
};
});
ASP.NET Core fügt einigen bekannten Ansprüchen Standardnamespaces hinzu, die in der App möglicherweise nicht benötigt werden. Sie können diese hinzugefügten Namespaces optional deaktivieren und genau die Ansprüche verwenden, die der OpenID Connect-Server erstellt hat.
public void Configure(IApplicationBuilder app)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
Mithilfe der Schnittstelle IClaimsTransformation
können Sie der ClaimsPrincipal
-Klasse zusätzliche Ansprüche hinzufügen. Die Schnittstelle erfordert eine einzige TransformAsync
-Methode. Diese Methode wird möglicherweise mehrmals aufgerufen. Fügen Sie nur dann einen neuen Anspruch hinzu, wenn er nicht bereits im ClaimsPrincipal
vorhanden ist. Eine ClaimsIdentity
wird erstellt, um die neuen Ansprüche hinzuzufügen, und diese kann dem ClaimsPrincipal
hinzugefügt werden.
public class MyClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
var claimType = "myNewClaim";
if (!principal.HasClaim(claim => claim.Type == claimType))
{
claimsIdentity.AddClaim(new Claim(claimType, "myClaimValue"));
}
principal.AddIdentity(claimsIdentity);
return Task.FromResult(principal);
}
}
Die IClaimsTransformation
-Schnittstelle und die MyClaimsTransformation
-Klasse können in der ConfigureServices-Methode als Dienst hinzugefügt werden.
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();
Weitere Informationen finden Sie im folgenden Dokument:
Hinzufügen von Ansprüchen zu Identity mit IUserClaimsPrincipalFactory
Weitere Informationen finden Sie im folgenden Dokument:
Speichern zusätzlicher Ansprüche und Token externer Anbieter in ASP.NET Core
Feedback zu ASP.NET Core
ASP.NET Core ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben: