Как идентификатор AspNet генерирует утверждения пользователя

#asp.net-identity #claims-based-identity #claims #identityserver4

#asp.net-identity #идентификатор на основе утверждений #утверждения #identityserver4

Вопрос:

У меня есть сценарий с одностраничным приложением, реализованным с помощью Typescript, который использует oidc-client для получения id_token и access_token из основного приложения AspNet, которое использует IdentityServer4.

На сервере идентификации я также использую Identity с EntityFramework, чтобы я мог извлекать пользователя и его профиль для генерации утверждений и т.д.

Я сталкиваюсь со странной ситуацией, когда я, например, обновляю FirstName для пользователя, он должным образом обновляется в базе данных, но при генерации утверждений пользовательского уровня ( given_name , family_name , name и email ) given_name не обновляется новым именем, поэтому выданный id_token не содержит обновленной информации в заявках.

У меня есть что-то вроде этого:

 public class AspNetIdentityProfileService : IProfileService
{
  private readonly UserManager<User> _userManager;
  private readonly IUserRepository _userRepository;

  public AspNetIdentityProfileService(UserManager<User> userManager, IUserRepository userRepository)
  {
     _userManager = userManager;
     _userRepository = userRepository;
  }

  // some code where I generate a List<Claim> calling below method

  private async Task<IEnumerable<Claim>> GetUserLevelClaimsAsync(User user)
  {
     //user contains the updated info because it comes from DB.
     List<Claim> userClaims = new List<Claim>();
     var standardClaims = await _userManager.GetClaimsAsync(user); //has old values
     userClaims.AddRange(standardClaims);
     userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant()));
     return userClaims;
  }
}
  

Почему await _userManager.GetClaimsAsync(user); игнорируется обновленная информация для пользователя? Откуда берется старая информация?
Я перезапустил приложение, удалив файлы cookie браузера на случай, если они были сохранены в файле cookie, который сервер идентификации выдает для целей единого входа.. но я все еще не знаю, где кэшируется старая информация.

ОБНОВЛЕНИЕ 1: это модель пользователя.

 public class User : IdentityUser
{
    //Extend properties
    public DateTime CreatedOn { get; set; }
    public DateTime ModifiedOn { get; set; }
    public Guid? PrimaryBusinessId { get; set; }
    public Business PrimaryBusiness { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get
        {
            return string.Join(" ", FirstName, LastName);
        }
    }

    public DateTime? LastLoggedInOn { get; set; }

    public UserRole Role { get; set; }

    public List<UserBusiness> UserBusinesses { get; set; }
}
  

ОБНОВЛЕНИЕ 2:
Существует очевидный обходной путь, который заключается в том, чтобы вручную добавлять утверждения из пользовательских свойств, вместо этого полагаясь на UserManager идентификатора. Но остается вопрос, почему UserManager не извлекает обновленные значения в DB? и где он находит извлеченные старые значения?

     private IEnumerable<Claim> GetUserLevelClaims(User user)
    {
        List<Claim> userClaims = new List<Claim>();
        //var standardClaims = await _userManager.GetClaimsAsync(user); //does not retrieve updated fields
        userClaims.Add(new Claim(JwtClaimTypes.Name, user.FullName));
        userClaims.Add(new Claim(JwtClaimTypes.FamilyName, user.LastName));
        userClaims.Add(new Claim(JwtClaimTypes.GivenName, user.FirstName));
        userClaims.Add(new Claim(JwtClaimTypes.Email, user.Email));
        userClaims.Add(new Claim(JwtClaimTypes.Role, user.Role.ToString().ToLowerInvariant()));
        return userClaims;
    }
  

Комментарии:

1. Можете ли вы вставить модель данных пользователя вашего приложения.

2. @Lutando вставил модель пользователя в обновление 1 Имя и фамилия, похоже, не являются частью IdentityUser, поэтому я добавил свои собственные свойства. Как вы думаете, Identity не может получить доступ к значению этих свойств? Утверждения, выданные для пользователя, имеют старое имя и фамилию, не уверен, где будут храниться эти значения.

3. Также добавлено обновление 2 с обходным путем

4. Я предположил, что вы на самом деле не сохраняли их как утверждения в базе данных, поэтому я попросил модель пользовательских данных. Кроме того, это обходное решение прекрасно и является обычной практикой. Вы не обязаны выдавать только утверждения, которые хранятся как утверждения. Выданные вами токены не заботятся о том, как вы храните или упорядочиваете их на своем уровне сохраняемости.

Ответ №1:

Вам нужно указать IProfileService , откуда получать утверждения.

В основном userManager из AspNetCore.Identity будут получены только связанные утверждения для этого пользователя. То есть IdentityUser.Claims. «Старые значения» все еще существуют в AspNetUserClaims таблице. Если вы обновите связанный объект для этого пользователя для любого утверждения в таблице, то IProfileService выдадите эти обновленные утверждения, поскольку вы полагаетесь на userManager получение своих утверждений.

В основном, чтобы узнать, какие утверждения принадлежат пользователю, вы можете видеть, что есть ‘корневая таблица’, вызываемая AspNetUsers . С этой таблицей связаны утверждения, называемые таблицей called AspNetUserClaims . В этой таблице просто отображаются пользователи и их 1-миллионные утверждения. Короче говоря, вам нужно отредактировать значение утверждений в этой таблице.

Не стесняйтесь добавлять больше утверждений в IProfileService в GetProfileDataAsync . Довольно часто дополнительные утверждения добавляются на основе самого объекта таблицы. как вы продемонстрировали в своем обновлении # 2

Ответ №2:

@Lutando указал мне правильное направление своими комментариями.

Чтобы ответить на мой собственный вопрос, менеджер пользователей собирает утверждения не из таблицы User, а из другой таблицы Identity, называемой UserClaims. Я не знал, что эта таблица использовалась, но теперь это имеет смысл.

Как также предполагает Лутандо, обходной путь вполне допустим, и мне не нужно полагаться на диспетчер пользователей удостоверения для генерации утверждений. Мне даже не нужно использовать эту таблицу UserClaims, потому что у меня есть имя и фамилия как часть моей таблицы пользователей, как показано в обновлении 1.