Change Userpassword (ASP.Identity) with localstorage based JWT-Token in ASP.NET Core

748 views Asked by At

Good day, i´m a very beginning C# developer and trying to do my first steps with ASP.NET Core.

For now i´m at a point where i need some external help. I developed a Blazor based website and added some users to my database. Now i would like to add a function for loggedin users to change their password. My projekt is splitted to a serverside and a clientside. The clientside contains all my blazor/razor pages include the ChangePasswordView and the serverside receives the REST-requests from the client.

For authorisation i´m using the JWT (JSON WebToken) and i added this token with some claims to a local storage in browser.

The procedure is as following:

  1. User is logged in
  2. User inputs the old and the new password and hits a submit button
  3. The request function goes from the clientside to the serverside
  4. The POST-request gets to serverside UserController class which contains a "ChangePassword(ChangePasswordModel pwModel)" method. It receives the pwModel with the old and the new password successfully.
  5. .... and now i have some problems.... I think i have to verify the JWTtoken from the local browserstorage or something like that, because the _userManager.GetUserAsync(User) always returns null.

How can help me to fix this issues to get a full functional "changePassword" method and what informations do you need?

Best regards, Larry

p.s. For sorry, this i my very first question on Stackoverflow and i tried to describe the issue as best as i can.

1

There are 1 answers

1
Ned Flanders On BEST ANSWER

It seems a little, you forgot to implement some details. First of all, you need to add JWT authentication to your Startup.

ConfigureServices:

        services.AddAuthentication()
            .AddJwtBearer(option =>
            {
                string jwtKey = Configuration.GetSection("Identity").GetSection("Token").GetValue<string>("JwtSecurityKey");

                option.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = Configuration.GetSection("Identity").GetSection("Token").GetValue<string>("JwtIssuer"),
                    ValidAudience = Configuration.GetSection("Identity").GetSection("Token").GetValue<string>("JwtAudience"),
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
                };
            });

Configure:

        app.UseAuthentication();
        app.UseAuthorization();

The Controller method has to be decorated with the Authorize(AuthenticationSchemes = "Bearer") attribute

    [HttpPost("ChangePasswort")]
    [Authorize(AuthenticationSchemes = "Bearer")]
    public async Task<IActionResult> ChangePasswortAsync([FromBody] ChangePasswordModel model)
    {
        string claim = HttpContext.User.FindFirstValue(ClaimsIdentity.DefaultNameClaimType);

        var user = await UserManager.GetUserAsync(HttpContext.User);

        var result = await UserManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);

        if(!result.Succeeded)
        {
            ...
        }
        ...
        return Ok(...);
    }

When you make a call to the controller, the HTTP request must have the Authorization header.

HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);