Securing Blazor WebAssembly Apps

Thanks for sharing that @Hawxy !

Hey folks :wave: , I updated this article to .NET 6.0, and now most of Blazor WASM’s well-known issues are gone, especially the annoying workaround to define a global audience to call an API! :tada:
Take a look and enjoy!

4 Likes

I had trouble just running the dotnet5 branch in the Github repo. Is there a change at Auth0 that would cause it to 401 calling the server from the client?

Hi @seandrexler,
Welcome to the Auth0 Community! :wave:

This article and the related sample project have recently been updated to work with .NET 6, which solves a few annoying issues with the previous versions.

Regarding your issue, please, can you verify if the associated error message is “invalid token” as shown here?

If this is the case, you need to set a default audience on your Auth0 tenant.
The Microsoft.AspNetCore.Components.WebAssembly.Authentication package coming with .NET 5 doesn’t support the audience parameter.

Take a look also at this thread and this one.

Otherwise, please, provide a detailed log of the HTTP requests. See here for more details on how to capture HTTP requests

1 Like

@andrea.chiarelli ,
Thanks! looks like I missed setting the default audience for my tenant. Once I set that in the tenant settings it worked just fine.
Since the audience is provided by the client in the dotnet 6 example do you still need the tenant default using dotnet6?

1 Like

Thanks! looks like I missed setting the default audience for my tenant. Once I set that in the tenant settings it worked just fine.

Awesome! Thank you for sharing!

Since the audience is provided by the client in the dotnet 6 example do you still need the tenant default using dotnet6?

No. you don’t need a default audience with .NET 6 anymore

1 Like

The logout was working intermittently for me in Chrome (in Brave it always worked). I compared it with the Okta sample and I noticed that the logout link was a button instead of an anchor. Sure enough, changing this …
<a href="#" @onclick="BeginSignOut">Log out</a>

… to this …
<button class="nav-link btn btn-link" @onclick="BeginSignOut">Log out</button>

resolved it

2 Likes

Thanks for sharing it with the rest of community!

Interesting. I will try!
Anyway, this makes me think that it’s a browser issue :thinking:

Can anyone please explain why there are FOUR calls made to the Auth0 endpoints every time the application starts? I’m using a Dev tenant, and I realize while that is slower than a production one, it is still taking over 2 seconds before the application loads just to get the authentication/authorization. See image below.

I’ve followed the guide exactly. Am I missing something? Are there settings I can use to maybe reduce this down to 1 or 2 calls? This makes my WASM application too slow for our customer use based on our standards of load times. I can’t use pre-rendering as it doesn’t work with authorization … any suggestions / guidance would be greatly appreciated!

Hey @brian.levin as soon as posible, @andrea.chiarelli will help you with this

Hey @brian.levin,
Welcome to the Auth0 Community :wave:
The four calls you highlighted are the typical calls of the Authorization Code Flow as per OpenID Connect standard specifications. So, I’m afraid you can’t drop them.
Actually, the only call you could remove is the one to the userinfo endpoint. You already have the user’s data in the ID token, so you don’t need to call that endpoint. However, this call is automatically made by the Blazor’s AuthenticationService.js script, so you can’t prevent it as far as I know (unless you want to put your hands in that code… :grimacing:)

Anyway, I made some tests with my developer tenant and I get lower times than yours for the call to the authorize endpoint, which is the slowest time in your case:

I wonder if it wasn’t a momentary slowdown :thinking:

Hi,

I also happened to have a 401 error if anyone can help to point out what did I do wrong in my case.

First of all, I follow this article How to Secure Blazor WASM Applications with Auth0
It is about creating Blazor WASM, Blazor Server and authenticate between them.
It’s work great no problem.

I based on that article and instead of using Blazor Server, I’m creating an AWS Serverless Project instead and apply the same setup just like Blazor Server to that project.

------------ SERVER SIDE ------------
This AWS Serverless Project only have 1 simple controller which contain 2 Get method.
One of them will have Authorize tag

ValuesController.cs
image

Startup.cs
image
Startup.cs under Configuration method
image

And of course the appsettings.json will contain the Domain and Audience information just like the article show
image

That is all for the server side.
I then deploy this project to AWS CloudFormation.

------------ CLIENT SIDE ------------
I have everything setup just like the article for Blazor WASM.
Only different here is that I will try to get the data and display in the index page.

index.razor
image

Program.cs

And the appsettings.json will have Authority, ClientId and Audience information

------------ AUTH0 DASHBOARD ------------
Everything is following the article to Create new Application for Blazor WASM and Create New API for AWS Serverless.

------------ RESULTS ------------
When I try to call the second Get method (without the Authorize tag) it will work fine but the other one (with the Authorize tag) even after I login successfully it will still return 401 from the browser console and failed to get the data.

Sorry for the long post but that is all for my case.
Please help to advice what should I do next to solve this issue.
Thanks.

Hi @van.vo,
Welcome to the Auth0 Community :wave: and thank you for reading the article and trying the sample project.

At first look, I can’t see anything wrong with your project. Maybe you can get more information on the reason for that 401 by capturing the full HTTP response, using Chrome’s Developer Tools, for example.

The first possible reason for this error that comes to my mind is a misspelled audience in the server or client configuration. Please, make sure that the audience’s value you store in the appsettings.json files matches the one you registered in the Auth0 dashboard in any detail, including any trailing slash

A small update for the .NET 7 space, this piece of work went in and should be in the next release: [Blazor][Wasm] Dynamic and extensible authentication requests · Issue #42580 · dotnet/aspnetcore · GitHub
This unblocks handling of the Auth0 Organization Invite flow in Blazor, and probably resolves some sore spots elsewhere.

Nothing to report on getting the metadata seed setting passed down as a library option. Due the underlying oidc-client library being end-of-life, I have a feeling this is going to take priority for .NET 8: Consider re-designing the Blazor WASM authentication stack · Issue #40764 · dotnet/aspnetcore · GitHub

1 Like

Awesome! Thank you so much for this news!

Best practice or not, I must say Prasanth_Reddy that is quite impressive code you built there.

Thanks for your article, i was able to get my Blazor WASM project up and running and my controller APIs are secured per your instructions. What i am missing is on the Authorized controller, my user is a claims identity but none of my profile information carried over. i looked through the claims, no email, no username, etc … what am i missing. On the server how to i know who is calling the API besides the Auth0 internal id? Do i have to add something to the token on the client side to send the additional profile claims? Thanks in advance

Thank you for reading my article. I’m glad you were able to secure your application following the article’s instructions.

Regarding your questions, you are using an access token to call your protected API. By nature, an access token conveys authorization information, while an ID token contains identity information.
Authorization information is everything your API needs to make authorization decisions: it can be permissions or roles, but sometimes, like maybe in your case, identity data.
Please, take a look at this article to learn more about the differences between ID and access tokens.

First, I suggest analyzing if you really need identity data to make authorization decisions. Maybe you just need permissions. In this case, check out this article about how to deal with permission-based authorization and this one about role-based authorization.

If you actually need identity information to make authorization decisions, you can add this data to your access token as custom claims using an Auth0 Action. Check out this document to learn how to do it.

I hope I’ve given you useful directions.

Thanks for responding.

First let me explain my use case. Pretty straight forward … Blazor WASM doing CRUD operations to a database via API Controllers.

The caveat is our database context in the controller has an override to SaveChanges which accepts a username as a parameter. By examining the Change Tracking of the context we automatically create an audit log of what the user is committing to the database.

Now I am using Actions on my Auth0 tenant to append the username to the identity.

The picture below shows all the claims available at the client and controller. Redacted a bit to obscure real end points.

You can see my ‘username’ of ‘leftdogxxxx’ was added under the custom claim and visible on the client. User.Identity.Name on the Client also shows “Kevin White”

On the server API controller, Identity.Name is the internal “auth0|617xxxxxxxx”

I’m sure I’m missing something simple. But I would really like to include the claim “https://auth.mydomain.com/username” from the client to be passed to the API controller. I feel it probably has to be done with an inherited BaseAddressAuthorizationMessageHandler

Or is the solution on the API to use the ‘auth0|617xxxxxxxx’ id, and make a call back to Auth0 to get the username, but that seems like a lot of redundant calls.

Just looking for the best practice. Any help is appreciated