# A guide on how to setup Blazor WebAssembly with Auth0

I have had some experience working on OpenID Connect.

Exploring Auth0 has made me realize one thing, it cant get simpler than this. Setting up identity with Auth0 was a delight, most of the time I didn't even need to look at the documentation (am I bragging or was the interface so user friendly?)

We will take a look at **Stonks**, a simple crypto listing app using Blazor WebAssembly and Auth0. The Blazor WebAssembly framework provides us with a frontend and a fake backend project, we will integrate Auth0 on both. From the backend logic we are going to make a call to coinapi.io to fetch a list of crypto currencies, narrow it down to a few thousand cryptos(**why are there 12k+ cryptos?**) and display them in our Blazor UI.

**Apps and tools**

* An IDE for .NET projects -&gt; VS or VSCode or Rider
    
* Latest version of VS would automatically install [.NET 5](https://dotnet.microsoft.com/download/dotnet/5.0) for us
    
* [Auth0](https://auth0.com) -&gt; auth + identity
    
* [Coinapi.io](https://www.coinapi.io) -&gt; fetch list of cryptos
    
* https://jwt.io -&gt; decrypt and analyze jwt tokens
    

## TL;DR

I have attached some demo videos on the different connection types in Auth0, their setup and behaviour. Head over to the end of the post and take a peek.

## Step1 - Bootstrap a blazor project

We will create the base Blazor project first.

1. Open command line
    
2. Go to the directory where you would want to create your projects, for me its  
    `cd StonksApplication`
    
3. Bootstrap the projects using `dotnet new blazorwasm --hosted`, this command will create a Client, a Server, and a Shared project for us. The final structure should look like
    

```plaintext
.
├── Client           # Client project
│   ├── Pages   
│   ├── Shared
│   └── ...
├── Server           # Backend project
│   ├── Controllers                          
│   └── ...    
├── Shared           # Shared Library
│   └── ...
└── ...
```

4. Open the solution inside VisualStudio, inside cmdline `start StonksApplication.sln`
    
5. One VisualStudio is up, we will go ahead and run the application
    

For me the application loads at **https://localhost:44304**

## Step2 - Auth0 setup

Once we have created and verified our Auth0 account, we will go ahead and setup the following

1. Application
    
2. Callbacks and CORS
    
3. API resources
    
4. Users
    

**Setup Application**  
Since ours is a SPA we will select that type while creating.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628620901437/MyIY532TA.png align="left")

**Setup Callbacks and CORS**  
In the application settings page set the following values (the description against the setting tells us exactly they are meant for)

![Untitled.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629010138186/Kk-nlq5ZF.png align="left")

We use the same base url where our app is running  
Allowed Callback URLs -&gt; **https://localhost:44304**/authentication/login-callback (this is the default blazor middleware callback path)  
Allowed Logout URLs -&gt; **https://localhost:44304**  
Allowed Origins (CORS) -&gt; **https://localhost:44304**

**Setup API resources**  
For our backend API, we will go ahead and create an API resource

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628621697053/s7pRCzKoo.png align="left")

Identifier -&gt; **https://localhost:44304/**

> The identifier(a.k.a audience) is critical, and in simple words mean "this API resource can be accessed by whosoever has this identifier".

**Users**  
We will also go ahead and create one user under the User Management tab. We will use this user to login in our application.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629532184380/WYjk6Js4_.png align="left")

Basic Auth0 configuration is now in place.

## Step3 - Configure Blazor projects for Auth0

We will configure Auth0 for our projects

1. StonksApplication.Client
    
2. StonksApplication.Server
    

### Configure Auth0 in Client project

*For brevity we are going to take a look at the major code blocks/components only.*

* Under `wwwroot` folder create a `appsettings.json` file.  
    Add a json object which holds the following configurations from Auth0.
    
    ![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628934381667/cYMaY4obN.png align="left")
    
* Configure oidc authentication inside `Program.cs`.
    

```csharp
public class Program
{
    public static async Task Main(string[] args)
    {
        ...
        builder.Services.AddOidcAuthentication(options =>
        {
            builder.Configuration.Bind("Auth0", options.ProviderOptions); 
            options.ProviderOptions.ResponseType = "code";
        });

        await builder.Build().RunAsync();
    }
}
```

Fetch and bind configuration from `appsettings.json` using `builder.Configuration.Bind("Auth0", options.ProviderOptions);`

Set the client to follow `authorization_code` flow using `options.ProviderOptions.ResponseType = "code";`. More on flows [here](https://darutk.medium.com/diagrams-of-all-the-openid-connect-flows-6968e3990660).

**Weird BLAZOR issue**

> As part of oidc configuration I should be also allowed to setup the audience property for my client, if missing, that would result into auth issues. More about it in later sections of the post, for now we move on.

* Under `Pages` folder create `Authentication.razor` which deals with login, logout authentication actions
    

```csharp
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Configuration

@inject NavigationManager Navigation
@inject IConfiguration Configuration

<RemoteAuthenticatorView Action="@Action">
	<LogOut>
		@{
			var authority = (string)Configuration["Auth0:Authority"];
			var clientId = (string)Configuration["Auth0:ClientId"];
			Navigation.NavigateTo($"{authority}/v2/logout?client_id={clientId}&returnTo={Navigation.BaseUri}");
		}
	</LogOut>
</RemoteAuthenticatorView>
@code{
	[Parameter] public string Action { get; set; }
}
```

* Under `Shared` folder, create `AccessControl.razor` which will have a label for username, login and logout buttons.
    

```csharp
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager

<AuthorizeView>
	<Authorized>
		Hello, @context.User.Identity.Name &nbsp;
		<button @onclick="BeginSignOut">Log out</button>
	</Authorized>
	<NotAuthorized>
		<button @onclick="BeginSignIn">Log in</button>
	</NotAuthorized>
</AuthorizeView>

@code{
	private async Task BeginSignOut(MouseEventArgs args)
	{
		await SignOutManager.SetSignOutState();
		Navigation.NavigateTo("authentication/logout");
	}
	private async Task BeginSignIn(MouseEventArgs args)
	{
		Navigation.NavigateTo("authentication/login");
	}
}
```

* Create a new `Stonks.razor` under `Pages` folder, this is the component where we will display the list of cryptos.  
    Mark the page with `Authorize` attribute, this will force the user to login to view this page.
    

```csharp
@page "/stonks"
@using StonksApplication.Shared
@attribute [Authorize]
```

### Configure Auth0 in Server project

*For brevity we are going to take a look at the major code blocks/components only*

* Inside appsettings.json file add a json object which holds the following configurations from Auth0.
    

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628934524269/zV_Tas97p.png align="left")

* Inside Startup.cs file of the project, setup authentication service
    

```csharp
public void ConfigureServices(IServiceCollection services)
		{
			...
			services.AddAuthentication(options =>
			{
				options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
				options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
			}).AddJwtBearer(options =>
			{
				options.Authority = _configuration.GetValue<string>("Auth0:Authority");
				options.Audience = _configuration.GetValue<string>("Auth0:Audience");
			});
		}
```

Set `DefaultAuthenticateScheme` and `DefaultChallengeScheme` to `Bearer`. We want to use jwt tokens for auth inside our Server by default. Set the `Authority` and `Audience` values from appsettings.json as well.

> This setup makes sure jwt(bearer token) validations are in place.

* Create a controller, mark the controller with the `Authorize` attribute. Only authorized requests will be allowed to go through from here on.
    

```csharp
[ApiController]
[Route("v1/stonks")]
[Authorize]
public class StonksController : ControllerBase
{
       public StonksController()
		{
               ...
		}
}
```

With all of this in place, along with a few additional stuff like

1. Attaching access tokens to API calls from Client To Server
    
2. Coinapi setup inside Server, making API calls to coinapi to fetch list of cryptos
    
3. **Weird Blazor issue resolution**
    
4. Code cleanup
    

Here is the final result (the user was created while setting up Auth0)

<iframe width="640" height="360" src="https://www.loom.com/embed/795544afd4fe478da0c0f52c6059682f"></iframe>

I did spend more time exploring other connection types and super excited to share them too.  
**Had alot of wow moments along the way.**

* Enterprise OIDC(extra setup was done on remote-identity-provider to allow calls from auth0 and a different user)
    

<iframe width="640" height="361" src="https://www.loom.com/embed/af2be6b41b9a4553b4a8c4e99d61b6f1"></iframe>

* Passwordless
    

<iframe width="640" height="360" src="https://www.loom.com/embed/bf2e317ff7a04751a5d901147db60d83"></iframe>

* Social
    

Placeholder for video.

I had a lot of fun exploring Auth0, hope you had some takeaways from it.  
In future I do plan to write about OIDC, OAuth and experiences in my blog. Thanks!

**Additional resources**

1. Github repo https://github.com/kndb-star/StonksApplication
    
2. Open issue in Blazor https://github.com/dotnet/aspnetcore/issues/20813
    

---

## 😡 Blazor issue

Calls to StonksApplication.Server kept on failing with a 401 httpstatus code.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628879831922/538lKSzvg.png align="left")

After successful login, as a result of our oidc setup in StonksApplication.Client, we get a id\_token and access\_token from Auth0. We can clearly see something is wrong with the access token (they are usually bigger in length)  

![0rwuVQ1Wl.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629563103225/T7UfG3mDs.png align="left")

As part of our login flow we couldn't pass the audience in the login request. And that was the root of all my hair pulling.  
Copy the access token, head to https://jwt.io, and decode the same

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628882651041/jDJw_mzS1z.png align="left")

We can confirm the token is invalid.  
From Auth0 docs, one way to solve this would be to set the audience value for all applications inside our Auth0 tenant. Basically, instead of the client requesting, we force set this.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1628882878130/q1mk8gQqO.png align="left")

We logout and login in our StonksApplication, and this time we see a different access token.

![aaaaa.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1629563348105/-1KMZfwUg.png align="left")

Copy the access token, head to https://jwt.io, and decode the same again

![audience.JPG](https://cdn.hashnode.com/res/hashnode/image/upload/v1628931120445/hwGQe0p2Z.jpeg align="left")

Our API calls are going through now.

![phew](https://media.giphy.com/media/gLFVVFawHtn9icDmZE/giphy.gif align="left")
