5

I have a Blazor Server application and need to get the current user ID. Its easy to get the email and the user name, but NOT the ID. It was so easy in .net core 2.2. Why they did not expose the ID is beyond me. I am using .net core 5.0. Is there any kind soul out there that could help with this one?

JakeL
  • 191
  • 1
  • 6
  • 18

2 Answers2

9

There are a couple ways to do it. Here's one I found with a little hacking around. I like it because it only requires a single injection, and because ASP also handles roles. Surprisingly, "nameidentifier" is the UserId (which is a GUID) in a standard EF Core login:

@inject AuthenticationStateProvider _authenticationStateProvider
        
@code {
    async Task<string> getUserId(){
        var user = (await _authenticationStateProvider.GetAuthenticationStateAsync()).User;
        var UserId = user.FindFirst(u => u.Type.Contains("nameidentifier"))?.Value;
        return UserId;
    }
}

I recommend in Visual Studio setting a break point after retrieving the user, and then hovering over it. That will allow you to inspect it and see all the little bits and pieces-- you'll be surprised how much neat information you can dig up in the User object!

Bennyboy1973
  • 3,413
  • 2
  • 11
  • 16
  • After nearly a full day of pulling my hair out, woke up this morning to this gift! It works like a charm, and then some!! Thank you ever so much! – JakeL May 10 '21 at 19:54
  • Any idea how to get the username in the Program.cs where @inject can't be used? – EyeSeeSharp May 09 '22 at 18:32
  • 1
    Program.cs is setting up your environment. Trying to get the username at that point is kind of like trying to find out who lives in in a house while it's being built. Nobody lives there, because it hasn't been built yet. – Bennyboy1973 May 09 '22 at 20:49
  • @Bennyboy1973, I understand what you are saying but if you put a breakpoint on the first line of the program.cs and debug the app, you get the log in window then, it hits break point. Just doesn't make sense. – Dbloch Oct 19 '22 at 14:23
  • This worked for me except in .NET 6 I had to use the Type "sub" instead of "nameidentifier". Might be because I'm using social / external login? ```user.FindFirst(u => u.Type.Contains("sub"))?.Value``` – Matt Mombrea Nov 28 '22 at 21:15
  • You can also consider cascading your `AuthenticationState` instead of injecting it on every component that uses it: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-7.0 – Bennyboy1973 Nov 29 '22 at 00:13
2

The documentation indicates to use the Task<AuthenticationState> approach instead of using AuthenticationStateProvider directly since the component isn't notified automatically if the underlying authentication state data changes.

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }

    async Task<string> getUserName(){
        var user = (await authenticationStateTask).User;
        return user.Identity.Name;
    }
    async Task<string> getUserId(){
        var user = (await authenticationStateTask).User;
        var userid = user.FindFirst(u => u.Type.Contains("nameidentifier"))?.Value;
        return userid;
    }           
}
JClarkCDS
  • 184
  • 2
  • 9
Stephen Pham
  • 1,329
  • 18
  • 23
  • The OP asked for the ID specifically. AuthenticationState returns a ClaimsPrincipal which doesn't contain the ID. I needed to add a line from @BennyBoy1973: var UserId = user.FindFirst(u => u.Type.Contains("nameidentifier"))?.Value; – JClarkCDS Feb 20 '23 at 17:29
  • Both my Username and UserID are same value, what's the reason do you guess? – Sharif Yazdian Jul 09 '23 at 00:33