0

Create a default Blazor server (not webassembly) application using windows identity platform as authorisation (I've used VS2022 / .net 6).

Is it possible to get hold of a JWT token in a code section of a blazor component (e.g. the LoginDisplay)?

For instance - I can get hold of the claims from the authentication state as follows (for my example in LoginDisplay.razor)

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

    protected override async Task OnInitializedAsync()
    {
        var authState = await authenticationStateTask;
        var user = authState.User;
        var identity = user.Identity as ClaimsIdentity;
        if (identity != null)
        {
            IEnumerable<Claim> claims = identity.Claims;
            
            // Can I get the a JWT Token signed by Azure B2C here?

        }
    }
}

Can I also get a JWT Token from the Azure service (I don't want to regenerate my own - I want an original one signed by microsoft).

As clarification - when using the MSAL javascript libraries on a different project (for a Single Page Application) I could do calls such as MSAL.acquireTokenSilent to get a token from the Azure B2C service for this purpose.

UPDATE - If HttpContext.GetTokenAsync returns null

In addition enets answer below. If you find that you can't access the JWT token using HttpContext.GetTokenAsync then see this question

Jonny
  • 796
  • 2
  • 10
  • 23

2 Answers2

1

To quote MS:

The built-in AuthenticationStateProvider service for Blazor Server apps obtains authentication state data from ASP.NET Core's HttpContext.User. This is how authentication state integrates with existing ASP.NET Core authentication mechanisms.

The Jwt token is in there as bearer.

To get the header there's a Question/Answer here by @enet that shows you how to access the HttpRequest from a Blazor Server App. - How to use the HttpContext object in server-side Blazor to retrieve information about the user, user agent.

I don't have a handy project which has JWT tokens to russle up some code for you. Someone else may be able to add another answer with code or add some to this.

MrC aka Shaun Curtis
  • 19,075
  • 3
  • 13
  • 31
  • 1
    The answer by @enet on the link you have put is probably one of the best explanations available of the whole availability of the HTTPContext for a blazor server side application. I had been playing getting the context in _hosts.cshtml but had no joy getting hold of the actual JWT. I shall read and report back, this is a great pointer. – Jonny Nov 08 '21 at 10:26
  • 1
    @Jonny, I saw your question before, but presently I'm not really active in stackoverflow. Your complement made me answer your question. Thank you... – enet Nov 08 '21 at 15:07
1

You can access the access token and the refresh tokenas describe below, provided that you've set your app to use Jwt Token authentication (OpenID Connect). See this answer how to do that. Note: There is also a second answer related to that question by the same user. Search for it. This answer can also be useful. See this answer, which contains links to useful answers. Note: You can Google search string such as this: "enet stackoverflow blazor jwt token", and such like to find answers by me. If you want to see answers about the AuthenticationStateProvider, just search "enet stackoverflow blazor AuthenticationStateProvider"

Getting the access token

in _Host.cshtml you can code something like this:

@using Microsoft.AspNetCore.Authentication

@{
    var tokens = new InitialApplicationState
    {
        AccessToken = await HttpContext.GetTokenAsync("access_token"),
        RefreshToken = await HttpContext.GetTokenAsync("refresh_token")
    };
}

And then pass the tokens object to your Blazor app like this:

<component type="typeof(App)" render-mode="ServerPrerendered" param- 
                                           InitialState="tokens"/>

Note that the tokens object is passed as a parameter to the App component, something like this:

@code{

    [Parameter]
    public InitialApplicationState InitialState { get; set; }

    protected override Task OnInitializedAsync()
    {
        TokenProvider.AccessToken = InitialState.AccessToken;
        TokenProvider.RefreshToken = InitialState.RefreshToken;

        return base.OnInitializedAsync();
    }
}

Note: TokenProvider is a singleton service instance that hold the JWT tokens, and make it available to other parts of your app. You can save the JWT tokens in the local storage or better the the session storage and read them when needed, etc.

Note: If you don't use Web Api, then you don't need Jwt token (authentication). Use Microsoft Identity authentication

enet
  • 41,195
  • 5
  • 76
  • 113
  • Thanks @enet for adding the code. Saved me setting up a project this afternoon. – MrC aka Shaun Curtis Nov 08 '21 at 15:19
  • [polite] You're welcome ;} – enet Nov 08 '21 at 15:23
  • I think I am close - just that the GetTokenAsync calls are returning null. From the links it seems that this is because I need to do SaveTokens = true but... The default blazor project does this in the program.cs // Add services to the container. builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); And there seems to be no place to set config - do I need to change this from OpenIdConnectDefaults.AuthenticationScheme? – Jonny Nov 08 '21 at 22:50
  • Ah ha - I'm having the same problem with the default .net core web app project .net in vs 2022. I.e. my issue isn't blazor, it is how I am using the (new?) AddMicrosoftIdentityWebApp methods (the SaveTokens doesn't work on its it own - I need other stuff). @enet - this means your answer is spot on as in how to get the tokens down to the blazor code. I'll just work out separately how to get the tokens in the first place and update my question accordingly so that it is a helpful "out of the box" question for others. – Jonny Nov 11 '21 at 10:53