Coverage Report - org.acegisecurity.providers.cas.CasAuthenticationProvider
 
Classes in this File Line Coverage Branch Coverage Complexity
CasAuthenticationProvider
97% 
100% 
2.2
 
 1  
 /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 2  
  *
 3  
  * Licensed under the Apache License, Version 2.0 (the "License");
 4  
  * you may not use this file except in compliance with the License.
 5  
  * You may obtain a copy of the License at
 6  
  *
 7  
  *     http://www.apache.org/licenses/LICENSE-2.0
 8  
  *
 9  
  * Unless required by applicable law or agreed to in writing, software
 10  
  * distributed under the License is distributed on an "AS IS" BASIS,
 11  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12  
  * See the License for the specific language governing permissions and
 13  
  * limitations under the License.
 14  
  */
 15  
 
 16  
 package org.acegisecurity.providers.cas;
 17  
 
 18  
 import org.acegisecurity.AcegiMessageSource;
 19  
 import org.acegisecurity.Authentication;
 20  
 import org.acegisecurity.AuthenticationException;
 21  
 import org.acegisecurity.BadCredentialsException;
 22  
 
 23  
 import org.acegisecurity.providers.AuthenticationProvider;
 24  
 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
 25  
 import org.acegisecurity.providers.cas.cache.NullStatelessTicketCache;
 26  
 
 27  
 import org.acegisecurity.ui.cas.CasProcessingFilter;
 28  
 
 29  
 import org.acegisecurity.userdetails.UserDetails;
 30  
 
 31  
 import org.apache.commons.logging.Log;
 32  
 import org.apache.commons.logging.LogFactory;
 33  
 
 34  
 import org.springframework.beans.factory.InitializingBean;
 35  
 
 36  
 import org.springframework.context.MessageSource;
 37  
 import org.springframework.context.MessageSourceAware;
 38  
 import org.springframework.context.support.MessageSourceAccessor;
 39  
 
 40  
 import org.springframework.util.Assert;
 41  
 
 42  
 
 43  
 /**
 44  
  * An {@link AuthenticationProvider} implementation that integrates with JA-SIG Central Authentication Service
 45  
  * (CAS).<p>This <code>AuthenticationProvider</code> is capable of validating  {@link
 46  
  * UsernamePasswordAuthenticationToken} requests which contain a <code>principal</code> name equal to either {@link
 47  
  * CasProcessingFilter#CAS_STATEFUL_IDENTIFIER} or {@link CasProcessingFilter#CAS_STATELESS_IDENTIFIER}. It can also
 48  
  * validate a previously created {@link CasAuthenticationToken}.</p>
 49  
  *
 50  
  * @author Ben Alex
 51  
  * @version $Id: CasAuthenticationProvider.java 2634 2008-02-15 14:03:52Z luke_t $
 52  
  */
 53  13
 public class CasAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
 54  
     //~ Static fields/initializers =====================================================================================
 55  
 
 56  4
     private static final Log logger = LogFactory.getLog(CasAuthenticationProvider.class);
 57  
 
 58  
     //~ Instance fields ================================================================================================
 59  
 
 60  
     private CasAuthoritiesPopulator casAuthoritiesPopulator;
 61  
     private CasProxyDecider casProxyDecider;
 62  13
     protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
 63  13
     private StatelessTicketCache statelessTicketCache = new NullStatelessTicketCache();
 64  
     private String key;
 65  
     private TicketValidator ticketValidator;
 66  
 
 67  
     //~ Methods ========================================================================================================
 68  
 
 69  
         public void afterPropertiesSet() throws Exception {
 70  12
         Assert.notNull(this.casAuthoritiesPopulator, "A casAuthoritiesPopulator must be set");
 71  11
         Assert.notNull(this.ticketValidator, "A ticketValidator must be set");
 72  10
         Assert.notNull(this.casProxyDecider, "A casProxyDecider must be set");
 73  9
         Assert.notNull(this.statelessTicketCache, "A statelessTicketCache must be set");
 74  8
         Assert.hasText(this.key, "A Key is required so CasAuthenticationProvider can identify tokens it previously authenticated");
 75  7
         Assert.notNull(this.messages, "A message source must be set");
 76  7
     }
 77  
 
 78  
     public Authentication authenticate(Authentication authentication)
 79  
         throws AuthenticationException {
 80  8
         if (!supports(authentication.getClass())) {
 81  1
             return null;
 82  
         }
 83  
 
 84  7
         if (authentication instanceof UsernamePasswordAuthenticationToken
 85  
             && (!CasProcessingFilter.CAS_STATEFUL_IDENTIFIER.equals(authentication.getPrincipal().toString())
 86  
             && !CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal().toString()))) {
 87  
             // UsernamePasswordAuthenticationToken not CAS related
 88  1
             return null;
 89  
         }
 90  
 
 91  
         // If an existing CasAuthenticationToken, just check we created it
 92  6
         if (authentication instanceof CasAuthenticationToken) {
 93  2
             if (this.key.hashCode() == ((CasAuthenticationToken) authentication).getKeyHash()) {
 94  1
                 return authentication;
 95  
             } else {
 96  1
                 throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.incorrectKey",
 97  
                         "The presented CasAuthenticationToken does not contain the expected key"));
 98  
             }
 99  
         }
 100  
 
 101  
         // Ensure credentials are presented
 102  4
         if ((authentication.getCredentials() == null) || "".equals(authentication.getCredentials())) {
 103  1
             throw new BadCredentialsException(messages.getMessage("CasAuthenticationProvider.noServiceTicket",
 104  
                     "Failed to provide a CAS service ticket to validate"));
 105  
         }
 106  
 
 107  3
         boolean stateless = false;
 108  
 
 109  3
         if (authentication instanceof UsernamePasswordAuthenticationToken
 110  
             && CasProcessingFilter.CAS_STATELESS_IDENTIFIER.equals(authentication.getPrincipal())) {
 111  2
             stateless = true;
 112  
         }
 113  
 
 114  3
         CasAuthenticationToken result = null;
 115  
 
 116  3
         if (stateless) {
 117  
             // Try to obtain from cache
 118  2
             result = statelessTicketCache.getByTicketId(authentication.getCredentials().toString());
 119  
         }
 120  
 
 121  3
         if (result == null) {
 122  2
             result = this.authenticateNow(authentication);
 123  2
             result.setDetails(authentication.getDetails());
 124  
         }
 125  
 
 126  3
         if (stateless) {
 127  
             // Add to cache
 128  2
             statelessTicketCache.putTicketInCache(result);
 129  
         }
 130  
 
 131  3
         return result;
 132  
     }
 133  
 
 134  
     private CasAuthenticationToken authenticateNow(Authentication authentication)
 135  
         throws AuthenticationException {
 136  
         // Validate
 137  2
         TicketResponse response = ticketValidator.confirmTicketValid(authentication.getCredentials().toString());
 138  
 
 139  
         // Check proxy list is trusted
 140  2
         this.casProxyDecider.confirmProxyListTrusted(response.getProxyList());
 141  
 
 142  
         // Lookup user details
 143  2
         UserDetails userDetails = this.casAuthoritiesPopulator.getUserDetails(response.getUser());
 144  
 
 145  
         // Construct CasAuthenticationToken
 146  2
         return new CasAuthenticationToken(this.key, userDetails, authentication.getCredentials(),
 147  
             userDetails.getAuthorities(), userDetails, response.getProxyList(), response.getProxyGrantingTicketIou());
 148  
     }
 149  
 
 150  
     public CasAuthoritiesPopulator getCasAuthoritiesPopulator() {
 151  1
         return casAuthoritiesPopulator;
 152  
     }
 153  
 
 154  
     public CasProxyDecider getCasProxyDecider() {
 155  1
         return casProxyDecider;
 156  
     }
 157  
 
 158  
     public String getKey() {
 159  2
         return key;
 160  
     }
 161  
 
 162  
     public StatelessTicketCache getStatelessTicketCache() {
 163  1
         return statelessTicketCache;
 164  
     }
 165  
 
 166  
     public TicketValidator getTicketValidator() {
 167  1
         return ticketValidator;
 168  
     }
 169  
 
 170  
     public void setCasAuthoritiesPopulator(CasAuthoritiesPopulator casAuthoritiesPopulator) {
 171  11
         this.casAuthoritiesPopulator = casAuthoritiesPopulator;
 172  11
     }
 173  
 
 174  
     public void setCasProxyDecider(CasProxyDecider casProxyDecider) {
 175  11
         this.casProxyDecider = casProxyDecider;
 176  11
     }
 177  
 
 178  
     public void setKey(String key) {
 179  11
         this.key = key;
 180  11
     }
 181  
 
 182  
     public void setMessageSource(MessageSource messageSource) {
 183  0
         this.messages = new MessageSourceAccessor(messageSource);
 184  0
     }
 185  
 
 186  
     public void setStatelessTicketCache(StatelessTicketCache statelessTicketCache) {
 187  12
         this.statelessTicketCache = statelessTicketCache;
 188  12
     }
 189  
 
 190  
     public void setTicketValidator(TicketValidator ticketValidator) {
 191  13
         this.ticketValidator = ticketValidator;
 192  13
     }
 193  
 
 194  
     public boolean supports(Class authentication) {
 195  11
         if (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)) {
 196  6
             return true;
 197  5
         } else if (CasAuthenticationToken.class.isAssignableFrom(authentication)) {
 198  3
             return true;
 199  
         } else {
 200  2
             return false;
 201  
         }
 202  
     }
 203  
 }