View Javadoc

1   /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.student.security.kim;
17  
18  import org.kuali.student.security.spring.KSRiceDefaultUserDetailsService;
19  import org.springframework.dao.DataAccessException;
20  import org.springframework.security.AuthenticationException;
21  import org.springframework.security.AuthenticationServiceException;
22  import org.springframework.security.BadCredentialsException;
23  import org.springframework.security.providers.AuthenticationProvider;
24  import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
25  import org.springframework.security.providers.dao.AbstractUserDetailsAuthenticationProvider;
26  import org.springframework.security.providers.dao.DaoAuthenticationProvider;
27  import org.springframework.security.providers.dao.SaltSource;
28  import org.springframework.security.providers.encoding.PasswordEncoder;
29  import org.springframework.security.providers.encoding.PlaintextPasswordEncoder;
30  import org.springframework.security.userdetails.UserDetails;
31  import org.springframework.security.userdetails.UserDetailsService;
32  import org.springframework.util.Assert;
33  
34  /**
35   * An {@link AuthenticationProvider} implementation that retrieves user details
36   * from an {@link UserDetailsService}. Slightly modified from {@link DaoAuthenticationProvider}
37   * 
38   * @author Kuali Student Team
39   *
40   */
41  public class KimAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
42      
43      //~ Instance fields ================================================================================================
44  
45      private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
46  
47      private SaltSource saltSource;
48  
49      private UserDetailsService userDetailsService;
50  
51      private boolean includeDetailsObject = true;
52  
53      //~ Methods ========================================================================================================
54  
55      protected void additionalAuthenticationChecks(UserDetails userDetails,
56              UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
57          Object salt = null;
58  
59          if (this.saltSource != null) {
60              salt = this.saltSource.getSalt(userDetails);
61          }
62  
63          if (authentication.getCredentials() == null) {
64              throw new BadCredentialsException(messages.getMessage(
65                      "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
66                      includeDetailsObject ? userDetails : null);
67          }
68  
69          String presentedPassword = authentication.getCredentials().toString();
70  
71          if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
72              throw new BadCredentialsException(messages.getMessage(
73                      "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),
74                      includeDetailsObject ? userDetails : null);
75          }
76      }
77  
78      protected void doAfterPropertiesSet() throws Exception {
79          Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
80      }
81  
82      protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
83              throws AuthenticationException {
84          UserDetails loadedUser;
85  
86          UserDetailsService ksRiceDefaultUserDetailsService = this.getUserDetailsService();
87          if(!(ksRiceDefaultUserDetailsService instanceof KSRiceDefaultUserDetailsService)){
88              throw new AuthenticationServiceException(
89                  "UserDetailsService is not an an instance of KSRiceDefaultUserDetailsService");
90          }
91          
92          try {
93              //loadedUser = this.getUserDetailsService().loadUserByUsername(username);
94              loadedUser = ((KSRiceDefaultUserDetailsService)ksRiceDefaultUserDetailsService).loadUserByUsernameAndToken(username, authentication);
95          }
96          catch (DataAccessException repositoryProblem) {
97              throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
98          }
99  
100         if (loadedUser == null) {
101             throw new AuthenticationServiceException(
102                     "UserDetailsService returned null, which is an interface contract violation");
103         }
104         return loadedUser;
105     }
106 
107     /**
108      * Sets the PasswordEncoder instance to be used to encode and validate passwords.
109      * If not set, {@link PlaintextPasswordEncoder} will be used by default.
110      *
111      * @param passwordEncoder The passwordEncoder to use
112      */
113     public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
114         this.passwordEncoder = passwordEncoder;
115     }
116 
117     protected PasswordEncoder getPasswordEncoder() {
118         return passwordEncoder;
119     }
120 
121     /**
122      * The source of salts to use when decoding passwords. <code>null</code>
123      * is a valid value, meaning the <code>DaoAuthenticationProvider</code>
124      * will present <code>null</code> to the relevant <code>PasswordEncoder</code>.
125      *
126      * @param saltSource to use when attempting to decode passwords via the <code>PasswordEncoder</code>
127      */
128     public void setSaltSource(SaltSource saltSource) {
129         this.saltSource = saltSource;
130     }
131 
132     protected SaltSource getSaltSource() {
133         return saltSource;
134     }
135 
136     public void setUserDetailsService(UserDetailsService userDetailsService) {
137         this.userDetailsService = userDetailsService;
138     }
139 
140     protected UserDetailsService getUserDetailsService() {
141         return userDetailsService;
142     }
143 
144     protected boolean isIncludeDetailsObject() {
145         return includeDetailsObject;
146     }
147 }