Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.
SOLVED

Programmatic User Creation in AEM

Avatar

Level 3

I am trying to implement a custom service which programmatically creates user under a particular folder i.e /home/users/myproject/user1.

 

Below are the methods available

 

createUser(String userID, String password)

          Creates an User for the given userID / password pair; neither of the specified parameters can be null.

createUser(String userID, String password, Principal principal, String intermediatePath)

          Creates an User for the given parameters.

 

Second one suits my requirement but when I pass the principal of an existing group it throws an exception saying Authorizable with principal “content-authors” already exists

 

“org.apache.jackrabbit.api.security.user.AuthorizableExistsException: Authorizable with principal content-authors already exists.”

 

If I pass a nonexisting group’s principal ex: “TestPrincipal” it resolves to null and says parameter cannot be null.

 

Below is the code

 

Session session = request.getResourceResolver().adaptTo(Session.class);

              JackrabbitSession js = (JackrabbitSession) session;

              UserManager usermanager;

              try {

                      usermanager = (UserManager) js.getUserManager();

                      PrincipalManager principalMgr = js.getPrincipalManager();

                      Principal groupPrincipal = principalMgr.getPrincipal("content-authors");

                      User user= usermanager.createUser("ascdcdc", "dcdsvdfv",groupPrincipal,"/home/users/a");

                      js.save();

              }

Any help is appreciated.

1 Accepted Solution

Avatar

Correct answer by
Level 10

Here are few sample code you can use to users:-

First:

org.apache.jackrabbit.api.security.user.UserManager userManager = resourceResolver.adaptTo(org.apache.jackrabbit.api.security.user.UserManager.class); if(userManager == null){ log.error("userManager == null!"); return; } String login = "login"; String password = "password"; org.apache.jackrabbit.api.security.user.User user = userManager.createUser(login, password);

Second:

ResourceResolver resolver=request.getResourceResolver(); Session session=request.getResourceResolver().adaptTo(Session.class); UserManager userManager = resolver.adaptTo(UserManager.class); Group group=userManager.createGroup("Group Name"); User user=userManager.createUser("username",”pwd”); if (! userManager.isAutoSave()) { session.save(); }

Third:

// Create UserManager Object org.apache.jackrabbit.api.security.user.UserManager; UserManager userManager = resolver.adaptTo(UserManager.class); // Create a Group and User Group group=userManager.createGroup("My Group"); User user = userManager.createUser(name, password); // Add Users to Group Authorizable authUser = userManager.getAuthorizable(user.getID()); group.addMember(authUser); // Provide permissions to Group AccessControlManager accCtrlMgr = session.getAccessControlManager(); JackrabbitSession jcrSession = (JackrabbitSession) session; PrincipalManager principalMgr = jcrSession.getPrincipalManager(); Principal groupPrincipal = principalMgr.getPrincipal(group); Privilege[] privileges = new Privilege[] { accCtrlMgr.privilegeFromName(Privilege.JCR_ALL) }; // Set privileges to particular path AccessControlList acl = accCtrlMgr.getApplicablePolicies(path).nextAccessControlPolicy(); acl.addAccessControlEntry(groupPrincipal, rootNodePrivilege); accCtrlMgr.setPolicy(path, acl); session.save();

View solution in original post

11 Replies

Avatar

Correct answer by
Level 10

Here are few sample code you can use to users:-

First:

org.apache.jackrabbit.api.security.user.UserManager userManager = resourceResolver.adaptTo(org.apache.jackrabbit.api.security.user.UserManager.class); if(userManager == null){ log.error("userManager == null!"); return; } String login = "login"; String password = "password"; org.apache.jackrabbit.api.security.user.User user = userManager.createUser(login, password);

Second:

ResourceResolver resolver=request.getResourceResolver(); Session session=request.getResourceResolver().adaptTo(Session.class); UserManager userManager = resolver.adaptTo(UserManager.class); Group group=userManager.createGroup("Group Name"); User user=userManager.createUser("username",”pwd”); if (! userManager.isAutoSave()) { session.save(); }

Third:

// Create UserManager Object org.apache.jackrabbit.api.security.user.UserManager; UserManager userManager = resolver.adaptTo(UserManager.class); // Create a Group and User Group group=userManager.createGroup("My Group"); User user = userManager.createUser(name, password); // Add Users to Group Authorizable authUser = userManager.getAuthorizable(user.getID()); group.addMember(authUser); // Provide permissions to Group AccessControlManager accCtrlMgr = session.getAccessControlManager(); JackrabbitSession jcrSession = (JackrabbitSession) session; PrincipalManager principalMgr = jcrSession.getPrincipalManager(); Principal groupPrincipal = principalMgr.getPrincipal(group); Privilege[] privileges = new Privilege[] { accCtrlMgr.privilegeFromName(Privilege.JCR_ALL) }; // Set privileges to particular path AccessControlList acl = accCtrlMgr.getApplicablePolicies(path).nextAccessControlPolicy(); acl.addAccessControlEntry(groupPrincipal, rootNodePrivilege); accCtrlMgr.setPolicy(path, acl); session.save();

Avatar

Level 10

We are going to create an AEM COmmunity article based on this use case - its a common use case. I have worked on this. Here is a sample that compiles (a few differecnes from 3rd example)

package com.adobe.cq.user;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
    
    
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
    

import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
  
import java.util.HashMap;
import java.util.Map;
    

import javax.jcr.Repository; 
import javax.jcr.SimpleCredentials; 
import javax.jcr.Node; 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
     

import org.apache.jackrabbit.commons.JcrUtils;
    

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
    

import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;

import javax.jcr.RepositoryException;

import org.apache.felix.scr.annotations.Reference;
import org.apache.jackrabbit.commons.JcrUtils;
    

import javax.jcr.Session;
import javax.jcr.Node; 
   
   

//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory ; 
import org.apache.sling.api.resource.ResourceResolver; 
import org.apache.sling.api.resource.Resource; 
 
//Jackrabbit User APIs
import org.apache.jackrabbit.api.JackrabbitSession ;
import org.apache.jackrabbit.api.security.user.UserManager  ;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.api.security.user.Group;
import  org.apache.jackrabbit.api.security.user.Authorizable ;
import javax.jcr.security.AccessControlManager ; 
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import java.security.Principal;
import javax.jcr.security.Privilege;
import javax.jcr.security.AccessControlList ; 
  
 
//This is a component so it can provide or consume services
@Component
   
@Service
public class CreateAEMUser implements CreateUser{
    
    /** Default log. */
    protected final Logger log = LoggerFactory.getLogger(this.getClass());
                   
    private Session session;
    
    //Inject a Sling ResourceResolverFactory
    @Reference
    private ResourceResolverFactory resolverFactory;
     
    @Override
    public String newCQUser(String name) {
             
     try
     {
      //Invoke the adaptTo method to create a Session 
      ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
      session = resourceResolver.adaptTo(Session.class);
                 
      //Create a UserManager instance from the session object
      UserManager userManager = ((JackrabbitSession) session).getUserManager();
     
      String path = "/home/users/geometrixx"; 
      
      JackrabbitSession js = (JackrabbitSession) session;

      // get user/principal for whom to read/set ACLs

    
      // Create a Group and User
      Group group = userManager.createGroup("My Group");
      User user = userManager.createUser(name, "AEM");
       
      // Add Users to Group
      Authorizable authUser = userManager.getAuthorizable(user.getID());
      group.addMember(authUser);
      
      
      
      // Provide permissions to Group
      AccessControlManager accCtrlMgr = session.getAccessControlManager();
      JackrabbitSession jcrSession = (JackrabbitSession) session;
      
      PrincipalManager principalMgr = jcrSession.getPrincipalManager();
      
      
      
      
      Principal groupPrincipal = principalMgr.getPrincipal("My Group");
      Privilege[] privileges = new Privilege[] { accCtrlMgr.privilegeFromName(Privilege.JCR_ALL) };
       
      
      
      
      // Set privileges to particular path
      javax.jcr.security.AccessControlPolicyIterator accList= accCtrlMgr.getApplicablePolicies(path); 
      javax.jcr.security.AccessControlList  acl =(AccessControlList) accList.nextAccessControlPolicy();
      acl.addAccessControlEntry(groupPrincipal, privileges);
      accCtrlMgr.setPolicy(path, acl);
      session.save();


         
        // Log out
        session.logout(); 
        
                    
                   
        return "All AEM Users are written to the log file" ;  
        
    }
    catch(Exception e)
    {
             log.info("CQ ERROR: "+e.getMessage())  ; 
    }
             
    return null;
     }
    }

Avatar

Level 1

@smacdonald2008 - The above snippet doesn't show how the user is created at a custom path inside /home. It only shows how the privileges are set for a path. Can you please help with the query of creating user at a custom intermediate path using UserManager.createUser(@NotNull java.lang.String userID, @nullable java.lang.String password, @notnull java.security.Principal principal, @nullable java.lang.String intermediatePath)

 

Thanks in advance!!

Avatar

Level 2

@smacdonald2008 - I found https://helpx.adobe.com/experience-manager/using/jackrabbit-users.html which talks about creating users/groups via the Jackrabbit API, but both that example and your example here use the frowned upon getAdministrativeResourceResolver() method.  Is there a set of permissions that can be given to a service user such that the service user (instead of the admin resource resolver) can be used to create users/groups?

Avatar

Level 2

NVM, I think I answered this for myself - looks like it works if I grant my service user the following permissions: rep:userManagement,jcr:modifyAccessControl,jcr:readAccessControl

Avatar

Level 10

I am going to try and place notes on these examples that they are just used for examples (to basically reduce code) - to do it properly - you are correct - you should use SLign User Mapping Service. See this Article for details how to do this: 

https://helpx.adobe.com/experience-manager/using/querying-experience-manager-sling.html

Avatar

Level 5

Is there a way to give my service user for example read access to '/content' using the jackrabbit api. My current issue is that this is not working because I am trying to do this in a session where the user of the session is also the same service user. I don't want to manually set permissions for my service user.

Avatar

Level 2

You can deploy rep:policy nodes from your code package - we do it all the time.  You can also see how to do this in GitHub - Adobe-Consulting-Services/acs-aem-commons  where they create a handful of service users and deploy their associated ACLs.

Avatar

Level 5

But don't you overwrite existing policies for example:

Screen Shot 2017-08-24 at 14.58.14.png

Avatar

Level 2

Make sure you test it locally, but I believe the trick is this in the pom.xml

<properties>

  <acHandling>merge_preserve</acHandling>

</properties>

Avatar

Level 1

@Murali89 , could you please suggest the solution for the above situation,

Creating users under a particular path... programmatically

 

Thanks