Enterprise Authentication in Xperience by Kentico
Xperience by Kentico ships enterprise-grade authentication out of the box: full SSO support via OpenID Connect (OIDC) for identity providers like Microsoft Entra ID, Okta, and Auth0, with claims-based role mapping and configurable multi-factor authentication. This guide covers how the system works, how it changed from Kentico Xperience 13, and exactly how to implement it correctly in production.
What this post covers
- The core authentication problems enterprises face with CMS platforms
- Key concepts: OIDC, SSO, claims, and role synchronization in Xperience by Kentico
- The legacy Kentico 13 approach vs. the modern Xperience by Kentico approach
- A specific implementation detail: certificate credentials vs. client secrets
- A comparison of supported identity providers (Entra ID, Okta, Auth0)
- What works well, honest trade-offs, and non-obvious decisions in the platform
- Five self-contained FAQ answers
The Problem With CMS Authentication at Enterprise Scale
Most CMS platforms treat authentication as an afterthought. For a five-person team editing a marketing site, a username and password per person is fine. For an enterprise with hundreds of editors, strict compliance requirements, and an existing identity infrastructure, that model creates real operational problems.
- Credential sprawl: Every new CMS demands its own set of user accounts. Security teams cannot enforce password policies consistently. When someone leaves the organization, IT has to remember the CMS login exists and manually disable it.
- No centralized MFA enforcement: If the CMS uses its own auth stack, you cannot push MFA requirements through your existing identity provider. Each system manages MFA separately, leading to gaps.
- Role duplication and drift: Access roles defined in Active Directory or Entra ID have to be manually recreated in the CMS. When roles change in the IdP, the CMS is never notified. Editors end up with stale permissions.
- Audit gaps: Security audits require a single login trail. Fragmented authentication means login events are spread across three or four systems, making forensics harder and compliance reporting painful.
- Vulnerability in legacy authentication layers: In March 2025, researchers at watchTowr Labs disclosed two critical authentication bypass vulnerabilities (CVE-2025-2746, CVE-2025-2747) affecting Kentico Xperience 13's Staging Service. Both were rated CVSS 9.8. CISA confirmed active exploitation. They traced back to a reliance on the retired WSE3 (Web Services Enhancements 3.0) library. The lesson: legacy authentication infrastructure carries legacy risk.
The Core Idea: How Authentication Works in Xperience by Kentico
Xperience by Kentico replaces the older, form-based and WIF-based authentication layers with a modern ASP.NET Core identity stack built around OpenID Connect (OIDC). Here are the six concepts you need to understand before writing any code.
1. OpenID Connect (OIDC)
OIDC is an authentication layer built on top of OAuth 2.0. It allows a third-party identity provider to issue an ID token confirming the user's identity. The token is a signed JWT (JSON Web Token) containing claims about the user: name, email, roles, and custom attributes. Xperience consumes that token rather than managing credentials itself. The full OIDC Core 1.0 specification is the authoritative reference.
2. Identity Providers (IdPs)
The IdP is the system that verifies user identity and issues tokens. Xperience by Kentico officially documents integration with Microsoft Entra ID, Auth0, and Okta, though any OIDC-compliant provider will work. The IdP is where MFA, conditional access policies, and user provisioning are managed. Xperience trusts what the IdP says; it does not re-verify credentials.
3. Claims
A claim is a key-value pair inside an ID token. For example: "preferred_username": "alice@acme.com" or "roles": ["contenteditors", "administrator"]. Xperience maps incoming claims to its internal user object properties (username, first name, last name, email) and to Kentico role assignments. The mapping is configurable via AdminExternalAuthenticationProviderOptions.
4. The AddAdminExternalAuthenticationProvider Method
This is the single ASP.NET Core extension method that wires up external authentication for the Xperience administration interface in Program.cs. It wraps the standard AddMicrosoftIdentityWebApp or AddOpenIdConnect calls and adds Kentico-specific behavior for user creation and role synchronization on top.
5. Role Synchronization Frequency
By default (UserSynchronizationFrequency.Never), Xperience creates a user on first login and never updates roles again. Setting the value to Always re-syncs role assignments from the IdP on every login. This is the setting that keeps your Kentico permissions in sync with Entra ID groups without manual intervention.
6. Split Authentication Contexts
Xperience by Kentico treats authentication for the administration UI and for the public live site as completely separate concerns. External authentication configured via AddAdminExternalAuthenticationProvider applies only to the admin panel. Public site authentication, including social login and member registration, is handled through the live site's ASP.NET Identity stack. The two are not shared and must be configured independently.
The Old Approach: Authentication in Kentico Xperience 13
Step 1: Configure Claims-Based Authentication in the Admin UI
In K13, SSO for the admin interface used Windows Identity Foundation (WIF) with a WS-Federation protocol. Administrators navigated to Settings > Security & Membership > Claims-based Authentication in the admin UI and entered the federation metadata URL of their IdP. This was a no-code UI-driven workflow, but it limited flexibility and only supported SAML 1.0 tokens, not SAML 2.0.
Step 2: Register the Relying Party Manually
Kentico did not expose a Federation Metadata endpoint, so the IdP configuration could not be automated. Each Identity Provider (typically ADFS or a similar on-premises system) had to be configured manually with Kentico's application details entered field by field. This made multi-environment setup (dev, staging, production) repetitive and error-prone.
Step 3: Limited Public Site SSO
For MVC-based K13 sites, SSO on the public-facing site was the developer's responsibility. The claims-based authentication in Settings applied to the admin app only. Public site SSO required writing custom middleware in Startup.Auth.cs using the older UseOpenIdConnectAuthentication OWIN pipeline, a pattern that does not exist in ASP.NET Core.
Step 4: Apply Hotfixes for Authentication Vulnerabilities
The Staging Service in K13 relied on WSE3 (Web Services Enhancements 3.0), a library Microsoft retired. In March 2025, two authentication bypass vulnerabilities affecting this component (CVE-2025-2746 and CVE-2025-2747, CVSS 9.8 each) were patched in K13.0.178. Teams on K13 had to apply hotfixes urgently. Kentico Xperience 13 reaches end of support on December 31, 2026, leaving organizations no long-term path on this version.
The New Approach: Authentication in Xperience by Kentico
Step 1: Register the Application in Your Identity Provider
The first step is entirely in the IdP. For Microsoft Entra ID, this means creating an App Registration in the Entra admin center, configuring the redirect URI (for example, https://yourdomain.com/admin-oidc), enabling optional claims (email, given_name, family_name, preferred_username) in Token Configuration, and adding either a certificate or a client secret. The same general flow applies to Okta and Auth0, with provider-specific terminology.
Step 2: Install the NuGet Package and Configure Program.cs
Install the Microsoft.Identity.Web NuGet package. In Program.cs, call builder.Services.AddAdminExternalAuthenticationProvider() and pass your IdP's tenant ID, client ID, callback path, and certificate reference. All configuration now lives in code and in environment-specific appsettings.json files, making CI/CD deployment straightforward and auditable through version control.
Step 3: Map Claims and Configure Role Synchronization
Configure the inner options lambda of AddAdminExternalAuthenticationProvider to set UserSynchronizationFrequency and RoleClaimName. Ensure the Xperience role code names match the role values sent in the IdP's claims exactly. If you need to translate IdP role names into Kentico role names, implement IClaimsTransformation and register it with the DI container. This is a clean separation: the transformation logic lives in one class, not scattered across settings screens.
Step 4: Verify Sign-In Behavior and Lock Down Secrets
Run the application and confirm that navigating to the admin UI redirects to the IdP's login page. The default behavior (AdminAuthenticationMode.PrioritizeExternal) hides the forms authentication option entirely. If you need both available during a transition period, set AdminAuthenticationMode.MaintainForms. For production deployments, move client secrets out of appsettings.json and into Azure Key Vault or deployment-time variable injection. Never commit secrets to source control.
Implementation Detail: Certificates Beat Client Secrets
Why certificates are the production-safe choice for Entra ID integration
When connecting Xperience by Kentico to Microsoft Entra ID, you have two credential options: a client secret (a string) or a certificate (an asymmetric key pair). The official Kentico documentation and Microsoft both recommend certificates for production. Here is the specific reason.
A client secret is a shared secret. It exists in two places: Entra ID and your appsettings.json (or wherever you store it). If either copy is exposed, for example through a leaked deployment artifact, a misconfigured logging statement, or a compromised pipeline variable, an attacker can impersonate your application to Entra ID and receive valid tokens for any user in the tenant.
A certificate uses asymmetric cryptography. The private key lives in Azure Key Vault and never leaves it. Your application loads the certificate reference at runtime using CertificateDescription.FromKeyVault("https://keyvault-name.vault.azure.net/", "certificate-name"). Only the public key is registered with Entra ID. Even if your config files are fully exposed, an attacker gains nothing actionable because the private key was never there.
The trade-off is real: certificate setup requires Azure Key Vault access and the EnableTokenAcquisitionToCallDownstreamApi() and AddInMemoryTokenCaches() calls in your DI registration, which are not needed for client secrets. Omitting those calls produces the Entra error AADSTS7000218 at sign-in. For development environments, client secrets remain acceptable.
Identity Provider Comparison
| Feature | Microsoft Entra ID | Okta | Auth0 |
|---|---|---|---|
| Protocol | OIDC (Authorization Code Flow) | OIDC (Authorization Code + Hybrid) | OIDC (Authorization Code + Hybrid) |
| NuGet Package | Microsoft.Identity.Web | Microsoft.AspNetCore.Authentication.OpenIdConnect | Microsoft.AspNetCore.Authentication.OpenIdConnect |
| Certificate Credentials | Recommended | Not documented | Not documented |
| Role Sync | Supported via App Roles | Supported via custom profile attribute | Supported via groups scope |
| Role Claim Key | Standard roles claim | Custom: XperienceAdminRoles | Standard groups claim scope |
| Username Claim | preferred_username | preferred_username | nickname (preferred_username not sent by default) |
| MFA Support | Built-in via Conditional Access | Built-in via Okta Verify | Built-in via Auth0 Actions |
| Multiple Providers | Only one external provider supported at a time in Xperience by Kentico admin | ||
| Best For | Microsoft 365 enterprises with existing Azure tenants | Enterprises with mixed SaaS ecosystems on Okta | Startups and teams wanting a flexible managed IdP with social login |
What's Working Well
Program.cs and appsettings.json. You can diff configuration changes, review them in PRs, and deploy them through standard CI/CD pipelines. This alone eliminates a class of configuration drift bugs.UserSynchronizationFrequency.Always is set and Entra ID App Roles are mapped to Kentico role code names, revoking a user's Entra role immediately removes their Kentico access on next login. No separate offboarding task is needed in the CMS. For organizations with strict access controls and regular staff turnover, this removes an entire manual process from the security workflow.Honest Trade-offs
AddAdminExternalAuthenticationProvider for the admin UI and once through the live site's ASP.NET Identity setup. Documentation for the live-site side is less comprehensive than for the admin side.Surprising Decisions Worth Noting
preferred_username claim, which Xperience uses as the Kentico username. Auth0 does not include this claim in ID tokens unless explicitly configured. If you miss this, user account creation fails silently at first login. The fix is to set options.UserNameClaimName = "nickname" in the Xperience configuration and confirm that Auth0 sends the nickname claim for all users. This single missed step has caused production issues on multiple Auth0 integrations.XperienceAdminRoles (this name must match the RoleClaimName set in your Program.cs) and configure it with the Combine values across groups behavior. Getting the attribute's data type (string array) or the combine setting wrong produces no error message; users simply arrive in Kentico with no roles assigned.The End Result
Enterprise authentication in Xperience by Kentico is a step change from what Kentico Xperience 13 offered. The platform replaces a fragmented, UI-driven, SAML 1.0-era system with a code-configured, OIDC-compliant identity layer that plugs directly into Microsoft Entra ID, Okta, or Auth0. Claims-based role synchronization means your Kentico permissions stay in sync with your central identity store without manual intervention. Certificates replace shared secrets at the credential layer, reducing the attack surface materially. The two critical CVEs that hit Kentico 13's Staging Service in 2025 are a concrete reminder of what happens when authentication relies on retired libraries.
The trade-offs are real: one external provider at a time, no native SAML 2.0 support, and separate configuration paths for admin and public site authentication. None of these are blockers for enterprises with a modern IdP already in place. They are considerations to account for during the design phase, not surprises to encounter during deployment.
For teams still running Kentico Xperience 13, the authentication architecture gap is one more reason to complete the migration to Xperience by Kentico before the December 31, 2026 end-of-support date. DotStark's XbyK upgrade services include identity and authentication migration as a first-class concern in every engagement.