keycloak-patterns
Lukk17/agent-standards/.agents/skills/keycloak-patterns/SKILL.md
Keycloak server administration and the Keycloak.AuthServices .NET client, covering realms and clients, authentication flows and MFA, RBAC and UMA authorization, LDAP federation, hardening and clustering, plus JWT Bearer and OIDC wiring, role policies, resource protection, and the Admin and Protection API SDKs. Use when you say \"set up SSO with Keycloak\", \"create a realm and a confidential client\", \"enable MFA for admins\", \"connect Keycloak to Active Directory\", \"why does my token fail audience validation\", \"add Keycloak auth to my .NET API\", \"require a realm role on this endpoint\", \"call the Keycloak Admin API from C#\", or \"protect this resource with UMA\". Not for Spring Security resource-server configuration, use `springboot-patterns`.
What's in it
- Keycloak Patterns
- Baseline
- When to activate
- When not to activate
- Decide which side of the boundary the task is on
- One realm per application and environment
- Assign roles to groups, never directly to users
- Never edit a built-in authentication flow in place
- Verify the audience, and keep the issuer public
- Keep every secret out of the repository and out of the process list
- Pin the version on both sides
- Which reference to open for which task
- Related skills
- Checklist
---
name: keycloak-patterns
description: "Keycloak server administration and the Keycloak.AuthServices .NET client, covering realms and clients, authentication flows and MFA, RBAC and UMA authorization, LDAP federation, hardening and clustering, plus JWT Bearer and OIDC wiring, role policies, resource protection, and the Admin and Protection API SDKs. Use when you say \"set up SSO with Keycloak\", \"create a realm and a confidential client\", \"enable MFA for admins\", \"connect Keycloak to Active Directory\", \"why does my token fail audience validation\", \"add Keycloak auth to my .NET API\", \"require a realm role on this endpoint\", \"call the Keycloak Admin API from C#\", or \"protect this resource with UMA\". Not for Spring Security resource-server configuration, use `springboot-patterns`."
---
# Keycloak Patterns
The identity boundary from both sides: the Keycloak server that issues tokens, and the .NET application that consumes
them. The hub carries the rules that hold on both sides, and each reference carries the depth for one of them.
---
### Baseline
Current as of September 2026: Keycloak 26, and Keycloak.AuthServices 2.x on .NET 8 or newer. Two things follow from
that pairing and are easy to get wrong:
- Keycloak 26 renamed the bootstrap admin variables to `KC_BOOTSTRAP_ADMIN_USERNAME` and
`KC_BOOTSTRAP_ADMIN_PASSWORD`. The older `KEYCLOAK_ADMIN` pair no longer works.
- A .NET application binds the `Keycloak` configuration section in the kebab-case adapter format, so `auth-server-url`
and `verify-token-audience` are keys, not properties invented locally.
---
### When to activate
- Standing up a Keycloak instance, or moving one from development mode to production.
- Creating a realm, a client, a role model, or an authentication flow, including MFA and identity brokering.
- Federating users from LDAP or Active Directory.
- Adding JWT Bearer or OIDC authentication to an ASP.NET Core API or web application.
- Enforcing realm or client roles through an authorization policy, or protecting a resource with UMA.
- Calling the Keycloak Admin REST API or Protection API from C#.
- Diagnosing a login failure, a rejected token, an audience mismatch, or a session that ends too soon.
---
### When not to activate
- Spring Security resource-server configuration. Use `springboot-patterns`.
- Verifying a JWT inside a Node service. Use `node-backend-patterns`.
- The HTTP contract and error bodies the protected endpoints expose. Use `api-design`.
- Threat modelling the wider application. Use the `security-auditor` agent.
- Running the Keycloak container inside a local stack. Use `docker-patterns`.
- Pinning the package versions across a multi-project solution. Use `build-dependency-management`.
---
### Decide which side of the boundary the task is on
Most confusion here comes from fixing the wrong side. A token that is rejected is either minted wrong or validated
wrong, and the two have different owners. Establish which before touching anything.
```text
Server side: the realm, the client registration, the flow, the mappers, the roles, the issuer URL.
Client side: the audience check, the policy, the claims transformation, the token cache, the SDK call.
```
The reference map below splits along exactly that line.
---
### One realm per application and environment
The master realm exists to administer Keycloak and nothing else. Running an application against it means an
application compromise is an administrative compromise. Each application and each environment gets its own realm, and
the client ID the application sends has to match the registration exactly.
---
### Assign roles to groups, never directly to users
Direct role assignment produces a permission model nobody can audit a year later. Put users in groups, attach roles to
groups, and use composite roles when a role genuinely implies others. On the .NET side, name the realm or client role
in an authorization policy rather than reading a raw claim, so the check survives a claims-mapping change.
---
### Never edit a built-in authentication flow in place
Duplicate the Browser flow, add the OTP or WebAuthn authenticator to the copy, set it Required or Conditional on a
group, and bind the copy to the realm. Editing the built-in flow leaves no clean way back when the change locks
everyone out, including you.
---
### Verify the audience, and keep the issuer public
`verify-token-audience` on means a token minted for another client is rejected rather than accepted by coincidence.
It only works when the server issues the audience it claims to, which is what `KC_HOSTNAME` and TLS termination are
for: an issuer pointing at an internal address produces tokens that fail validation everywhere the public URL is
expected.
---
### Keep every secret out of the repository and out of the process list
A client secret belongs in configuration or a secret store, never in a committed `appsettings.json`. Supply server
runtime configuration through the environment rather than the command line, so nothing lands in a process listing. A
realm export contains client secrets, so treat the export directory as a secret rather than as a configuration
artifact to commit.
---
### Pin the version on both sides
A Keycloak image tagged `latest` silently upgrades across a major version and can change flow defaults, admin console
behaviour, and the database schema in one `docker pull`. Pin a major tag such as `26.0`, build once with
`bin/kc.sh build`, and start with `start --optimized` against PostgreSQL. Pin the NuGet package versions the same way.
---
### Which reference to open for which task
Each entry below carries its own reference map, so open the entry for your side of the boundary and let it route you.
| Task | Reference |
| --- | --- |
| Server administration: realms, clients, flows and MFA, RBAC, LDAP, hardening, clustering, server-side failures | [references/administration.md](references/administration.md) |
| The .NET client library: JWT Bearer and OIDC setup, role policies, resource protection, Admin and Protection SDKs | [references/dotnet-auth-services.md](references/dotnet-auth-services.md) |
---
### Related skills
- `springboot-patterns` and `node-backend-patterns` for validating Keycloak tokens outside .NET.
- `api-design` for the status codes and problem bodies an authorization failure should return.
- The `security-auditor` agent for threat modelling around the identity boundary.
- `docker-patterns` for running the Keycloak container safely in a local stack.
- `build-dependency-management` for pinning the image tag and the package versions.
- `observability-and-logging` for what the OpenTelemetry instrumentation should feed into.
---
### Checklist
- [ ] The container image is pinned to a major version, and the server runs `start --optimized` against PostgreSQL.
- [ ] Bootstrap admin credentials are replaced by a real admin account and removed.
- [ ] Applications run against their own realm, never master, and every client has exact redirect URIs.
- [ ] Every client, confidential or public, requires PKCE, and MFA is enforced for administrative accounts through a
copied flow.
- [ ] Roles reach users through groups, and policies name realm or client roles rather than raw claims.
- [ ] `KC_HOSTNAME` and TLS are configured so the issuer matches the public URL.
- [ ] `verify-token-audience` is on and `ssl-required` is `external` or `all` outside local development.
- [ ] Client secrets and realm exports are handled as secrets, never committed.
- [ ] Brute-force protection and event logging are enabled, exported, and visible in traces.
More agent context in Lukk17/agent-standards
60 other files this repository gives its agents.
AGENTS.md
CLAUDE.md
Skill
- agentic-engineering.agents/skills/agentic-engineering/SKILL.md
- ai-regression-testing.agents/skills/ai-regression-testing/SKILL.md
- angular.agents/skills/angular/SKILL.md
- ansible.agents/skills/ansible/SKILL.md
- api-design.agents/skills/api-design/SKILL.md
- architecture-decision-records.agents/skills/architecture-decision-records/SKILL.md
- ascend-memory.agents/skills/ascend-memory/SKILL.md
- ascend-web-hunter.agents/skills/ascend-web-hunter/SKILL.md
- audio-scribe.agents/skills/audio-scribe/SKILL.md
- automation-inventory.agents/skills/automation-inventory/SKILL.md
- backend-patterns.agents/skills/backend-patterns/SKILL.md
- bash.agents/skills/bash/SKILL.md
- build-dependency-management.agents/skills/build-dependency-management/SKILL.md
- code-formatter.agents/skills/code-formatter/SKILL.md
- code-reviewer.agents/skills/code-reviewer/SKILL.md
- coding-standards.agents/skills/coding-standards/SKILL.md
- dart-flutter-patterns.agents/skills/dart-flutter-patterns/SKILL.md
- database-migrations.agents/skills/database-migrations/SKILL.md
- deployment-patterns.agents/skills/deployment-patterns/SKILL.md
- design-system.agents/skills/design-system/SKILL.md
- docker-patterns.agents/skills/docker-patterns/SKILL.md
- e2e-runbooks.agents/skills/e2e-runbooks/SKILL.md
- e2e-testing.agents/skills/e2e-testing/SKILL.md
- embedded-c-arduino.agents/skills/embedded-c-arduino/SKILL.md
- frontend-design.agents/skills/frontend-design/SKILL.md
- g-code-3d-printing.agents/skills/g-code-3d-printing/SKILL.md
- github-ops.agents/skills/github-ops/SKILL.md
- git-workflow.agents/skills/git-workflow/SKILL.md
- golang-patterns.agents/skills/golang-patterns/SKILL.md
- hexagonal-architecture.agents/skills/hexagonal-architecture/SKILL.md
- home-assistant.agents/skills/home-assistant/SKILL.md
- java-coding-standards.agents/skills/java-coding-standards/SKILL.md
- jetbrains-ide-ops.agents/skills/jetbrains-ide-ops/SKILL.md
- jira-integration.agents/skills/jira-integration/SKILL.md
- kicad.agents/skills/kicad/SKILL.md
- markdown-writer.agents/skills/markdown-writer/SKILL.md
- mongodb-patterns.agents/skills/mongodb-patterns/SKILL.md
- nextjs-app-router-patterns.agents/skills/nextjs-app-router-patterns/SKILL.md
- node-backend-patterns.agents/skills/node-backend-patterns/SKILL.md
- observability-and-logging.agents/skills/observability-and-logging/SKILL.md
- obsidian.agents/skills/obsidian/SKILL.md
- performance-optimization.agents/skills/performance-optimization/SKILL.md
- postgres-patterns.agents/skills/postgres-patterns/SKILL.md
- powershell.agents/skills/powershell/SKILL.md
- project-tracking.agents/skills/project-tracking/SKILL.md
- python-patterns.agents/skills/python-patterns/SKILL.md
- pytorch-patterns.agents/skills/pytorch-patterns/SKILL.md
- react-patterns.agents/skills/react-patterns/SKILL.md
- research.agents/skills/research/SKILL.md
- review-duplication.agents/skills/review-duplication/SKILL.md
- security-review.agents/skills/security-review/SKILL.md
- seo.agents/skills/seo/SKILL.md
- soap-webservices.agents/skills/soap-webservices/SKILL.md
- springboot-patterns.agents/skills/springboot-patterns/SKILL.md
- tdd-workflow.agents/skills/tdd-workflow/SKILL.md
- unity.agents/skills/unity/SKILL.md
- user-communication.agents/skills/user-communication/SKILL.md
- web-accessibility.agents/skills/web-accessibility/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

