How to get JWT authenticated sign-in user from identity claims in asp.net web api

techstack

I implemented a JWT token authentication where the register and login are working fine.

This is what I normally do with inbuilt authentication

var currentUser = await _userManager.GetUserAsync(HttpContext.User); 
var category = _context.Categories.Where(m=>m.ApplicationUserId == currentUser.Id); 
return View(await category.ToListAsync());

I will get the current logged in user from the httpContext, then match the current user id(that is the application user Id of the current user) with the application userid and return the matching list.

if the condition did not match then do something else.

I cant seem to get this with JWT authentication. I am using blazor client

I have tried different approach but still not getting it. I thought I could get the current user like this but I the application user Id. I was getting the username of the current user.

        internal async Task<List<Staff>> GetAllStaffServices()
        {
            var currentUser = httpContextAccessor.HttpContext.User.Identity.Name.ToString();
            var another = userManager.FindByNameAsync(currentUser);

            //var userId = this.User.FindFirst(ClaimTypes.NameIdentifier).Value;
            var staff = applicationDbContext.Staffs.Where(m => m.ApplicationUserId == another.Id);

            return await staffs.ToListAsync();
        }

This is my login method

    public async Task<IActionResult> Login([FromBody] LoginModel login)
        {
            var result = await _signInManager.PasswordSignInAsync(login.UserName, login.Password, false, false);

            if (!result.Succeeded) return BadRequest(new LoginResult { Successful = false, Error = "Username and password are invalid." });

            var user = await _signInManager.UserManager.FindByNameAsync(login.UserName);
            var roles = await _signInManager.UserManager.GetRolesAsync(user);

            var claims = new List<Claim>();


            claims.Add(new Claim(ClaimTypes.Name, login.UserName));
            claims.Add(new Claim(JwtRegisteredClaimNames.Jti, user.Id));
            claims.Add(new Claim(JwtRegisteredClaimNames.Email, user.Email));

            foreach (var role in roles)
            {
                claims.Add(new Claim(ClaimTypes.Role, role));
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtSecurityKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var expiry = DateTime.Now.AddDays(Convert.ToInt32(_configuration["JwtExpiryInDays"]));

            var token = new JwtSecurityToken(
                _configuration["JwtIssuer"],
                _configuration["JwtAudience"],
                claims,
                expires: expiry,
                signingCredentials: creds
            );

            return Ok(new LoginResult { Successful = true, Token = new JwtSecurityTokenHandler().WriteToken(token) });
        }
    }

config services

     public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddDefaultIdentity<RegisterInfoModel>().AddRoles<IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = Configuration["JwtIssuer"],
                            ValidAudience = Configuration["JwtAudience"],
                            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
                        };
                    });
            services.AddScoped<StaffServices>();
            services.AddMvc().AddNewtonsoftJson();
            services.AddResponseCompression(opts =>
            {
                opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
                    new[] { "application/octet-stream" });
            });
        }

enet
  • You shouldn't add user.Id as a claim. What for ?
  • You shouldn't add user.Email as a claim. What for ? UserName == Email
  • Now you can, in your Web Api end point annotated by Authorize attribute, code something like this:

    var userName = HttpContext.User.Identity.Name.ToString();
    var user= userManager.FindByNameAsync(userName);
    
    var staff = applicationDbContext.Staffs.Where(m => m.ApplicationUser.Id == 
    user.Id);
    
    return await staffs.ToListAsync();
    

Note: No need to use HttpContextAccessor... HttpContext is available in the controller

The code here is very similar to yours. It extricates the user name from the HttpContext, call the FindByNameAsync to retrieve the user, and then use it.

Please, run it and report if its OK. If not, report the issue.

Update: If you wish to add the user Id to the Jwt token, in addition to the user name, you should do the following in your Login method:

claims.Add(new Claim(ClaimTypes.Name, login.UserName));
 claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));

And to get the user id from the GetAllStaffServices method, you can call UserManager.GetUserId, passing it a claims principal object extracted from HttpContext:

var userId = UserManager.GetUserId (HttpContext.User);

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to get Identity User from his authentication JWT token in .Net Core API?

Claims Identity .NET CORE 3.0 API JWT

ASP.NET Web API get user identity in controller constructor

Get User Roles with ASP.net Identity and Web API

Get Authenticated Identity User data in ASP.NET MVC

How to get user claims after signin through SignInManager in ASP .NET CORE Identity?

How does Asp.Net Identity 2 User Info get mapped to IdentityServer3 profile claims

Get JWT claims directly from the token, ASP Net Core 2.1

How to get max value of claims value in ASP.NET Identity?

JWT: How to get a List of Values from a specific Key in the Claims. C# Asp.Net Core

How do I get current user in .NET Core Web API (from JWT Token)

How to create a JWT token with custom JSON claims in Payload using .Net (C#) in Asp.NET Core WEB API

ASP.net Core Identity Sign in as another user from Administrator

ASP .NET CORE 2.2 JWT & Claims identity Authentication for Website

.NET Core Web API HttpContext.User.Claims and HttpContext.User.Identity are always null in Controllers

How to sign out other user in ASP.NET Core Identity

how to get claims of another user using ASP.NET Core

How to get FirstName + LastName from the user's google account authenticated using Asp.Identity in MVC5 application

How to get claims in .Net Core 3.1 Web API Controller?

How many claims can a Role/User have in ASP.Net.Core.Identity?

Access user identity from controller in ASP.NET Core Web API

Force another user to refresh their Claims with ASP.NET Identity 2.1.0

ASP.NET Identity: Why User Properties AND Claims?

Dynamic User Claims in ASP.NET Identity EF

How to check if user is logged in to ASP.NET Core web application when using ASP.NET Core Web API to house identity

Can't get claims from JWT token with ASP.NET Core

Claims for IdentityServer4 user not included in JWT and not sent to Web Api

How to get the authenticated user from a separate class library in .Net Core

What is the claims in ASP .NET Identity