🌐 Website Implementation
Authentication Authorization
📖 Docs

Authentication and Authorization - Optimizely CMS 12

Exam Area: Content Area 3 – Website Implementation & Delivery (25%)
Source: https://academy.optimizely.com/student/path/3128969/activity/4970332 | /4970330
Published: Feb 10 / Feb 17, 2026


Overview (Academy Key Points)

  • Authentication: Establishes who the user is (ASP.NET Core schemes, cookies, OIDC/SSO).
  • Authorization: Decides what the user can do (roles, permissions-to-functions, policies).
  • Access management: CMS-specific controls (ACLs, virtual roles, function permissions).
  • Hardening: Reduce UI attack surface (decoupled setup, path changes, policy gates, HTTPS/cookies).

1. Security Architecture Overview (Academy – 4970332)

There are 3 cooperating layers:

LayerDescription
AuthenticationEstablishes user identity (principal)
AuthorizationEvaluates if identity can access a capability
Access managementCMS-specific: roles, permissions-to-functions, virtual roles, ACLs

2. Authentication Models (Academy – 4970332)

Mixed-mode authentication:

services
  .AddAuthentication()
  .AddCookie("a-scheme")
  .AddCookie("another-scheme");

// Set default scheme
services
  .AddAuthentication(options => {
    options.DefaultScheme = "another-scheme";
    options.DefaultAuthenticateScheme = "another-scheme";
  });

3. Azure AD / Entra ID – OpenID Connect (Academy – 4970332)

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddAuthentication(options => {
            options.DefaultAuthenticateScheme = "azure-cookie";
            options.DefaultChallengeScheme = "azure";
        })
        .AddCookie("azure-cookie", options => {
            options.Events.OnSignedIn = async ctx => {
                if (ctx.Principal?.Identity is ClaimsIdentity claimsIdentity)
                {
                    // Syncs user and roles so they are available to the CMS
                    var synchronizingUserService = ctx.HttpContext.RequestServices
                        .GetRequiredService<ISynchronizingUserService>();

                    await synchronizingUserService.SynchronizeAsync(claimsIdentity);
                }
            };
        })
        .AddOpenIdConnect("azure", options => {
            options.SignInScheme = "azure-cookie";
            options.SignOutScheme = "azure-cookie";
            options.ResponseType = OpenIdConnectResponseType.Code;
            options.CallbackPath = "/signin-oidc";
            options.ClientSecret = "CLIENT SECRET";
            options.UsePkce = true;
        });
}

Note: If EPiServer.CMS.UI.AspNetIdentity is installed, avoid calling services.AddCmsAspNetIdentity() in startup so the UI can synchronize users when setting access rights.


4. Authorization Model (Academy – 4970332)

CMS 12 combines:

GateDescription
Feature gatesAdmin features, APIs, diagnostics
UI gatesEdit/admin UI access
Content gatesRead/edit/publish rights on a content item

5. Permissions to Functions (Academy – 4970332)

Controls access to CMS features via Config → Permissions to functions.

// Alt 1 – via PermissionService
bool hasPermission = ServiceLocator.Current.GetInstance<PermissionService>()
    .IsPermitted(HttpContext.Current.User, SystemPermissions.DetailedErrorMessage);

// Alt 2 – via PrincipalInfo
bool hasPermission = PrincipalInfo.Current.IsPermitted(SystemPermissions.DetailedErrorMessage);

6. Virtual Roles (Academy – 4970332)

Virtual roles: membership is determined at runtime (not stored in the database). CMS ships with:

Mapped roles in appsettings.json:

"EPiServer": {
  "Cms": {
    "MappedRoles": {
      "Items": {
        "SearchAdmins": {
          "MappedRoles": [ "WebAdmins", "Administrators" ],
          "ShouldMatchAll": "false"
        }
      }
    }
  }
}

7. Securing the Edit/Admin UI (Academy – 4970332)

Block access to edit/admin on the public front end:

var publicFront = _configuration.GetValue<bool?>("PublicFront");
if (publicFront.GetValueOrDefault(true))
{
    services.Configure<AuthorizationOptions>(o => 
        o.AddPolicy(CmsPolicyNames.CmsAdmin, b => b.RequireAssertion(c => false)));
    services.Configure<AuthorizationOptions>(o => 
        o.AddPolicy(CmsPolicyNames.CmsEdit, b => b.RequireAssertion(c => false)));
}

8. Cookie Security and HTTPS (Academy – 4970332)

services.ConfigureApplicationCookie(c => c.Cookie.SecurePolicy =
    _webHostingEnvironment.IsDevelopment()
        ? Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest
        : Microsoft.AspNetCore.Http.CookieSecurePolicy.Always);

Note: SameSite=None must specify Secure, which implies HTTPS.


9. Content Access Rights – IContentSecurityRepository (Academy – 4970330)

public void GrantEditorPermission(ContentReference contentLink, string groupName)
{
    var securityRepository = ServiceLocator.Current.GetInstance<IContentSecurityRepository>();
    
    // 1. Get the current security descriptor
    var securityDescriptor = securityRepository.Get(contentLink);
    
    // 2. Create a writable clone
    var writableDescriptor = securityDescriptor.CreateWritableClone() as IContentSecurityDescriptor;
    
    // 3. Add or update access entry
    var entry = new AccessControlEntry(groupName, AccessLevel.Edit | AccessLevel.Read | AccessLevel.Publish);
    writableDescriptor.AddEntry(entry);
    
    // 4. Save the modified security descriptor
    securityRepository.Save(contentLink, writableDescriptor, SecuritySaveType.Replace);
}

AccessLevel values:

AccessLevel.Read        = 1
AccessLevel.Create      = 2
AccessLevel.Edit        = 4
AccessLevel.Delete      = 8
AccessLevel.Publish     = 16
AccessLevel.Administer  = 64

Performance Best Practices (Academy – 4970330):


10. ASP.NET Core Identity (Default)

// In Program.cs
builder.Services
    .AddCmsAspNetIdentity<ApplicationUser>()
    .AddDefaultTokenProviders();

public class ApplicationUser : IdentityUser
{
    public string FullName { get; set; }
}

Review Questions

  1. What are the three layers of CMS 12 security? (Authentication, Authorization, Access management)
  2. What is ISynchronizingUserService used for? (Sync OIDC users/groups into the Optimizely database upon sign-in)
  3. What is a Virtual Role? (A role whose membership is determined at runtime, not stored in the DB)
  4. What is CmsPolicyNames.CmsAdmin used for? (Policy gate controlling access to the Admin UI)
  5. Why should permissions not be assigned to individual usernames? (Not scalable – prefer groups/virtual roles)
  6. What does ShouldMatchAll: false mean in mapped roles? (A user in ANY of the mapped roles is considered to be in the virtual role)
  7. What does cookie SecurePolicy.Always require? (HTTPS – cookies are only sent over HTTPS connections)