Blazor Authentication with Auth0

Benjamin Vertonghen
9 min readDec 4, 2021

In this small series we’ll setup a Blazor Web Assemly Application which communicates with a C# REST API. We’ll protect the endpoints with Auth0 as Identity Provider based on Roles (RBAC).

Blazor + Auth0 = ❤️

Articles in this series:

  1. Blazor Authentication with Auth0 (this one)
  2. Blazor Authorization with Auth0
  3. Blazor With Auth0, using the Management API

In this article you’ll learn:

  • How to authenticate your users with Auth0
  • Login with a social provider (Google in this case)
  • Protect your Blazor Client
  • Protect your REST API
  • Connect the authentication flow between the Client and the Server.

Technology Used

  • .NET 6
  • Blazor Web Assembly (WASM)
  • Auth0

The application we’ll be creating is a simple yet fully secured application based on two roles Customer and Administrator. We’ll call the App Weather Station which returns data only to those who are logged-in and Administrators are the only ones who can add new forecasts to the app.

Final Result (from this post)

The use cases

  • As a customer I want to see weatherforecasts.
  • As an administrator I want to add new forecasts.

What is Role Based Access Control (RBAC)?

Within an organization, roles are created for various job functions. The permissions to perform certain operations are assigned to specific roles. Members or staff (or other system users) are assigned particular roles, and through those role assignments acquire the permissions needed to perform particular system functions. Since users are not assigned permissions directly, but only acquire them through their role (or roles), management of individual user rights becomes a matter of simply assigning appropriate roles to the user’s account; this simplifies common operations, such as adding a user, or changing a user’s department.

How can Auth0 help us?

Auth0 provides authentication and authorization as a service. We are here to give developers and companies the building blocks they need to secure their applications without having to become security experts. You can connect any application (written in any language or on any stack) to Auth0 and define the identity providers you want to use (how you want your users to log in). Based on your app’s technology, choose one of our SDKs (or call our API), and hook it up to your app. Now each time a user tries to authenticate, Auth0 will verify their identity and send the required information back to your app.

Start by creating a simple Blazor Web Assembly Hosted application

dotnet new blazorwasm -o WeatherStation --hosted -f net6.0

Make sure you’re running on port 5001(HTTPS). Adjust the launchsettings of the Server project.

WeatherStation.Server/Properties/launchSettings.json:

{
"profiles": {
"WeatherStation.Server": {
"commandName": "Project",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

Your file may look a bit different but make sure the applicationUrl is set to port 5001 for HTTPS.

Let’s first create a revamped version of the WeatherForecastController so that we can Add Forecasts to it later on. The forecasts should be a static list so we can mutate them as an Administrator later in the article.

Replace the contents of WeatherForecastController.cs with the following:

Registering the Blazor WASM App with Auth0

If you don’t have an Auth0 account yet, you can sign up for a free one right now.

After accessing the Auth0 Dashboard, move to the Applications section, and follow these steps:

  1. Click the Create Application button.
  2. Provide a friendly name for your application (Weather Station Client) and select Single Page Web Applications as the application type.
  3. Finally, click the Create button.
  4. Move to the Settings Tab
  5. In the Allowed Callback URLs paste in the following link: https://localhost:5001/authentication/login-callback
  6. In the Allowed Logout URLs paste in the following link: https://localhost:5001

Finally, click the Save Changes button to apply the changes.

Configure your Blazor app for Authentication

Now, you need to configure your Blazor project by applying some changes to make it aware of Auth0. So, move to the Client/wwwroot folder and create an appsettings.json file with the following content:

Replace the placeholders <YOUR_AUTH0_DOMAIN> and <YOUR_CLIENT_ID> with the respective values taken from the Auth0 dashboard.

Now, add the authentication package to the Blazor client project by running the following command in the Client folder:

dotnet add package Microsoft.AspNetCore.Components.WebAssembly.Authentication -v 6.0.0

After adding the package, still in the Client folder, edit the Program.cs file by replacing its content with the following C# code:

You added the call to AddOidcAuthentication() with specific options. In particular, you specified to use the parameters from the Auth0 section of the appsettings.json configuration file. Also, you specified the type of authentication and authorization flow you want to use; in this specific case, the Authorization Code flow is recommended.

To complete the implementation of authentication support in your application, open the index.html file under the Client/wwwroot folder and add the reference to the AuthenticationService.js script as shown below:

Adjust the UI of your Blazor app

At this point, you prepared the infrastructure for your Blazor app to support authentication. Now you need to make some changes to the User Interface so Authorization can be used.

Then, open the App.razor file in the same folder and replace its content with the following:

You used the AuthorizeRouteView Blazor component to customize the content according to the user's authentication status. The CascadingAuthenticationState component will propagate the current authentication state to the inner components so that they can work on it consistently.

The next step is to create a new Razor component that allows the user to log in and to see their name when authenticated. So, create a new file named AccessControl.razor in the Client/Shared folder with the following content:

The component uses the AuthorizeView component to show different content according to the user's authentication status. Basically, it shows the Log in link when the user is not authenticated. It shows the name of the user and the Log out link when the user is authenticated.

Note the URL the user is redirected to when they click the Log out link (authentication/logout). You will learn about that URL in a moment.

Now, open the MainLayout.razor file in the Shared folder and add the AccessControl component just before the About link. The final code should look like the following:

When you registered your Blazor app with Auth0, you specified a few URLs in the form https://localhost:5001/authentication/* as allowed URLs for login callback and logout. You also used the logout URL in the AccessControl component.

To manage these URLs, you need to implement a page responsible for handling different authentication stages. For this purpose, create a new Authentication.razor file in the Pages folder with the following code:

As you can see, this component implements a page containing the RemoteAuthenticatorView component. This component manages the users' authentication status and interacts with the authorization server on the Auth0 side. While the login interaction doesn't require any specific code, you need to manage the logout transaction. In fact, by design Blazor clears your authentication state on the client side but doesn't disconnect you from Auth0. To close your session on the Auth0 side, you need to explicitly call the logout endpoint, as shown in the code above.

Finally, you need to add the Authorize attribute to the FetchData.razor page to protect it from unauthorized accesses. Open the FetchData.razor file in the Pages folder and add the attribute as shown below:

At this point, you can test the authentication integration. Start the server (make sure it’s running on port 5001 (HTTPS) and once the app is running, click the FetchData menu item, you should see the following screen:

Not authorized Page

Note the Log In in the upper right corner. By clicking on it, the Auth0 Universal Login page is shown, and the authentication process takes place. Notice that you can also sign-in with Google by default which is nice. Other providers (Facebook, LinkedIn, …) already exist and can be added if you want to. If you don’t have a Google account you can use the Sign-up tab to create a new account.

After authentication, you will be able to access the FetchData page and see the name or e-mail address.

Registering the API with Auth0

The data shown in the FetchData page is loaded from the /Weather API implemented in the server project. This API is not protected, so any client could access it. In fact, the Blazor WASM client is able to access it without any problem. However, in a production-ready scenario, you need to protect the API to prevent unauthorized access.

Similarly to what you did with the Blazor WASM application, you need to register the API with Auth0. So, head your browser to the Auth0 Dashboard, move to the API section, and follow these steps:

  1. Click the Create API button.
  2. Provide a friendly name for your API (for example, Weather Station API) and a unique identifier (also known as audience) in the URL format (for example, https://api.weather.com).
  3. Leave the signing algorithm to RS256 and click the Create button.

In the server project under the Server folder, open the appsettings.json. Its content look like the following:

Replace the <YOUR_AUTH0_DOMAIN> placeholder with the Auth0 domain value you used for the Blazor WASM client. Also, replace the <YOUR_API_IDENTIFIER> placeholder with the unique identifier you defined for your API in the Auth0 Dashboard: it should be https://api.weather.com, if you kept the suggested value. This value will be used as the Audience in the access token.

In the Client’s appsettings.json it’s now time to also set the Audience property to the same as the one from your API https://api.weather.com in our case.

Still in the client, adjust Program.cs to also supply the Audience property.

In the Server folder, run the following command to install the library that will handle the authorization process:

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer -v 6.0.0

Then, open the Program.cs file from the server project and apply the changes shown below:

You added the reference to the Microsoft.AspNetCore.Authentication.JwtBearer namespace and added the statements that configure the server to handle the authorization process through Auth0.

Finally, open the WeatherController.cs file in the Controllers folder add a Authorize attribute, so that users need to be authentication before making the call.

Currently you won’t be able to make a call to the server, since we did not provide an access token yet. Let’s fix that next.

Calling the Protected API

To enable your Blazor WASM application to access the protected API, you need to get an access token from Auth0 and provide it along with your API call. You might think to write some code that attaches this token when you make an HTTP request to the server. However, you can centralize the access token attachment to your API calls in a straightforward way.

Start by moving to the Client folder and installing the Microsoft.Extensions.Http package with the following command:

dotnet add package Microsoft.Extensions.Http -v 6.0.0

This package allows you to create named HTTP clients and customize their behavior. In your case, you will create an HTTP client that automatically attaches an access token to each HTTP request and throws if there isn’t one.

Next, move to the program.cs file in the client and replace it’s contents with the following:

The AddHttpClient() method defines a named HttpClient instance (WeatherAPI) with the current server's address as the base address to use when requesting a resource. Also, the BaseAddressAuthorizationMessageHandler class is added to the HttpClient instance as the HTTP message handler. This class is provided by the Microsoft.AspNetCore.Components.WebAssembly.Authentication namespace and is responsible for attaching the access token to any HTTP request to the application's base URI.

The actual HttpClient instance is created by the CreateClient() method of the IHttpClientFactory service implementation, which solves socket exhaustion. More about socket exhaustion and why we’re using HttpClientFactory instead of a plain’ol HttpClient, can be read in the Microsoft Documentation here.

We ❤ open source so the source code can be found on Github

HOGENT-Web/csharp-ch-10-example-1 (github.com)

Kudo’s to Andrea Chiarelli, which set the baseline for this series.

In the next article we cover how to add roles and protect certain endpoints with Role Based Access Control since article is becoming pretty long already…

Go to the next article, Blazor Authorization with Auth0

Update 7/12/2022

There seems to be an issue with inconsistent logouts ( you might need to logout twice instead of once). There is an open issue on GitHub with a work-around for this.

--

--