Поделиться через


Сопоставление, настройка и преобразование утверждений в ASP.NET Core

Дэмиен Боуден

Утверждения можно создавать из любых данных пользователя или данных удостоверения личности, которые могут быть созданы с помощью доверенного поставщика удостоверений или удостоверений ASP.NET Core. Утверждение — это пара "имя-значение", которая представляет собой предмет, а не то, что он может делать. В этой статье рассматриваются следующие области:

  • Настройка и сопоставление утверждений с помощью клиента OpenID Connect
  • Задание утверждения имени и роли
  • Сброс пространств имен утверждений
  • Настройка, расширение утверждений с помощью TransformAsync

Сопоставление утверждений с помощью проверки подлинности OpenID Connect

Утверждения профиля можно вернуть в id_tokenобъекте , который возвращается после успешной проверки подлинности. Клиентское приложение ASP.NET Core требует только области профиля. При использовании утверждений не требуется дополнительное id_token сопоставление утверждений.

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

Для предыдущего кода требуется пакет NuGet Microsoft.AspNetCore.Authentication.OpenIdConnect .

Другим способом получения утверждений пользователя является использование API сведений о пользователе OpenID Connect. Клиентское приложение ASP.NET Core использует GetClaimsFromUserInfoEndpoint свойство для настройки этого свойства. Одним из важных отличий от первых параметров является то, что необходимо указать утверждения, которые требуется использовать MapUniqueJsonKey метод, в противном случае в клиентском приложении будут доступны только namegiven_nameemail стандартные утверждения. Утверждения, включенные в список id_token , сопоставляются по умолчанию. Это основное отличие от первого варианта. Необходимо явно определить некоторые необходимые утверждения.

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.

Примечание.

По умолчанию обработчик Open ID Connect использует запросы авторизации по протоколу PAR, если документ обнаружения поставщика удостоверений заявляет о поддержке PAR. Документ обнаружения поставщика удостоверений обычно находится в .well-known/openid-configuration. Если невозможно использовать PAR в конфигурации клиента у поставщика удостоверений, можно отключить PAR, используя параметр 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;
    });

Чтобы убедиться, что проверка подлинности выполняется только при использовании PAR, используйте pushedAuthorizationBehavior.Require . Это изменение также представляет новое событие OnPushAuthorization для OpenIdConnectEvents , которое можно использовать для настройки запроса принудительной авторизации или обработки его вручную. Дополнительные сведения см. в предложении API.

Сопоставление утверждений имен и ролей

Утверждение Name и утверждение роли сопоставляются со свойствами по умолчанию в контексте HTTP ASP.NET Core. Иногда требуется использовать различные утверждения для свойств по умолчанию или утверждение имени, а утверждение роли не совпадает со значениями по умолчанию. Утверждения можно сопоставить с помощью свойства TokenValidationParameters и задать любое утверждение по мере необходимости. Значения из утверждений можно использовать непосредственно в httpContext User.Identity. Свойство name и роли.

User.Identity.Name Если отсутствуют значения или роли отсутствуют, проверьте значения в возвращенных утверждениях и задайте NameClaimType значения и RoleClaimType значения. Возвращенные утверждения из проверки подлинности клиента можно просмотреть в контексте 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"
       };
  });

Пространства имен утверждений, пространства имен по умолчанию

ASP.NET Core добавляет пространства имен по умолчанию в некоторые известные утверждения, которые могут не потребоваться в приложении. При необходимости отключите эти добавленные пространства имен и используйте точные утверждения, созданные сервером 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.

Если необходимо отключить пространства имен для каждой схемы, а не глобально, можно использовать параметр 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.

Расширение или добавление настраиваемых утверждений с помощью IClaimsTransformation

Интерфейс IClaimsTransformation можно использовать для добавления дополнительных утверждений в ClaimsPrincipal класс. Для интерфейса требуется один метод TransformAsync. Этот метод может вызываться несколько раз. Добавьте новое утверждение только в том случае, если оно еще не существует в .ClaimsPrincipal Создается ClaimsIdentity для добавления новых утверждений и его можно добавить в .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);
    }
}

Интерфейс IClaimsTransformation и MyClaimsTransformation класс можно зарегистрировать как службу:

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

Сопоставление утверждений от внешних поставщиков удостоверений

См. следующий документ:

Сохранение дополнительных утверждений и маркеров от внешних поставщиков в ASP.NET Core

Утверждения можно создавать из любых данных пользователя или удостоверений, которые могут быть выданы доверенным поставщиком удостоверений или средствами ASP.NET Core Identity. Утверждение — это пара "имя-значение", которая представляет собой предмет, а не то, что он может делать. В этой статье рассматриваются следующие области:

  • Настройка и сопоставление утверждений с помощью клиента OpenID Connect
  • Задание утверждения имени и роли
  • Сброс пространств имен утверждений
  • Настройка, расширение утверждений с помощью TransformAsync

Сопоставление утверждений с помощью проверки подлинности OpenID Connect

Утверждения профиля можно вернуть в id_tokenобъекте , который возвращается после успешной проверки подлинности. Клиентское приложение ASP.NET Core требует только области профиля. При использовании утверждений не требуется дополнительное id_token сопоставление утверждений.

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

Другим способом получения утверждений пользователя является использование API сведений о пользователе OpenID Connect. Клиентское приложение ASP.NET Core использует GetClaimsFromUserInfoEndpoint свойство для настройки этого свойства. Одним из важных отличий от первых параметров является то, что необходимо указать утверждения, которые требуется использовать MapUniqueJsonKey метод, в противном случае в клиентском приложении будут доступны только namegiven_nameemail стандартные утверждения. Утверждения, включенные в список id_token , сопоставляются по умолчанию. Это основное отличие от первого варианта. Необходимо явно определить некоторые необходимые утверждения.

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

Сопоставление утверждений имен и ролей

Утверждение Name и утверждение роли сопоставляются со свойствами по умолчанию в контексте HTTP ASP.NET Core. Иногда требуется использовать различные утверждения для свойств по умолчанию или утверждение имени, а утверждение роли не совпадает со значениями по умолчанию. Утверждения можно сопоставить с помощью свойства TokenValidationParameters и задать любое утверждение по мере необходимости. Значения из утверждений можно использовать непосредственно в httpContext User.Identity. Свойство name и роли.

User.Identity.Name Если отсутствуют значения или роли отсутствуют, проверьте значения в возвращенных утверждениях и задайте NameClaimType значения и RoleClaimType значения. Возвращенные утверждения из проверки подлинности клиента можно просмотреть в контексте 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"
       };
   });

Пространства имен утверждений, пространства имен по умолчанию

ASP.NET Core добавляет пространства имен по умолчанию в некоторые известные утверждения, которые могут не потребоваться в приложении. При необходимости отключите эти добавленные пространства имен и используйте точные утверждения, созданные сервером OpenID Connect.

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

Расширение или добавление настраиваемых утверждений с помощью IClaimsTransformation

Интерфейс IClaimsTransformation можно использовать для добавления дополнительных утверждений в ClaimsPrincipal класс. Для интерфейса требуется один метод TransformAsync. Этот метод может вызываться несколько раз. Добавьте новое утверждение только в том случае, если оно еще не существует в .ClaimsPrincipal Создается ClaimsIdentity для добавления новых утверждений и его можно добавить в .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);
    }
}

Интерфейс IClaimsTransformation и MyClaimsTransformation класс можно добавить в метод ConfigureServices в качестве службы.

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

Расширение или добавление пользовательских утверждений в ASP.NET Core Identity

См. следующий документ:

Добавление утверждений в Identity использование IUserClaimsPrincipalFactory

Сопоставление утверждений от внешних поставщиков удостоверений

См. следующий документ:

Сохранение дополнительных утверждений и маркеров от внешних поставщиков в ASP.NET Core