What is Blazor? A Tutorial on Building Web Apps with Authentication

Hey @Stef, thanks for your suggestions.
The article about Blazor WASM and Auth0 integration will be published in a few days. It will include how to overcome the missing audience support you mentioned with a practical example.

4 Likes

Thanks for the headsup Andrea!

Hi! I have this Blazor server site:

https://lenceria-7yeyjec4xa-de.a.run.app

If login in from the web, authentication works fine, but authentication fails if login from a mobile device (mobile browser). Please, if you can explain the difference, it would be very important for me.

Thanks in advance.

Any error/log to share, @sarmientodiego1979?

Thanks for answering.
I was making changes to replay.

The throwing error is:

An unhandled exception occurred while processing the request.
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()

Stack Query Cookies Headers Routing
Exception: OpenIdConnectAuthenticationHandler: message.State is null or empty.

Show raw exception details
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Show raw exception details

Remember that from the web it works fine, and from mobile phones it does not.
In case you want to enter: http://lenceria-7yeyjec4xa-de.a.run.app/

I made it work. If anyone needs it, write me.

Thanks.

1 Like

Glad you have figured it out!

Happy to hear this, @sarmientodiego1979
Out of curiosity, was it a matter of Auth0 configuration or application code?

It was a code problem. I am deploying Blazor in Google Cloud Run, so there were not many examples about it.

Specifically, the problem was in the http / https callback (I suppose that related to load balancing). To solve it I had to put the following code in the Configure method of Startup.cs:

app.UseForwardedHeaders (new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedProto
});

Regards.

2 Likes

@sarmientodiego1979 Thank you so much for sharing this!

1 Like

Hey Community, :wave:
For those waiting for the tutorial about securing a Blazor WebAssembly client, it has been published:

Please, let me know your thoughts!

4 Likes

AWESOME! Thanks Andrea!

2 Likes

Welcome to Auth0 Community @twheeler!

1 Like

Andrea, thanks for the article, it’s been super helpful! After reading it, I’ve decided to switch my small dotnet core app from IdentityServer to using Auth0 instead. However, I am facing the following problems at the moment - any help/advice is greatly appreciated:

  1. Since I had the users stored in the same DB with my other data, I used UserManager<ApplicationUser> to access user details so I could show their names, emails etc. in the UI. By users hear I don’t mean current user, but let’s say a list of users IDs recorded in CreatedBy column in some of my tables. After switching to Auth0, UserManager is no longer available as-is. What’s your recommendation around implementing a replacement functionality? Should I use Auth0’s management APIs to implement my own version of UserManager? If so, is there a ready to use NuGet package available?
  2. Related question to above - I used to have User IDs stored as Guid. Seems like Auth0’s sub claims are not guids any longer - should I change the datatype of User ID columns to strings in my entities? What’s your recommendation around referencing users in SQL data stores?
  3. In my app I used IdentityServer with pre-configured in-memory Test Client and Test User to run my integration tests by calling into GetDiscoveryDocumentAsync() and RequestPasswordTokenAsync(). What is the recommended approach to design integration testing harness in Auth0?

Thanks for the guide, with a bit of tinkering I managed to get it working as expected.

Thought I would share some code I pulled together to centralise the Bearer token being added to requests in case anyone wants to do the same.

I created a custom message handler class like suggested in the Microsoft docs article. To add the bearer to each request I overrode the SendAsync method to get the access token and add it to each request.

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    private readonly IAccessTokenProvider _provider;

    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(new[] { "api uri" });

        _provider = provider;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var accessTokenResult = await _provider.RequestAccessToken();

        if (accessTokenResult.TryGetToken(out var token))
        {
            //add token to request
            if (!string.IsNullOrWhiteSpace(token.Value))
                request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.Value);
            else
                throw new HttpRequestException("No Token!!");
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

In the Program.cs file I added the following HttpClients, one for authenticated and another ones requiring no authentication. If you got an error on the AddHttpClient method you might need to add the Microsoft.Extensions.Http nuget package to your project.

builder.Services.AddHttpClient("ServerAPI", client => client.BaseAddress = new Uri("api URI")).AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("ServerAPI.NoAuthenticationClient", client => client.BaseAddress = new Uri("API URI"));

On the razor component making the api call you can use the code from the docs:

@inject IHttpClientFactory ClientFactory

...

@code {
    private ExampleType[] examples;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            var client = ClientFactory.CreateClient("ServerAPI");

            examples = 
                await client.GetFromJsonAsync<ExampleType[]>("{API METHOD}");

            ...
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        
    }
}

You can also created a typed client class to handle all requests using this method, just need to declare the HttpClient in the constructor using the client factory interface.

3 Likes

Hi @nathanuel81,
Thanks for joining Auth0 Community and appreciating this tutorial, but above all, thanks for sharing this code!

Hi @yuramag,
Thanks for joining the Auth0 Community and appreciating my article.

Regarding point 1, you can use the Auth0 SDK to deal with the Management API.

For the other two points, I’m afraid not to be able to give you a satisfactory answer on my own. I will try to gather additional information from my colleagues.
Alternatively, you can contact our Professional Services.

Thanks @andrea.chiarelli , nice article. Looks like the default audience was the only thing I was missing.

Maybe it would be a great addition to also talk about roles & permissions.

1 Like

Thanks for that feedback @davy!

Thanks, @davy. I will take into account your suggestion.