In this article, we are going to learn about integrating Keycloak authentication in a Blazor WebAssembly (WASM) frontend and a .NET Web API backend. With this setup, we will enable secure user authentication across both applications.

Keycloak is an open-source identity and access management solution that provides authentication, authorization, and user management out of the box. It supports industry-standard protocols like OpenID Connect and OAuth2, making it a great choice for securing applications.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

Initial projects where the Blazor WebAssembly (with individual accounts authentication type selected) client app consumes Web API are already prepared. We will use those throughout this article.

So, let’s start.

Installing Keycloack Using Docker

We assume you already have a Docker Desktop installed since it is the easiest way to work with Docker. If you don’t have it installed, just use the provided link and install it, it is simply as that.

We can open the docker desktop app and then run this command in the CMD or PowerShell window:

docker run -p 8080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.1.1 start-dev

This will download the image and install the required container mapping the port 8080, and providing the username and admin parameters.

With the image downloaded, we can see that the container is already running, and let’s navigate to  localhost:8080/admin to be redirected to the login popup.

Let’s use credentials: admin, admin.

Preparing Keycloak Authentication With a Realm, Clients, and Users

So, the first thing we are going to do is to create a new realm. A realm in Keycloak is an isolated authentication and authorization space where users, roles, clients, and identity providers are managed. It acts as a container for everything related to identity and access management.

By default, a master realm is created, but we need a new one:

Creating New Realm for Keycloak Authentication

So, we need to:

  • Click on the master realm and once the menu appears click on the Create realm button
  • Add a name for our realm – BlazorWebApiRealm
  • Click the Create button

With this, we create a new realm and navigate directly there.

Create Web API Client For Keycloak Authentication

So, we need to register both clients (Web API and Blazor WASM), and let’s start with the Web API client.

To do that, let’s open the Clients menu and click the Create client button:

Create client for Keycloack Authentication

Once the “Create client” page opens, we can populate the required fields:

  • The Client type is OpenID Connect which is set by default
  • Client ID: web-api (you can add the Name and Description if you want)
  • Client Authentication: Off
  • Authorization: Off
  • Standard Flow Enabled:  Off
  • Direct Access Grants Enabled:  Off
  • Both Root and Home URLs are blank
  • Click Save.

Since the Web API client is our server app, we don’t need to populate anything except the Client ID field.

Mapping to Correct Audience

We need to map a correct Audience for the Web API client because without this step the aud claim will be just an “account”, which we don’t want.

To do that, let’s open the Client scopes menu and hit the Create client scope button:

Create client scope for Keycloack authentication

Once the page opens

  • Then, we need to populate the Name: blazor_api_scope, and add some description
  • Also, let’s turn on Include in token scope so that the scope is included in the generated access token (if you need it)
  • Finally, let’s click the Save button

After we are done with the scope creation, we will see a new page with the Mappers tab. We need to open that tab and:

  • Click the Configure new mapper button
  • Chose Audience from the table – this will be a Mapper type
  • Add any meaningful name like blazor_api audience
  • Select the web-api client in the Included Client Audience DDL
  • Click the Save button 

This ensures any time the blazor_api_scope is requested and granted, the blazor_api_audience will be added to the access token.

Create Blazor Client For Keycloak Authentication

So, as we did with the previous client, we have to navigate to the Clients menu and hit the Create client button.

Now, we can populate the required fields

  • Client type is by default OpenID Connect
  • Client ID: blazor-client (you can provide a name and a description if you want)
  • Client Type: Public – client authentication is set to off because Blazor WASM apps are considered public clients
  • We should select the Standard flow only
  • Valid Redirect URIs: https://localhost:5000/authentication/login-callback
  • Logout Redirect: https://localhost:5000/authentication/logout-callback
  • Click the Save button to save changes

Once we save changes, we can see the Web origins populated automatically for CORS. Also, pay attention that our app is running on localhost:5000 – if yours is running on a different port, you should provide that one.

Additionally, we need to allow our front-end app to request the client scope we created earlier. That’s how it can get access tokens with the correct audience.

So, from the current screen:

  • Open the Client scopes tab and click the Add client scope button
  • Select the previously created scope blazor_api_scope
  • Add-Optional as we want the client to request it and not add it by default

Great.

We should be able to locate blazor_api_scope in the scope list right after the address and basic scopes.

Create a User

To create a new user in Keycloak, let’s navigate to the Users menu and hit a Create new user button:

Create a new User in Keycloak

Once on the form, let’s populate the necessary fields:

  • Username: codemaze
  • Email: [email protected]
  • First name: Code
  • Last name: Maze
  • Click the Create button to create a new user

This user needs a password to log in. So, to set the initial password:

  • Click Credentials at the top of the page
  • Click the Set password button and populate the form with a password
  • Toggle Temporary to Off so the user does not need to update this password at the first login
  • Hit the Save button

Excellent.

With all the previous steps, we have prepared a Keycloak authentication with the Keycloak’s dashboard, and now we can do some coding.

Configure Web API For the Keycloak Authentication

Inside the Web API project, we first need to install the package: Microsoft.AspNetCore.Authentication.JwtBearer

It will help us with the authentication process.

Then, in the Program.cs class, let’s add the required code for the authentication:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(policy =>
{
    policy.AddPolicy("CorsPolicy", opt => opt
        .AllowAnyOrigin()
        .AllowAnyHeader()
        .AllowAnyMethod());
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.Authority = "http://localhost:8080/realms/BlazorWebApiRealm";
        options.Audience = "web-api";
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true
        };
    });
builder.Services.AddAuthorization();

builder.Services.AddControllers();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseCors("CorsPolicy");

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

app.MapControllers();

app.Run();

So, with the AddAuthentication method, we register JWT Bearer Authentication as the authentication scheme. It ensures that incoming requests must include a valid JWT token.

Then, with options.Authority we specify the Keycloak realm endpoint (/realms/BlazorWebApiRealm). It can be found on the Realm Settings menu -> OpenID Endpoint Configuration link. It will open a new page with the authority (issuer) as the first element.

We also provide the correct audience, which is the client ID of the Web API client.

Additionally, we disable the requirement for HTTPS in local development. In production, this should be true to enforce secure communication.

Then, we provide validation parameters to ensure the valid issuer, audience, token expiration, and token signature.

Finally, we call the AddAuthorization() method to add the authorization policy services and also call the UseAuthentication() method to enable authentication middleware.

Blazor WASM Configuration.

Ok, after we are done with the server app, we can continue with the Blazor WebAssembly app and configure the Keycloak authentication there.

We must have this package: Microsoft.AspNetCore.Components.WebAssembly.Authentication installed. Since we use the Blazor WASM app with Individual Users for Authentication, it should already be installed.

Now, let’s modify the Program.cs class:

builder.Services.AddOidcAuthentication(options =>
{
    options.ProviderOptions.Authority = "http://localhost:8080/realms/BlazorWebApiRealm";
    options.ProviderOptions.ClientId = "blazor-client";
    options.ProviderOptions.ResponseType = "code";
    options.ProviderOptions.DefaultScopes.Add("blazor_api_scope");
});

Here, we modify the existing AddOidcAuthentication() method, and provide information about the authority (realm), client ID, the response type, and we explicitly ask for the mapped scope.

Then, let’s modify the HttpClient configuration to include the access token:

builder.Services.AddHttpClient("WeatherAPI", client => client.BaseAddress = new Uri("https://localhost:5001/"))
    .AddHttpMessageHandler(sp =>
    {
        var handler = sp.GetRequiredService<AuthorizationMessageHandler>()
            .ConfigureHandler(authorizedUrls: ["https://localhost:5001"]);

        return handler;
    });

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("WeatherAPI"));

For this to work, we need to install the Micrososft.Extensions.Http package.

Here, we configure an HTTP client to securely communicate with a protected Web API. With the AddHttpClient() method, we register an HTTP client named “WeatherAPI” with a base address. We also attach an AuthorizationMessageHandler, which ensures that authentication tokens are included when making requests to the specified authorized URLs.

Then, we use the AddScoped() method to register a scoped service that retrieves the named HTTP client (WeatherAPI) from the IHttpClientFactory, allowing it to be injected into Blazor components or services. With this, the client app automatically handles authentication and authorization when making API requests.

If you want to learn more about HttpClientFactory, and how to use it with typed and named clients, you can read our HttpClientFactory article

Ok, let’s protect the Blazor’s Weather page:

@page "/weather"
@inject HttpClient Http
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

This will require an authorized user to access this page.

Finally, in the @code section of the same page, we need to modify the Http call:

forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("weatherforecast");

Test Keycloak Authentication With the Blazor Client App

Let’s run both API and Blazor applications. Once that is done, we will see the Login link in the upper-right corner, so let’s click on it:

Login button for the authentication in Blazor WASM

Once we do that, the Keycloak Authentication popup will appear where we need to use the credentials of our created user. You can also see the “Hello” message and the Log out button.

Now, we can navigate to the Weather page, and we should get the data:

Data retreived from authenticated API server app

 However, the API endpoint is not authorized.

We can click the Log out button, and we will be logged out.

Authorizing Web API and Testing Again

So, first, we need to add the Authorize attribute to our controller:

[HttpGet]
[Authorize]
public IEnumerable<WeatherForecast> Get()

Again, we can run both apps, authenticate, and fetch the data. Everything should work.

Inspecting the Token

To inspect the scope and the token, we can open the dev tools -> applications tab.

There, under the Session storage menu, we can find the third “oidc” key:

Inspect access token in browser

We can copy the access token (bottom-right of the screen), which we can inspect on the jwt.io site. There, we will see what are the values for the issuer and audience properties, and those should match our configuration:

{
  "exp": 1739446851,
  "iat": 1739446551,
  "auth_time": 1739446549,
  "jti": "c1e7e9a7-8bf0-4766-b694-7105c6894a02",
  "iss": "http://localhost:8080/realms/BlazorWebApiRealm",
  "aud": [
    "web-api",
    "account"
  ],
  ...
}

Excellent.

Conclusion

By integrating Keycloak authentication with Blazor WebAssembly and a .NET Web API, we provide a secure and scalable identity management solution. With the OpenID Connect and OAuth2 support, we ensure that only authenticated users can access protected resources. The Web API validates JWT tokens issued by Keycloak, while the Blazor WASM app handles authentication and API requests using an AuthorizationMessageHandler.

In the next article, we will learn about Role-Based Authorization between Blazor WASM and Web API apps, using Keycloak.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!