.Net Core重置密码令牌和Identityserver 4令牌无效

时间:2018-07-29 19:32:09

标签: asp.net-core asp.net-identity identityserver4

我的应用程序和API使用IdentityServer 4保护。

我有一个用于用户管理的集中API(注册新用户,更新,删除和重置密码)。此api生成的令牌将被Identityserver用来重置用户密码。

问题是我总是收到无效的令牌错误。我知道这与url编码无关,因为忘记的密码由身份服务器处理,并且身份服务器生成的令牌工作正常。问题在于令牌是由不同的api(甚至在一台机器上)生成的。

我曾考虑创建一个通用的数据保护提供程序,但不清楚如何实现。 基本上,如何重置一个由另一个api接受的api创建的密码令牌?

我正在使用Asp Identity的用户管理器来生成重置密码令牌:

var token = await _userManager.GeneratePasswordResetTokenAsync(appUser);

这是我的IdentityServer设置为使用Asp身份的方式:

services
    .AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
            options.Lockout.AllowedForNewUsers = true;
            options.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(12, 0, 0);
            options.Lockout.MaxFailedAccessAttempts = int.Parse(Configuration["MaxFailedAttempts"]);
        })
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

...

var builder = services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
                options.Authentication.CookieSlidingExpiration = true;
            })
            .AddAspNetIdentity<ApplicationUser>()
            .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = b =>
                    b.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));

                    options.DefaultSchema = Globals.SCHEMA_IDS;
                })
            // this adds the operational data from DB (codes, tokens, consents)
            .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = b =>
                    b.UseSqlServer(connectionString,
                    sql => sql.MigrationsAssembly(migrationsAssembly));

                    options.DefaultSchema = Globals.SCHEMA_IDS;
                    // this enables automatic token cleanup. this is optional.
                    options.EnableTokenCleanup = true;
                    options.TokenCleanupInterval = 30;
                })
            .AddProfileService<CustomProfileService>()
            .AddSigninCredentialFromConfig(Configuration.GetSection("SigninKeyCredentials"), Logger);

这是我的UserManagement Api设置为使用Asp身份的方式:

services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser, IdentityRole, ApplicationDbContext>>();
services.AddTransient<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();
services.AddTransient<IPasswordHasher<ApplicationUser>, PasswordHasher<ApplicationUser>>();
services.AddTransient<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services.AddTransient<IdentityErrorDescriber>();

var identityBuilder = new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole), services);
identityBuilder.AddTokenProvider("Default", typeof(DataProtectorTokenProvider<ApplicationUser>));
services.AddTransient<UserManager<ApplicationUser>>();

2 个答案:

答案 0 :(得分:0)

由于这是一个2个月大的问题,我想您已经解决了。我的建议是:看一下令牌的使用寿命。像这样在您的startup.cs中设置它:

services.Configure<DataProtectionTokenProviderOptions>(options =>
{
  options.TokenLifespan = TimeSpan.FromHours(tokenlifespan); 
});

希望这对您有帮助!

答案 1 :(得分:0)

不得不继续讨论其他问题,而现在又回到了这一点。最后,通过确保所有API和IdentityServer实例都配置为使用ASP.NET Core数据保护来解决此问题。我使用redis作为我的分布式缓存系统,因此只需要配置我的api和identityserver,现在生成令牌时所有东西都使用相同的密钥。以下是我在每个startup.cs中使用的内容:

public void ConfigureServices(IServiceCollection services)
{
  ...            
            services.AddSession();
            services.Configure<RedisConfiguration>(Configuration.GetSection("redis"));
            services.AddDistributedRedisCache(options =>
            {
                options.Configuration = Configuration.GetValue<string>("redis:host");
            });
            var redis = ConnectionMultiplexer.Connect(Configuration.GetValue<string>("redis:host"));
            services.AddDataProtection()
                .PersistKeysToRedis(redis, "DataProtection-Keys")
                .SetApplicationName(<application name>);
            services.AddTransient<ICacheService, CacheService>();
...
}

,然后别忘了使用会话(在API中):

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...
            app.UseAuthentication();
            app.UseSession();
            ...
        }

使用会话(在IdentityServer中):

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...
            app.UseIdentityServer();
            app.UseSession();
            ...
        }