具有ASP.net标识的IdentityServer 4无法正常工作

时间:2017-04-14 21:30:44

标签: identityserver4 asp.net-core-identity

我正在尝试使用Entity Framework支持的IdentityServer 4和ASP.net Core Identity创建一个Auth服务器。

我有用户&声明在启动时存储在ASP.net身份表中,客户端,资源存储在Identity Server表中。

当我尝试获取令牌时,我收到了屏幕截图中附带的错误。

enter image description here

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。

感谢您的帮助。

0 个答案:

没有答案