У меня установлена и работает Asp.Net Identity 2 с пользовательским хранилищем пользователей, поддерживаемым SQL Server через Dapper.На данный момент в моей разработке / тестировании я занимаюсь только локальными учетными записями (но буду добавлять внешних провайдеров входа).У меня есть пользовательский пользователь, который включает стандартные свойства, которые нужны Asp.Net Identity, и добавил несколько своих собственных (FirstName, LastName):
public class AppUser : IUser<Guid>
{
public Guid Id { get; set; }
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public bool LockoutEnabled { get; set; }
public DateTimeOffset LockoutEndDate { get; set; }
public int AccessFailedCount { get; set; }
// Custom User Properties
public string FirstName { get; set; }
public string LastName { get; set; }
}
В моем веб-приложении MVC я настраиваю OIDC следующим образомИтак:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["OpenIdConnectAuthenticationOptions.Authority"],
ClientId = "MVC.Web",
Scope = "openid profile email",
RedirectUri = ConfigurationManager.AppSettings["OpenIdConnectAuthenticationOptions.RedirectUri"],
ResponseType = "id_token",
SignInAsAuthenticationType = "Cookies"
});
Поскольку я включил profile
в качестве запрошенной области, я получаю:
preferred_username: testuser
И поскольку я включил email
в качестве запрошенной области, я получаю:
email: user@test.com
email_verified: true
Я явно не говорю своему AspNetIdentityUserService
, как сопоставить свойство UserName
в моем AppUser
с утверждением preferred_username
, и я не уверен, как это происходит. Поэтому я не понимаю, как связать свойство FirstName
с заявкой given_name
, чтобы оно было возвращено с id_token
.
ЧтоЯ исследовал:
Так что, если вы посмотрите на образец IdentityServer3 AspNetIdentity здесь Я нашел это ClaimsIdentityFactory
, которое выглядело так, как будто оно должно сработать:
public override async Task<ClaimsIdentity> CreateAsync(UserManager<User, string> manager, User user, string authenticationType)
{
var ci = await base.CreateAsync(manager, user, authenticationType);
if (!String.IsNullOrWhiteSpace(user.FirstName))
{
ci.AddClaim(new Claim("given_name", user.FirstName));
}
if (!String.IsNullOrWhiteSpace(user.LastName))
{
ci.AddClaim(new Claim("family_name", user.LastName));
}
return ci;
}
Итак, я добавил это в свое приложение и подключил его в своем обычном UserManager
.И я достигаю точки останова, когда создается экземпляр класса, но я никогда не достигаю точки останова для метода CreateAsync
, и мои утверждения не возвращаются.
Я также видел это IdentityServer3 CustomПользовательский пример здесь , и я нашел этот GetProfileDataAsync
метод, который выглядел так, как будто это было бы правильно (но мне кажется, что я копаю глубже, чем следовало бы для чего-то, казалось бы, такого простого / обычного):
public override Task GetProfileDataAsync(ProfileDataRequestContext context)
{
// issue the claims for the user
var user = Users.SingleOrDefault(x => x.Subject == context.Subject.GetSubjectId());
if (user != null)
{
context.IssuedClaims = user.Claims.Where(x => context.RequestedClaimTypes.Contains(x.Type));
}
return Task.FromResult(0);
}
У меня была та же проблема, в том, что точка останова в этом методе никогда не была отключена.Я даже зашел так далеко, что посмотрел исходный код IdentityServer3 и увидел, что он вызывается только в том случае, если в области действия установлен флаг IncludeAllClaimsForUser
.Но я здесь использую стандартную область действия profile
, поэтому я начал сомневаться, нужно ли мне сделать собственное определение для области профиля, для которой установлен флаг IncludAllClaimsForUser
, или есть способ добавить этот флаг встандартный охват.
И чтобы добавить ко всему этому ... Это нужно сделать только при использовании локальной учетной записи.Когда я внедряю внешних провайдеров входа в систему, я буду запрашивать там профиль и ожидать, что смогу получить имя и фамилию.Итак, мне интересно, что произойдет, когда у меня уже есть эти претензии (или как определить, нужно ли мне их извлекать из моего пользовательского магазина или нет).Похоже, мне нужно подключиться к чему-то, что запускается только при локальном входе в систему.
А потом я действительно начал задаваться вопросом, правильно ли я поступаю, так как вижу / нахожу так малоинформация об этом (я бы ожидал, что это будет довольно распространенный сценарий, который другие уже реализовали, и ожидал найти документы / образцы).Пытаюсь решить это за день сейчас.Надеюсь, у кого-то есть быстрый ответ / указатель!