Freigeben über


Zuordnen, Anpassen und Transformieren von Ansprüchen in ASP.NET Core

Von Damien Bowden

Ansprüche können anhand beliebiger Benutzer- oder Identitätsdaten erstellt werden, die über einen vertrauenswürdigen Identitätsanbieter oder eine ASP.NET Core-Identität ausgegeben werden können. 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

Zuordnung von Ansprüchen mithilfe der OpenID Connect-Authentifizierung

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.

Zuordnen von Namens- und Rollenansprüchen

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

Anspruchsnamespaces, Standardnamespaces

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.

Erweitern oder Hinzufügen von benutzerdefinierten Ansprüchen mit IClaimsTransformation

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

Zuordnen von Ansprüchen von externen Identitätsanbietern

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 Benutzer- oder Identitätsdaten erstellt werden, die über einen vertrauenswürdigen Identitätsanbieter oder eine ASP.NET Core-Identität ausgegeben werden können. 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

Zuordnung von Ansprüchen mithilfe der OpenID Connect-Authentifizierung

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

Zuordnen von Namens- und Rollenansprüchen

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

Anspruchsnamespaces, Standardnamespaces

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

Erweitern oder Hinzufügen von benutzerdefinierten Ansprüchen mit IClaimsTransformation

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

Erweitern oder Hinzufügen benutzerdefinierter Ansprüche in ASP.NET Core Identity

Weitere Informationen finden Sie im folgenden Dokument:

Hinzufügen von Ansprüchen zu Identity mit IUserClaimsPrincipalFactory

Zuordnen von Ansprüchen von externen Identitätsanbietern

Weitere Informationen finden Sie im folgenden Dokument:

Speichern zusätzlicher Ansprüche und Token externer Anbieter in ASP.NET Core