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...