Search code examples
c#asp.net-identityasp.net-core-3.1

IHttpContextAccessor UserId is null


After referring to different questions in StackOverflow, and also following the accepted answer:

IHttpContextAccessor.HttpContext.User.Identity shows all null properties in CurrentUserService service

But still, I couldn't access the UserId from the IHttpContextAccessor, the value of UserId is null when I am trying to access:

var UserId = _currentUserService.UserId;

My CurrentUserService Looks:

 public class CurrentUserService : ICurrentUserService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public CurrentUserService(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        private bool _init = false;
        private string _userId;
        public string UserId
        {
            get
            {
                if (!_init)
                {
                    _userId = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
                    _init = true;
                }
                return _userId;
            }
        }
        ///public string UserId { get { return _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); } }

        public bool IsAuthenticated => _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated;

    }

When I am not logged in and trying to access the controller, it redirects to the login page. And after the login the value of _httpContextAccessor.HttpContext?.User are also being populated as shown in the image below:

enter image description here

Is there something I am missing or it is the problem from the framework by design?

An example where I am trying to invoke the UserId.

In View:

 <div class="row">
        <div class="col-md-12">
            <a asp-action="BorrowRequest" asp-controller="Book" asp-route-bookId="@Model.Id" class="btn btn-primary">
                Request for Borrow
            </a>
        </div>
 </div>

In Controller:

[HttpGet]
[Authorize]
public async Task<ActionResult> BorrowRequest(int bookId)
{
    try
    {
        var UserId = _currentUserService.UserId;

        await Task.Delay(200);
        return RedirectToAction(nameof(Index));
    }
    catch
    {
        return View();
    }
}

Solution

  • Something was replacing the name for claims for the user id from ClaimTypes.NameIdentifier to sub, which is shown in the figure.

    So, To not let Microsoft Identity override claim names I used:

    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); just before the app.UseAuthentication() in the API startup.

    Referring: Why is ClaimTypes.NameIdentifier not mapping to 'sub'?