Replace ASP.NET Core Identity with Keycloak JWT ****** integration)#151
Draft
Replace ASP.NET Core Identity with Keycloak JWT ****** integration)#151
Conversation
… integration Co-authored-by: FlorianAlbert <61190722+FlorianAlbert@users.noreply.github.com>
…tity' into copilot/replace-aspnet-core-identity
Copilot
AI
changed the title
[WIP] Replace ASP.NET Core Identity with Keycloak integration
Replace ASP.NET Core Identity with Keycloak JWT ****** integration)
Mar 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The API previously owned both the identity store and auth endpoints via
IdentityDbContext+MapIdentityApi<User>(). This replaces that with Keycloak as the OIDC provider; the API becomes a stateless JWT ****** server.AppHost
Aspire.Hosting.Keycloakand registers Keycloak on stable port8080(prevents browser cookie/session issues on restart) with OTLP export and realm importKeycloak realm (
Realms/finance-observer-realm.json)finance-observerrealm: email verification, registration, password reset enabledfinance-observer-swaggerwith authorization code + PKCE for Scalar/OpenAPI UIfinance-observer-apias the resource server audiencemaildev) for local transactional emailAPI (
Startup/Program.cs)Removes
IdentityOptionsconfig,MapIdentityApi<User>(), andAddIdentityEmailSending(); adds:UseAuthentication()is inserted beforeUseAuthorization(). OpenAPI document now includes an OIDC security scheme pointing to Keycloak's discovery endpoint onlocalhost:8080(browser-accessible, not service-discovery).User model & EF Core
UserdropsIdentityUser<Guid>base class; gains explicitId,required string ExternalId(Keycloaksub), andstring? EmailFinanceObserverContextchanges base fromIdentityDbContext<…>toDbContextUserConfigurationaddsToTable("Users")and a unique index onExternalIdReplaceIdentityWithKeycloakdrops all sevenAspNet*Identity tables, creates the newUserstable, and re-targets foreign keys fromTransactionandEmailUserRemoved
Microsoft.AspNetCore.Identity.EntityFrameworkCoreandMicrosoft.Extensions.Identity.StorespackagesAddIdentityApiEndpoints<User>().AddEntityFrameworkStores<>()DI registrationIdentity.EmailSendingproject reference fromStartup.csproj(Keycloak handles transactional auth emails natively)Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
crl.comodoca.com/tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/9142823CD1647D8918F254C0BD1A1471/missingpackages_workingdir --packages /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/nugetconfig/nuget.config --force 2304�� DataAccess/DbAccess.EntityFrameworkCore/DbAccess.EntityFrameworkCore.csproj s2820864534 es /run/containerd/rm io.containerd.ru-f(dns block)ocsp.comodoca.com/tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/9142823CD1647D8918F254C0BD1A1471/missingpackages_workingdir --packages /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/missingpackages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal --configfile /tmp/codeql-scratch-3140803c200ce6d4/dbs/csharp/working/nugetconfig/nuget.config --force 2304�� DataAccess/DbAccess.EntityFrameworkCore/DbAccess.EntityFrameworkCore.csproj s2820864534 es /run/containerd/rm io.containerd.ru-f(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
This section details on the original issue you should resolve
<issue_title>Replace ASP.NET Core Identity with Keycloak (OpenID Connect) using Aspire best practices</issue_title>
<issue_description>## Summary
Replace the current ASP.NET Core Identity + EF Core authentication stack with Keycloak as the centralised Identity and Access Management provider. The API will act as a stateless JWT Bearer resource server, validating tokens issued by Keycloak via OpenID Connect (OIDC). Aspire's first-party Keycloak integration is available and must be used throughout.
Motivation
The current setup uses
MapIdentityApi<User>()andIdentityDbContext, which means the API owns both the identity store and the auth endpoints. This couples application concerns with security concerns and does not scale well. Keycloak provides a production-ready, standards-compliant OIDC provider that handles login, registration, email verification, password reset, MFA, and token issuance — leaving the API free to focus on business logic.Current State
User : IdentityUser<Guid>inServer/CrossCutting/Model/User.csFinanceObserverContext : IdentityDbContext<User, IdentityRole<Guid>, Guid>AddIdentityApiEndpoints<User>().AddEntityFrameworkStores<FinanceObserverContext>()inDbAccess.EntityFrameworkCore/Extensions/HostApplicationBuilderExtensions.csapp.MapIdentityApi<User>()inServer/Presentation/Startup/Program.csIdentityEmailSender : IEmailSenderinServer/Logic/Business/Identity.EmailSendingMicrosoft.AspNetCore.Identity.EntityFrameworkCore,Microsoft.Extensions.Identity.StoresTarget State
The API becomes a pure resource server. All authentication flows (register, login, token refresh, email verification, password reset) are delegated to Keycloak. The API only validates Bearer JWTs from Keycloak and applies authorization policies based on claims.
Tasks
1. AppHost – Add Keycloak resource (
AspireInfrastructure/AppHost/Program.cs)Aspire.Hosting.KeycloakNuGet package (current available version:13.1.2-preview.1.26125.13) toAspireInfrastructure/AppHost/AppHost.csprojandDirectory.Packages.props.8080) to avoid issues with browser cookies persisting OIDC sessions across AppHost restarts (Aspire Keycloak docs best practice):WithDataVolume()for the Keycloak resource during early development to avoid state management issues when restarting the app (Aspire best practice).Directory.Packages.propsto add the new package version entry.2. Keycloak realm configuration
Realms/directory in the AppHost project containing a realm import JSON file.finance-observer)finance-observer-swagger)IdentityEmailSender)3. API – Replace Identity auth with JWT Bearer (
Server/Presentation/Startup/Program.cs)Aspire.Keycloak.AuthenticationNuGet package toServer/Presentation/Startup/Startup.csprojandDirectory.Packages.props.builder.Services.Configure<IdentityOptions>(...)builder.Services.AddAuthorization()replacement is fine to keep but clean upapp.MapIdentityApi<User>()📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.