Как передать параметры сопоставления утверждений в IdentityServerJwt в ASP.NET Core 3.0 Preview 5?

На основе статьи о пользовательских утверждениях, я добавил пользовательское утверждение идентификатора клиента в процесс входа на сервер Identity следующим образом:

using System;
using System.Security.Claims;
using System.Threading.Tasks;
using MyNamespace.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using MyNamespace.Data;
using MyNamespace.Constants;

namespace MyNamespace.Factories
{

    public class TenantClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
    {
        public TenantClaimsPrincipalFactory(
            UserManager<ApplicationUser> userManager,
            IOptions<IdentityOptions> optionsAccessor)
            : base(userManager, optionsAccessor) {
        }

        // TODO: Remove hard binding to application db context
        protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user) {
            var identity = await base.GenerateClaimsAsync(user);
            var tenantId = ApplicationDbContext.DefaultTenantId;
            if (user.TenantId != Guid.Empty) {
                tenantId = user.TenantId;
            }
            identity.AddClaim(new Claim(CustomClaimTypes.TenantId, tenantId.ToString()));
            return identity;
        }
    } 

}

Метод генерации утверждений выполняется при входе в систему, и утверждения добавляются к удостоверению, поэтому эта часть выглядит нормально. Позже я пытаюсь прочитать претензию позже в службе поставщика арендаторов следующим образом.

using System;
using MyNamespace.Data;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Linq;
using MyNamespace.Constants;

namespace MyNamespace.Services
{

    public interface ITenantProvider
    {
        Guid GetTenantId();
    }

    public class TenantProvider : ITenantProvider
    {
        private IHttpContextAccessor _httpContextAccessor;

        public TenantProvider(IHttpContextAccessor httpContextAccessor
        {
            _httpContextAccessor = httpContextAccessor;
        }

        // TODO: Remove hard binding to application db context
        public Guid GetTenantId()
        {
            var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
            var user = _httpContextAccessor.HttpContext.User;
            var tenantId = _httpContextAccessor.HttpContext.User.FindFirst(CustomClaimTypes.TenantId).Value;    

            Guid tenantGuid = ApplicationDbContext.DefaultTenantId;
            Guid.TryParse(tenantId, out tenantGuid);

            return tenantGuid;
        }
    }

}

Однако, насколько я понимаю, претензия, идентифицированная CustomClaimTypes.TenantId, является не сопоставляется сервером идентификации автоматически. Мой вопрос заключается в следующем: как я могу отобразить

options.ClaimActions.MapUniqueJsonKey(CustomClaimTypes.TenantId, CustomClaimTypes.TenantId);

из Startup.cs, где я добавляю Identity server к своим зависимостям:

services.AddAuthentication()
            .AddIdentityServerJwt();

person conciliator    schedule 29.05.2019    source источник


Ответы (1)


Итак, в конце концов я получил решение, отличное от того, что искал изначально. Вместо сопоставления утверждений, созданных фабрикой, я наткнулся на Еще один пост здесь, в StackOverflow. В общем, я сделал следующее. Я реализовал следующее ProfileService

namespace MyNamespace.Services
{

    public class ProfileService : IProfileService
    {
        protected UserManager<ApplicationUser> _userManager;

        public ProfileService(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }

        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var user = await _userManager.GetUserAsync(context.Subject);

            var claims = new List<Claim>
            {
                new Claim(CustomClaimTypes.TenantId, user.TenantId.ToString()),
            };

            context.IssuedClaims.AddRange(claims);
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            var user = await _userManager.GetUserAsync(context.Subject);

            context.IsActive = (user != null) && user.IsActive;
        }
    }

}

Затем я добавил сервис в контейнер внедрения зависимостей по адресу Configure:

services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
                .AddProfileService<ProfileService>();

services.AddAuthentication()
                .AddIdentityServerJwt();

Таким образом, я все еще могу хорошо провести время, позволив AddIdentityServerJwt настроить IdentityServer4, одновременно получая свои претензии.

person conciliator    schedule 03.06.2019
comment
Я начал использовать тот же пример предварительного просмотра, клиентское приложение входит в систему, но я не могу получить какую-либо информацию об удостоверении личности (имя пользователя, утверждения и т. д.). Как мне сослаться на ProfileService и что мне передать для контекста? - person Mark Redman; 26.07.2019
comment
@MarkRedman, вы пытаетесь получить доступ к идентификационной информации со стороны сервера? Если вы хотите получить доступ к сеансу пользователя с одного из ваших контроллеров, вы можете использовать var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;. Не забудьте сначала передать IHttpContextAccessor httpContextAccessor в конструкторе вашего контроллера, сохранив ссылку на httpContextAccessor в приватном поле. - person conciliator; 26.07.2019
comment
У меня нет поступающих претензий (и добавленных вручную в AspNetUserClaims для тестирования). Я просто знаю, что пользователь прошел проверку подлинности, это реализация по умолчанию: docs.microsoft.com/en-us/aspnet/core/security/authentication/, используя реагировать. - person Mark Redman; 26.07.2019
comment
Хм - я не знаю, чувак. Возможно, вам было бы легче помочь, если бы вы написали отдельный вопрос по проблеме, с которой столкнулись, рассказав нам, как вы вручную добавили в AspNetUserClaims и так далее. Дай мне голову, и я посмотрю на это. ;) - person conciliator; 26.07.2019
comment
Я проведу еще несколько исследований и посмотрю, не пропустил ли я какую-либо дополнительную конфигурацию... - person Mark Redman; 26.07.2019