Not every organization wants to move from ADFS to Microsoft Entra ID. Some want to stay vendor-neutral, keep identity infrastructure on-premises, or simply avoid per-user licensing costs. Keycloak fills that gap — it handles SAML 2.0, OIDC, and integrates directly with Active Directory via LDAP federation.
The migration isn’t trivial, though. ADFS and Keycloak have different architectural models, and some ADFS features don’t have direct Keycloak equivalents. This guide covers the practical steps, common blockers, and configuration patterns you’ll need.
Architecture Differences
Before diving into migration steps, understand what changes:
| Aspect | ADFS | Keycloak |
|---|---|---|
| Identity Source | Built into AD trust | LDAP Federation (connects to AD) |
| SAML Support | Native | Native |
| WS-Federation | Native | Community extension only |
| OIDC/OAuth | Added in ADFS 2016+ | Native, first-class |
| MFA | External adapter or Azure MFA | Built-in OTP, WebAuthn, conditional |
| Session Management | Per-application tokens | Centralized SSO sessions |
| Deployment | Windows Server role | Docker/Kubernetes/bare metal (Java) |
The fundamental shift: ADFS relies on the Windows domain trust model and is tightly coupled to Active Directory. Keycloak is a standalone identity broker that connects to AD as an external user store.
Step 1: Set Up Keycloak with AD Integration
Deploy Keycloak
For production, run Keycloak 26.x on a supported database (PostgreSQL recommended):
# Docker Compose for initial setup
docker run -d --name keycloak \
-p 8443:8443 \
-e KC_DB=postgres \
-e KC_DB_URL=jdbc:postgresql://db:5432/keycloak \
-e KC_DB_USERNAME=keycloak \
-e KC_DB_PASSWORD=changeme \
-e KC_HOSTNAME=idp.yourdomain.com \
-e KC_HTTPS_CERTIFICATE_FILE=/opt/keycloak/conf/server.crt \
-e KC_HTTPS_CERTIFICATE_KEY_FILE=/opt/keycloak/conf/server.key \
quay.io/keycloak/keycloak:26.5.2 start
Configure LDAP User Federation
In the Keycloak admin console, navigate to your realm → User Federation → Add LDAP provider:
| Setting | Value |
|---|---|
| Vendor | Active Directory |
| Connection URL | ldaps://dc01.corp.local:636 |
| Bind DN | CN=svc-keycloak,OU=Service Accounts,DC=corp,DC=local |
| Bind Credential | (service account password) |
| Users DN | OU=Users,DC=corp,DC=local |
| Username LDAP attribute | sAMAccountName |
| UUID LDAP attribute | objectGUID |
| User Object Classes | person, organizationalPerson, user |
| Search Scope | Subtree |
Key settings that catch people off guard:
- Import Users: Set to ON for the migration period so Keycloak caches user data. You can switch to NO_IMPORT later if you want pure pass-through.
- Sync Registrations: OFF unless you want Keycloak to write back to AD.
- Periodic Full Sync: Enable with a 1-hour period during migration to keep users current.
Map AD Groups
Add a Group LDAP mapper to import AD security groups:
- LDAP Groups DN:
OU=Groups,DC=corp,DC=local - Group Name LDAP Attribute:
cn - Membership LDAP Attribute:
member - Mode:
READ_ONLY
This gives you AD group membership in Keycloak, which you’ll use for SAML role claims.
Step 2: Migrate SAML Applications
Export ADFS Relying Party Configuration
For each SAML relying party in ADFS, grab the essential settings:
Get-AdfsRelyingPartyTrust -Name "My App" | Select-Object `
Identifier, SamlEndpoint, IssuanceTransformRules, `
EncryptClaims, SignedSamlRequestsRequired, TokenLifetime
Create Keycloak SAML Client
In Keycloak admin console → Clients → Create client:
- Client ID: Use the same Entity ID from ADFS (e.g.,
https://app.yourdomain.com/saml) - Client Protocol: SAML
- Valid Redirect URIs: The ACS URL from ADFS SAML endpoint
- Name ID Format: Match your ADFS NameID claim (typically
urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressorunspecified)
Translate Claim Rules to Protocol Mappers
ADFS claim rules become Keycloak Protocol Mappers on the SAML client.
NameID from email — ADFS rule:
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
=> issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
Value = c.Value);
Keycloak mapper: Built-in, just set Name ID Format to email and Force Name ID Format to ON.
Group/Role claim — ADFS rule that maps group SID to a role:
In Keycloak, create a Role list mapper or a Group Membership mapper:
- Mapper Type:
Group list - Group attribute name:
http://schemas.microsoft.com/ws/2008/06/identity/claims/role - Full group path: OFF
- Single Group Attribute: ON
Custom attribute claim — ADFS pulling from AD attribute:
Create a User Attribute mapper:
- SAML Attribute Name:
http://schemas.yourdomain.com/claims/department - User Attribute:
department(mapped from LDAP federation)
Step 3: Handle WS-Federation Apps
This is the trickiest part. Keycloak doesn’t support WS-Federation natively.
Option A: Convert to SAML or OIDC — The cleanest approach. Most WS-Fed apps (especially .NET apps using WIF) can switch to SAML with minimal code changes. In ASP.NET Core:
// Old: WS-Federation
services.AddAuthentication()
.AddWsFederation(options => {
options.MetadataAddress = "https://adfs.corp.local/federationmetadata/...";
options.Wtrealm = "https://myapp.corp.local";
});
// New: SAML via Keycloak
services.AddAuthentication()
.AddSaml2(options => {
options.SPOptions.EntityId = new EntityId("https://myapp.corp.local");
options.IdentityProviders.Add(
new IdentityProvider(new EntityId("https://idp.yourdomain.com/realms/corp"), options.SPOptions)
{
MetadataLocation = "https://idp.yourdomain.com/realms/corp/protocol/saml/descriptor"
});
});
Option B: Use the keycloak-wsfed extension — The keycloak-wsfed community extension adds WS-Federation protocol support. Note that it lags behind Keycloak releases — verify compatibility with your Keycloak version before relying on it.
Option C: Keep ADFS as a bridge — For a small number of WS-Fed apps, you can federate ADFS as a downstream IdP under Keycloak. Keycloak becomes the primary IdP, and ADFS handles only the remaining WS-Fed apps. Not elegant, but pragmatic.
Step 4: Testing and Cutover
Parallel Run
Run Keycloak alongside ADFS during testing:
- Configure your first test application to point to Keycloak’s SAML endpoint instead of ADFS
- Verify login works with AD credentials (via LDAP federation)
- Check all claims/attributes are present in the SAML response
- Test logout — ADFS and Keycloak handle SLO differently
Use Keycloak’s SAML Tracer or browser extensions to compare the SAML assertion structure between ADFS and Keycloak.
DNS Cutover Strategy
For a gradual rollout, use DNS-based switching:
- ADFS is at
sts.corp.local— keep this active - Keycloak is at
idp.corp.local— new endpoint - Migrate apps one by one from the ADFS endpoint to the Keycloak endpoint
- Once all apps are migrated, optionally point
sts.corp.localto Keycloak for any hardcoded references
What to Validate
- User login with AD credentials works
- MFA enrollment and challenge (if applicable)
- SAML assertions contain correct NameID format
- All custom claims/attributes present
- Group-based role claims match ADFS output
- Single Logout (SLO) functions correctly
- Session timeout behavior matches expectations
- Service account / programmatic token requests work
Keycloak Features You Gain
After migration, take advantage of capabilities ADFS lacks:
- Built-in WebAuthn/Passkey support: No third-party adapter needed
- Fine-grained authentication flows: Conditional OTP, identity brokering, step-up auth
- Admin REST API: Full automation of user, client, and realm management
- Kubernetes-native deployment: Helm charts and the Keycloak Operator for production clusters
- OIDC as first-class protocol: Modern SPAs and APIs work natively without the OAuth bolt-on that ADFS provides
Cost Comparison
For a 5,000-user organization:
| Item | ADFS | Keycloak |
|---|---|---|
| Software License | Included with Windows Server | Free (Apache 2.0) |
| Infrastructure | 2+ Windows Servers + WAP | 2+ containers (Linux) |
| Windows Server CALs | ~$20/user | Not needed |
| SSL Certificates | Required | Required |
| Database | WID or SQL Server | PostgreSQL (free) |
| Support | Microsoft Premier/Unified | Red Hat SSO or community |
The infrastructure savings alone often justify the migration, particularly for organizations running ADFS on dedicated Windows Server VMs with SQL Server backend.
Keycloak isn’t zero-cost — you still need operational expertise and potentially Red Hat support for the commercial build. But the licensing model is fundamentally different: you pay for support, not per-user fees.
