Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
Bedrock Mission!

Learn more

View all

Sign in to view all badges

Adobe Summit 2023 [19th to 23rd March, Las Vegas and Virtual] | Complete AEM Session & Lab list
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();
0 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 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