AEM user, group, creation, and permission programmatically

Contents

Objective

After reading this Article, You should have an understanding of –

  • Creation of a new user with user ID
  • Creation of a new group with group ID
  • Addition of a user into the group
  • Addition of ACL permission to a user
  • Removal of ACL permission from a user
  • Addition of ACL permission to a group

Introduction

In AEM, we have the useradmin console to create users, groups, and permissions – AEM user and group creation and permission, but sometimes we encounter the scenario of creating the user and group programmatically. For example, there is a subscription form on a website, and when the form details are submitted, a new user should be created. We also need to provide permission for the given user. To achieve this, we have to write a service using access control and the Jackrabbit API. In this section, we will go over all of the scenarios, such as user creation, group creation, providing permission to a specific path, and retrieving user details. 

Hence, without any further delay, let’s get started:

Creation of a new user with user ID

We can use a service or servlet to create a user programmatically. In this scenario, we are going to use servlets. So for the creation of a user, we need user details like the user ID, user first name, user last name, user email, and password. These details we will fetch from the servlet request parameter. The user ID, user last name, and password are the only parameters required to create a user. We also need a resource resolver, which we will get with the help of the system user, as explained in the previous post – ResourceResolver 

So let’s see the code implementation for user creation:

User creation code snippet :

				
					        //Fetching all User Details from Servlet Parameter
        String userID = request.getParameter("userID");
        String userFirstName = request.getParameter("userFirstName");
        String userLastName = request.getParameter("userLastName");
        String userEmail = request.getParameter("userEmail");
        String password = request.getParameter("password");

        //Getting ResourceResolver and Session using System Users
        Map<String, Object> param = new HashMap<>();
        param.put(ResourceResolverFactory.SUBSERVICE, SYSTEM_USER);
        resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
        Session session = resourceResolver.adaptTo(Session.class);
        assert session != null;

        //Getting UserManager from ResourceResolver
        UserManager userManager = resourceResolver.adaptTo(UserManager.class);
        assert userManager != null;

        //Creation of a new user with userID
        User createdUser = null;
        if (userManager.getAuthorizable(userID) == null) {
            createdUser = userManager.createUser(userID, password);

            //Setting the createdUser Profile Property
            ValueFactory valueFactory = session.getValueFactory();
            Value firstNameValue = valueFactory.createValue(userFirstName, PropertyType.STRING);
            createdUser.setProperty("./profile/givenName", firstNameValue);

            Value lastNameValue = valueFactory.createValue(userLastName, PropertyType.STRING);
            createdUser.setProperty("./profile/familyName", lastNameValue);

            Value emailValue = valueFactory.createValue(userEmail, PropertyType.STRING);
            createdUser.setProperty("./profile/email", emailValue);

            session.save();
            logger.info("User successfully created with ID : {}", createdUser.getID());
        } else {
                logger.info("User already exist..");
        }
				
			

Creation of a new group with group ID

In this scenario, we are going to use servlets, and we need group details like the group ID, group name, and group email. These details we will fetch from the servlet request parameter. The group ID is the only parameter required to create a group.

So let’s see the code implementation for group creation:

Group creation code snippet :

				
					//Fetching all Group Details from Servlet Parameter
    String groupID = request.getParameter("groupID");
    String groupName = request.getParameter("groupName");
    String groupEmail = request.getParameter("groupEmail");
            
    //Creation of a new group with groupID
    Group createdGroup = null;
    if (userManager.getAuthorizable(groupID) == null) {
        createdGroup = userManager.createGroup(groupID);

        //Setting the createdGroup Profile Property
        ValueFactory valueFactory = session.getValueFactory();
        Value groupNameValue = valueFactory.createValue(groupName, PropertyType.STRING);
        createdGroup.setProperty("./profile/givenName", groupNameValue);

        Value groupEmailValue = valueFactory.createValue(groupEmail, PropertyType.STRING);
        createdGroup.setProperty("./profile/email", groupEmailValue);

        session.save();
        logger.info("Group successfully created with ID : {}", createdGroup.getID());
    } else {
        logger.info("Group already exist..");
    }
				
			

Addition of a user into the group

In this scenario, we will take the help of the user manager’s authorizable. We will use addMember methods and save the session to reflect the changes.

So let’s see the code implementation:

Adding user into the group code snippet :

				
					            //Adding the User to the Group
            if (createdUser != null && createdGroup != null) {
                Authorizable authorizeUser = userManager.getAuthorizable(createdUser.getID());
                createdGroup.addMember(authorizeUser);
            }
				
			

Addition of ACL permission to a user for specific path

AEM permissions define what actions a user or group of users can perform on a resource. AEM permissions use Access Control Lists (ACLs) to evaluate and determine what should be the final permissions applicable to a user or group of users for a given resource or path. 

Access Control Lists (ACLs) are a combination of direct and indirect permissions that are applied to a user or group of users. Some permissions might be directly applied to a user, and some are inherited from the parent group. By default, there are seven types of restrictions in AEM, i.e. read, modify, create, delete, read ACL, edit ACL, and replicate. 

In Java code, we provide permission with the help of the Jackrabbit API and JCR Privileges. Some restrictions come as a combination of many privileges. For more information on privileges, see the GitHub reference – JCR Privileges In this section, we will see the code implementation to provide all permission for the given path /conf/learning.

So let’s see the code implementation for providing permission:

Adding an ACL permission to a user for a specific path code snippet :

				
					//Adding an ACL Permission to a User for a Specific Path (/conf/learning)
    JackrabbitAccessControlList specificPathUserAcl = AccessControlUtils.getAccessControlList(session, "/conf/learning");
    if (specificPathUserAcl != null) {
        JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
        PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
        Principal principal = principalManager.getPrincipal(userID);
        //Providing all permission for /conf/learning
        Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_ALL);

        specificPathUserAcl.addEntry(principal, privileges, true);
        accessControlManager.setPolicy(specificPathUserAcl.getPath(), specificPathUserAcl);
        session.save();
    } else
        logger.info("JackrabbitAccessControlList is null for specific path (/conf/learning).");
				
			

Addition of ACL permission to a user for all paths

In this section, we will see the code implementation to provide permission for all paths, i.e., /apps, /etc, /conf, /content, etc. AccessControlUtils helps us provide more than one ACL for a given path. Here, we offer read and access control read permission.

So let’s see the code implementation:

Adding an ACL permission to a user for all paths code snippet :

				
					            //Adding an ACL Permission to a User for All Path (/)
            JackrabbitAccessControlList allPathUserAcl = AccessControlUtils.getAccessControlList(session, "/");
            if (allPathUserAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(userID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_READ, Privilege.JCR_READ_ACCESS_CONTROL);

                allPathUserAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(allPathUserAcl.getPath(), allPathUserAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for the All JCR path (/).");
				
			

Removal of ACL permission from a user for given path

In this section, we will see the code implementation for removing permission from a user. Permissions in AEM are saved in the crx/de rep:policy node for a given path. When we grant a permission, an allow node with the desired privileges is created, and when we revoke the permission, a deny node with the previous privileges is created. So here we will remove all permissions for a given path.

So let’s see the code implementation:

Removal an ACL permission from a user for given paths code snippet :

				
					            //Removing ACL for a given Path (setting rep:policy -> deny)
            JackrabbitAccessControlList removeUserAcl = AccessControlUtils.getAccessControlList(session, "/conf/we-retail");
            if (removeUserAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(userID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_ALL);

                removeUserAcl.addEntry(principal, privileges, false);
                accessControlManager.setPolicy(removeUserAcl.getPath(), removeUserAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for given path");
				
			

Addition of ACL permission to a group for specific path

Group permissions in AEM define what actions a group of users can perform on a resource in the same way that user permissions do. When we grant permission to a group and indirectly it applies to all users present in that group. In this section, we will see the code implementation to provide read and ACL read permissions for the given path /conf/we-retail.

So let’s see the code implementation for providing permission:

Adding an ACL permission to a group for a specific path code snippet :

				
					            //Adding an ACL Permission to a Group for a Specific Path (/conf/we-retail)
            JackrabbitAccessControlList specificPathGroupAcl = AccessControlUtils.getAccessControlList(session, "/conf/we-retail");
            if (specificPathGroupAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(groupID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_READ, Privilege.JCR_READ_ACCESS_CONTROL);

                specificPathGroupAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(specificPathGroupAcl.getPath(), specificPathGroupAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for specific path (/conf/we-retail).");
				
			

Addition of ACL permission to a group for all paths

In this section, we will see the code implementation to provide write permission for all paths, i.e., /apps, /etc, /conf, /content, etc.

So let’s see the code implementation:

Adding an ACL permission to a group for all paths code snippet :

				
					            //Adding an ACL Permission to a Group for All Path (/)
            JackrabbitAccessControlList allPathGroupAcl = AccessControlUtils.getAccessControlList(session, "/");
            if (allPathGroupAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(groupID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_WRITE);

                allPathGroupAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(allPathGroupAcl.getPath(), allPathGroupAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for the All JCR path (/).");
				
			

For reference, please see the attached full servlet code:

				
					package com.adobe.learning.core.servlets;

import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.jackrabbit.commons.jackrabbit.authorization.AccessControlUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.*;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.Privilege;
import javax.servlet.Servlet;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Shiv
 */
@Component(service = Servlet.class, property = {Constants.SERVICE_DESCRIPTION + "= User and Group creation and permission",
        "sling.servlet.paths=" + "/bin/userGroupCreation", "sling.servlet.methods=" + HttpConstants.METHOD_GET
})
public class UserGroupCreationPermission extends SlingSafeMethodsServlet {

    private static final Logger logger = LoggerFactory.getLogger(UserGroupCreationPermission.class);
    private static final String SYSTEM_USER = "system_user";

    @Reference
    transient ResourceResolverFactory resourceResolverFactory;

    transient ResourceResolver resourceResolver;

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {

        //Fetching all User Details from Servlet Parameter
        String userID = request.getParameter("userID");
        String userFirstName = request.getParameter("userFirstName");
        String userLastName = request.getParameter("userLastName");
        String userEmail = request.getParameter("userEmail");
        String password = request.getParameter("password");

        //Fetching all Group Details from Servlet Parameter
        String groupID = request.getParameter("groupID");
        String groupName = request.getParameter("groupName");
        String groupEmail = request.getParameter("groupEmail");

        try {
            //Getting ResourceResolver and Session using System Users
            Map<String, Object> param = new HashMap<>();
            param.put(ResourceResolverFactory.SUBSERVICE, SYSTEM_USER);
            resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
            Session session = resourceResolver.adaptTo(Session.class);
            assert session != null;

            //Getting UserManager from ResourceResolver
            UserManager userManager = resourceResolver.adaptTo(UserManager.class);
            assert userManager != null;

            //Creation of a new user with userID
            User createdUser = null;
            if (userManager.getAuthorizable(userID) == null) {
                createdUser = userManager.createUser(userID, password);

                //Setting the createdUser Profile Property
                ValueFactory valueFactory = session.getValueFactory();
                Value firstNameValue = valueFactory.createValue(userFirstName, PropertyType.STRING);
                createdUser.setProperty("./profile/givenName", firstNameValue);

                Value lastNameValue = valueFactory.createValue(userLastName, PropertyType.STRING);
                createdUser.setProperty("./profile/familyName", lastNameValue);

                Value emailValue = valueFactory.createValue(userEmail, PropertyType.STRING);
                createdUser.setProperty("./profile/email", emailValue);

                session.save();
                logger.info("User successfully created with ID : {}", createdUser.getID());
            } else {
                logger.info("User already exist..");
            }


            //Creation of a new group with groupID
            Group createdGroup = null;
            if (userManager.getAuthorizable(groupID) == null) {
                createdGroup = userManager.createGroup(groupID);

                //Setting the createdGroup Profile Property
                ValueFactory valueFactory = session.getValueFactory();
                Value groupNameValue = valueFactory.createValue(groupName, PropertyType.STRING);
                createdGroup.setProperty("./profile/givenName", groupNameValue);

                Value groupEmailValue = valueFactory.createValue(groupEmail, PropertyType.STRING);
                createdGroup.setProperty("./profile/email", groupEmailValue);

                session.save();
                logger.info("Group successfully created with ID : {}", createdGroup.getID());
            } else {
                logger.info("Group already exist..");
            }

            //Adding the User to the Group
            if (createdUser != null && createdGroup != null) {
                Authorizable authorizeUser = userManager.getAuthorizable(createdUser.getID());
                createdGroup.addMember(authorizeUser);
            }

            //Getting AccessControlManager from session
            AccessControlManager accessControlManager = session.getAccessControlManager();

            //Adding an ACL Permission to a User for a Specific Path (/conf/learning)
            JackrabbitAccessControlList specificPathUserAcl = AccessControlUtils.getAccessControlList(session, "/conf/learning");
            if (specificPathUserAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(userID);
                //Providing all permission for /conf/learning
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_ALL);

                specificPathUserAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(specificPathUserAcl.getPath(), specificPathUserAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for specific path (/conf/learning).");

            //Adding an ACL Permission to a User for All Path (/)
            JackrabbitAccessControlList allPathUserAcl = AccessControlUtils.getAccessControlList(session, "/");
            if (allPathUserAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(userID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_READ, Privilege.JCR_READ_ACCESS_CONTROL);

                allPathUserAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(allPathUserAcl.getPath(), allPathUserAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for the All JCR path (/).");

            //Removing ACL for a given Path (setting rep:policy -> deny)
            JackrabbitAccessControlList removeUserAcl = AccessControlUtils.getAccessControlList(session, "/conf/we-retail");
            if (removeUserAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(userID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_ALL);

                removeUserAcl.addEntry(principal, privileges, false);
                accessControlManager.setPolicy(removeUserAcl.getPath(), removeUserAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for given path");

            //Adding an ACL Permission to a Group for a Specific Path (/conf/we-retail)
            JackrabbitAccessControlList specificPathGroupAcl = AccessControlUtils.getAccessControlList(session, "/conf/we-retail");
            if (specificPathGroupAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(groupID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_READ, Privilege.JCR_READ_ACCESS_CONTROL);

                specificPathGroupAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(specificPathGroupAcl.getPath(), specificPathGroupAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for specific path (/conf/we-retail).");

            //Adding an ACL Permission to a Group for All Path (/)
            JackrabbitAccessControlList allPathGroupAcl = AccessControlUtils.getAccessControlList(session, "/");
            if (allPathGroupAcl != null) {
                JackrabbitSession jackrabbitSession = (JackrabbitSession) session;
                PrincipalManager principalManager = jackrabbitSession.getPrincipalManager();
                Principal principal = principalManager.getPrincipal(groupID);
                Privilege[] privileges = AccessControlUtils.privilegesFromNames(session, Privilege.JCR_WRITE);

                allPathGroupAcl.addEntry(principal, privileges, true);
                accessControlManager.setPolicy(allPathGroupAcl.getPath(), allPathGroupAcl);
                session.save();
            } else
                logger.info("JackrabbitAccessControlList is null for the All JCR path (/).");

            session.logout();
        } catch (RepositoryException | LoginException e) {
            logger.error("Error in Get Drop Down Values", e.getMessage());
        }
    }
}

				
			

Conclusion

  • So in this post, we tried to cover all use cases for working with users and groups programmatically. We saw the creation of users or groups and the provisioning of privileges with the help of Jackrabbit and JCR APIs. I hope you enjoyed this post. If you find it useful, leave us a comment. I would love to hear your thoughts and suggestions to make it better. Also, you can connect with me on LinkedIn.

Leave a Reply

Your email address will not be published. Required fields are marked *