Tolulope
Tolulope

Reputation: 498

How can I Use JWT Token to Manage User Identity?

I have An API project that uses JWT authentication and issues a token on Login.

I'm using ASP.NET core MVC project as a client

On Successful login in the client application, a JWT token is returned, Now that I have the JWT token,

How can I access User.Identity in my client application?

What do I need to do to get and use the User Identity throughout the application?

How can I Manage Authorization in the Client Application?

API project

  // configure strongly typed settings objects
            var appSettingsSection = Configuration.GetSection("JwtSettings");
            services.Configure<JwtSettings>(appSettingsSection);


            // configure jwt authentication
            var appSettings = appSettingsSection.Get<JwtSettings>();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
          .AddJwtBearer(x =>
          {
              x.RequireHttpsMetadata = false;
              x.SaveToken = true;
              x.TokenValidationParameters = new TokenValidationParameters
              {
                  ValidateIssuerSigningKey = true,
                  IssuerSigningKey = new SymmetricSecurityKey(key),
                  ValidateIssuer = true,
                  ValidateAudience = true,
                  ValidateLifetime = true,
                  ValidIssuer = appSettings.Issuer,
                  ValidAudience = appSettings.Audience,
                  ClockSkew = TimeSpan.Zero

              };
              x.Events = new JwtBearerEvents
              {
                  OnAuthenticationFailed = context =>
                  {
                      if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                      {
                          context.Response.Headers.Add("Token-Expired", "true");
                      }
                      return Task.CompletedTask;
                  }
              };
          });

Login Endpoint

  [HttpPost]
        public ActionResult Login([FromBody] LoginViewModel user)
        {
            if (user == null)
            {
                return BadRequest("Invalid client request");
            }


            if (user.Email == "[email protected]")
            {
                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(appSettings.Secret));
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);

                var tokeOptions = new JwtSecurityToken(
                    issuer: appSettings.Issuer,
                    audience: appSettings.Audience,
                    claims: new List<Claim>(),
                    notBefore: DateTime.UtcNow,
                    expires: DateTime.UtcNow.AddMinutes(30),
                    signingCredentials: signinCredentials
                );

                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);

                return Ok(new GenericResponse<string> { Data = tokenString, Message = null, Success = true });
            }
            else
            {
                return Unauthorized(new GenericResponse<string> { Data = null, Message = "Unauthorized", Success = false });
            }

        }

Upvotes: 1

Views: 2487

Answers (2)

Tolulope
Tolulope

Reputation: 498

To make Brando's answer work, I ended up doing this.

            app.Use(async (context, next) =>
            {
                string token = context.Session.GetString(config.AccessTokenName);

                if (!string.IsNullOrEmpty(token))
                {
                    var jwttoken = new JwtSecurityTokenHandler().ReadJwtToken(token);            
                    var userIdentity = new ClaimsIdentity(jwttoken.Claims);
                    context.User = new ClaimsPrincipal(userIdentity);
                }

                await next();

            });

Upvotes: 1

Brando Zhang
Brando Zhang

Reputation: 27962

As far as I know, if you want to create a custom ClaimsPrincipal, I suggest you could try to use custom middleware in your client asp.net core application.

You could get the token from Request.Headers or Session(Based on your own logic).

Then you could use JwtSecurityTokenHandler().ReadJwtToken to read the token.

More details, you could refer to below codes:

Add app.use codes into the startup.cs Configure method.Notice: you should put it before the use.endpoint.

        app.UseRouting();
        app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints
        app.UseCookiePolicy();
        app.UseSession();

        app.Use(async (context, next) =>
        {
            // you could get from token or get from session. 
            string token = context.Request.Headers["Authorization"];
            if (!string.IsNullOrEmpty(token))
            {
                var tok = token.Replace("Bearer ", "");
                var jwttoken = new JwtSecurityTokenHandler().ReadJwtToken(tok);
                var claims = new List<Claim> { /* add claims */ };
                var userIdentity = new ClaimsIdentity(claims, ClaimTypes.Name);
                context.User = new ClaimsPrincipal(userIdentity);
            }

            await next();

        });

Then you could directly get the token username in the client action:

        var user = User.Identity.Name;

Result:

enter image description here

Upvotes: 3

Related Questions