IdentityServer4 и ASP.Net Identity: добавление дополнительных утверждений - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь использовать IdentityServer4 с ASP.Net Identity Core, предоставляя хранилище пользователей.Я свободно следовал этому руководству: https://www.scottbrady91.com/Identity-Server/Getting-Started-with-IdentityServer-4, и дошел до того, что я могу регистрировать и аутентифицировать пользователей локально, используя ASP.Net Identity.

Моя проблема заключается в том, что я добавляю некоторые претензии по регистрации:

var createUserResult = await _userManager.CreateAsync(user, model.Password);

if (createUserResult.Succeeded)
{
    var claims = new List<Claim>
    {
        new Claim(JwtClaimTypes.Email, user.Email),
        new Claim(JwtClaimTypes.Role, "user"),
        new Claim("test-claim", "loremipsum")
    };

    await _userManager.AddClaimsAsync(user, claims);

    await HttpContext.SignInAsync(user.Id, user.UserName, new AuthenticationProperties());
    return Redirect(model.ReturnUrl ?? "~/");
}

Они сохранены правильно, и я вижу их в базе данных.Однако после входа в систему пользовательский объект имеет только следующие утверждения:

  • sub
  • name
  • auth_time
  • idp
  • amr

При просмотре в Интернете кажется, что мне нужно переопределить UserClaimsPrincipalFactory и зарегистрировать эту реализацию в контейнере DI:

public class CustomUserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
{
    public CustomUserClaimsPrincipalFactory(
        UserManager<ApplicationUser> userManager,
        RoleManager<IdentityRole> roleManager,
        IOptions<IdentityOptions> options) : base(userManager, roleManager, options)
    {
        Console.WriteLine("Test");
    }

    public override async Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
    {
        var principal = await base.CreateAsync(user);
        ((ClaimsIdentity) principal.Identity).AddClaim(new Claim("yolo", "swag"));

        return principal;
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var identity = await base.GenerateClaimsAsync(user);
        identity.AddClaim(new Claim("yolo", "swag"));

        return identity;
    }
}

Зарегистрирован в контейнере DI следующим образом:

services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, CustomUserClaimsPrincipalFactory>();

Насколько я понимаю, эта фабрика основных участников должна добавить требуемые утверждения к объекту User, но этого не происходит.Я вижу, что основная фабрика пользовательских утверждений создается с использованием точки останова в конструкторе, но функция GenerateClaimsAsync никогда не вызывается.

Идентификационные данные IdentityServer и ASP.Net регистрируются следующим образом:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddIdentityServer(config =>
    {
        config.PublicOrigin = _configuration.PublicOriginUrl;
    })
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder => builder.UseNpgsql(
            _sqlConnectionString,
            sqlOptions => sqlOptions.MigrationsAssembly(MigrationsAssembly));
    })
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = builder => builder.UseNpgsql(
            _sqlConnectionString,
            sqlOptions => sqlOptions.MigrationsAssembly(MigrationsAssembly));
    })
    .AddAspNetIdentity<ApplicationUser>()
    .AddDeveloperSigningCredential();

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

Как реализовать основную фабрику пользовательских утверждений пользователя таким образом, чтобы я мог сделать что-то подобное в представлении?

// "yolo" is a custom claim
@User.FindFirst("yolo")

1 Ответ

0 голосов
/ 18 декабря 2018

Я решил это (по крайней мере, таким образом, чтобы удовлетворить мои требования).Логика, которая выполняла вход в проект быстрого запуска, выглядела следующим образом:

...
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password)) {
    await _events.RaiseAsync(
        new UserLoginSuccessEvent(user.UserName, user.Id, user.UserName));


    AuthenticationProperties props = null;
    if (AccountOptions.AllowRememberLogin && model.RememberLogin) {
        props = new AuthenticationProperties {
            IsPersistent = true,
            ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
        };
    };

    await HttpContext.SignInAsync(user.Id, user.UserName, props);
    ...
}

Посмотрев на методы расширения , которые IdentityServer4 добавляет к HttpContext, я обнаружил, что некоторые из них принимаютмассив претензий.

Я изменил логику входа в систему в контроллере своей учетной записи:

...
var userClaims = await _userManager.GetClaimsAsync(user);
await HttpContext.SignInAsync(user.Id, user.UserName, props, userClaims.toArray());
...

Это успешно добавляет все заявки пользователя из базы данных в текущий сеанс.Отсюда я смог выбрать только те заявки, которые хотел, и вместо этого передать их массив.

Теперь, когда требуемые заявки сохранены как часть сеанса, я могу вызвать @User.FindFirst("yolo") изпредставление или другие контроллеры, как мне требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...