User Group Permission | Community
Skip to main content
Prince_Shivhare
Community Advisor
Community Advisor
February 24, 2025
Solved

User Group Permission

  • February 24, 2025
  • 3 replies
  • 698 views

Hey Team,

I have a use case related to ACLs:
I overlaid /libs/cq/core/content/tools to create a custom tool under the Tools section of the AEM console. Now, I want to hide it for all users except one specific user group. How can I achieve this?

I tried using the rep:policy node, where I denied access for the everyone group and allowed it for the group I created, but it's not working.

Can anyone please help me here?

Thanks

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by Tethich

Hi @prince_shivhare 

 

Maybe instead of /libs/cq/core/content/tools, you can overlay directly /libs/cq/core/content/nav/tools.

Then use granite:rendercondition to control the access for specific tool of your choice.
After you export the /apps/cq/core/content/nav/tools from AEM you will see an xml similar with the one below:

 

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured"> <tools jcr:primaryType="nt:unstructured" jcr:title="Tools" id="cq-tools" order="{Long}200"> <workflow jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </workflow> ..... <general jcr:primaryType="nt:unstructured" sling:orderBefore="workflow"> <crxdelite jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </crxdelite> ..... <my-tool jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </my-tool> </general> <cloudservices jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </cloudservices> </tools> </jcr:root>

 

I have not added the entire XML, I only kept few of the Tools available ootb just for you to get an idea. In addition I added one called my-tool, which might be your tool there.

 

In this way you can control access to any tool, custom or ootb one, by adding granite:condition. You can see it points to /apps/my-project/.../my-condition, which will be a custom resource backed-up by a Sling model:

 

 

And in the Sling model you can implement your logic to decide whether the current logged in user should have access or not to the given tool.


So you can get the Authorizable from the resource resolver.

 

... final Session session = resourceResolver.adaptTo(Session.class); final UserManager userManager = resourceResolver.adaptTo(UserManager.class); userManager.getAuthorizable(session.getUserID() ...

 

And then use existing API to find maybe in which group this Authorizable is and based on the group decide if it should have access or not to the tool: https://developer.adobe.com/experience-manager/reference-materials/6-4/javadoc/org/apache/jackrabbit/api/security/user/Authorizable.html

I would not worry about performance as this is probably mainly for Editors within the company, so they should not put that much of a request load on AEM. Plus, we are talking only about author tier/instance, so live site is not impacted.

3 replies

giuseppebaglio
Level 10
February 24, 2025

Creating custom tools in the AEM console and restricting access through ACLs can be tricky because of how permission inheritance works in the JCR repository. When you overlay /libs/cq/core/content/tools and add a rep:policy node, you're likely encountering one of these issues:

 

  • Permission evaluation in the repository follows a "most specific denial wins" principle. If there are other policies elsewhere in the inheritance chain that deny access, they might be taking precedence.
  • The content structure in /libs is often protected by other ACLs higher in the hierarchy that your overlay doesn't override.
  • The AEM console UI might use additional permission checks beyond just reading the node structure.

Here's a step-by-step solution that addresses these potential issues:

  • Create your overlay: Make sure your overlay structure matches exactly and is in the correct location like /apps/cq/core/content/tools/your-custom-tool
  • At the specific tool node (not at the parent level), create a complete ACL structure:

 

/apps/cq/core/content/tools/your-custom-tool + rep:policy (nt:unstructured) + allow-specific-group (rep:GrantACE) - rep:principalName = "your-group-name" - rep:privileges = ["jcr:read", "jcr:readAccessControl"] + deny-everyone (rep:DenyACE) - rep:principalName = "everyone" - rep:privileges = ["jcr:read"] - rep:glob = "*"

 

  • Make sure your overlay uses a custom resource type:

 

/apps/cq/core/content/tools/your-custom-tool - sling:resourceType = "/apps/your-project/components/tools/your-custom-tool"

 

  • Youc could also add a security check in the component's JSP/HTL, something like:

 

// In your component's servlet or HTL helper class ResourceResolver resolver = request.getResourceResolver(); boolean hasAccess = resolver.getUserID().equals("admin") || resolver.isUserMember("your-group-name"); if (!hasAccess) { response.sendError(HttpServletResponse.SC_FORBIDDEN); return; }

 

 

Besides, if you're still experiencing issues, you can use the ACS AEM Commons ACL Packager tool to export and inspect the effective permissions.

 

Hope this helps!

 

Tethich
Community Advisor
TethichCommunity AdvisorAccepted solution
Community Advisor
February 24, 2025

Hi @prince_shivhare 

 

Maybe instead of /libs/cq/core/content/tools, you can overlay directly /libs/cq/core/content/nav/tools.

Then use granite:rendercondition to control the access for specific tool of your choice.
After you export the /apps/cq/core/content/nav/tools from AEM you will see an xml similar with the one below:

 

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured"> <tools jcr:primaryType="nt:unstructured" jcr:title="Tools" id="cq-tools" order="{Long}200"> <workflow jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </workflow> ..... <general jcr:primaryType="nt:unstructured" sling:orderBefore="workflow"> <crxdelite jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </crxdelite> ..... <my-tool jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </my-tool> </general> <cloudservices jcr:primaryType="nt:unstructured"> <granite:rendercondition jcr:primaryType="nt:unstructured" sling:resourceType="/apps/my-project/.../my-condition" /> </cloudservices> </tools> </jcr:root>

 

I have not added the entire XML, I only kept few of the Tools available ootb just for you to get an idea. In addition I added one called my-tool, which might be your tool there.

 

In this way you can control access to any tool, custom or ootb one, by adding granite:condition. You can see it points to /apps/my-project/.../my-condition, which will be a custom resource backed-up by a Sling model:

 

 

And in the Sling model you can implement your logic to decide whether the current logged in user should have access or not to the given tool.


So you can get the Authorizable from the resource resolver.

 

... final Session session = resourceResolver.adaptTo(Session.class); final UserManager userManager = resourceResolver.adaptTo(UserManager.class); userManager.getAuthorizable(session.getUserID() ...

 

And then use existing API to find maybe in which group this Authorizable is and based on the group decide if it should have access or not to the tool: https://developer.adobe.com/experience-manager/reference-materials/6-4/javadoc/org/apache/jackrabbit/api/security/user/Authorizable.html

I would not worry about performance as this is probably mainly for Editors within the company, so they should not put that much of a request load on AEM. Plus, we are talking only about author tier/instance, so live site is not impacted.

joerghoh
Adobe Employee
Adobe Employee
February 24, 2025
Prince_Shivhare
Community Advisor
Community Advisor
February 27, 2025

Hey Everyone,
Thanks for your answers. I'll try to implement your suggestion and will update this post accordingly.
Thank you