AEM in 40 Days
CalendarPhase 5 · Advanced Development

Day 31 of 40

Users, Groups and Service Users

Permissions in the repository and identity in the Admin Console

~50 min read3 videos4 source pages

By the end of today you should be able to

  1. Explain how repository ACLs decide what a user can see and do
  2. Create a service user with least privilege using repoinit
  3. Explain how Adobe IMS identity maps onto AEM groups
  4. Diagnose a permission problem methodically

Two identity systems, joined at the group

On Cloud Service, identity comes from Adobe, but authorisation is decided by the repository:

  • Adobe IMS — the Admin Console holds users, IMS groups and product profiles. This is where a person is granted access to your AEM environment at all.
  • AEM groups and ACLs — the repository decides what that person can actually read and write.

The join is by name. A product profile in the Admin Console maps to an AEM group; a user in that profile lands in that group on first login, and the group's ACLs then apply. The three default profiles are AEM Administrators, AEM Users and AEM Contributors.

Where to make the change

Adding a person to a team → Admin Console. Changing what that team may do → AEM groups and ACLs, versioned in your project via repoinit. Getting this backwards leads to permissions that exist on one environment and not another.

How ACLs work

Access control entries are set on nodes and inherited down the tree:

  • An entry is allow or deny, for a principal, with a set of privileges.
  • Privileges include jcr:read, jcr:write, jcr:modifyProperties, jcr:addChildNodes, jcr:removeNode, crx:replicate, jcr:readAccessControl, jcr:modifyAccessControl.
  • Entries inherit downward, and a closer entry overrides a more distant one.
  • Deny generally beats allow at the same level, so deny entries are a blunt instrument — prefer granting narrowly over denying broadly.

Tools → Security → Permissions gives you the UI, including a "test" facility that answers "can this user read this path?" directly — far better than reasoning about inheritance by hand.

Service users

Background code has no logged-in user. A service user is a system user with no password, granted exactly the access one piece of code needs. Creating one has three parts.

1. Create the user and its ACLs with repoinit, in ui.config:

create service user wknd-content-reader with path system/wknd

set ACL for wknd-content-reader
    allow jcr:read on /content/wknd
    allow jcr:read on /conf/wknd
end

2. Map the subservice name to the user with a Service User Mapper configuration:

// org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-wknd.cfg.json
{
  "user.mapping": [
    "com.adobe.aem.guides.wknd.core:wknd-content-reader=wknd-content-reader"
  ]
}

3. Use it, and always close the resolver:

Map<String, Object> params = Collections.singletonMap(
        ResourceResolverFactory.SUBSERVICE, "wknd-content-reader");

try (ResourceResolver resolver =
         resolverFactory.getServiceResourceResolver(params)) {
    // ...
}
Least privilege, genuinely

Grant read where read suffices, and scope to the narrowest path that works. A service user with write access to /content is an incident waiting to happen — and it will pass code review unless someone is paying attention.

Diagnosing a permission problem

  1. Which user is actually acting? A request user, or a service user? They have completely different rights.
  2. Use the permission test tool in Tools → Security → Permissions for the exact user and path.
  3. Check group membership — on Cloud Service, is the person in the right product profile, and did they log in after it was granted?
  4. Look for a deny entry higher up the tree overriding your allow.
  5. Check the service user mapping — a missing or misspelled subservice name yields a null resolver, which usually surfaces as a confusing NullPointerException rather than a permission error.
Today's takeaway

IMS decides who gets in; the repository decides what they can do, joined by group name. Service users are created in repoinit, mapped by subservice name, scoped to least privilege, and their resolvers are always closed.

Watch

Adobe's own videos for this topic. They load only when you press play.

Service Users
AEM Groups and Permissions
Adobe IMS Product Profiles

Read on Experience League

The primary sources these notes are drawn from.

Your notes

Saved automatically to this browser.

Check yourself

10 questions on today's material. 80% to pass.

Take the quiz