Question

I am trying to incorporate Modeshape into a Spring application where authentication has already occurred on login, prior to connecting to a JCR repository. This is working, in that I can get a reference using

session = repository.login();

However this appears to be bypassing the custom authenticationProvider I want to for workspace level access control (docs section 6.5). Here's my config:

<configuration xmlns:...>

<mode:repositories>
    <mode:repository jcr:name="my_repo" mode:source="my_source">

       <mode:authenticationProviders>
           <mode:authenticationProvider
                       jcr:name="customAuthProvider" 
                 mode:classname="com.myapp.CustomSecurityContext" /> 
       </mode:authenticationProviders>

   </mode:repository>
</mode:repositories>

<mode:sources jcr:primaryType="nt:unstructured">
     <mode:source jcr:name="my_source" ....
     </mode:sources>
</configuration>

The CustomSecurityContext is never instantiated (there are spring annotations but the (POJO) constructor never gets called. Any ideas what could be wrong?

@Configurable (preConstruction = true)
public class CustomSecurityContext implements SecurityContext, AuthorizationProvider {

    @Autowired
    private ServletCredentials servletCredentials;

    @Autowired
    CustomUserDetailsManager userDetailsManager;

    @Autowired
    WorkspaceRole workspaceRole;

    private static final Logger log = LogUtil.getLogger();

    public CustomSecurityContext () {
        System.out.println(" ******** THIS NEVER GETS CALLED ********");
    }

    @Override
    public String getUserName() {
        HttpServletRequest request = servletCredentials.getRequest();

        if (request != null) {
            return request.getUserPrincipal().getName();
        }

        log.warn("HttpServletRequest is null, defaulting to getUserName() = null");
        return null;
    }

    @Override
    public boolean hasRole(String roleName) {

        int idUser = userDetailsManager.getIdUser();

        if (idUser == userDetailsManager.getSystemUserID()) {
            // The system itself can work with all workspaces
            return true;
        }

        if (roleName == null) {
            log.warn("roleName is null when calling hasRole, returning false");
            return false;
        }

        return workspaceRole.hasRole(idUser, roleName);
    }

    @Override
    public void logout() {
        log.debug("Calling logout"); // Not applicable as the session credentials are managed by Spring.

    }

    @Override
    public boolean hasPermission(ExecutionContext context, String repositoryName, String repositorySourceName, String workspaceName, Path path, String... actions) {

        log.info("Checking hasPermission for repository '" + repositoryName + "', workspace '" + workspaceName + ", path: '" + path);

        if (actions != null) {
            for (String action : actions) {
                log.info("Action : " + action);
            }
        }
        return true;  // TODO:...
    }
}
Was it helpful?

Solution

I ran with your configuration (or at least this configuration in our test cases with the <mode:authenticationProviders> fragment), and debugged the code (version 2.8.0.Final) and saw that ModeShape does try to instantiate the class. If instantiation fails for whatever reason (the code literally tries to catch all Throwables), then ModeShape will write an error message to the log:

Unable to initialize authentication provider "com.myapp.CustomSecurityContext" for repository "my_repo": <whatever the reason is>

Are you not seeing this? If not, check that the logs are being written properly. Also, feel free to contact us in our discussion forums to get assistance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top