I override Identity classes:
[Table("Roles")]
public partial class AppRole : IdentityRole<int, AppUserRole, AppRoleClaim>
{
}
[Table("RoleClaims")]
public partial class AppRoleClaim : IdentityRoleClaim<int>
{
}
[Table("Users")]
public partial class AppUser : IdentityUser<int, AppUserClaim, AppUserRole, AppUserLogin>
{
}
[Table("UserClaims")]
public partial class AppUserClaim : IdentityUserClaim<int>
{
}
[Table("UserLogins")]
public partial class AppUserLogin : IdentityUserLogin<int>
{
[Key]
[Required]
public int Id { get; set; }
}
[Table("UserRoles")]
public partial class AppUserRole : IdentityUserRole<int>
{
}
[Table("UserTokens")]
public partial class AppUserToken : IdentityUserToken<int>
{
[Key]
[Required]
public int Id { get; set; }
}
public class AppRoleManager : RoleManager<AppRole>
{
public AppRoleManager(IRoleStore<AppRole> store, IEnumerable<IRoleValidator<AppRole>> roleValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, ILogger<RoleManager<AppRole>> logger, IHttpContextAccessor contextAccessor) : base(store, roleValidators, keyNormalizer, errors, logger, contextAccessor)
{
}
}
public class AppRoleStore : RoleStore<AppRole, AppDbContext, int, AppUserRole, AppRoleClaim>
{
public AppRoleStore(AppDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
{
}
protected override AppRoleClaim CreateRoleClaim(AppRole role, Claim claim)
{
return new AppRoleClaim(role, claim);
}
}
public class AppSignInManager : SignInManager<AppUser>
{
public AppSignInManager(UserManager<AppUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<AppUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<AppUser>> logger) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger)
{
}
}
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<AppUser> passwordHasher, IEnumerable<IUserValidator<AppUser>> userValidators, IEnumerable<IPasswordValidator<AppUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<AppUser>> logger) : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
var LoginStore = Store;
}
}
public class AppUserStore : UserStore<AppUser, AppRole, AppDbContext, int, AppUserClaim, AppUserRole, AppUserLogin, AppUserToken, AppRoleClaim>
{
public AppUserStore(AppDbContext context, IdentityErrorDescriber describer = null) : base(context, describer)
{
}
protected override AppUserClaim CreateUserClaim(AppUser user, Claim claim)
{
return new AppUserClaim(user, claim);
}
protected override AppUserLogin CreateUserLogin(AppUser user, UserLoginInfo login)
{
return new AppUserLogin(user, login);
}
protected override AppUserRole CreateUserRole(AppUser user, AppRole role)
{
return new AppUserRole(user, role);
}
protected override AppUserToken CreateUserToken(AppUser user, string loginProvider, string name, string value)
{
return new AppUserToken(user, loginProvider, name, value);
}
}
and I want to use external login for Google, but when I call await UserManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
I get error:
Entity type 'AppUserLogin' is defined with a single key property, but 2 values were passed to the 'DbSet.Find' method.
I am following tutorials openiddict and ASP.NET Core and Angular 2, but I am pretty sure this error does not have anything with this 2 tutorials. I think my code is not working, because I change TKey for UserLogins table: public partial class AppUserLogin : IdentityUserLogin<int>
. Even searching for is defined with a single key property results nothing.
Solution is in DbContext.OnModelCreating
method.
I change from:
modelBuilder.Entity<AppUserLogin>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
});
to:
modelBuilder.Entity<AppUserLogin>(entity =>
{
entity
.HasKey(u => u.Id);
entity.Property(p => p.Id)
.ValueGeneratedOnAdd();
entity
.HasKey(u => new { u.LoginProvider, u.ProviderKey });
});
and it works.