Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Curious about chaining authentication providers

Hybrid View

  1. #1

    Default Curious about chaining authentication providers

    I'm wondering if you could chain the providers together so if the username isn't found in the first provider, it would look in the second provider and so on before it throws a bad credentials exception.

    For example. I have a ldap provider that does 99% of the authentication, but I would like to be able to add users to the app without adding them to ldap in certain instances (using the inMemoryDaoImpl). Is there a simple way of doing this, loosely coupled, so the other providers don't know about each other?
    PJ

  2. #2
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    Yes, it surely does. Basically your competing AuthenticationProviders should each return true to the support(Class) method, but can return null OR a valid Authentication when authenticate(Authentication) is called. If they return null, the next supporting AuthenticationProvider will be tried.

    See the JavaDocs for AuthenticationProvider.authenticate(Authentication ) for more details.

  3. #3

    Default

    sounds great, thanks, i'll give it a shot.
    PJ

  4. #4

    Default

    Quote Originally Posted by Ben Alex
    Yes, it surely does. Basically your competing AuthenticationProviders should each return true to the support(Class) method, but can return null OR a valid Authentication when authenticate(Authentication) is called. If they return null, the next supporting AuthenticationProvider will be tried.

    See the JavaDocs for AuthenticationProvider.authenticate(Authentication ) for more details.
    I'm kinda stratching my head how you return null from provider.authenticate(authentication) without throwing a null-pointer exception?
    PJ

  5. #5
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    See CasAuthenticationProvider, where it only authenticates requests containing a CAS_STATEFUL/STATELESS_IDENTIFIER:

    Code:
            if (!supports(authentication.getClass())) {
                return null;
            }
    
            if (authentication instanceof UsernamePasswordAuthenticationToken
                && (!CasProcessingFilter.CAS_STATEFUL_IDENTIFIER.equals(
                    authentication.getPrincipal().toString())
                && !CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(
                    authentication.getPrincipal().toString()))) {
                // UsernamePasswordAuthenticationToken not CAS related
                return null;
            }
    If all the AuthenticationProviders do not support a given Authentication, or return null to it, the ProviderManager will throw a ProviderNotFoundException back to the class that called the AuthenticationManager. Thus the calling class never needs to worry about receiving a NullPointerException.

  6. #6
    Join Date
    Dec 2004
    Posts
    3

    Default chaining the same type Provider

    What was discussed above is for chaining different types of AuthenticationProvider, how about chaining the same type of AuthenticationProvider?

  7. #7
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    You can chain the same AuthenticationProvider class (but different beans) if you like. Returning null will simply cause the next bean to be polled, until finally one returns a populated Authentication.

    None of the Acegi Security AuthenticationProviders are designed to have multiple instances of the same class polled by the same ProviderManager. So you'd need to write your own AuthenticationProvider to do this.

    If you say had two databases containing your users, your better approach would be to write a ProviderAuthenticationDao. It would accept a list of AuthenticationDaos. As each returned UsernameNotFoundException, the next would be polled. That would probably be a cleaner approach to this sort of requirement.

  8. #8
    Join Date
    Feb 2005
    Location
    Bangalore
    Posts
    1

    Default Chaining authentication providers

    I have started exploring the Acegi framework since yesterday. I am really excited with being able to use such a powerful framework with such little effort. I am planning to chain a series of authentication providers using the ProviderManager bean.

    Something like this:
    Code:
     <bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
        <property name="providers">
          <list>
            <ref bean="XxxDaoAuthenticationProvider"/> 
            <ref bean="YyyDaoAuthenticationProvider"/>
          </list>
        </property>
      </bean>
    The default net.sf.acegisecurity.providers.dao.DaoAuthenticati onProvider implementation suits my purpose.

    But this is where I am getting stuck. Chaining is not happenning if I throw a UsernameNotFoundException in the AuthenticationDao wired to XxxDaoAuthenticationManager. Further, I am not allowed to return a null UserDetails object from the loadUserByUsername() method (violates contract).

    The question is: Being a greenhorn, am I missing something OR should I implement my own version of DaoAuthenticationProvider to return a null Authentication object?

  9. #9
    Join Date
    Aug 2004
    Location
    Sydney, Australia
    Posts
    2,768

    Default

    If the DaoAuthenticationProvider model suits your needs, you simply would have one DaoAuthenticationProvider instance and a custom/fronting AuthenticationDao wired to it.

    As mentioned previously, the one custom/fronting AuthenticationDao would be responsible for polling your series of concrete AuthenticationDao beans. The AuthenticationDao beans can thus throw the UsernameNotFoundException, instructing the custom/fronting AuthenticationDao to try the next one.

    Does that make sense? Or is there some reason why this would not work in your particular environment?

  10. #10
    Join Date
    Feb 2005
    Posts
    1

    Default

    I am trying to get "chaining" to work with first an in memory lookup then a user database lookup.

    Have set up the databased users to utilise a PasswordEncoder and a SaltSource (the primary key for the user) using the information suggested elsewhere on this board.

    Both sets of users now authenticate fine separately. But when I put them together using a custom AuthenticationDao implementation that loops over the list of AuthenticationDao implementations (two in this case) as suggested above, I realised that there was a problem with the fact that the DaoAuthenticationProvider accepted a single SaltSource and PasswordEncoder, rather than getting these at the level of the AuthenticationDao implementing classes themselves (consequently the databased users worked fine, but the in memory ones did not and obviously could not execute the method specified by the getUserPropertyToUse method).

    Am I missing something here in assuming that there is no way to separately specify PasswordEncoders and SaltSources for each of these two sets of users?

    Or is there an obvious way I could get round this (I guess maybe using a SystemWideSalt and just setting up the username=password,ROLE list in the applicationContent.xml with encoded passwords)?

    (The custom AuthenticationDao implementation iterating over the list of AuthenticationDaos works fine when I don't utilise a PasswordEncoder (or SaltSource), allowing authentication of users from either set: in memory or database... so that bit seems to be fine.)

    Thank you...

Similar Threads

  1. Replies: 2
    Last Post: Oct 13th, 2005, 02:47 PM
  2. Loosing my SecureContext
    By sklakken in forum Security
    Replies: 3
    Last Post: Jul 21st, 2005, 01:44 PM
  3. Chaining Authentication Providers
    By mraible in forum Security
    Replies: 2
    Last Post: Apr 20th, 2005, 06:23 AM
  4. Chaining Authentication Providers?
    By dhainlin in forum Security
    Replies: 1
    Last Post: Jan 22nd, 2005, 03:34 PM
  5. Replies: 8
    Last Post: Dec 7th, 2004, 06:13 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •