In this article we will learn how to create and use Service Users in your AEM code to provide controlled, programmatic access to the AEM repository.
As we all know we used to create the system users using the /crx/explorer and used to provide the required permissions from /useradmin dashboard. But now as we are moving towards AEMaaCs and the recommended way is to push the system users and it’s permissions through code. So let’s see how we can achieve that.
So let’s go ahead and update the OSGI config which comes OOTB as part of recent archetypes i.e, org.apache.sling.jcr.repoinit.RepositoryInitializer-myproject-statistics.config which can be found in you project structure at /ui.config/src/main/content/jcr_root/apps/myproject/osgiconfig.
1. Service User – permission to single path
scripts=["
create service user myprojectUserService
set ACL on /content/dam/myproject
allow jcr:all for myprojectUserService
end
"]
2. Service User – permission to multiple paths
scripts=["
create service user myprojectUserService
set ACL on /content/dam/myproject,/conf/myproject
allow jcr:all for myprojectUserService
end
"]
We can give different permissions as per our requirement, here I have given jcr:all for the above paths but if you want to give only read/write permissions you can do something like below:
3. Service User – permission to single path with only read permission
scripts=["
create service user myprojectUserService
set ACL on /content/dam/myproject
allow jcr:read for myprojectUserService
end
"]
4. Service User – permission to multiple paths with only write permission
scripts=["
create service user myprojectUserService
set ACL on /content/dam/myproject
allow jcr:write for myprojectUserService
end
"]
The recommended way is to create the service user under system/cq:services/<my-project> when using the principle ACL. You do it my using the following script:
scripts=["
create service user myprojectUserService with forced path system/cq:services/my-project
set principal ACL for myprojectUserService
allow jcr:read on /content/dam/myproject
end
"]
So once we are done creating the service user we will map it to a subServiceName which will be used in our java code to get the proper resolver to access the AEM content.
We can create our OSGI config i.e, org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-myproject.cfg.json
{
"user.mapping": [
"myproject.core:myprojectUserService=[myprojectUserService]"
]
}
So once we are done creating the above configurations we can utilise the above service user to get our resource resolver which will help us access the AEM content.
final Map<String, Object> authInfo = Collections.singletonMap(
ResourceResolverFactory.SUBSERVICE,
"myprojectUserService");
try (ResourceResolver serviceResolver = resourceResolverFactory.getServiceResourceResolver(authInfo)) {
// Do some work with the service user's resource resolver and underlying resources.
} catch (LoginException e) {
log.error("Login Exception when obtaining a User for the Bundle Service: {} ", e);
}
Thank you for reading.
Happy Coding!