我正在尝试使用Entity Framework支持的IdentityServer 4和ASP.net Core Identity创建一个Auth服务器。
我有用户&声明在启动时存储在ASP.net身份表中,客户端,资源存储在Identity Server表中。
当我尝试获取令牌时,我收到了屏幕截图中附带的错误。
Startup.cs
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var connectionString = @"server=localhost;database=IdentityServer;trusted_connection=yes";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddScoped<ApplicationUser>();
//services.AddScoped<SignInManager<ApplicationUser>>();
services.AddScoped<UserManager<ApplicationUser>>();
services.AddScoped<UserStore<ApplicationUser>>();
services.AddEntityFrameworkSqlServer();
services.AddDbContext<ApplicationDbContext>(builder =>
{
builder.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationsAssembly));
});
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services
.AddIdentityServer()
.AddProfileService<ProfileService>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
.AddTemporarySigningCredential()
.AddConfigurationStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)))
.AddOperationalStore(builder =>
builder.UseSqlServer(connectionString, options =>
options.MigrationsAssembly(migrationsAssembly)))
.AddAspNetIdentity<ApplicationUser>();
services
.AddMvcCore()
.AddJsonFormatters();
}
//This method gets called by the runtime.Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// this will do the initial DB population
InitializeDatabase(app);
loggerFactory.AddConsole();
app.UseIdentity();
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
private static void InitializeDatabase(IApplicationBuilder app)
{
using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var configContext = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
configContext.Database.Migrate();
if (!configContext.Clients.Any())
{
foreach (var client in Config.GetClients())
{
configContext.Clients.Add(client.ToEntity());
}
configContext.SaveChanges();
}
if (!configContext.IdentityResources.Any())
{
foreach (var resource in Config.GetIdentityResources())
{
configContext.IdentityResources.Add(resource.ToEntity());
}
configContext.SaveChanges();
}
var appContext = app.ApplicationServices.GetRequiredService<ApplicationDbContext>();
if (!appContext.Users.Any())
{
foreach (var user in Config.GetUsers())
{
var identityUser = new ApplicationUser();
var hash = new PasswordHasher<IdentityUser>().HashPassword(identityUser, user.Password);
identityUser.PasswordHash = hash;
identityUser.UserName = user.Username;
identityUser.NormalizedUserName = user.Username;
identityUser.Email = user.Username;
identityUser.NormalizedEmail = user.Username;
identityUser.EmailConfirmed = true;
foreach (var claim in user.Claims)
{
identityUser.Claims.Add(new IdentityUserClaim<string> { UserId = user.SubjectId, ClaimType = claim.Type, ClaimValue = claim.Value });
}
appContext.Users.Add(identityUser);
appContext.SaveChanges();
}
}
if (configContext.ApiResources.Any()) return;
foreach (var resource in Config.GetApiResources())
{
configContext.ApiResources.Add(resource.ToEntity());
}
configContext.SaveChanges();
}
}
}
ResourceOwnerPasswordValidator.cs
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly IUserStore<ApplicationUser> _userStore;
public ResourceOwnerPasswordValidator(IUserStore<ApplicationUser> userStore, UserManager<ApplicationUser> userManager)
{
_userStore = userStore;
_userManager = userManager;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
var user = await _userStore.FindByNameAsync(context.UserName, CancellationToken.None);
if (user != null && await _userManager.CheckPasswordAsync(user, context.Password))
{
context.Result = new GrantValidationResult(
subject: user.Id,
authenticationMethod: context.Request.GrantType,
claims: user.Claims.Select(c=>new Claim(c.ClaimType, c.ClaimValue)));
}
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
"invalid custom credential");
}
}
我无法弄清楚为什么没有调用ResourceOwnerPasswordValidator。
感谢您的帮助。