3 Replies Latest reply on Aug 15, 2011 2:01 PM by mmulligan03

    Using LDAP for authentication & JPA for roles and permissions

    mmulligan03 Newbie

      I am trying to setup the following scenario in my application.
      1. User accounts are stored in an LDAP server, Active Directory to be exact.
      2. Roles and permissions are stored in a relational database.


      Following the SEAM documentation about security (chapter 15) I have tried to specify using both LDAP and JPA but I get the following error.


      
      13:23:48,386 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.core.locale
      13:23:48,386 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.core.locale
      13:23:48,386 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.jms.topicConnection
      13:23:48,386 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.core.manager
      13:23:48,401 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.captcha.captcha
      13:23:48,401 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.core.expressions
      13:23:48,401 INFO  [Initialization] two components with same name, higher precedence wins: org.jboss.seam.security.identityStore
      13:23:48,401 ERROR [[/]] Exception sending context initialized event to listener instance of class org.jboss.seam.servlet.SeamListener
      java.lang.IllegalStateException: Two components with the same name and precedence - component name: org.jboss.seam.security.identityStore, component classes: com.company.CustomLdapIdentityStore, org.jboss.seam.security.management.JpaIdentityStore
              at org.jboss.seam.init.Initialization.addComponentDescriptor(Initialization.java:601)
              at org.jboss.seam.init.Initialization.installScannedComponentAndRoles(Initialization.java:954)
              at org.jboss.seam.init.Initialization.scanForComponents(Initialization.java:894)
              at org.jboss.seam.init.Initialization.init(Initialization.java:706)
              at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:36)
              at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3910)
              at org.apache.catalina.core.StandardContext.start(StandardContext.java:4389)
              at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeployInternal(TomcatDeployment.java:321)
              at org.jboss.web.tomcat.service.deployers.TomcatDeployment.performDeploy(TomcatDeployment.java:145)
              at org.jboss.web.deployers.AbstractWarDeployment.start(AbstractWarDeployment.java:461)
              at org.jboss.web.deployers.WebModule.startModule(WebModule.java:118)
              at org.jboss.web.deployers.WebModule.start(WebModule.java:97)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:157)
              at org.jboss.mx.server.Invocation.dispatch(Invocation.java:96)
              at org.jboss.mx.server.Invocation.invoke(Invocation.java:88)
              at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
              at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:668)
              at org.jboss.system.microcontainer.ServiceProxy.invoke(ServiceProxy.java:206)
              at $Proxy38.start(Unknown Source)
              at org.jboss.system.microcontainer.StartStopLifecycleAction.installAction(StartStopLifecycleAction.java:42)
              at org.jboss.system.microcontainer.StartStopLifecycleAction.installAction(StartStopLifecycleAction.java:37)
              at org.jboss.dependency.plugins.action.SimpleControllerContextAction.simpleInstallAction(SimpleControllerContextAction.java:62)
              at org.jboss.dependency.plugins.action.AccessControllerContextAction.install(AccessControllerContextAction.java:71)
              at org.jboss.dependency.plugins.AbstractControllerContextActions.install(AbstractControllerContextActions.java:51)
              at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348)
              at org.jboss.system.microcontainer.ServiceControllerContext.install(ServiceControllerContext.java:297)
              at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1652)
              at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:938)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1082)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:988)
              at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:826)
              at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:556)
              at org.jboss.system.ServiceController.doChange(ServiceController.java:688)
              at org.jboss.system.ServiceController.start(ServiceController.java:460)
              at org.jboss.system.deployers.ServiceDeployer.start(ServiceDeployer.java:163)
              at org.jboss.system.deployers.ServiceDeployer.deploy(ServiceDeployer.java:99)
              at org.jboss.system.deployers.ServiceDeployer.deploy(ServiceDeployer.java:46)
              at org.jboss.deployers.spi.deployer.helpers.AbstractSimpleRealDeployer.internalDeploy(AbstractSimpleRealDeployer.java:62)
              at org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer.deploy(AbstractRealDeployer.java:55)
              at org.jboss.deployers.plugins.deployers.DeployerWrapper.deploy(DeployerWrapper.java:179)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.doDeploy(DeployersImpl.java:1454)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1172)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1193)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.doInstallParentFirst(DeployersImpl.java:1225)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.install(DeployersImpl.java:1113)
              at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348)
              at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1652)
              at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:938)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1082)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:988)
              at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:826)
              at org.jboss.dependency.plugins.AbstractController.change(AbstractController.java:556)
              at org.jboss.deployers.plugins.deployers.DeployersImpl.process(DeployersImpl.java:789)
              at org.jboss.deployers.plugins.main.MainDeployerImpl.process(MainDeployerImpl.java:699)
              at org.jboss.system.server.profileservice.repository.MainDeployerAdapter.process(MainDeployerAdapter.java:117)
              at org.jboss.system.server.profileservice.repository.ProfileDeployAction.install(ProfileDeployAction.java:70)
              at org.jboss.system.server.profileservice.repository.AbstractProfileAction.install(AbstractProfileAction.java:53)
              at org.jboss.system.server.profileservice.repository.AbstractProfileService.install(AbstractProfileService.java:403)
              at org.jboss.dependency.plugins.AbstractControllerContext.install(AbstractControllerContext.java:348)
              at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:1652)
              at org.jboss.dependency.plugins.AbstractController.incrementState(AbstractController.java:938)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:1082)
              at org.jboss.dependency.plugins.AbstractController.resolveContexts(AbstractController.java:988)
              at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:778)
              at org.jboss.dependency.plugins.AbstractController.install(AbstractController.java:543)
              at org.jboss.system.server.profileservice.repository.AbstractProfileService.registerProfile(AbstractProfileService.java:308)
              at org.jboss.system.server.profileservice.ProfileServiceBootstrap.start(ProfileServiceBootstrap.java:256)
              at org.jboss.bootstrap.AbstractServerImpl.start(AbstractServerImpl.java:461)
              at org.jboss.Main.boot(Main.java:221)
              at org.jboss.Main$1.run(Main.java:556)
              at java.lang.Thread.run(Thread.java:619)
      
      



      Here is how I have this configured in my components.xml:



      <security:identity 
          class="com.company.user.identity.UserIdentity"  /> 
                                              
      <security:identity-manager name="identityManager" 
          identity-store="#{ldapIdentityStore}" />
                  
      <security:identity-manager 
          identity-store="#{ldapIdentityStore}" 
          role-identity-store="#{jpaIdentityStore}" />
                  
      <security:ldap-identity-store
          name="customLdapIdentityStore"
          class="com.company.CustomLdapIdentityStore"
          server-address="ad.company.corp"
          bind-DN="user@company.corp"
          bind-credentials="User_password"
          user-DN-prefix=""
          user-DN-suffix="company.corp"
          role-DN-prefix="cn="
          role-DN-suffix=",dc=company,dc=corp"
          user-context-DN="dc=company,dc=corp"
          role-context-DN="dc=company,dc=corp"
          user-name-attribute="sAMAccountName"
          user-role-attribute="memberOf"
          role-name-attribute="cn"
          user-password-attribute="userPassword"
          user-object-classes="User"
          first-name-attribute="givenName"
          last-name-attribute="sn" />
      
      <security:jpa-permission-store  
          user-permission-class="com.company.user.business.model.Permissions" />
      
      <security:jpa-identity-store
          user-class="com.company.user.business.model.User"
          role-class="com.company.user.business.model.Role" />




      Things to note, (things I know work):
      1. The custom identity class works without problem.
      2. The CustomLdapIdentityStore works when authenticating against my active directory server.  The class extends the LdapIdentityStore and fixes a problem for active directory authentication.
      3. I got the same error before I wrote my custom class to work with active directory.


      Am I missing something in my configuration?

        • 1. Re: Using LDAP for authentication & JPA for roles and permissions
          Martin Frey Newbie

          Hi


          The problem is that you have two identitysotres with the same compnent names active. I cannot tell you if its going to work with this config but you can try to give each store a specific name. Jpa and an ldapidentitystore.


          I would be interested if you succeed with that. We use currently no identitystores and implemented our own ldap provider and handle the rules completely on our own together with drools.


          Greetings
          Martin

          • 2. Re: Using LDAP for authentication & JPA for roles and permissions
            mmulligan03 Newbie

            Are you referring to the fact that I have security:identity-manager twice in my components.xml?


            I removed the first identity manager entry and changed my components.xml to read


            <security:identity 
                class="com.company.user.identity.UserIdentity"  />
                    
            <security:identity-manager name="identityManager" 
                identity-store="#{ldapIdentityStore}" 
                role-identity-store="#{jpaIdentityStore}" />
                
            <security:ldap-identity-store
                class="com.company.CustomLdapIdentityStore" />
            
            <security:jpa-permission-store  
                user-permission-class="com.company.user.business.model.Permissions" />
            
            <security:jpa-identity-store
                name="jpaIdentityStore"
                user-class="com.company.user.business.model.User"
                role-class="com.company.user.business.model.Role" />
            
            



            This works, but its not loading my roles. Not even hitting the database. 


            I removed the configuration from the ldap identity store because my custom class wasn't loading it. Does anyone know how to have my custom class use this configuration instead of having to hard code it into the class itself?


            The reason I'm trying it this way is because in the seam documentation it states to use both ldap and jpa all that is needed is to specify the role-identity-store but that seems to not be the case. Is anyone using both Ldap and Jpa for their application?


            • 3. Re: Using LDAP for authentication & JPA for roles and permissions
              mmulligan03 Newbie

              I've gotten it to use both my LDAP configuration and my JPA configuration but when I try to query the database my entitiy manager is null...



              Here is what I did.


              my components.xml


              <security:identity 
                  class="com.company.user.identity.UserIdentity"  />
                              
              <security:identity-manager 
                  identity-store="#{customLdapIdentityStore}" 
                  role-identity-store="#{customJpaIdentityStore}" />
                          
              <security:ldap-identity-store
                  class="com.company.CustomLdapIdentityStore"
                  name="customLdapIdentityStore"
                  server-address="128.1.200.1"
                  bind-DN="mmulligan@company.corp"
                  bind-credentials=""
                  user-DN-prefix=""
                  user-DN-suffix="mainoffice.company.corp"
                  role-DN-prefix="CN="
                  role-DN-suffix=",dc=company,dc=corp"
                  user-context-DN="DC=company,DC=corp"
                  role-context-DN="DC=company,DC=corp"
                  user-name-attribute="sAMAccountName"
                  user-role-attribute="memberOf"
                  role-name-attribute="CN"
                  user-password-attribute="userPassword"
                  user-object-classes="User"
                  first-name-attribute="givenName"
                  last-name-attribute="sn" />
              
              <security:jpa-permission-store  
                  user-permission-class="com.company.user.business.model.UserPermissions" />
              
              <security:jpa-identity-store
                  class="com.company.CustomJpaIdentityStore"
                  name="customJpaIdentityStore"
                  user-class="com.company.user.business.model.User"
                  role-class="com.company.user.business.model.Role" />



              My custom LDAP authentication:




              @Name("customLdapIdentityStore")
              @Startup
              @AutoCreate
              @Install(precedence = BUILT_IN, value = false)
              @Scope(ScopeType.APPLICATION)
              @BypassInterceptors
              public class CustomLdapIdentityStore extends org.jboss.seam.security.management.LdapIdentityStore {
              
                   /**
                    * 
                    */
                   private static final long serialVersionUID = 2847257857074353708L;
              
                   public boolean authenticate() {
                        return this.authenticate(Identity.instance().getCredentials().getUsername(), Identity.instance()
                                  .getCredentials().getPassword());
                   }
              
                   @Override
                   protected String getUserDN(String username) {
                        return String.format("%s%s%s", getUserDNPrefix(), username, "@" + getUserDNSuffix());
                   }
              }



              The only real reason for this was to allow Active directory authentication.  The use of the @ symbol on the configuration is not allowed.


              My JPA identity store.




              @Name("customJpaIdentityStore")
              @Startup
              @AutoCreate
              @Install(precedence = BUILT_IN, value = false)
              @Scope(ScopeType.APPLICATION)
              @BypassInterceptors
              public class CustomJpaIdentityStore extends org.jboss.seam.security.management.JpaIdentityStore {
              
                   /**
                    * 
                    */
                   private static final long serialVersionUID = -5735032540820393723L;
                   private Object userEnabledProperty;
              
                   @Create
                   @Override
                   public void init() {
                        super.init();
                        return;
                   }
              
                   @Override
                   public boolean authenticate(String username, String password) {
                        Object user = lookupUser(username);
                        if(user != null)
                             return true;
                        return false;
                   }
              
                   public Object lookupUser(String username) {
                        try {
                             System.out.println("Username: " + username);
                             EntityManager em = ((EntityManager)getEntityManager().getValue());
                             if(em == null){
                                  System.out.println("WTF!!!!");
                             }
                             User user = (User) em.createQuery(
                                  "select u from " + getUserClass().getName() + " u where u.username = :user").setParameter("user", username).getSingleResult();
              
                             return user;
                        } catch (NoResultException ex) {
                             return null;
                        }
                   }
              }
              



              Which gets executed but the entity manager is always null... does anyone know why or a way around using the ValueExpression?