Getting the identity of the logged in user

David Thielen 2,421 Reputation points
2023-05-07T08:35:19.58+00:00

The is for a Blazor (server side) application. As I understand it, I have three objects for a logged in user:

  1. AuthenticationState which I can get in my razor page as it's injected. This allows me to make calls to see if claims allow users to take actions or see data.
  2. IdentityUser which is the ASP.NET Identity user which has their email, phone etc. I can get that using the code below.
  3. User which is my app user object. User.AspUserId == IdentityUser.Id so I can read that object once I have the IdentityUser.
		private async Task<IdentityUser?> GetUser()
		{
			var userPrincipal = (await authenticationStateTask).User;
			var userid = userPrincipal.FindFirst(u => u.Type.Contains("nameidentifier"))?.Value;
			if (!string.IsNullOrEmpty(userid))
				return await UserDbContext.Users.FirstOrDefaultAsync(u => u.Id == userid);
			return null;
		}

My questions are:

  1. Are these three objects what I should be using?
  2. There's a AuthenticationStateProvider.AuthenticationStateChanged Event. Should I set this up and use it to re-read my IdentityUser and User object and otherwise I can keep those objects without re-reading them per page.
    1. If so, where do I store these objects as they're a per session object.
  3. Is my GetUser() code above the best way to get the IdentityUser?
  4. Anything I'm missing in all this?

thanks - dave

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,451 questions
{count} votes

Accepted answer
  1. Mohammad Majed Asad 155 Reputation points
    2023-05-10T09:18:14.4+00:00

    Yes, these three objects are commonly used in Blazor server-side applications for handling user authentication and authorization:

    AuthenticationState: Represents the authentication state of the user, including the user's claims.

    IdentityUser: Represents the ASP.NET Identity user, which contains user information like email, phone, etc.

    User (App User): Represents your application-specific user object, which is associated with the IdentityUser through a relationship like User.AspUserId == IdentityUser.Id.

    You can use the AuthenticationStateChanged event to track changes in the user's authentication state and update your IdentityUser and User objects accordingly. This way, you don't have to re-read them for every page. To store these objects per session, you can use a scoped service:

    Create a scoped service that holds the IdentityUser and User objects.

    Register the service in the Startup.cs or Program.cs file, depending on your Blazor version.

    Inject the service into your components and access the stored IdentityUser and User objects.

    This approach ensures that the objects are stored and shared per session.

    Your GetUser() method is a valid way to retrieve the IdentityUser object. However, you can improve it by including null checks and exception handling to make it more robust. Additionally, you can consider moving this method to a separate service (e.g., UserService) to keep your code modular and maintainable.

    You seem to be on the right track with handling user authentication and authorization in your Blazor server-side application. Some additional tips to consider:

    Make sure to protect your components and routes using the [Authorize] attribute or a custom authorization policy.

    Leverage Blazor's built-in components, like AuthorizeView, to conditionally display content based on the user's authentication or authorization status.

    Use the UserManager and SignInManager classes from ASP.NET Core Identity to handle user management tasks, such as creating users, validating passwords, and signing in.

    To improve security and user experience, consider implementing features like two-factor authentication, account lockout, and password reset.

    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 59,051 Reputation points
    2023-05-08T21:34:54.91+00:00

    You should just inject another singleton to hold the data. it can use the AuthenticationStateProvider via injection to get the values and could subscribe to the change event to detect login/logout if the event fires.

    note: blazor only has singleton and transient services. also the httpcontext user is injected as a singleton when the blazor app starts. if not defined and required, the blazor app will unload, redirect to login page and reload.