Announcement Announcement Module
Collapse
No announcement yet.
Active Directory Authentication: UserDN? Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Active Directory Authentication: UserDN?

    Using Spring Security 3.0.2 The Reference guide reads:

    Active Directory Authentication
    In addition to standard LDAP authentication (binding with a DN), Active Directory has its own non-standard syntax for user authentication.
    But makes no note of how to implement this. I need to bind to AD using the sAMAccountName, which is usually done either via domain\sAMAccountName or sAMAccountName@domain.

    The problem with the ldap-authentication-provider is that the syntax parser will not parse either format. A search of the forum produced a number of similar questions, but none that had what I could tell was a concise example using the current framework.

    Does anyone know how to do this? Am I missing something obvious?

    Thanks in advance for any/all replies and to all readers of this thread.

  • #2
    Why not just "(sAMAccountName={0})" as the user search criteria - or are you expecting that they won't have to put the domain in when they authenticate (and thus you are trying to somehow encode the domain in the search expression)?

    Comment


    • #3
      I've started to reply to this thread a couple of times and found it difficult to express my problem, mostly because I think my LDAP knowledge is a bit on the weak side.

      Here is my current ldapAuthenticator bean(s):
      Code:
      	<beans:bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
      		<beans:constructor-arg ref="contextSource" />
      		<beans:property name="userDnPatterns">
      			<beans:list>
      				<beans:value>sAMAccountName={0}</beans:value>
      			</beans:list>
      		</beans:property>
      	</beans:bean>
      	
      	<beans:bean id="contextSource" 
      			class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
           <beans:constructor-arg value="ldap://mycompany:389/DC=mycompany,DC=subdomain,DC=corp"/>
      	</beans:bean>
      When I try to login without the domain in the user name form Example username = sAMAccountName, I simply get an authentication Bad Credentials error. If I try the domain name in the user id field like domain\username I get:
      Code:
      Reason: Failed to parse DN; nested exception is org.springframework.ldap.core.TokenMgrError: Lexical error at line 1, column 19. Encountered: "\\" (92), after : ""
      If I try domain\\user I get the same invalid bad credientials message.

      My preference would be to not have to have the user enter the domain name in the user id field as it is not something they would understand. The current implementation that authenticates against LDAP doesn't require that.

      Should I be using a user search instead of a userDNPattern?

      Comment


      • #4
        Stymied

        So, trying another direction, I tried to remove the userDNPattern and just use a userSearch. I changed my configuration to:
        Code:
        	<beans:bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
        		<beans:constructor-arg ref="contextSource" />
        		<beans:property name="userSearch" ref="userSearch"/>
        	</beans:bean>
        
        	<beans:bean id="userSearch"
        			class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
        		<beans:constructor-arg>
        			<beans:value>DC=domain,DC=subdomain,DC=corp</beans:value>
        		</beans:constructor-arg>
        		<beans:constructor-arg>
        			<beans:value>(sAMAccountName={0})</beans:value>
        		</beans:constructor-arg>
        		<beans:constructor-arg ref="contextSource" />
        		<beans:property name="searchSubtree">
        			<beans:value>true</beans:value>
        		</beans:property>
        	</beans:bean>
        Now I am getting an error that basically I think is telling me that I can't perform this user search becuase anonymous user searches are not allowed.

        Reason: Uncategorized exception occured during LDAP processing; nested exception is javax.naming.
        NamingException: [LDAP: error code 1 - 00000000: LdapErr: DSID-0C090627,
        comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece];
        remaining name 'DC=domain,DC=subdomain,DC=corp'
        Is this the case, or could I simply have the searchBase incorrect?
        What puzzles me about the existing implementation is that I can't see how what I am trying to do is different.

        In the existing implementation, the code basically does a JNDI lookup of the user account using a search:

        Look up the context:
        Code:
        		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        		env.put(Context.PROVIDER_URL, getURL());
        		env.put(Context.SECURITY_AUTHENTICATION, securityAuthenticationType);
        		env.put(Context.SECURITY_PRINCIPAL, "domain\\" + getUsername());
        		env.put(Context.SECURITY_CREDENTIALS, getPassword());
        Perform the search:
        Code:
        // Filter = "(sAMAccountName=" + username + ")"
        			ctx = new InitialDirContext(env);
        			results = ctx.search(ldapSearch.getDn()
        					           , ldapSearch.getFilter()
        					           , ldapSearch.getControls());
        Thanks in advance for any replies!

        Comment


        • #5
          Resolved

          Ok, so my problem was two fold -- I'm posting this for anyone else that may be looking for why they can't get this to work for them.

          1) The AD server configuration in my scenario does not allow a user search for an unauthenticated user. In order to execute my user search I had to request that the AD admin create a service account for my application to bind to.

          2) Don't append the baseDN to the baseDN (first argument of the constructor) for FilterBasedLdapUserSearch.

          Here's the working configuration:
          Code:
          	<beans:bean id="bindAuthenticator" class="org.springframework.security.ldap.authentication.BindAuthenticator">
          		<beans:constructor-arg ref="contextSource" />
          		<beans:property name="userSearch" ref="userSearch"/>
          	</beans:bean>
          
          	<beans:bean id="userSearch"
          			class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
          		<beans:constructor-arg>
          			<beans:value></beans:value>
          		</beans:constructor-arg>
          		<beans:constructor-arg>
          			<beans:value>(sAMAccountName={0})</beans:value>
          		</beans:constructor-arg>
          		<beans:constructor-arg ref="contextSource" />
          		<beans:property name="searchSubtree">
          			<beans:value>true</beans:value>
          		</beans:property>
          	</beans:bean>
          	
          	
          	<beans:bean id="contextSource" 
          			class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
               <beans:constructor-arg value="ldap://myldap:389/DC=domain,DC=subdomain,DC=com"/>
               <beans:property name="userDn" value="CN=myUserAccount,OU=Users,DC=domain,DC=subdomian,DC=com"/>
               <beans:property name="password" value="password"/>
          IMHO, the fact that the userDNPattern doesn't work with a domain\userAccount seems like something that should.

          Thanks to those who read and helped.

          Comment


          • #6
            Congratulations on figuring it out - sounds like it was an interesting problem for you to solve!

            Comment

            Working...
            X