3 Replies Latest reply on May 1, 2014 9:52 AM by rhauch

    custom authentication, when I can access my updated security context, maybe I'm confused

    mike.conway

      OK, I've got a custom authentication..

      public class IrodsAuthenticationProvider implements AuthenticationProvider {
      ...
      @Override
        public ExecutionContext authenticate(Credentials credentials,
        String repositoryName, String workspaceName,
        ExecutionContext repositoryContext,
        Map<String, Object> sessionAttributes) {
        log.info("authenticate()");
        // FIXME: of course remove this!
        log.info("credentials:{}", credentials);
        IRODSAccount irodsAccount = null;
        if (credentials instanceof SimpleCredentials) {
        SimpleCredentials simpleCredentials = (SimpleCredentials) credentials;
        log.info("simple credential");
        try {
        irodsAccount = IRODSAccount.instance(host, port,
        simpleCredentials.getUserID(), new String(
        simpleCredentials.getPassword()), "", zone, "");
        } catch (JargonException e) {
        log.error("unable to create irodsAccount", e);
        throw new JargonRuntimeException(e);
        }
        } else if (credentials instanceof GuestCredentials) {
        log.info("guest credentials");
        try {
        irodsAccount = IRODSAccount.instanceForAnonymous(host, port,
        "", zone, "");
        } catch (JargonException e) {
        log.error("unable to create irodsAccount", e);
        throw new JargonRuntimeException(e);
        }
        } else {
        throw new JargonRuntimeException("unknown credentials type");
        }
        try {
        log.info("authenticate....");
        IRODSFileSystemSingletonWrapper.instance()
        .getIRODSAccessObjectFactory()
        .authenticateIRODSAccount(irodsAccount);
        IrodsSecurityContext irodsSecurityContext = new IrodsSecurityContext(
        irodsAccount);
        return repositoryContext.with(irodsSecurityContext);
        } catch (AuthenticationException ae) {
        log.error("authentication exception", ae);
        return null;
        } catch (JargonException e) {
        log.error("general JargonException during authentication", e);
        throw new JargonRuntimeException(
        "general exception during authentication");
        }
        }
      ...

       

      As you can see, on successful authentication, I attempt to augment my context with my new 'irodsSecurityContext'

       

      Fair enough...this is called by ModeShape, and seems to work.

       

      The question here is, when is this called?  I need to access the stored security context in order to do a login to the back end iRODS grid, which I do by mapping the user/password to an iRODS account.  Therefore, I add code like this in my connector:

       

       

      protected File fileFor(String id, final boolean closeInFinally) {
      log.info("fileFor()");
      log.info("id:{}", id);

       

      ...yadda...

       

      try {
      return (File) IRODSFileSystemSingletonWrapper.instance()
      .getIRODSAccessObjectFactory()
      .getIRODSFileFactory(getIrodsAccount())
      .instanceIRODSFile(directoryPathWithTrailingSlash, id);

       

       

       

       

       

       

      This getIrodsAccount() simply tries to do this:

       

      private IRODSAccount getIrodsAccount() {

       

        if (this.getContext().getSecurityContext() instanceof IrodsSecurityContext) {

             IrodsSecurityContext irodsContext = (IrodsSecurityContext) this

             .getContext().getSecurityContext();

       

             return irodsContext.getIrodsAccount();

       

       

       

       

       

       

      And here it fails because what I get is a NullSecurityContext, and the login() seems to be called after my fileFor() call where I try to derive the iRODS account.

       

       

       

      So timing?

       

       

      I do note that the unit tests seem to fire up the repository and run the initialize() method, and at that point attempt to log into iRODS, apparently it is trying to resolve the configured projection.  So that's a bit of a chicken-and-egg problem...it wants to connect before I've authenticated.  My immediate reaction is that I might need a proxy account to handle the init, which seems kludgy.

       

      I also noted, in JcrRepository, a somewhat cryptic allowAutoStartDuringLogin member variable, and wondered if there was any way to rectify this through some alternative configuration?

       

      Hope that question makes sense.  Our connector is basically working, and we're moving from hard-coded auth to this actual pluggable auth model

       

      we're hacking away on the development branch here: DICE-UNC/jargon-modeshape at development · GitHub

       

      Cheers

      MC

        • 1. Re: custom authentication, when I can access my updated security context, maybe I'm confused
          rhauch

          The "authenticate" method is only called when logging into a repository to get a Session. No user authentication is ever used during repository startup or initialization, which includes establishing any connections used in projections.

           

          When a repository starts up, it creates an internal ExecutionContext that is then passed around to lots of components. Yes, an ExecutionContext has a slot for a user-specific SecurityContext, but the repository's ExecutionContext doesn't have a SecurityContext. Note that once the repository's ExecutionContext is created, it is kept by the repository (and other components inside the repository) forever.

           

          The repository initializes the connectors upon repository startup, and the connectors are handed the repository's ExecutionContext; that context object will never change on the connector. Once a connector is initialed, it will operate outside the bounds of any session-specific information. Really, it operates much like the lower half of ModeShape, like the workspace caches, which simply access and cache the persisted content.

           

          Can you explain what you trying to accomplish? Are you trying to have the connector know something about the sessions that are accessing content? Recall that the connectors can be configured to cache information; if so, then external nodes loaded by a connector for session1 might be cached and accessed by session2 without the connector knowing.

          • 2. Re: custom authentication, when I can access my updated security context, maybe I'm confused
            mike.conway

            Hi Randall, this is all occurring in the context of JUnit tests

             

            unit test 'startup' code is as follows

             

             

             

             

            engine = new ModeShapeEngine();

              engine.start();

              RepositoryConfiguration config = RepositoryConfiguration

              .read("conf/testConfigAuth1.json");

             

             

              // Verify the configuration for the repository ...

              org.modeshape.common.collection.Problems problems = config.validate();

              if (problems.hasErrors()) {

              System.err.println("Problems starting the engine.");

              System.err.println(problems);

              System.exit(-1);

              }

             

             

              javax.jcr.Repository repo = engine.deploy(config);

             

             

              String repositoryName = config.getName();

              log.info("repo name:{}", repositoryName);

              IRODSAccount irodsAccount = testingPropertiesHelper

              .buildIRODSAccountFromTestProperties(testingProperties);

              SimpleCredentials simpleCredentials = new SimpleCredentials(

              irodsAccount.getUserName(), irodsAccount.getPassword()

              .toCharArray());

             

             

              session = repo.login(simpleCredentials, "default");

             

             

             

             

            This attempts to grab a session via our authenticator using a test IRODSAccount.  This is the first thing that runs, and the issue seems to occur in startup

             

             

            At the point of repo.login..

             

             

             

             

            JcrRepository.login() method called

             

             

             

             

            here are the logs at this point

             

             

             

             

            164209 [main] DEBUG org.modeshape.jcr.JcrRepository  - Starting 'irodsRepo' repository with configuration:

            { "name" : "irodsRepo" , "workspaces" : { "predefined" : [ "otherWorkspace" ] , "default" : "default" , "allowCreation" : true } , "security" : { "anonymous" : { "roles" : [ "readonly" , "readwrite" , "admin" ] , "useOnFailedLogin" : false } , "providers" : [ { "name" : "iRODS custom provided" , "classname" : "org.irods.jargon.modeshape.connector.IrodsAuthenticationProvider" } ] } , "storage" : { "cacheConfiguration" : "conf/infinispan.xml" , "cacheName" : "persistentRepository" , "binaryStorage" : { "type" : "file" , "directory" : "target/federation_repository/binaries" , "minimumBinarySizeInBytes" : 0 } } , "externalSources" : { "irods" : { "classname" : "org.irods.jargon.modeshape.connector.IRODSWriteableConnector" , "directoryPath" : "/test1/home/test1" , "projections" : [ "default:/irodsGrid => /" ] , "readOnly" : false , "addMimeTypeMixin" : false , "cacheTtlSeconds" : 0 , "exclusionPattern" : ".+[.]tmp$" } } , "query" : { "enabled" : false , "rebuildUponStartup" : "never" } , "node-types" : [ "conf/irods.cnd" ] }

            166939 [main] DEBUG org.modeshape.jcr.LocalEnvironment  - Starting cache manager using configuration at 'conf/infinispan.xml'

            170477 [main] WARN  org.modeshape.jcr.RepositoryConfiguration  - The field readOnly is not present on org.irods.jargon.modeshape.connector.IRODSWriteableConnector or any of its super types

            170508 [main] DEBUG org.modeshape.jcr.JcrRepository  - Loading cache 'persistentRepository' from cache container org.infinispan.manager.DefaultCacheManager@61ae717f@Address:null

            170555 [main] INFO  org.infinispan.factories.GlobalComponentRegistry  - ISPN000128: Infinispan version: Infinispan 'Delirium' 5.2.7.Final

            171021 [main] WARN  org.infinispan.transaction.lookup.GenericTransactionManagerLookup  - ISPN000104: Falling back to DummyTransactionManager from Infinispan

            173594 [main] INFO  org.infinispan.jmx.CacheJmxRegistration  - ISPN000031: MBeans were successfully registered to the platform MBean server.

            174033 [main] DEBUG org.modeshape.common.util.StringURLClassLoader  - org.modeshape.extractor.tika is not a valid url

            176264 [main] DEBUG org.modeshape.jcr.mimetype.TikaMimeTypeDetector  - Initializing the Tika MIME type detectors

            176265 [main] DEBUG org.modeshape.jcr.mimetype.TikaMimeTypeDetector  -  - Found detector: org.gagravarr.tika.OggDetector

            176265 [main] DEBUG org.modeshape.jcr.mimetype.TikaMimeTypeDetector  -  - Found detector: org.apache.tika.parser.microsoft.POIFSContainerDetector

            176265 [main] DEBUG org.modeshape.jcr.mimetype.TikaMimeTypeDetector  -  - Found detector: org.apache.tika.parser.pkg.ZipContainerDetector

            176265 [main] DEBUG org.modeshape.jcr.mimetype.TikaMimeTypeDetector  -  - Found detector: org.apache.tika.mime.MimeTypes

            176335 [main] DEBUG org.modeshape.jcr.LocalEnvironment  - Starting cache manager using configuration at 'org/modeshape/jcr/default-workspace-cache-config.xml'

            177158 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - Initializing the 'irodsRepo' repository

            177799 [main] INFO  org.infinispan.jmx.CacheJmxRegistration  - ISPN000031: MBeans were successfully registered to the platform MBean server.

            177962 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - System root: Node 9db8771317f1e7/: { "properties" : { "http://www.jcp.org/jcr/1.0" : { "primaryType" : { "$name" : "mode:root" } , "uuid" : "9db8771317f1e7/" } } }

            177972 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - jcr:system child reference: null

            177972 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - System node: null

            177973 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - Creating the 'system' workspace in repository 'irodsRepo'

            177985 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            178073 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 15 node(s)

            179877 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            184257 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 186 node(s)

            184358 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            184362 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 1 node(s)

            184388 [main] WARN  org.modeshape.jcr.RepositoryConfiguration  - The field name is not present on org.irods.jargon.modeshape.connector.IrodsAuthenticationProvider or any of its super types

            184406 [main] DEBUG org.modeshape.jcr.JcrRepository  - Enabling anonymous authentication and authorization.

            184668 [main] DEBUG org.modeshape.jcr.JcrRepository  - Queries have been DISABLED for the 'irodsRepo' repository. Nothing will be indexed, and all queries will return empty results.

            184669 [main] DEBUG org.modeshape.jcr.JcrRepository  - No JNDI found, so not registering 'irodsRepo' repository

            186726 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            186740 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 2 node(s)

            186768 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            186861 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 7 node(s)

            187221 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            187226 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 1 node(s)

            187230 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            187237 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 2 node(s)

            187431 [main] INFO  org.infinispan.jmx.CacheJmxRegistration  - ISPN000031: MBeans were successfully registered to the platform MBean server.

            187433 [main] DEBUG org.modeshape.jcr.cache.RepositoryCache  - Creating 'default' workspace in repository 'irodsRepo'

            187446 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Locking nodes in Infinispan

            187451 [main] DEBUG org.modeshape.jcr.cache.document.WritableSessionCache  - Altered 2 node(s)

            187523 [main] INFO  org.irods.jargon.modeshape.connector.IRODSWriteableConnector  - getting documentMapper

            187523 [main] INFO  org.irods.jargon.modeshape.connector.IRODSWriteableConnector  - initialized

            187565 [main] INFO  org.irods.jargon.modeshape.connector.IRODSWriteableConnector  - fileFor()

            187565 [main] INFO  org.irods.jargon.modeshape.connector.IRODSWriteableConnector  - id:/

             

             

             

             

             

             

             

             

             

             

             

             

            I note the curious message 184388 [main] WARN  org.modeshape.jcr.RepositoryConfiguration  - The field name is not present on org.irods.jargon.modeshape.connector.IrodsAuthenticationProvider or any of its super types.  I will dig into this further.

             

             

             

             

            Note that the initialize() method of my connector is called, and fileFor() has been called in my class, which seems to have been called by   FederatedDocumentStore.getExternalProjection() via the getDocumentId() method of my connector.  That fileFor() method is where I am trying to extract out my IRODS credentials from the security context, yet my authenticate provider has not yet been called.

             

             

            At this point, the IRODSWriteableConnector has a security context of org.modeshape.jcr.ExecutionContext$NullSecurityContext@3236d036

             

             

            Prior to this run, I had a kludge in my code where, encountering a NullSecurityContext, I would plug in a hard coded account, and what I found was that the IrodsAuthenticationProvider was being called after this initial start up sequence

             

            I may just be confused, but it does look like Modeshape is trying to access iRODS before the IrodsAuthenticationProvider has provisioned the security context

             

            FWIW the unit test is here, around line 101

             

            https://github.com/DICE-UNC/jargon-modeshape/blob/development/jargon-modeshape/irods-connector/src/test/java/org/irods/jargon/modeshape/connector/IRODSWriteableConnectorRepoTest.java

             

            and the connector is here, with my fileFor being called during initialization around line 250

             

            https://github.com/DICE-UNC/jargon-modeshape/blob/development/jargon-modeshape/irods-connector/src/test/java/org/irods/jargon/modeshape/connector/IRODSWriteableConnectorRepoTest.java

             

            You would find the authentication provider in that same package, but it seems like the provider (not being called yet) isn't at issue.

             

            The json config I'm using is here

             

            https://github.com/DICE-UNC/jargon-modeshape/blob/development/jargon-modeshape/irods-connector/src/test/resources/conf/testConfigAuth1.json

             

            I'm sure some of the above is still a bit naive, but I think indeed there's a sequencing issue?

             

            Cheers

            Mike C

            • 3. Re: custom authentication, when I can access my updated security context, maybe I'm confused
              rhauch

              I'm still not convinced that there is an ordering issue, because a connector's ExecutionContext should never be changed from the initial context (with null security context) it receives during repository initialization. As I tried to explain in my previous post, we didn't design the connector framework to know the sessions on behalf of which it is doing normal work, because the result of that work is accessible from that session and others.

               

              You can certainly make your connector use an iRODS account and use that for all of its work. Really, this would be akin to an application (e.g., like our repository) that allows users to log in (e.g., like our sessions) but which actually uses a database connection with application-specific credentials (e.g., your connector's iROD account).