This project has retired. For details please refer to its Attic page.
ArchivaUserManagerAuthenticator xref
View Javadoc
1   package org.apache.archiva.web.security;
2   /*
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  
21  import org.apache.archiva.admin.model.RepositoryAdminException;
22  import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
23  import org.apache.archiva.redback.authentication.AbstractAuthenticator;
24  import org.apache.archiva.redback.authentication.AuthenticationConstants;
25  import org.apache.archiva.redback.authentication.AuthenticationDataSource;
26  import org.apache.archiva.redback.authentication.AuthenticationException;
27  import org.apache.archiva.redback.authentication.AuthenticationFailureCause;
28  import org.apache.archiva.redback.authentication.AuthenticationResult;
29  import org.apache.archiva.redback.authentication.Authenticator;
30  import org.apache.archiva.redback.authentication.PasswordBasedAuthenticationDataSource;
31  import org.apache.archiva.redback.policy.AccountLockedException;
32  import org.apache.archiva.redback.policy.MustChangePasswordException;
33  import org.apache.archiva.redback.policy.PasswordEncoder;
34  import org.apache.archiva.redback.policy.UserSecurityPolicy;
35  import org.apache.archiva.redback.users.User;
36  import org.apache.archiva.redback.users.UserManager;
37  import org.apache.archiva.redback.users.UserNotFoundException;
38  import org.slf4j.Logger;
39  import org.slf4j.LoggerFactory;
40  import org.springframework.context.ApplicationContext;
41  import org.springframework.stereotype.Service;
42  
43  import javax.annotation.PostConstruct;
44  import javax.inject.Inject;
45  import java.util.ArrayList;
46  import java.util.List;
47  
48  /**
49   * @author Olivier Lamy
50   * @since 1.4-M4
51   */
52  @Service("authenticator#archiva")
53  public class ArchivaUserManagerAuthenticator
54      extends AbstractAuthenticator
55      implements Authenticator
56  {
57      private Logger log = LoggerFactory.getLogger( getClass() );
58  
59      @Inject
60      private UserSecurityPolicy securityPolicy;
61  
62      @Inject
63      private ApplicationContext applicationContext;
64  
65      @Inject
66      private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
67  
68      private List<UserManager> userManagers;
69  
70      private boolean valid = false;
71  
72      @PostConstruct
73      @Override
74      public void initialize()
75          throws AuthenticationException
76      {
77          try
78          {
79              List<String> userManagerImpls =
80                  redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls();
81  
82              userManagers = new ArrayList<>( userManagerImpls.size() );
83  
84              for ( String beanId : userManagerImpls )
85              {
86                  userManagers.add( applicationContext.getBean( "userManager#" + beanId, UserManager.class ) );
87              }
88              valid=true;
89          }
90          catch ( RepositoryAdminException e )
91          {
92              log.error( "Error during repository initialization {}", e.getMessage(), e );
93              // throw new AuthenticationException( e.getMessage(), e );
94          }
95      }
96  
97  
98      @Override
99      public AuthenticationResult authenticate( AuthenticationDataSource ds )
100         throws AuthenticationException, AccountLockedException, MustChangePasswordException
101     {
102         boolean authenticationSuccess = false;
103         String username = null;
104         Exception resultException = null;
105         PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) ds;
106         List<AuthenticationFailureCause> authnResultErrors = new ArrayList<>();
107 
108         for ( UserManager userManager : userManagers )
109         {
110             try
111             {
112                 log.debug( "Authenticate: {} with userManager: {}", source, userManager.getId() );
113                 User user = userManager.findUser( source.getUsername() );
114                 username = user.getUsername();
115 
116                 if ( user.isLocked() )
117                 {
118                     //throw new AccountLockedException( "Account " + source.getUsername() + " is locked.", user );
119                     AccountLockedException e =
120                         new AccountLockedException( "Account " + source.getUsername() + " is locked.", user );
121                     log.warn( "{}", e.getMessage() );
122                     resultException = e;
123                     authnResultErrors.add(
124                         new AuthenticationFailureCause( AuthenticationConstants.AUTHN_LOCKED_USER_EXCEPTION,
125                                                         e.getMessage() ) );
126                 }
127 
128                 if ( user.isPasswordChangeRequired() && source.isEnforcePasswordChange() )
129                 {
130                     //throw new MustChangePasswordException( "Password expired.", user );
131                     MustChangePasswordException e = new MustChangePasswordException( "Password expired.", user );
132                     log.warn( "{}", e.getMessage() );
133                     resultException = e;
134                     authnResultErrors.add(
135                         new AuthenticationFailureCause( AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION,
136                                                         e.getMessage() ) );
137                 }
138 
139                 PasswordEncoder encoder = securityPolicy.getPasswordEncoder();
140                 log.debug( "PasswordEncoder: {}", encoder.getClass().getName() );
141 
142                 boolean isPasswordValid = encoder.isPasswordValid( user.getEncodedPassword(), source.getPassword() );
143                 if ( isPasswordValid )
144                 {
145                     log.debug( "User {} provided a valid password", source.getUsername() );
146 
147                     try
148                     {
149                         securityPolicy.extensionPasswordExpiration( user );
150 
151                         authenticationSuccess = true;
152 
153                         //REDBACK-151 do not make unnessesary updates to the user object
154                         if ( user.getCountFailedLoginAttempts() > 0 )
155                         {
156                             user.setCountFailedLoginAttempts( 0 );
157                             if ( !userManager.isReadOnly() )
158                             {
159                                 userManager.updateUser( user );
160                             }
161                         }
162 
163                         return new AuthenticationResult( true, source.getUsername(), null );
164                     }
165                     catch ( MustChangePasswordException e )
166                     {
167                         user.setPasswordChangeRequired( true );
168                         //throw e;
169                         resultException = e;
170                         authnResultErrors.add( new AuthenticationFailureCause(
171                             AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION, e.getMessage() ).user( user ) );
172                     }
173                 }
174                 else
175                 {
176                     log.warn( "Password is Invalid for user {} and userManager '{}'.", source.getUsername(),
177                               userManager.getId() );
178                     authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
179                                                                            "Password is Invalid for user "
180                                                                                + source.getUsername() + "." ).user( user ) );
181 
182                     try
183                     {
184 
185                         securityPolicy.extensionExcessiveLoginAttempts( user );
186 
187                     }
188                     finally
189                     {
190                         if ( !userManager.isReadOnly() )
191                         {
192                             userManager.updateUser( user );
193                         }
194                     }
195 
196                     //return new AuthenticationResult( false, source.getUsername(), null, authnResultExceptionsMap );
197                 }
198             }
199             catch ( UserNotFoundException e )
200             {
201                 log.warn( "Login for user {} and userManager {} failed. user not found.", source.getUsername(),
202                           userManager.getId() );
203                 resultException = e;
204                 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
205                                                                        "Login for user " + source.getUsername()
206                                                                            + " failed. user not found." ) );
207             }
208             catch ( Exception e )
209             {
210                 log.warn( "Login for user {} and userManager {} failed, message: {}", source.getUsername(),
211                           userManager.getId(), e.getMessage() );
212                 e.printStackTrace();
213                 resultException = e;
214                 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_RUNTIME_EXCEPTION,
215                                                                        "Login for user " + source.getUsername()
216                                                                            + " failed, message: " + e.getMessage() ) );
217             }
218         }
219         return new AuthenticationResult( authenticationSuccess, username, resultException, authnResultErrors );
220     }
221 
222     @Override
223     public boolean supportsDataSource( AuthenticationDataSource source )
224     {
225         return ( source instanceof PasswordBasedAuthenticationDataSource );
226     }
227 
228     @Override
229     public String getId()
230     {
231         return "ArchivaUserManagerAuthenticator";
232     }
233 
234     public boolean isValid() {
235         return valid;
236     }
237 }