ASP身份2 + Web API令牌身份validation – 持久声明未加载

我在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 GenerateUserIdentityAsync(UserManager 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(); //Rename Identity 2.0 Tables to something nicer.. modelBuilder.Entity().ToTable("LibraryUser"); modelBuilder.Entity().ToTable("LibraryUser"); modelBuilder.Entity().ToTable("Role"); modelBuilder.Entity().ToTable("UserRole"); modelBuilder.Entity().ToTable("UserClaim"); modelBuilder.Entity().ToTable("UserLogin"); } 
  3. 我有一个名为LibraryUserManager的简单UserManager类,它只为我的用户类型扩展UserManager。

     public class LibraryUserManager : UserManager 
  4. 当数据库被播种时(调用Update-Database时),将创建以下用户:

     // -- Create Admin User, put in admin role.. LibraryUserManager userManager = new LibraryUserManager(new UserStore(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. 当我的自定义Auth Provider对用户进行身份validation时,会找到它们(通过用户管理器)并调用GenerateUserIdentityAsync:

编辑:显示该方法的其余部分……

  var userManager = context.OwinContext.GetUserManager(); 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 data = new Dictionary { { "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. 当用户被authed时…我在LibraryUser.GenerateUserIdentityAsync(上面第1点下的代码)中放置了一个断点,并且CreateIdentityAsync返回的ClaimsIdentity.Claims集合中的唯一声明是默认声明(name,identity_provider,security_stamp和另一个)。 。)..我手动添加的声明不会从数据库返回..

任何人都能看到我所缺少的东西吗?

我试图提供所有信息,如果您需要更多请注释,我会修改我的问题。

提前致谢

_L

冲突行位于OnModelCreating方法内:

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

因为您使用LibraryUser作为IdentityUser的派生类,所以您不需要将IdentityUser显式映射到表。 这样做会弄乱数据库中如何生成主键和外键。

声称放入数据库(你在AddClaim() )并使其包含在令牌中是不同的。 您必须手动将声明数据放在inheritance的OAuthAuthorizationServerProvider类中,ASP.NET在Provider文件夹或您提供的任何oauth提供程序中提供默认的ApplicatoinOAuthProvider.cs。

在那里,覆盖GrantResourceOwnerCredentials()方法做了AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); 为了将声明置于令牌中。

然后,Windows Identity将读取您放置的令牌的声明。

  public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { using (var userManager = _container.GetInstance()) { 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 data = new Dictionary { {"Id", user.Id.ToString(CultureInfo.InvariantCulture)}, {"http://axschema.org/namePerson", user.Nickname,}, {"http://axschema.org/contact/email", user.Email,}, }; return new AuthenticationProperties(data); }