Using Keycloak in .NET Aspire projects

Oleksii Nikiforov - Jun 5 - - Dev Community

TL;DR

You can use Keycloak.AuthServices.Templates to add Keycloak support for .NET Aspire projects. See the docs for more details - Keycloak.AuthServices/Aspire Support.

Source code: https://github.com/NikiforovAll/keycloak-aspire-starter-template

Introduction

From the official docs:

.NET Aspire is designed to improve the experience of building .NET cloud-native apps. It provides a consistent, opinionated set of tools and patterns that help you build and run distributed apps.

Personally, I’m a big fan of Aspire because it enables great developer experience and productivity. I recommend trying it on your own πŸš€

This article will show you how to get started with Keycloak and Aspire. It is based on Keycloak.AuthServices.Templates template. Templates make it really easy to get started.

πŸ’‘Here is a basic example of how the integration looks like:

var builder = DistributedApplication.CreateBuilder(args);

var keycloak = builder
    .AddKeycloakContainer("keycloak")
    .WithDataVolume();

var realm = keycloak.AddRealm("Test");

builder.AddProject<Projects.Api>("api")
    .WithReference(realm);

builder.Build().Run();

Enter fullscreen mode Exit fullscreen mode

Scaffold a solution

Install a templates pack:

❯ dotnet new install Keycloak.AuthServices.Templates
# The following template packages will be installed:
# Keycloak.AuthServices.Templates::2.5.0
# Success: Keycloak.AuthServices.Templates::2.5.0 installed the following templates:
# Template Name Short Name Language Tags
# ----------------------- ----------------------- -------- -------------------------------------
# Keycloak Aspire Starter keycloak-aspire-starter [C#] Common/.NET Aspire/Cloud/API/Keycloak
# Keycloak WebApi keycloak-webapi [C#] Common/API/Keycloak


❯ dotnet new keycloak-aspire-starter -o $dev/keycloak-aspire-starter-template
# The template "Keycloak Aspire Starter" was created successfully.

Enter fullscreen mode Exit fullscreen mode

Here is what was generated:

❯ tre
.
β”œβ”€β”€ .gitignore
β”œβ”€β”€ Api
β”‚ β”œβ”€β”€ Api.csproj
β”‚ β”œβ”€β”€ Extensions.OpenApi.cs
β”‚ β”œβ”€β”€ Program.cs
β”‚ β”œβ”€β”€ Properties
β”‚ β”‚ └── launchSettings.json
β”‚ β”œβ”€β”€ appsettings.Development.json
β”‚ └── appsettings.json
β”œβ”€β”€ AppHost
β”‚ β”œβ”€β”€ AppHost.csproj
β”‚ β”œβ”€β”€ KeycloakConfiguration
β”‚ β”‚ β”œβ”€β”€ Test-realm.json
β”‚ β”‚ └── Test-users-0.json
β”‚ β”œβ”€β”€ Program.cs
β”‚ β”œβ”€β”€ Properties
β”‚ β”‚ └── launchSettings.json
β”‚ β”œβ”€β”€ appsettings.Development.json
β”‚ └── appsettings.json
β”œβ”€β”€ Directory.Build.props
β”œβ”€β”€ Directory.Packages.props
β”œβ”€β”€ README.md
β”œβ”€β”€ ServiceDefaults
β”‚ β”œβ”€β”€ Extensions.cs
β”‚ └── ServiceDefaults.csproj
β”œβ”€β”€ global.json
└── keycloak-aspire-starter-template.sln

Enter fullscreen mode Exit fullscreen mode

Run it

❯ dotnet run --project ./AppHost/
# Building...
# info: Aspire.Hosting.DistributedApplication[0]
# Aspire version: 8.0.1+a6e341ebbf956bbcec0dda304109815fcbae70c9
# info: Aspire.Hosting.DistributedApplication[0]
# Distributed application starting.
# info: Aspire.Hosting.DistributedApplication[0]
# Application host directory is: C:\Users\Oleksii_Nikiforov\dev\keycloak-aspire-starter-template\AppHost
# info: Aspire.Hosting.DistributedApplication[0]
# Now listening on: http://localhost:15056
# info: Aspire.Hosting.DistributedApplication[0]
# Distributed application started. Press Ctrl+C to shut down.

Enter fullscreen mode Exit fullscreen mode

Here are resources from Aspire Dashboard:

As you can see, there is a quay.io/keycloak/keycloak:24.0.3 container running. It is available on your local machine: http://localhost:8080/. Use admin:admin credentials.

The template project was generated with exemplary import files. It imports Test realm, adds workspaces-client, and seeds test users:

Now, we can open Swagger UI and retrieve an access token. Note, imported realm is configured to support Implicit Flow. We can use it during the development process as demonstrated below.

To invoke the API you can use Swagger UI or other HTTP tool of your choice. Here is an example of how to use cURL:

curl -X 'GET' \
  'https://localhost:51492/hello' \
  -H 'accept: text/plain' \
  -H 'Authorization: Bearer <AUTH_TOKEN>'

# Hello World!

Enter fullscreen mode Exit fullscreen mode

Code Explained

Basically, to setup Keycloak installation with Aspire we need to setup two things:

  1. Add Keycloak Resource to Aspire AppHost.
  2. Configure Web API to target Keycloak installation

Here is how to add Keycloak as resource to Aspire:

// AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);

var keycloak = builder
    .AddKeycloakContainer("keycloak")
    .WithDataVolume()
    .WithImport("./KeycloakConfiguration/Test-realm.json")
    .WithImport("./KeycloakConfiguration/Test-users-0.json");

var realm = keycloak.AddRealm("Test");

builder.AddProject<Projects.Api>("api").WithReference(keycloak).WithReference(realm);

builder.Build().Run();

Enter fullscreen mode Exit fullscreen mode

The code above does the following:

  1. Starts a Keycloak Instance
  2. Imports realm and test users
  3. Reference to Keycloak adds Keycloak to service discovery
  4. Reference to Realm adds Keycloak__Realm and Keycloak__AuthServerUrl environment variables.

And here is how to configure Api to integrated with Keycloak and use workspaces-client:

// Api/Program.cs
using Api;
using Keycloak.AuthServices.Authentication;

var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;

builder.AddServiceDefaults();
services.AddApplicationOpenApi(configuration);

services.AddKeycloakWebApiAuthentication(
    configuration,
    options =>
    {
        options.Audience = "workspaces-client";
        options.RequireHttpsMetadata = false;
    }
);
services.AddAuthorization();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseApplicationOpenApi();

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

app.MapGet("/hello", () => "Hello World!").RequireAuthorization();

app.Run();

Enter fullscreen mode Exit fullscreen mode

Conclusion

The integration of Keycloak with .NET Aspire projects provides a first class support for building distributed, cloud native systems. By leveraging the Keycloak.AuthServices.Templates template, developers can easily scaffold a solution and configure their APIs to work with Keycloak.


πŸ™Œ Keycloak.AuthServices.Templates is under development. Please, feel free to submit PRs. contributionswelcome πŸ™Œ

References

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .