Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net Core Reset Password Token and Identityserver 4 token invalid

My applications and APIs are protected using IdentityServer 4.

I have a centralized API for user management (registering new users, updating, deleting and resetting passwords). The token generated by this api will be used by identityserver to reset the user's password.

Problem is I always get invalid token error. I know this has nothing to do with url encoding because forgotten password is handled by identity server and the token generated by identity server works fine. The problem is when a token is generated by different api (even on a single machine).

I looked into creating a common data protection provider but I'm unclear how this is done. Basically, how can I have reset password token created by one api accepted by another?

I'm using Asp Identity's usermanager to generate the reset password token:

var token = await _userManager.GeneratePasswordResetTokenAsync(appUser);

This is how my IdentityServer is setup to use Asp Identity:

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);

and this is how my UserManagement Api is setup to use Asp Identity:

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>>();
like image 609
user1015196 Avatar asked Jul 29 '18 19:07

user1015196


People also ask

What does it mean when it says Reset password token is invalid?

If you're trying to reset your password and you receive an error citing an “invalid token” or asking you for your token, it's likely that the link you clicked on to reset your password has expired. For security reasons, passwords are never sent out across the Internet.

Why is my token saying invalid?

This error means that the app has experienced an authentication problem and can't verify your account information. If it occurs, you'll be automatically signed out of your account. You need to sign in to your account to continue working on your projects.


1 Answers

Had to move on to other issues and just now getting back to this. I ended up solving this by ensuring that all my APIs and IdentityServer instance was configured to use ASP.NET Core Data Protection. I'm using redis as my distributed caching system and so just had to configure each of my api and identityserver and everything is now using the same keys when generating tokens. Below is what I use in each 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>();
...
}

and then don't forget to use the session (in APIs):

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

use the session (in IdentityServer):

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...
            app.UseIdentityServer();
            app.UseSession();
            ...
        }
like image 60
user1015196 Avatar answered Oct 13 '22 17:10

user1015196