Add Auth0 Authentication to Blazor Web Apps

Thanks for the great article. There is so little information about how to configure the client components to use security when they are calling an API.

Are you able to do ‘Part 2’ of the article and show how we can extend this solution to call an API endpoint (maybe secured by Auth0 as well?), and use the access token to call an external API? This is the big missing piece to making Blazor .Net 8 apps useful!
Thanks!

Hey @ripteqdavid,
Thank you for appreciating my article and welcome to the Auth0 Community!

Actually, the topic of calling an API has been asked a number of times. I hope to cover this soon.
In the meantime, I invite you to take a look at my suggestions on calling “internal” and external APIs here and here

Hi Andrea,

Great article. And i am slowly digesting it.
My case looks like a bit different (as i understand your article). In my case I would like to have a .Net 8 Blazor WebApp in Interactive WASM Rendering mode which will call a serverless Azure function secured by OIDC identity provider.

What would you suggest in this case. My server calls are directly from browser to Azure function. Is there an example i can refer to ?

Sorry my bad. I did not see your reply here to another question. Looks like the same question.

"Thank you for appreciating my article and welcome to the Auth0 Community!

Actually, the topic of calling an API has been asked a number of times. I hope to cover this soon
"

Hi,

Thank’s for tutorial it’s interresting, but if i can expose my opinion, only show how to used in Blazor app is not enough, secure and after didn’t have a concret sample for calling API, it’s quite “useless” ? Sorry if words is too hard, but for some it’s blocking, because having API for data and cannot be call ?

For my part i’ve used :

 builder.Services
                .AddAuth0WebAppAuthentication(options =>
                {
                    options.Domain = builder.Configuration["Auth0:Domain"];
                    options.ClientId = builder.Configuration["Auth0:ClientId"];
                    options.ClientSecret = builder.Configuration["Auth0:ClientSecret"];
                })
                .WithAccessToken(options =>
                {
                    options.Audience = builder.Configuration["Auth0:Audience"];
                });


app.MapForwarder("/{**catch-all}", "https://localhost:5000", transformBuilder =>
            {
                transformBuilder.AddRequestTransform(async transformContext =>
                {
                    var accessToken = await transformContext.HttpContext.GetTokenAsync("access_token");
                    transformContext.ProxyRequest.Headers.Authorization = new("Bearer", accessToken);
                });
            }).RequireAuthorization();

If i’ve connected and go manualy on /api/my-url it’s forward with AccessToken
If i try from HttpClient from Page it’s try to call auth flow :frowning:

Kr,

Hey @Hantse,
Writing a follow up of this article focused on calling protected APIs is in my plans.
In the meantime, I suggest using different approaches depending on whether the API is internal or external to your application.
See this answer for my suggestion for the two approaches.

I get the following error running my application and a cloned copy of yours from github with my auth0 credentials in.

InvalidOperationException: IDX20803: Unable to obtain configuration from: ‘https://https://dev-opynqcjq58yhxawc.us.auth0.com/.well-known/openid-configuration’.

Hey @brianrhody,
Looks like you assigned your tenant URL (https://dev-opynqcjq58yhxawc.us.auth0.com) instead of your tenant domain (dev-opynqcjq58yhxawc.us.auth0.com) to the Domain key in appsettings.json.

Thank you for writing this article it made switching over to the new Blazor model much easier. The question that I have is how would I be able to intercept the creation of the ClaimsPrincipal so that I can have it pull additional claims from the JWT token?

Prior to switching to this new model I was able to accomplish this by calling,

and passing in a custom ClaimsPrincipal factory.

As far as I can see, your code snippet is for Blazor WebAssembly. In the Blazor model discussed in this article, the authentication happens on the server side so you can’t use AddAccountClaimsPrincipalFactory().

I’m not sure about what you wan to achieve, but if you just need to access all the claims from the ID token, you can do it through the AuthenticationState. Take a look at this example:

var state = await authenticationState;

var myClaimValue = state.User.Claims
    .Where(c => c.Type.Equals("myClaimName"))
    .Select(c => c.Value)
    .FirstOrDefault() ?? string.Empty;

I hope this helps.

We have added custom claims for our users in Auth0, for example key: “permission”, value: “customer.read”, and the only way to retrieve them is by reading the Access Token that is returned from Auth0 when a user logs in. I just cannot figure out where I can intercept the point that the Access token is turned into the ClaimsPrincipal object. This is what is in the the Jwt token contains

image

But this “permissions” do not come through when the ClaimsPrincipal object is created.

Hey @wdavis,
The access token is NOT mapped to the ClaimsPrincipal object. The ClaimsPrincipal object contains ONLY the claims coming from the ID token.

The access token is intended for calling a protected API, and only the API should inspect it.

See here for the difference between ID and access tokens.
See here to learn how to check permissions on the API side.

If for some reason you need additional claims in your ID token, you can add them using Actions.
See here for an example of adding custom claims to an ID token using Actions.

If in your case the API is implemented in the same Blazor app, I would not use token-based protection. Take a look at this article to have more context on calling an API.

So, How would I be able to access the user’s permissions so that I can use them in the UI?

You should use Actions to add permissions to the ID token as custom claims (see here to learn how to do this).
If your UI does not need the granularity of permissions, you may consider creating roles instead. However, this depends on your specific use case.

I am terrible with authentication. In this scenario, what would I need to do to force users to login before gaining access to the application?

I thought to try adding an Authorization Policy but that didn’t seem to work. Would you be able to point me in the right direction?

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

I’m not sure what you mean by “force users to login before gaining access to the application”. If you mean that you want the login screen to be the first page the user sees when accessing your application, you can simply add the Authorize attribute to the Home page, in the case of the sample project.
In other words, the content of your Home.razor component will be as follows:

<!-- BlazorIntAuto/Components/Pages/Home.razor -->

@page "/"
@attribute [Authorize]   <!-- 👈 new code -->

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

I hope this helps.

Hi,

My first post here, hope it is not off-topic.

One thing that I find confusing after going through the tutorials is how to handle the “next step” after sign up.

Typically, in the days you were in control of the callback redirect before all the middleware magic, you would be invoked, check if the user existed in your database, add them if not.

How do you do this now in a good way?

I saw some articles from @andrea.chiarelli and some say:
a) Redirect to a “newuser” page after login and do your stuff there: What is Blazor? A Tutorial on Building Web Apps with Authentication - #158 by andrea.chiarelli

b) But I also found options of people hooking into OpenIdConnectEvents with OnTokenValidated

c) Or even play with “OnTicketReceived” to obtain the same. c# - Trying so save user data to dbcontext after first signup with Auth0 in asp.net core - Stack Overflow

What is the recommended way to do it? It is quite confusing for newcomers :smiley:

Hi @psantosl,
All of the methods you mention are alternative. Basically, you can use the redirectUri parameter or the event handler based on your preference or application logic. You can also use Actions to obtain the same result without modifying your application code.

For example, if you simply want to redirect a user to a given page after authentication, without any specific processing, you can simply use the redirectUri parameter.
If you want to do some processing, such as adding claims to the authenticated user, the OnTokenValidated event is the proper place. But you can do it with an Action too, without modifying your application code.

The only thing I can suggest is to use the OnTokenValidated event instead of OnTicketReceived. This will ensure that the ID token you receive is valid and the data it contains is trustworthy.

I hope this helps.

It does help! Thank you!

Actually, the confusing part for me is “where” to put the code to add the recently logged in user to our internal user database… and I guess this is not that easy to do with an Action, so I should do it in application code and using whether the redirect or the OnTokenValidated. Ok! Thanks!

1 Like

Thank you so so much for this article, it was easy to follow and very well explained.
Can you please fix the redirectUri? it’s not working after logging in it always goes to the home page.
thank you again.