.NET logo

How to get the current user in ASP.NET Core?

This post was most recently updated on August 1st, 2020.

Reading Time: 3 minutes.

This post describes how to get the currently logged in user using ASP.NET Core. This is compared with how it’s done in ASP.NET Framework.

Background

In ASP.NET Core (and .NET Core in general), a lot of things are done a bit differently than what you might be used to if you’re coming from the .NET Framework world. That’s what I’ve been learning building more and more stuff with it, instead of good old .NET Framework. The learning curve is definitely there, but it’s not that bad – most of the things work in a similar fashion, but a huge number of details are different.

In ASP.NET Framework, you’d do this by accessing HttpContext.Current.User and its properties (see below for an example), in .NET Core this is handled via dependency injection.

var username = HttpContext.Current.User.Identity.Name;

You can’t do this in (most versions of) .NET Core. How to do it there, then?

Solution

Time needed: 10 minutes.

Let’s go through the steps first on a high level, and then take a closer look below.

  1. Make sure your application has permissions to request user properties or claims

    See details here.

  2. Modify your app startup to add the required background services

    See details here.

  3. Implement the property / claim enumeration in your code

    See details here.

Now, that’s good – let’s take a closer look to these 3 steps below!

Background

Now I’ll describe how to manage user identity when developing your application – before that, you need to configure your application registration in a way that your identity provider actually supplies you with the user information in the first place. For Azure AD, see my other post, here:
https://www.koskila.net/iterating-group-memberships-using-claims-in-net-core/

When that all is done, let’s jump into the ways you can access User/Identity in your program!

Modify your Startup

First, you add this in your Startup.cs, in ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
     // omitted for clarity
 
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

Or if you’re at least on .NET Core 3.0, you can do this as well:

public void ConfigureServices(IServiceCollection services)
{
     // omitted for clarity
 
     services.AddHttpContextAccessor();
}

Accessing the User Properties in your code

Then you add these pieces of code to your Controller, database context or other class:

  1. Private variable to hold the injected reference to our HttpContextAccessor
  2. New variable with the correct type (or interface) to the class constructor (like IHttpContextAccessor httpContextAccessor below)
  3. Assignment from the injected variable (in the constructor) to the hidden private variable (to make the reference available outside the constructor)

Below, my code is shown accessing the HttpContext (and through that, Current User) in a DbContext class. It’s assigned in the constructor, after which you may use it in any other method!

private readonly IHttpContextAccessor _httpContextAccessor;
 
// omitted for clarity
 
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor)
            : base(options)
{
  _httpContextAccessor = httpContextAccessor;
}

For our little example call further below, you’ll need to add a reference to Claims like this:

using System.Security.Claims;

And finally, you call it like this – for example, to get the reference to the user, and grab their id:

var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;

This can be injected to Controllers and Views, Custom Components and if need be, properties passed to background Threads (don’t pass the context! That’ll break.)

What about pure & classic Razor pages?

Okay, so here it’s different because Razor takes care of some of the background work for you. If you’re using Razor pages, you can just do this:

@{
    var username = HttpContext.User.Identity.Name;
}

That’s because Razor exposes HttpContext in Razor.Component.

And with this, you should be good! :)

mm
4.3 8 votes
Article Rating
Subscribe
Notify of
guest
49 Comments
Inline Feedbacks
View all comments
Andrew Barzyk

Sorry, as many comments start… I’m new to EF… I added the code to my DB Context and am getting this error:
InvalidOperationException: The DbContext of type ‘AppDbContext’ cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions.

Any chance you could explain in more detail how you “add this to your Controller, database context or other class?”

Amit Sadashiv Patil

When I am doing the above procedure in one of my controller class, it works. I am able to see the username. But when I do this procedure in my ApplicationDbContext (InterviewSchedulerContext class in my case) class, the above-mentioned solution does not work. I am getting “Microsoft.AspNetCore.Http.IHttpContextAccessor.HttpContext.get returned null” error.

Error details:
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=InterviewScheduler
StackTrace:
at InterviewScheduler.Entities.InterviewSchedulerContext..ctor(DbContextOptions`1 options, IHttpContextAccessor httpContextAccessor) in C:\Users\amipatil\source\repos\InterviewScheduler 1857 83326\InterviewScheduler\Entities\InterviewSchedulerContext.cs:line 22

Could you help me out?
Thank you in advance.

John Hermsen

Hi Amit,

EFCore uses an InternalServiceProvider which is different from the ApplicationServiceProvider.
To access the application service provider you can use the IDbContextOptions service.
E.g. constructor:
public MyContext(IDbContextOptions dbContextOptions)
{
var coreOptionsExtension = _dbContextOptions?.FindExtension();
var context Accessor = coreOptionsExtensions.ApplicationServiceProvider.GetService();
}

Hope this helps.

Alan

Hi Antti,

Thanks for taking the time to post, but this isn’t working for me at all. The ‘FindFirst’ method is returning NULL. When I inspect the _httpContextAccessor object, it doesn’t appear to have a user information either.

Do I need to run my app under IIS (full – not express) ? Do I need to try this with IE or Edge instead of Google Chrome?

I’m currently using ASP.net Core 2.2 with Visual Studio 2019 Community and Chrome.

Thanks,
Alan

Alan

Hi Antti,

Thanks for getting back to me so quickly.

So, I was able to get the user info, by just enabling Windows Authentication in my launch settings. I found that I didn’t need to apply your solution to get this point.

However, I realize that this will only work in IIS / IIS Express. I plan to host my web server and ASP.Net Core app on Nginx. I’m assuming that this is not going to get me access to the Windows ID?

So, even assuming I deploy to an IIS Server instead. Is there anyway to get my users ID without having them log in the application (and having to put the IIS Server on our AD domain)?

Thanks,
Alan

Alan

Antti,

So, at this point, I’m a little confused. I thought that the only way I could access the local windows ID (in my case, the AD identity), was to enable Windows Authentication. So, you’re saying that I should be able to access the local AD identity, using the code your outlined solution? But this requires IIS or IIS Express to be used at the Web Server, correct? Also, does my Web Server need to be on the same domain as my users? If not, does the Web Server need to be on any domain at all?

I know that this is a big ask, but I can’t get the solution you outline to work. As I mentioned before, “FindFirst(ClaimTypes.NameIdentifier)” is returning null, and a visual inspection of the HttpContextAccessor object seems to confirm that my Windows User info is not being populated. Is it possible that you could just post a very basic Visual Studio ASP.Net Core solution that accesses or displays the Windows User info? Perhaps, it just a problem with the way I’m implementing your solution.

Thanks,
Alan

John Chandler

Hi Alan,

I am having the very same issue as you are. I am using VS 2017 ASP.Net Core 2.2.

I have: “windowsAuthentication”: true in launchSettings

I have tried several different solutions and they all give me a null reference error.

I’m still researching and will post if I find a working solution for me. Please do the same! :)

Alan

John,

See point #4 on the post I just made to Annti (at approx. 10:50 CST, 8/20/2019).

Alan

Alan

Correction – please look at point #5 from last post to Annti (at 11:15 CST, 8/20/2019).

John Chandler

I found a working solution!:

string userName = _httpContextAccessor.HttpContext.User.Identity.Name;

https://forums.asp.net/t/2146004.aspx?Get+Windows+User+Name+ASP+net+Core+2+1

Alan

Hi Antti,

Thanks again for your continued replies (as well as everyone else). I appreciate your patience, but please bare with me as I clarify a few things, because it seems like I haven’t been clear as to what I need:

1) All of the users of my ASP.Net Core application will be Windows users on the same AD domain.

2) I’m trying to find a way to obtain their Windows ID in the ASP.Net Core application without relying on the Windows Authentication feature.

3) The main reason that I don’t want to rely on Windows Authentication is that, based on my understanding of how this features works, I would be required to put the IIS Web Server on the Domain – This is an administrative hurdle, I would rather avoid if I could.

4) If I enable Windows Authentication on my app, then I can easily obtain the Windows ID, either running on IIS express or IIS on the same machine that I’m testing the application from in a browser. I’ve verified this behavior from two different Windows PC’s, one on a domain, and one NOT on a domain.

All I need to do is (in VS Community 2019) create a new ASP.Net Core Web application, selecting the Windows Authentication option. (When running under IIS, you also need to enable Windows Authentication on the IIS Server). I don’t need to implement your code at all.

This is a code snippet from the pre-built “_Layout.cshtml” that references that displayes user ID:

Hello, @User.Identity.Name!

5) At this point, I still don’t understand whether or not any sort of Authentication must be implemented in order to implement your solution, or whether or not your solution requires IIS or IIS Express. All I know is that I can’t get it to work for me. When I look at the Claims collection, when I try to implement your solution, I think I have one or two records and most of the fields are null.

6) I’m again requesting a sample project you might have where your solution works. As I mentioned on point #2. I’m specifically looking for a solution that doesn’t require me to use any Authentication at all.

Thanks,
Alan

Alan

Antti,

Thanks so much for your continued replies. Thank to everyone, who have recently replied as well :)

I appreciate your continued patience. Please bare with my as I clarify a few points. It seems like I haven’t been clear enough regarding my needs.

1) All of the users of the ASP.Net Core application are Windows users on the same AD Domain, on my company’s network. There will be no public access to the application

2) I need to obtain Windows ID of anyone using the application.

3) I want to implement a solution that DOES NOT require Windows Authentication ( or any Authentication at all).

4) I’m trying to avoid using Windows Authentication as, based on my understanding of the Windows Authentication feature, I would also be required to put my application’s IIS server on the domain as well. Otherwise, the Authentication won’t work properly.

Putting this server on the domain is an administrative hurdle, I would very much like to avoid.

5) If I enable Windows Authentication on my app, then I can easily obtain the Windows ID, either running on IIS express or IIS on the same machine that I’m testing the application from in a browser. I’ve verified this behavior from two different Windows PC’s, one on a domain, and one NOT on a domain.

All I need to do is (in VS Community 2019) create a new ASP.Net Core Web application, selecting the Windows Authentication option. (When running under IIS, you also need to enable Windows Authentication on the IIS Server).

I don’t need to implement your code at all.

This is a code snippet from the pre-built “_Layout.cshtml” that references that displays user ID:

Hello, @User.Identity.Name!

6) I’ve tried implementing your code and I can’t get it to work. When I look at the Claims property, I think I’m only getting one or two records, and most of the fields are null, including the user name.

I still don’t understand whether or not your solution requires any implemented Authentication framework, or whether or not IIS / IIS Express is required.

7) So, I’ll make another request for some sample shell project you have where your able to obtain the Windows User ID. As I mentioned in point 3, I’m NOT interested in a solution that requires Windows Authentication.

Thanks,
Alan

Alan

Sorry for the double-post :) I thought my first post didn’t take.

Alan Farkas

Antti,

No worries. Thanks for your reply. So, yes. That is all correct. You accurately re-stated my situation :)

Since my last email, I have managed to get the use of a server that’s already on our domain. I installed IIS and deployed my app to it. The integrated Windows authentication is working perfectly (in Chrome, ID, but not Firefox) up to a point.

So, if I connect to the web app using the server name (ex. http://server1:5100) or use a domain alias for the server (ex. http://myapp), the user’s Window ID get’s passed thru just fine. However, if I connect to the web app using a FQDN (ex. http://myapp.domain.local), then I’m presented with a login box that requires me to enter my credentials (or any other valid domain credentials). Once the credentials are entered, then the app picks up the user ID that was used to login.

It doesn’t look like there’s an easy way around this. Based on some obscure blog posts I found, I believe that this is “expected” functionality. My understanding is that IE (and apparently Chrome) see the host name URLs (ex. http://server1) as a local intranet address, but any URL with a period in it (ex. http://myapp.domain.local) is automatically seen as a public URL. As a security constraint, the browsers will not automatically pass the integrated Windows info to a public URL.

BTW, the login prompting always occurs under Firefox, regardless of which URL I use for the app. This isn’t really an issue, though, as our users will be instructed to use either IE or Chrome.

Alan

Lars Torbjörn Linden

public class ResignController : Controller
{
private readonly IUserRepo _userRepo;

public ResignController(IUserRepo userRepo)
{
_userRepo = userRepo;

}

// within a method
{
UserModel UserName = _userRepo.GetUser();
}

}

// Repo
public UserModel GetUser()
{
if (_httpContextAccessor?.HttpContext == null)
{
return null;
}

ClaimsPrincipal claimsPrincipal = _httpContextAccessor.HttpContext.User;

return new UserModel
{
UserName = claimsPrincipal.Claims.SingleOrDefault(c =>
c.Type == ClaimTypes.Name)?.Value
};

}
//Model
public class UserModel
{
public string UserName { get; set; }

}

Andrii

https://stackoverflow.com/questions/36641338/how-to-get-current-user-in-asp-net-core
asp core 3.1 it is work
var r = User.Identity.UserId();
var s = User.Identity.CompanyId();

public static Guid CompanyId(this IIdentity usrIdentity)
{
var claimsIdentity = (ClaimsIdentity)usrIdentity;
var dataIdentity = claimsIdentity.FindFirst(ClaimsKeys.CompanyIdClaim);

if (dataIdentity == null)
{
return Guid.Empty;
}

Guid.TryParse(dataIdentity.Value, out var res);

return res;
}

Kanika

Can you please elaborate this.. unable to catch you after second step!

Ivan Salo

Hi Antti,

I am getting an error in EF Core 2.2
The DbContext of type ‘DataContext’ cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions.

Can you suggest how to resolve it?

Thanks,
Ivan Salo.

Ivan Salo

Thanks. Switching to non-pooled version did a trick.

1 2 3