Проверка подлинности токена веб-API ASP Identity 2 + - постоянные утверждения не загружаются

У меня возникли проблемы с утверждениями в ASP.NET Web API Token Auth.

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

Разбивка моей установки выглядит следующим образом.

  1. Пользовательский класс: имеет метод GenerateUserIdentityAsync (довольно стандартный) и несколько пользовательских свойств:

    public class LibraryUser : IdentityUser{
        //Add Custom Properties Here
        public string Company { get; set; }
    
        public string DisplayName { get; set; }
    
        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<LibraryUser> manager, string authenticationType)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
    
            // Add custom user claims here
            return userIdentity;
        }
    }
    
  2. Мой DBContext объявляет некоторые простые изменения имени, чтобы БД выглядела лучше

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    
        // Modify the Model creation properties..
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    
        //Rename Identity 2.0 Tables to something nicer..
        modelBuilder.Entity<LibraryUser>().ToTable("LibraryUser");
        modelBuilder.Entity<IdentityUser>().ToTable("LibraryUser");
        modelBuilder.Entity<IdentityRole>().ToTable("Role");
        modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin");
    }
    
  3. У меня есть класс Simple UserManager с именем LibraryUserManager, который просто расширяет UserManager для моего типа пользователя.

    public class LibraryUserManager : UserManager<LibraryUser>
    
  4. Когда база данных заполнена (при вызове Update-Database), создается следующий пользователь:

    // -- Create Admin User, put in admin role..
    LibraryUserManager userManager = new LibraryUserManager(new UserStore<LibraryUser>(context));
    
    var user = new LibraryUser()
    {
        UserName = "admin@admin.com",
        Email = "admin@admin.com",
        DisplayName = "Administrator",
        Company = "Test"
    };
    
    userManager.Create(user, "Password1.");
    
    userManager.AddClaim(user.Id, new Claim(ClaimTypes.Role, "user"));
    userManager.AddClaim(user.Id, new Claim(ClaimTypes.Role, "author"));
    userManager.AddClaim(user.Id, new Claim(ClaimTypes.Role, "reviewer"));
    userManager.AddClaim(user.Id, new Claim(ClaimTypes.Role, "admin"));
    
  5. Как только это будет выполнено.. в базе данных есть пользователь (в таблице LibraryUser) и утверждения (в таблице UserClaim)

  1. Когда пользователь проходит проверку подлинности с помощью моего пользовательского поставщика проверки подлинности, он обнаруживается (через диспетчер пользователей) и вызывается GenerateUserIdentityAsync:

РЕДАКТИРОВАТЬ: показывая остальную часть этого метода...

    var userManager = context.OwinContext.GetUserManager<LibraryUserManager>();

    LibraryUser user = await userManager.FindAsync(context.UserName, context.Password);

    //check if a user exists
    if (user == null)
    {
        context.SetError("invalid_grant", "The user name or password is incorrect.");
        return;
    }

    ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType);
    AuthenticationProperties properties = CreateProperties(user.UserName, user.DisplayName, oAuthIdentity);           
    AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);

    context.Validated(ticket);
  1. Содержимое создаваемых свойств (названных выше):

    public static AuthenticationProperties CreateProperties(string userName, string displayName, ClaimsIdentity oAuthIdentity)
    {
        IDictionary<string, string> data = new Dictionary<string, string>
        {
            { "userName", userName },
            { "displayName", displayName },
            { "roles", string.Join(",", oAuthIdentity.Claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())}
        };
    
        return new AuthenticationProperties(data);
    }
    
  2. Когда пользователь авторизован.. Я установил точку останова в LibraryUser.GenerateUserIdentityAsync (код по пункту 1 выше), и единственными утверждениями в коллекции ClaimsIdentity.Claims, возвращенными CreateIdentityAsync, являются стандартные (name, identity_provider, security_stamp и еще один)..... претензии, которые я добавил вручную, не возвращаются из БД..

Кто-нибудь может увидеть, что мне не хватает??

Я постарался предоставить всю информацию, которую могу, если вам потребуется больше комментариев, пожалуйста, и я исправлю свой вопрос.

Заранее спасибо

_L

2 ответа

Решение

Конфликтующая строка находится внутри метода OnModelCreating:

modelBuilder.Entity<LibraryUser>().ToTable("LibraryUser");
modelBuilder.Entity<IdentityUser>().ToTable("LibraryUser"); // <-- this one

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

Претензии для размещения в базе данных (вы сделали в AddClaim()) и сделать в токене разные. Вы должны поместить данные претензии вручную в унаследованный OAuthAuthorizationServerProvider класс, который ASP.NET предоставляет по умолчанию ApplicatoinOAuthProvider.cs в папке "Provider" или в любом другом провайдере oauth.

Там переопределить GrantResourceOwnerCredentials() метод сделал AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); для того, чтобы положить претензии в токене.

Затем Windows Identity будет считывать утверждения из поставленного токена.

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        using (var userManager = _container.GetInstance<ApplicationUserManager>())
        {
            var user = await userManager.FindAsync(context.UserName, context.Password);
            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }

            ClaimsIdentity oAuthIdentity = await userManager.CreateIdentityAsync(user,
                context.Options.AuthenticationType);
            ClaimsIdentity cookiesIdentity = await userManager.CreateIdentityAsync(user,
                CookieAuthenticationDefaults.AuthenticationType);
            AuthenticationProperties properties = CreateProperties(user);

            // Below line adds additional claims in token.
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesIdentity);
        }
    }


    public static AuthenticationProperties CreateProperties(AspNetUser user)
    {
        IDictionary<string, string> data = new Dictionary<string, string>
        {
            {"Id", user.Id.ToString(CultureInfo.InvariantCulture)},
            {"http://axschema.org/namePerson", user.Nickname,},
            {"http://axschema.org/contact/email", user.Email,},
        };

        return new AuthenticationProperties(data);
    }
Другие вопросы по тегам