Search code examples
aemjcr

AEM Workflow: Get session of the initiator to check permissions


To check the permissions of the initiator you can call session.checkPermission()

However, com.day.cq.workflow.WorkflowSession.getSession() returns always the admin session so I'm not able to check the initator's permissions on a given node.

How can I get the session of the initator?

Update

Authorizable authorizable = userManager.getAuthorizable(initiator);
Credentials credentials = ((User) authorizable).getCredentials(); 
Session userSession = adminSession.impersonate(credentials);`

Throws:

javax.jcr.LoginException: Login Failure: all modules ignored
at org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl.login(RepositoryImpl.java:271)
at com.adobe.granite.repository.impl.CRX3RepositoryImpl.login(CRX3RepositoryImpl.java:92)
at org.apache.jackrabbit.oak.jcr.repository.RepositoryImpl.login(RepositoryImpl.java:202)
at org.apache.jackrabbit.oak.jcr.session.SessionImpl.impersonate(SessionImpl.java:284)
Caused by: javax.security.auth.login.LoginException: Login Failure: all modules ignored
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:906)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
... 15 common frames omitted`

Solution

  • First, as @CptBartender mentioned in the comments, the admin should have rights to all content or if you're taking advantage of the Service Accounts, that service account should have access to the content that it needs to update.

    The initiator is always admin or workflow-service in newer AEM versions that use Sling service accounts. The user requests the start of the workflow and the admin or service account runs the process. If you want to find the user who kicked off the workflow you can look in the meta data with item.getWorkflowData().getMetaDataMap().get("userId", String.class). Notice that data matches the resources created in the JCR at a path similar to /etc/workflow/instances/server0/2016-06-13/update_asset_2/data/metaData. Furthermore, you can get the participant of individual workflow process steps by getting the HistoryItem and then the userId.

    With the initiator determined, you should be able to impersonate with something such as:

    @Component
    @Service
    @Properties({
        @Property(name = Constants.SERVICE_DESCRIPTION, value = "Workflow step description"),
        @Property(name = Constants.SERVICE_VENDOR, value = "Company Name"),
        @Property(name = "process.label", value = "Process Label will show in the workflow dropdown") })
    public class MyCustomStep implements WorkflowProcess {
    
        public void execute(WorkItem item, WorkflowSession wfsession, MetaDataMap args) throws WorkflowException {
    
            /* Always admin or service-workflow */
            final String initiator = item.getWorkflow().getInitiator();
    
            /* Get actual user who initiated workflow */
            final String initiator = item.getWorkflowData().getMetaDataMap().get("userId", String.class);
    
            /* Get workflow history */
            final List<HistoryItem> histories = wfsession.getHistory(item.getWorkflow());
    
            /* Get first item in workflow history */
            final HistoryItem firstItem = histories.get(0);
    
            /* Get the user that participated in the last item */
            final String firstUser = firstItem.getUserId();
    
            /* Get impersonated session */
            try {
                Session userSession = wfsession.getSession().impersonate(new SimpleCredentials(initiator,new char[0]));
            } catch (javax.jcr.LoginException e) {
                e.printStackTrace();
            } catch (RepositoryException e) {
                e.printStackTrace();
            }
        }
    }