#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.