Sdílet prostřednictvím


Mapování, přizpůsobení a transformace deklarací identity v ASP.NET Core

Autor: Damien Bowden

Nároky lze vytvořit z libovolného uživatele nebo údajů identity, které mohou být vystaveny pomocí důvěryhodného poskytovatele identity nebo ASP.NET Core Identity. Atribut je párová hodnota názvu, která představuje, co předmět je, ne co může předmět dělat. Tento článek se zabývá následujícími oblastmi:

  • Konfigurace a mapování deklarací identity pomocí klienta OpenID Connect
  • Nastavit název a nárok role
  • Resetování oborů názvů nároků
  • Upravte a rozšiřte deklarace identity pomocí TransformAsync

Mapování deklarací identity pomocí ověřování OpenID Connect

Nároky profilu mohou být vráceny v id_token, které je vráceno po úspěšném ověření. Klientská aplikace ASP.NET Core vyžaduje jenom obor profilu. Při použití id_token se nevyžaduje žádné další mapování deklarací.

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

Předchozí kód vyžaduje balíček NuGet Microsoft.AspNetCore.Authentication.OpenIdConnect .

Dalším způsobem, jak získat deklarace identity uživatelů, je použít rozhraní OPENID Connect User Info API. Klientská aplikace ASP.NET Core používá GetClaimsFromUserInfoEndpoint vlastnost ke konfiguraci. Jedním z důležitých rozdílů od prvního nastavení je, že musíte zadat deklarace identity, které požadujete pomocí MapUniqueJsonKey metody, jinak budou v klientské aplikaci k dispozici pouze namegiven_name a email standardní deklarace identity. Položky zahrnuté ve id_token jsou mapovány výchozí. Jedná se o hlavní rozdíl od první možnosti. Musíte explicitně definovat některé požadované nároky.

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.

Poznámka:

Výchozí obslužná rutina Open ID Connect používá Pushed Authorization Requests (PAR), pokud dokument pro zjišťování zprostředkovatele identity inzeruje podporu pro PAR. Dokument zjišťování zprostředkovatele identity se obvykle nachází v .well-known/openid-configuration. Pokud v konfiguraci klienta u zprostředkovatele identity nemůžete použít PAR, můžete ho zakázat pomocí možnosti PushedAuthorizationBehavior.

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

Pokud chcete zajistit, aby ověřování proběhlo úspěšně jenom v případě použití funkce PAR, použijte místo toho PushedAuthorizationBehavior.Require. Tato změna také zavádí novou událost OnPushAuthorization pro OpenIdConnectEvents, která se dá použít k přizpůsobení žádosti o nabízenou autorizaci nebo k jeho ručnímu zpracování. Další informace najdete v návrhu rozhraní API .

Požadavek na jméno a mapování rolových požadavků

Deklarace názvu a role jsou mapovány na výchozí vlastnosti v kontextu HTTP ASP.NET Core. Někdy se vyžaduje použití různých deklarací identity pro výchozí vlastnosti nebo deklarace názvu a deklarace identity role neodpovídá výchozím hodnotám. Nároky lze mapovat pomocí vlastnosti TokenValidationParameters a nastavit je na jakýkoli požadovaný nárok. Hodnoty z deklarací identity lze použít přímo ve vlastnosti User..Name objektu HttpContext a v rolích.

Pokud User.Identity.Name nemá žádnou hodnotu nebo chybí role, zkontrolujte hodnoty ve vrácených tvrzeních a nastavte hodnoty NameClaimType a RoleClaimType. Vrácené deklarace identity z ověřování klienta se dají zobrazit v kontextu HTTP.

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

Obory názvů pro požadavky, výchozí obory názvů

ASP.NET Core přidá některé výchozí obory názvů do známých identitních deklarací, které nemusí být v aplikaci potřeba. Volitelně tyto přidané obory názvů zakažte a použijte přesné deklarace identity vytvořené serverem OpenID Connect.

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.

Pokud potřebujete zakázat obory názvů podle schématu, a ne globálně, můžete použít možnost MapInboundClaims = false.

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.

Rozšíření nebo přidání vlastních deklarací pomocí IClaimsTransformation

Rozhraní IClaimsTransformation lze použít k přidání dalších deklarací identity do ClaimsPrincipal třídy. Rozhraní vyžaduje jednu metodu TransformAsync. Tato metoda se může volat vícekrát. Přidejte novou položku pouze v případě, že ještě neexistuje v ClaimsPrincipal. Vytvoří se ClaimsIdentity na přidání nových nároků, který lze přidat k ClaimsPrincipal.

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

Rozhraní IClaimsTransformation a MyClaimsTransformation třída lze zaregistrovat jako službu:

builder.Services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();

Mapování identitních tvrzení z externích poskytovatelů identity

Projděte si následující dokument:

Zachování dalších deklarací identity a tokenů od externích poskytovatelů v ASP.NET Core

Nároky mohou být vytvořeny z libovolného uživatelského nebo identitního data, které lze vystavit pomocí důvěryhodného poskytovatele identity nebo ASP.NET Core Identity. Nárok je dvojice názvu a hodnoty, která reprezentuje, čím subjekt je, ne co subjekt může dělat. Tento článek se zabývá následujícími oblastmi:

  • Konfigurace a mapování deklarací identity pomocí klienta OpenID Connect
  • Nastavte jméno a nárok na roli
  • Resetování oborů názvů nároků
  • Přizpůsobte, rozšiřte nároky pomocí TransformAsync

Mapování údajů o identitě pomocí ověřování OpenID Connect

Nároky profilu lze vrátit v id_token, který je vrácen po úspěšném ověření. Klientská aplikace ASP.NET Core vyžaduje jenom obor profilu. Při použití id_token pro nároky se nevyžaduje žádné další mapování nároků.

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

Dalším způsobem, jak získat deklarace identity uživatelů, je použít rozhraní OPENID Connect User Info API. Klientská aplikace ASP.NET Core používá GetClaimsFromUserInfoEndpoint vlastnost ke konfiguraci. Jedním z důležitých rozdílů od prvního nastavení je, že musíte zadat deklarace identity, které požadujete pomocí MapUniqueJsonKey metody, jinak budou v klientské aplikaci k dispozici pouze namegiven_name a email standardní deklarace identity. Nároky zahrnuté v id_token jsou mapovány výchozí. Jedná se o hlavní rozdíl od první možnosti. Musíte vyloženě definovat některé požadované nároky.

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

Název tvrzení a mapování tvrzení o roli

Nárok na jméno a nárok na roli jsou mapovány na výchozí vlastnosti v kontextu HTTP ASP.NET Core. Někdy se vyžaduje použití různých deklarací identity pro výchozí vlastnosti nebo deklarace názvu a deklarace identity role neodpovídá výchozím hodnotám. Nároky lze mapovat pomocí vlastnosti TokenValidationParameters a nastavit na jakýkoli nárok podle potřeby. Hodnoty z deklarací identity lze použít přímo v httpContext User.Identity. Name property and the roles.

Pokud User.Identity.Name nemá žádnou hodnotu nebo chybí role, zkontrolujte hodnoty ve vrácených položkách a nastavte hodnoty pro NameClaimType a RoleClaimType. Vrácené deklarace identity z ověřování klienta se dají zobrazit v kontextu HTTP.

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

Obory názvů deklarací identity, výchozí obory názvů

ASP.NET Core přidává výchozí obory názvů k některým známým nárokům, které nemusí být v aplikaci potřeba. Volitelně tyto přidané obory názvů zakažte a použijte přesné deklarace identity vytvořené serverem OpenID Connect.

public void Configure(IApplicationBuilder app)
{
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

Rozšíření nebo přidání vlastních deklarací pomocí IClaimsTransformation

Rozhraní IClaimsTransformation lze použít k přidání dalších deklarací identity do ClaimsPrincipal třídy. Rozhraní vyžaduje jednu metodu TransformAsync. Tato metoda se může volat vícekrát. Přidejte nový nárok pouze v případě, že ještě neexistuje v ClaimsPrincipal. Vytvoří se ClaimsIdentity pro přidání nových nároků, které lze přidat do ClaimsPrincipal.

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

Rozhraní IClaimsTransformation a MyClaimsTransformation třída lze přidat do metody ConfigureServices jako službu.

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IClaimsTransformation, MyClaimsTransformation>();

Rozšíření nebo přidání vlastních nároků v ASP.NET Core Identity

Projděte si následující dokument:

Přidejte nároky pomocí Identity IUserClaimsPrincipalFactory

Mapování požadavků od externích poskytovatelů identity

Projděte si následující dokument:

Zachování dalších deklarací identity a tokenů od externích poskytovatelů v ASP.NET Core