Condividi tramite


Mapping, personalizzazione e trasformazione delle attestazioni in ASP.NET Core

Di Damien Bowden

Attestazioni possono essere create da qualsiasi utente o dai dati di identità che possono essere emessi usando un provider di identità attendibile o l'identità di ASP.NET Core. Un'attestazione è una coppia di valori nome che rappresenta ciò che l'oggetto è, non le operazioni che l'oggetto può eseguire. Questo articolo illustra le aree seguenti:

  • Come configurare ed eseguire il mapping delle attestazioni usando un client OpenID Connect
  • Impostare il nome e l'attestazione del ruolo
  • Reimpostare gli spazi dei nomi delle attestazioni
  • Personalizzare ed estendere le attestazioni usando TransformAsync

Mapping delle attestazioni tramite l'autenticazione OpenID Connect

Le attestazioni del profilo possono essere restituite in id_token, che viene restituito dopo un'autenticazione riuscita. L'app client ASP.NET Core richiede solo l'ambito del profilo. Quando si usa per id_token le attestazioni, non è necessario alcun mapping di attestazioni aggiuntive.

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

Il codice precedente richiede il pacchetto NuGet Microsoft.AspNetCore.Authentication.OpenIdConnect .

Un altro modo per ottenere le attestazioni utente consiste nell'usare l'API OpenID Connect User Info. L'app client ASP.NET Core usa la GetClaimsFromUserInfoEndpoint proprietà per configurarlo. Una differenza importante rispetto alle prime impostazioni consiste nel fatto che è necessario specificare le attestazioni necessarie usando il MapUniqueJsonKey metodo , altrimenti solo le namegiven_name attestazioni standard e email saranno disponibili nell'app client. Le attestazioni incluse in id_token vengono mappate per impostazione predefinita. Questa è la differenza principale per la prima opzione. È necessario definire in modo esplicito alcune delle attestazioni necessarie.

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.

Nota

Il gestore Open ID Connect predefinito usa richieste di autorizzazione push (PAR) se il documento di individuazione del provider di identità annuncia il supporto per PAR. Il documento di individuazione del provider di identità si trova in genere in .well-known/openid-configuration. Se non è possibile usare PAR nella configurazione del client sul provider di identità, PAR può essere disabilitato utilizzando l'opzione 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;
    });

Per assicurarsi che l'autenticazione abbia esito positivo solo se si usa PAR, usare invece PushedAuthorizationBehavior.Require . Questa modifica introduce anche un nuovo evento OnPushAuthorization in OpenIdConnectEvents che può essere usato per personalizzare la richiesta di autorizzazione push o gestirla manualmente. Per altri dettagli, vedere la proposta dell'API.

Mapping dell'attestazione del nome e dell'attestazione del ruolo

L'attestazione Name e l'attestazione Role vengono mappate alle proprietà predefinite nel contesto HTTP principale di ASP.NET. A volte è necessario usare attestazioni diverse per le proprietà predefinite oppure l'attestazione del nome e l'attestazione del ruolo non corrispondono ai valori predefiniti. Le attestazioni possono essere mappate usando la proprietà TokenValidationParameters e impostate su qualsiasi attestazione in base alle esigenze. I valori delle attestazioni possono essere usati direttamente in HttpContext User.Identity. Proprietà Name e ruoli.

Se non User.Identity.Name ha alcun valore o i ruoli sono mancanti, controllare i valori nelle attestazioni restituite e impostare i NameClaimType valori e RoleClaimType . Le attestazioni restituite dall'autenticazione client possono essere visualizzate nel contesto 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"
       };
  });

Spazi dei nomi delle attestazioni, spazi dei nomi predefiniti

ASP.NET Core aggiunge spazi dei nomi predefiniti ad alcune attestazioni note, che potrebbero non essere necessarie nell'app. Facoltativamente, disabilitare questi spazi dei nomi aggiunti e usare le attestazioni esatte create dal server 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.

Se è necessario disabilitare gli spazi dei nomi per schema e non a livello globale, è possibile usare l'opzione 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.

Estendere o aggiungere attestazioni personalizzate usando IClaimsTransformation

L'interfaccia IClaimsTransformation può essere usata per aggiungere attestazioni aggiuntive alla ClaimsPrincipal classe . L'interfaccia richiede un singolo metodo TransformAsync. Questo metodo può essere chiamato più volte. Aggiungere una nuova attestazione solo se non esiste già in ClaimsPrincipal. Viene ClaimsIdentity creato un oggetto per aggiungere le nuove attestazioni e può essere aggiunto a 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);
    }
}

L'interfaccia IClaimsTransformation e la MyClaimsTransformation classe possono essere registrate come servizio:

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

Mappare le attestazioni dai provider di identità esterni

Fare riferimento al documento seguente:

Rendere persistenti attestazioni e token aggiuntivi da provider esterni in ASP.NET Core

Le attestazioni possono essere create da qualsiasi utente o dati di identità che possono essere emessi utilizzando un provider di identità attendibile o ASP.NET Core Identity. Un'attestazione è una coppia di valori nome che rappresenta ciò che l'oggetto è, non le operazioni che l'oggetto può eseguire. Questo articolo illustra le aree seguenti:

  • Come configurare ed eseguire il mapping delle attestazioni usando un client OpenID Connect
  • Impostare il nome e l'attestazione del ruolo
  • Reimpostare gli spazi dei nomi delle attestazioni
  • Personalizzare ed estendere le attestazioni usando TransformAsync

Mapping delle attestazioni tramite l'autenticazione OpenID Connect

Le attestazioni del profilo possono essere restituite in id_token, che viene restituito dopo un'autenticazione riuscita. L'app client ASP.NET Core richiede solo l'ambito del profilo. Quando si usa per id_token le attestazioni, non è necessario alcun mapping di attestazioni aggiuntive.

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

Un altro modo per ottenere le attestazioni utente consiste nell'usare l'API OpenID Connect User Info. L'applicazione client ASP.NET Core usa la GetClaimsFromUserInfoEndpoint proprietà per configurarlo. Una differenza importante rispetto alle prime impostazioni consiste nel fatto che è necessario specificare le attestazioni necessarie usando il MapUniqueJsonKey metodo , altrimenti solo le namegiven_name attestazioni standard e email saranno disponibili nell'applicazione client. Le attestazioni incluse in id_token vengono mappate per impostazione predefinita. Questa è la differenza principale per la prima opzione. È necessario definire in modo esplicito alcune delle attestazioni necessarie.

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

Mapping dell'attestazione del nome e dell'attestazione del ruolo

L'attestazione Name e l'attestazione Role vengono mappate alle proprietà predefinite nel contesto HTTP principale di ASP.NET. A volte è necessario usare attestazioni diverse per le proprietà predefinite oppure l'attestazione del nome e l'attestazione del ruolo non corrispondono ai valori predefiniti. Le attestazioni possono essere mappate usando la proprietà TokenValidationParameters e impostate su qualsiasi attestazione in base alle esigenze. I valori delle attestazioni possono essere usati direttamente in HttpContext User.Identity. Proprietà Name e ruoli.

Se non User.Identity.Name ha alcun valore o i ruoli sono mancanti, controllare i valori nelle attestazioni restituite e impostare i NameClaimType valori e RoleClaimType . Le attestazioni restituite dall'autenticazione client possono essere visualizzate nel contesto 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"
       };
   });

Spazi dei nomi delle attestazioni, spazi dei nomi predefiniti

ASP.NET Core aggiunge spazi dei nomi predefiniti ad alcune attestazioni note, che potrebbero non essere necessarie nell'app. Facoltativamente, disabilitare questi spazi dei nomi aggiunti e usare le attestazioni esatte create dal server OpenID Connect.

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

Estendere o aggiungere attestazioni personalizzate usando IClaimsTransformation

L'interfaccia IClaimsTransformation può essere usata per aggiungere attestazioni aggiuntive alla ClaimsPrincipal classe . L'interfaccia richiede un singolo metodo TransformAsync. Questo metodo può essere chiamato più volte. Aggiungere una nuova attestazione solo se non esiste già in ClaimsPrincipal. Viene ClaimsIdentity creato un oggetto per aggiungere le nuove attestazioni e può essere aggiunto a 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);
    }
}

L'interfaccia IClaimsTransformation e la MyClaimsTransformation classe possono essere aggiunte nel metodo ConfigureServices come servizio.

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

Estendere o aggiungere attestazioni personalizzate in ASP.NET Core Identity

Fare riferimento al documento seguente:

Aggiungere attestazioni all'uso di Identity IUserClaimsPrincipalFactory

Mappare le attestazioni dai provider di identità esterni

Fare riferimento al documento seguente:

Rendere persistenti attestazioni e token aggiuntivi da provider esterni in ASP.NET Core