Spring Security
  1. Spring Security
  2. SEC-984

CasAuthenticationProvider cannot authenticate on custom attributes

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.0.0 M1
    • Component/s: CAS
    • Labels:
      None

      Description

      I have this system where users need to signin using an existing CAS. The response from the CAS is the username and a lot of additional attributes. I need one of these attributes in order to get the information in need to create a UserDetails object, because the information is retrieved from another webservice, where one of the custom attributes is the key, instead of the username.

      When authentication is performed in CasAuthenticationProvider and the method authenticateNow(Authentication authentication) is invoked, it initially validates the ticket using the supplied ticket validator.

      I have written my own custom validator which extends from Cas20ServiceTicketValidator, and then made an override implementation of customParseResponse(final String response, final Assertion assertion), where I parse the responce and add additional attributes to the assertion map.

      My problem occurs when the UserDetails should be retrieved from the UserDetailsService, when userDetailsService.loadUserByUsername(assertion.getPrincipal().getName()) is invoked. In order to retrieve the information needed to create a UserDetails object, I need the custom attributes, which i retrieved through my custom validator, but this information is not parsed to the loadUserByUsername method.

      My current solution to this problem is to make my own implementation of CasAuthenticationProvider. Which does not use the UserDetailsService interface but instead my own, where i can pass my attributes together with the username.

      A solution to this problem could be to add the following method to the UserDetailsService interface:
      UserDetails loadUserByUsername(String username, Assertion assertion) throws UsernameNotFoundException, DataAccessException;

      Where the Assertion is the response from ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService());

      It is then possible to create the UserDetails based on both the username and custom attributes.

        Activity

        Hide
        Luke Taylor added a comment -

        The UserDetailsService interface is used throughout the framework and can't be changed as it is one of the most common customization points - to do so would break.

        I've discussed it with Scott and we've agreed that extracting a template method would allow you to extend the provider with minimal overhead. So something like

        protected UserDetails loadUserDetails(Assertion assertion)

        { return userDetailsService.loaduserDetails(assertion.getPrincipal().getName()); }

        as the default implementation.

        Show
        Luke Taylor added a comment - The UserDetailsService interface is used throughout the framework and can't be changed as it is one of the most common customization points - to do so would break. I've discussed it with Scott and we've agreed that extracting a template method would allow you to extend the provider with minimal overhead. So something like protected UserDetails loadUserDetails(Assertion assertion) { return userDetailsService.loaduserDetails(assertion.getPrincipal().getName()); } as the default implementation.
        Hide
        Scott Battaglia added a comment -

        Added template method and appropriate javadoc. Name differs slightly from the one described in here:

            /**
             * Template method for retrieving the UserDetails based on the assertion.  Default is to call configured userDetailsService and pass the username.  Deployers
             * can override this method and retrieve the user based on any criteria they desire.
             * 
             * @param assertion The CAS Assertion.
             * @returns the UserDetails.
             */
            protected UserDetails loadUserByAssertion(final Assertion assertion) {
                return this.userDetailsService.loadUserByUsername(assertion.getPrincipal().getName());
            }
        

        Luke, I changed this to 2.0.4 since its done.

        Show
        Scott Battaglia added a comment - Added template method and appropriate javadoc. Name differs slightly from the one described in here: /** * Template method for retrieving the UserDetails based on the assertion. Default is to call configured userDetailsService and pass the username. Deployers * can override this method and retrieve the user based on any criteria they desire. * * @param assertion The CAS Assertion. * @returns the UserDetails. */ protected UserDetails loadUserByAssertion( final Assertion assertion) { return this .userDetailsService.loadUserByUsername(assertion.getPrincipal().getName()); } Luke, I changed this to 2.0.4 since its done.
        Hide
        Henrik Kragh-Hansen added a comment -

        I have downloaded version 2.0.4 of spring security, and I have not been able to locate any method corresponding to the changes described here.

        The CasAuthenticationProvider class still contains the method:

        private CasAuthenticationToken authenticateNow(Authentication authentication) throws AuthenticationException {
        try

        { final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService()); final UserDetails userDetails = userDetailsService.loadUserByUsername(assertion.getPrincipal().getName()); *** }

        }

        Here the .loadUserByUsername is still invoked directly.
        I might have missunderstood how you have corrected this problem.

        I have tried downloading 2.0.4 through maven and directly from your homepage and I cant locate the correction anywhere.

        Show
        Henrik Kragh-Hansen added a comment - I have downloaded version 2.0.4 of spring security, and I have not been able to locate any method corresponding to the changes described here. The CasAuthenticationProvider class still contains the method: private CasAuthenticationToken authenticateNow(Authentication authentication) throws AuthenticationException { try { final Assertion assertion = this.ticketValidator.validate(authentication.getCredentials().toString(), serviceProperties.getService()); final UserDetails userDetails = userDetailsService.loadUserByUsername(assertion.getPrincipal().getName()); *** } } Here the .loadUserByUsername is still invoked directly. I might have missunderstood how you have corrected this problem. I have tried downloading 2.0.4 through maven and directly from your homepage and I cant locate the correction anywhere.
        Hide
        Scott Battaglia added a comment -

        Click on the FishEye link in JIRA, the change appears there.

        -Scott

        Show
        Scott Battaglia added a comment - Click on the FishEye link in JIRA, the change appears there. -Scott
        Hide
        Henrik Kragh-Hansen added a comment -

        Well the changes in the FishEye view is very nice, and they solve my problems, but my problem is that the version of the implementation in the 2.0.4 jar of spring security is:

        @version $Id: CasAuthenticationProvider.java 2710 2008-03-10 18:33:34Z sbattaglia $

        where the changes should be in:

        @version $Id: CasAuthenticationProvider.java 3284 2008-10-01 18:49:52Z sbattaglia $

        The 2.0.4 version is from 2008-10-02 so I dont know why this change is not available in the 2.0.4 release.
        As stated in my previous post I have tried to download 2.0.4 from your homepage and through maven, and both does not contain the

        protected UserDetails loadUserByAssertion(final Assertion assertion)

        method, and I have also checked the source, which appears to be the old version.

        Regards Henrik

        Show
        Henrik Kragh-Hansen added a comment - Well the changes in the FishEye view is very nice, and they solve my problems, but my problem is that the version of the implementation in the 2.0.4 jar of spring security is: @version $Id: CasAuthenticationProvider.java 2710 2008-03-10 18:33:34Z sbattaglia $ where the changes should be in: @version $Id: CasAuthenticationProvider.java 3284 2008-10-01 18:49:52Z sbattaglia $ The 2.0.4 version is from 2008-10-02 so I dont know why this change is not available in the 2.0.4 release. As stated in my previous post I have tried to download 2.0.4 from your homepage and through maven, and both does not contain the protected UserDetails loadUserByAssertion(final Assertion assertion) method, and I have also checked the source, which appears to be the old version. Regards Henrik
        Hide
        Scott Battaglia added a comment -

        I don't do the builds so I can't speak for why it didn't make it in unless someone didn't check out correctly before doing the build. Maybe Luke will see this and know why.

        Show
        Scott Battaglia added a comment - I don't do the builds so I can't speak for why it didn't make it in unless someone didn't check out correctly before doing the build. Maybe Luke will see this and know why.
        Hide
        Luke Taylor added a comment -

        Hi guys,

        2.0.4 was scheduled for the 12th September and was tagged before that:

        http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.4/

        Thats the tag the build team used, so nothing that's been done in trunk since then will be included. We use the maven release plugin, so there should never be any issues with failing to do a proper checkout for a release.

        I've changed the fix version back to 2.5

        Show
        Luke Taylor added a comment - Hi guys, 2.0.4 was scheduled for the 12th September and was tagged before that: http://acegisecurity.svn.sourceforge.net/svnroot/acegisecurity/spring-security/tags/spring-security-parent-2.0.4/ Thats the tag the build team used, so nothing that's been done in trunk since then will be included. We use the maven release plugin, so there should never be any issues with failing to do a proper checkout for a release. I've changed the fix version back to 2.5

          People

          • Assignee:
            Scott Battaglia
            Reporter:
            Henrik Kragh-Hansen
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: