Securing Blazor WebAssembly Apps

As far as I understand, your Action adds the custom claim https://auth.mydomain.com/username to the ID token with a statement like the following:

api.idToken.setCustomClaim(`${namespace}/username`,  event.user.username);

You need to add the same custom claim to the access token with a statement like the following:

api.accessToken.setCustomClaim(`${namespace}/username`,  event.user.username);

This way, you will find the custom claim https://auth.mydomain.com/username on the server side as well.

Remember: the API receives the access token, not the ID token, which is used to populate the client-side identity.

I hope this clarifies.

2 Likes

Thatā€™s exactly what i needed thank you so much. Such a simple mistake. Sometimes all you need is that extra set of eyes to see. :smile:

1 Like

Hello, Iā€™m having a headache trying to get my WASM application to authenticate through auth0.

Iā€™ve followed the tutorial.

These are my clientā€™s Program.cs and appsettings.json files:

These are the apiā€™s Program.cs and appsettings.json files

Iā€™ve set up the SPA and API applications in the Auth0 dashboard. When running the application, I can successfully log in and I see the pages which are attributed as Authorized only when logged in.

However, the calls to my [Authorized] controller endpoints always result in 401, which Iā€™ve noticed is a reoccurring problem here. Iā€™m running .NET 6 and despite that Iā€™ve tried setting up the tenantā€™s default audience, which did not help.

The requestā€™s header does contain a bearer:

If anyone would help me figure the mistake I keep doing, please, I would highly appreciate it.

Hi @magoc.dan,
Welcome to the Auth0 Community!

I noticed that your API uses the following code to register authentication and authorization middleware:

app.UseAuthorization();
app.UseAuthentication();

The middleware registration order is important. You should first register the authentication middleware and then the authorization middleware, as proposed in the tutorial. In other words, your code should be as follows:

app.UseAuthentication();
app.UseAuthorization();

Check out this article to learn more about securing an ASP.NET Web API.

1 Like

Thatā€¦ actually worked. Thank you very much for pointing it out!

1 Like

You are welcome! :slightly_smiling_face:

1 Like

This was my issue. I missed this line and couldnā€™t figure out why my access token was invalid! Thanks a bunch. :grinning:

Iā€™ve been following the tutorial at Auth0 for securing a Blazor WASM and API with Aut0, which is found here ā†’ How to Secure Blazor WASM Applications with Auth0

Securing the app works fine, but adding the API gives me issues. As soon as I add the authenticate attribute to the API Controller it results in this:

fetchdata:1 Access to fetch at ā€˜https://localhost:7226/weatherforecastā€™ from origin ā€˜https://localhost:7298ā€™ has been blocked by CORS policy: No ā€˜Access-Control-Allow-Originā€™ header is present on the requested resource. If an opaque response serves your needs, set the requestā€™s mode to ā€˜no-corsā€™ to fetch the resource with CORS disabled.

Iā€™ve added a policy to allow the app in the program.cs

builder.Services.AddCors(options =>
{
  options.AddPolicy("Open", builder => builder.WithOrigins("https://localhost:7298").AllowAnyMethod().AllowAnyHeader());
});

I've played around with the program.cs and also added app.UseCors before authentication/authorization (as a provided solution I found online), which then results in another issue.

> Failed to load resource: the server responded with a status of 401 ()
>
>
>
> blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0. System.Text.Json.JsonException: The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.

That error seems to indicate an issue with the bearertoken not being set, but it is setup using BaseAddressAuthorizationMessageHandler.

builder.Services.AddHttpClient(ā€œAPIClientā€, client =>
{
client.BaseAddress = new Uri(ā€œhttps://localhost:7226ā€);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add(HeaderNames.Accept, ā€œapplication/jsonā€);
}).AddHttpMessageHandler();


I've added the project to GitHub, if more details on the code is of interest https://github.com/obrungot/BlazorAuthenticationPlayGround.git

Hey @obiwan,
Welcome to the auth0 Community! :wave:

The article proposes the ASP.NET Core hosted approach to publish your Blazor WASM app (see here). This means that the Blazor WASM app comes from the same domain as the Web API runs, and you donā€™t need to set up CORS.
Honestly, if you donā€™t have any specific reasons to publish your Web API on a different domain, I would stick with the ASP.NET Core hosted approach.

1 Like

Hello

I followed the excellent article by @andrea.chiarelli on securing Blazor Wasm with Auth0:

I have been able to secure our application, and everything has been running without a problem. There is one issue that remains that I have not been able to resolve. The following message is output to the console multiple (approximately 50 times) during log in:

Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user

Iā€™m guessing itā€™s something to do with silent v interactive login.

Does anyone have any ideas why I am getting this message.

Many thanks

Hi @Ditchford ,
I tried to figure out what is happening with your application but honestly Iā€™m afraid I canā€™t do much.

As far as I know, this message is shown when your application comes across a <NotAuthorized> element and in the Blazor WASM case, it should happen on the client side (i.e., the server is not involved).

For example, in the sample project of my article, this message is shown only once, before the user authentication. This is correct because the current not authenticated user is attempting to access the quiz page.
If you switch between the home page and the quiz page before authenticating, you can see this message shown in the JavaScript console for each attempt to access the quiz page. No request is submitted to the server though.

I hope this may help to identify what is happening in your application.

1 Like

Hey @andrea.chiarelli. Thanks for that. It made me go back and re-examine my login workflow. The tip about the tags was spot on. The main issue (I think) is that I have used the tags , , in several places in my MainLayout and each of these is generating a message during login. Add to that the fact that Blazor appears to render MainLayout twice and a strange bug where the following code does not initially return the authenticated user:

AuthenticationState authenticationState = await authenticationStateTask;
ClaimsPrincipal user = authenticationState.User;
string emailaddress = user.Identity.Name ?? ā€œā€;

In the above when the email address is empty, I reload MainLayout and on the second pass the email is populated.

The combination of all the above explains the multiple messages, and why I have to refactor my login code.

Thank you

1 Like

That was a great articla. Is there an article on securing Azure Static Web Apps (serverless) build with Blazor WASM (not hosted) using Okta? Thank you.

1 Like

Hi @spmoran-blazor,
Welcome to the Auth0 Community! :wave:

You can read this article to learn how to secure a Blazor WASM app with Okta.

For deployment to Azure Static Web Apps, we donā€™t currently have a specific article. You can refer to the Microsoft documentation.
Of course, keep in mind that you can only deploy the WASM application to Azure Static Web Apps.
I hope this helps.

2 Likes

Hi Andrea,

We have an issue with passing a query parameter from Blazor to Auth0. It seems to be similar to the issue here that said it has been fixed but doesnā€™t seem to work in our case [Blazor][Wasm] Dynamic and extensible authentication requests Ā· Issue #42580 Ā· dotnet/aspnetcore Ā· GitHub

We have an invite code that is relevant to our Blazor application that needs to be passed to create a new tenant in the app. Blazor seems to be unable to add the invite code to the query parameter when redirecting to the auth0 login page. On login success the invite code will disappear after redirecting back to our app.

We have tried with a vanilla blazor app on macos and windows and the problem still exists. Any suggestions or advice appreciated.

Thanks

Hey @cashbucket,
Welcome to the Auth0 Community!

Iā€™m not sure I correctly understand your problem.
To pass any additional parameter to Auth0 during the authentication, you should add them to the OIDC configuration as in the following example:

options.ProviderOptions.AdditionalProviderParameters.Add("myparam", "myvalue");

This works, otherwise you could not even pass the audience parameter, for example.

Please, can you provide more details on what you are trying to do?
What version of .NET are you using?
What parameter are you trying to pass to Auth0?
Can you share a sample code or more details on the flow you are implementing?

2 Likes

Hi @andrea.chiarelli thank you for your response!

The mechanism that you pointed out works, however itā€™s only for static values. What weā€™re looking for is a way to pass custom parameters with dynamic values.

We have a system where a new user receives a link to our application to register with an invite code. Weā€™re looking for a way to relay that invite code to auth0 so that we can use it in custom rules/hooks to the workflow. We would also like that invite code to be transmitted back to our application on login-callback.

Below is a snippet of our code extracting the invite_code value from our invite link query parameter and adding it to additional parameters on authentication redirect. However invite_code parameter is not appended to the /authorize endpoint.

InteractiveRequestOptions requestOptions =
      new()
      {
          Interaction = InteractionType.SignIn,
          ReturnUrl = Navigation.Uri,
      };

  QueryHelpers.ParseQuery(Navigation.ToAbsoluteUri(Navigation.Uri).Query)
      .TryGetValue("invite_code", out var inviteCode);

  requestOptions.TryAddAdditionalParameter("invite_code", inviteCode);

  Navigation.NavigateToLogin("authentication/login", requestOptions);

What are we missing?

Having an issue connecting from Blazor WebAssembly to ASP.net Core backend api.

Able to login from BlazorWebAssembly and get a token. However, sending this topic to API returns:
WWW-Authenticate: Bearer error=ā€œinvalid_tokenā€, error_description=ā€œThe signature is invalidā€

UI client and Backend API are not using same base URL. Client HttpClient is set up to use AuthorizationMessageHandler:

builder.Services.AddHttpClient(GlobalConstants.USERMANAGEMENT_API, client => client.BaseAddress = new Uri(userServiceUrl))
.AddHttpMessageHandler(sp => sp.GetRequiredService()
.ConfigureHandler(
authorizedUrls: new { userServiceUrl }));

Api is set up per starter guide:
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.Authority = AuthSettings.GetAuthority(builder.Configuration);
options.Audience = AuthSettings.GetAudience(builder.Configuration);

});

I double checked that Authority and Audience match between client and api.
Not using RBAC.

Any ideas to try?

Thank you

Hi @al-cashbucket,
Iā€™ve done some tests using your code and it actually looks like it doesnā€™t work as expected.
Your code looks correct. I checked out the Microsoft documentation and it seems like this should be the correct approach. I feel like this is a bug in the Blazor authentication library.
I suggest you open an issue with the Blazor team.
In the meantime, Iā€™ll keep investigating in case I missed something.

1 Like

Thanks @andrea.chiarelli

My theory at the moment is that the Microsoft Authentication library is making a request to /.well-known/openid-configuration to determine what the valid authentication request parameters and then automatically dropping any parameters that arenā€™t valid. I found that standard parameters such as prompt, login_hint, display, etc works with the above code, but not anything custom. Is there anything we could configure on the auth0 side to allow it?