Search code examples
controllerblazoridentityserver-sidewebassembly

Access logged user information in Blazor WASM in server side controller


Using the Blazor template provided in Visual Studio 2019 with Identity 4 and individual accounts.

I have this controller on the server side

[ApiController, Route("api/[controller]")]
public class DataController : Controller
{
    [HttpGet, Route("GetUser")]
    public async Task<ActionResult<bool>> GetUser()
    {
        return User?.Identity?.IsAuthenticated;
    }
}

And on the client side I have a Page with this code

@page "/User"
@inject HttpClient Http

@userIsLogged

@code {
    private bool userIsLogged;

    protected override async Task OnInitializedAsync()
    {
        userIsLogged = await Http.GetFromJsonAsync<bool>("api/data/GetUser");
    }
}

If the user is logged on and I enter into the page from the browser I can see the True text indicating that the user is already logged.

But if I try to request the controller result directly in the browser by entering in https://localhost:44395/Api/Data/GetUser, without using the HttpClient I don't see the expected result even if the user is already logged.

From other posts like this, I guess the problem is related to this line

services.AddAuthentication().AddIdentityServerJwt()

But I don't find how to solve.

My goal is to be able to access to the Identity information of the logged user, usermane, roles, etc from the client using the HttpClient as well as from calling the ActionResult directly from the browser. Can you point me out what is missing in the project in order to do that?

Thanks Ignacio


Solution

  • IdentityServer uses JWT ( Json Web Token) to protect its resources ( in this case is the API ) in same time the application is registered as a client that allowed to access the Web Api ( which included within it's Scope)

    So the reason it is working during the connection from the application because the httpclient send the token as you see in the following pic

    enter image description here The Token issued by IdentityServer

    Also Notice when you start your application Blazor application will request the required parameters from identityserver (OidcConfigurationController) as you see in the following pic

    enter image description here

    Also see the returned parameters to the blazor app which show the scope clearly enter image description here

    So the conclusion, yes you won't be able to access your secure api unless it is within the application that has access to it

    Update (after Question has been updated )

    You will need to inject The following provider in your page

    @inject Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider AuthenticationStateProvider
    

    Then use it as following

    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
                user = authState.User;
                var claims = user.Claims?.ToList();
    

    Also if you want to secure your pages based on Roles/policy you could add the policy in program.cs

    as following

    builder.Services.AddAuthorizationCore(options =>
                {
                    options.AddPolicy("Admin", policy =>
                    {
                        policy.RequireAuthenticatedUser();
                        policy.RequireRole("Admin");
                    });
                    
                });
    

    Then use it within your partial class as following

    [Authorize(Policy = "Admin")]
    

    or within your page as following

    @using Microsoft.AspNetCore.Authorization
    @attribute [Authorize(Policy ="Admin")]
    

    Good luck

    If this answered your question, feel free to Mark as answered