Blazor JWT Authentication

Viewed 1907

I am trying to figure out correct way to implement JWT auth with Blazor (WASM). After going through the docs a got an idea on how the built in components work but still the whole picture is not clear to me. So in my scenario i have an API sever that will be used, the API server can issue JWT tokens and they can be used to authenticate against the endpoints where required.

So right now i am trying to figure out the correct role for each component. For start we have AuthenticationStateProvider, as i understand this component has the responsibility of obtaining the JWT token either from server or if one stored locally, also it could handle token refresh when required?

Now since i will be using Typed HTTP Clients i will be using IHttpClientFactory, along with that i will have AuthorizationMessageHandler to attach tokens to desired HTTP Client instances.

Things fall apart for me when i am trying to deal with IAccessTokenProvider, as i understand the default implementation will be called once a HTTP Client is created and http request is about to be made. What is not clear is how this IAccessTokenProvider will obtain the token. So the question is whether i should create my own implementation of IAccessTokenProvider and if so how it should handle the tokens. As i said i wont be using any built in authentication providers and will have my own JWT auth system instead.

Thanks.

1 Answers

The first three paragraphs are very clear and correct. This is how you should do that. I can post here some code snippet to demonstrate how it is done in practice...

Things fall apart for me when i am trying to deal with IAccessTokenProvider,

No wonder... The IAccessTokenProvider is not relevant here. The IAccessTokenProvider is a token provider used in the new JWT token authentication system for WebAssembly Blazor App. But if you want to implement the JWT authentication yourself, you must do that as you've described in the first three paragraphs... which I can summarize like this:

  • When a user makes a first access to a protected web api endpoint and he's not authenticated (or registered), he's redirected to the relevant pages, type his credentials, etc, which you pass to your Web Api end point dedicated to authenticate the user (register if necessary, etc.), after which the action method called produce the JWT token, and send it back to the WebAssembly Blazor App running on the browser. You should store the JWT Token (perhaps in the local store), and retrieve it whenever you perform HTTP calls (Adding the JWT Token to the headers of the request).

The above described process also involve the implementation of the AuthenticationStateProvider object, that is updated with the authentication state, and notifies subscribers, such as the CascadingAuthenticationState, that the authentication state has changed, at the end of which process other components and objects adapt themselves to the new situation... you know, re-rendering, etc.

So, you see, you've received a JWT Token from your Web Api, stored it a local store, read it, and use it. Reading the Jwt Token from your local store and parsing it, to great extent, is something that the IAccessTokenProvider does, but in the new authentication system, and as you do not use this system, the IAccessTokenProvider is not relevant.

What about automatic Token injection in headers of HTTP client, can i or should i still investigate custom AuthorizationMessageHandler or this component would not be usable without IAccessTokenProvider?

You may add your Jwt Token to each HTTP call as demonstrated below:

    @code {
    Customer[] customers;

    protected override async Task OnInitializedAsync()
    {
        // Read the token from the local storage
        var token = await TokenProvider.GetTokenAsync();
        customers = await Http.GetFromJsonAsync<Customer[]>(
            "api/customers",
            new AuthenticationHeaderValue("Bearer", token));
    }
}

which is perfectly fine. But of course you can create a custom DelegatingHandler modeled after the AuthorizationMessageHandler or still better the BaseAddressAuthorizationMessageHandler as you're going to use the IHttpClientFactory to provide your HttpClient service. Try first to attempt to use them without any modifications, and if it's not practical just emulate their functionality.

The last things that bothers me is the implementation of obtaining access token and storing it locally.The best approach i can think of so far is to have a global authentication service, this service will provide the functionality of obtaining the token, refreshing it, storing etc. Both IAccessTokenProvider and AuthenticationStateProvider will use it when token is requested plus will be notified whenever authentication state changes like user logs in or out.

Perfect... Note: The AuthenticationStateProvider should be notified of the change in the status of the Jwt Token. As for instance, when you get a new token from your Web Api endpoint, your code should add it to the local store, and then notify the CUSTOM AuthenticationStateProvider of the change. Your code also should notify the AuthenticationStateProvider in case you delete a Jwt Token, so that your user interface will reflect this changes, etc.

Good luck.

Hope this helps...

Related