Leveraging Sitecore Out-of-the-Box Item Security for Headless Applications
Making Sitecore content security seamless in headless architectures.
Start typing to search...
When moving from MVC-based Sitecore solutions to headless architecture like Next.js, one critical aspect is content security. Fortunately, Sitecore's out-of-the-box item security can be extended to work with headless applications.
This post will walk you through why leveraging Sitecore’s built-in security is advantageous, and how you can extend Sitecore to expose security metadata for headless consumption.
Inheritance Is Handled Automatically
Sitecore’s item security naturally supports inheritance.
Reuse Existing Security Rules During Migration
When migrating from MVC to Headless, you can keep the existing security definitions in your content tree without additional work.
To expose page level security metadata to your headless app (like in a Next.js front-end), you need to extend the Sitecore CM instance by attaching event handlers that update custom fields based on item security.
Add an Access Control section to your page templates with three new fields:
accessControlSecured (Boolean) — a toggle to determine whether the item is public or secured.accessControlAllowed (Multline-Text) — roles allowed to read a page.accessControlDenied (Multline-Text) — roles denied to read a page.Attach handlers to these events:
OnItemAddedOnItemMovedOnItemSaved//Shows how to verify which fields are changing, this prevents an infinite loop of updates.
var changes = ((ItemChanges)((SitecoreEventArgs)args).Parameters[1]).FieldChanges;
bool securityFieldChanged = changes.Contains(Sitecore.FieldIDs.Security);
//Use ExtractParameter to get the affected item in the Event Handler
var item = Event.ExtractParameter(args, 0) as Item;
Apply the following to the item and all its descendants:
Always get the Anonymous role for public/private evaluation.
bool isSecured = AuthorizationManager.GetAccess(item, anonymousRole, AccessRight.ItemRead).Permission != AccessPermission.Allow;
Update accessControlSecured based on the evaluation.
Get all roles present in the __Security field, process only the relevant page-level roles (filter by domain or naming patterns if necessary).
The __Security field is a multi-line text with roles, user names, and access rights all together. Use a text extraction method to get only the roles.
Collect the roles from the item and all its parents.

Get all present roles in all parent items.
foreach (var role in allRoles)
{
if (AuthorizationManager.GetAccess(item, role, AccessRight.ItemRead).Permission == AccessPermission.Allow)
canReadRoles.Add(role);
}
foreach (var role in allRoles)
{
if (AuthorizationManager.GetAccess(item, role, AccessRight.ItemRead).Permission == AccessPermission.Deny)
deniedRoles.Add(role);
}
Populate accessControlAllowed and accessControlDenied fields accordingly.
Process all subitems to ensure security inheritance is respected.
When the __Security field changes, or an item is moved, all its descendants will be affected. Repeating the evaluation process updating the access control fields is necessary.

Update access control in all descendants
Now, with all the fields properly set, you can easily determine access in the head application.
For example, in a Next.js application using SSG (Static Site Generation), a middleware plugin can read the accessControlSecured, accessControlAllowed, and accessControlDenied fields to perform access evaluations at runtime.
Works great for manually curated content trees and reasonable role counts.
Leveraging Sitecore's native item security for headless apps saves time, preserves existing definitions, and simplifies future maintenance.
By extending the CM instance with event handlers, you expose security metadata without rebuilding complex permission systems.