question

wavemaster avatar image
0 Votes"
wavemaster asked AgaveJoe edited

HttpContextAccessor not found in Blazor Wasm app with authentication

This is a Blazor Wasm app from a VS2019 template with Authentication/Authorization.

I need to know who the user is that is logged in.

 User = HttpContextAccessor.HttpContext.User.Identity.Name;

HttpContextAccessor has a squiggle with cannot be found complaint.

My page has:
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using System.Security.Claims
@attribute [Authorize]

@inject HttpClient http
@inject NavigationManager navManager
@inject ISnackbar Snackbar
@inject IDialogService DialogService
@inject IHttpContextAccessor HttpContextAccessor

Program.Main in the Client project has:
builder.Services.AddHttpContextAccessor();

What am I doing wrong here?

dotnet-aspnet-core-blazor
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AgaveJoe avatar image
1 Vote"
AgaveJoe answered AgaveJoe edited

Not even the Id which holds the hash, this is so Mickey Mouse.

The userId (sub) is in the claims collection.

 @page "/getuser"
 @inject AuthenticationStateProvider authProvider
 @attribute [Authorize]
    
 <h3>GetUser</h3>
    
 <div>
     <ul>
         @foreach (var claim in authState.User.Claims)
         {
             <li><b>@claim.Type</b>: @claim.Value</li>
         }
     </ul>
 </div>
    
 <div>
     UserId = @(userId ?? "No sub found!")
 </div>
 @code {
     private Models.WeatherForecast[] forecasts;
     AuthenticationState authState;
     private string userId;
    
     protected override async Task OnInitializedAsync()
     {
         authState = await authProvider.GetAuthenticationStateAsync();
         userId = authState.User.Claims.FirstOrDefault(c => c.Type == "sub").Value;
     }
 }

And since we are on the subject, I was expecting all the razor pages necessary to do CRUD against this Identity db to be available for me to use. I only have Login, Logout and Register. Where is the rest?

The identity server project contains the account related data and UI. If I recall it's the standard Identity Razor Page Class. Scaffold the pages you want if you need make changes to the code or just view the code. It might be a good idea to create a test project and scaffold Identity. I'm not sure if scaffold pages contains the CRUD you're looking for but the default Identity configuration exposes all the APIs. For example, adding a role to the Roles table. You'll have to write the UI bits yourself but the RoleManager API has everything you need to create and fetch roles from the DB.

It is up to you to write code if you want to manage accounts from the Blazor application. That UI does have account maintenance logic which makes sense because Identity Server manages accounts. Someone might have created a GitHub repo. Just do an internet search. You might get lucky. To roll your own, host Web API on the Identity Server then expose the logic via Web API. Copy Razor Page code paste it into an API action. You're only interested in the data not the Razor Page UI.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RenaNi-MSFT avatar image
0 Votes"
RenaNi-MSFT answered wavemaster commented

Hi @wavemaster ,

As the document said:

Additionally, again for security reasons, you must not use IHttpContextAccessor within Blazor apps. Blazor apps run outside of the context of the ASP.NET Core pipeline. The HttpContext isn't guaranteed to be available within the IHttpContextAccessor, nor is it guaranteed to be holding the context that started the Blazor app.

For the workaround, you could refer to the github issue here:https://github.com/dotnet/aspnetcore/issues/22820#issuecomment-726068641



If the answer is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Best Regards,

Rena


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Ok, don't use IHttpContextAccessor, but use AuthenticationStateProvider instead.

I have read a little from where that link took me, but that doesn't tell me anything that I can understand. I need working code, not specialists talking amongst themselves.

Then my question becomes what do I need to add to a Blazor WASM app based on the VS2019 template with Authentication/Authorization option, so that I can do something along these lines:

 @context.user. userId


0 Votes 0 ·
AgaveJoe avatar image
0 Votes"
AgaveJoe answered wavemaster commented

The following code assumes you are using the Identity Provider template. Inject the AuthenticationStateProvider service to get the AuthenticationState which contains the user.


 @page "/getuser"
 @inject AuthenticationStateProvider authProvider
 @attribute [Authorize]
    
 <h3>GetUser</h3>
    
 <div>
     Name = @Name
 </div>
    
 @code {
     private Models.WeatherForecast[] forecasts;
     private string Name;
    
     protected override async Task OnInitializedAsync()
     {
         AuthenticationState authState = await authProvider.GetAuthenticationStateAsync();
         Name = authState.User.Identity.Name;
     }
 }


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Yes, this works..... but.....

System.Security.Identity only exposes:
AuthenticationType,
IsAuthenticated,
and Name (email address).

Not even the Id which holds the hash, this is so Mickey Mouse.

The whole purpose of this was to get some sort of an Id as in PK, and tie that to my db to implement user specific functionality.

Now I am wondering how to proceed, do I add a column to AspNetUsers table type int of course, or can I tell the script that creates this db on initialization to create a table with PK Id (int)?


And since we are on the subject, I was expecting all the razor pages necessary to do CRUD against this Identity db to be available for me to use. I only have Login, Logout and Register. Where is the rest?


0 Votes 0 ·