Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
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