1 package org.apache.archiva.web.security;
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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
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.UserManagerException;
38 import org.apache.archiva.redback.users.UserNotFoundException;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.context.ApplicationContext;
42 import org.springframework.stereotype.Service;
44 import javax.annotation.PostConstruct;
45 import javax.inject.Inject;
46 import java.util.ArrayList;
47 import java.util.List;
50 * @author Olivier Lamy
53 @Service("authenticator#archiva")
54 public class ArchivaUserManagerAuthenticator
55 extends AbstractAuthenticator
56 implements Authenticator
58 private Logger log = LoggerFactory.getLogger( getClass() );
61 private UserSecurityPolicy securityPolicy;
64 private ApplicationContext applicationContext;
67 private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
69 private List<UserManager> userManagers;
73 public void initialize()
74 throws AuthenticationException
78 List<String> userManagerImpls =
79 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls();
81 userManagers = new ArrayList<UserManager>( userManagerImpls.size() );
83 for ( String beanId : userManagerImpls )
85 userManagers.add( applicationContext.getBean( "userManager#" + beanId, UserManager.class ) );
88 catch ( RepositoryAdminException e )
90 throw new AuthenticationException( e.getMessage(), e );
95 public AuthenticationResult authenticate( AuthenticationDataSource ds )
96 throws AuthenticationException, AccountLockedException, MustChangePasswordException
98 boolean authenticationSuccess = false;
99 String username = null;
100 Exception resultException = null;
101 PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) ds;
102 List<AuthenticationFailureCause> authnResultErrors = new ArrayList<AuthenticationFailureCause>();
104 for ( UserManager userManager : userManagers )
108 log.debug( "Authenticate: {} with userManager: {}", source, userManager.getId() );
109 User user = userManager.findUser( source.getUsername() );
110 username = user.getUsername();
112 if ( user.isLocked() )
114 //throw new AccountLockedException( "Account " + source.getUsername() + " is locked.", user );
115 AccountLockedException e =
116 new AccountLockedException( "Account " + source.getUsername() + " is locked.", user );
117 log.warn( "{}", e.getMessage() );
119 authnResultErrors.add(
120 new AuthenticationFailureCause( AuthenticationConstants.AUTHN_LOCKED_USER_EXCEPTION,
124 if ( user.isPasswordChangeRequired() && source.isEnforcePasswordChange() )
126 //throw new MustChangePasswordException( "Password expired.", user );
127 MustChangePasswordException e = new MustChangePasswordException( "Password expired.", user );
128 log.warn( "{}", e.getMessage() );
130 authnResultErrors.add(
131 new AuthenticationFailureCause( AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION,
135 PasswordEncoder encoder = securityPolicy.getPasswordEncoder();
136 log.debug( "PasswordEncoder: {}", encoder.getClass().getName() );
138 boolean isPasswordValid = encoder.isPasswordValid( user.getEncodedPassword(), source.getPassword() );
139 if ( isPasswordValid )
141 log.debug( "User {} provided a valid password", source.getUsername() );
145 securityPolicy.extensionPasswordExpiration( user );
147 authenticationSuccess = true;
149 //REDBACK-151 do not make unnessesary updates to the user object
150 if ( user.getCountFailedLoginAttempts() > 0 )
152 user.setCountFailedLoginAttempts( 0 );
153 if ( !userManager.isReadOnly() )
155 userManager.updateUser( user );
159 return new AuthenticationResult( true, source.getUsername(), null );
161 catch ( MustChangePasswordException e )
163 user.setPasswordChangeRequired( true );
166 authnResultErrors.add( new AuthenticationFailureCause(
167 AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION, e.getMessage() ) );
172 log.warn( "Password is Invalid for user {} and userManager '{}'.", source.getUsername(),
173 userManager.getId() );
174 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
175 "Password is Invalid for user "
176 + source.getUsername() + "." ) );
181 securityPolicy.extensionExcessiveLoginAttempts( user );
186 if ( !userManager.isReadOnly() )
188 userManager.updateUser( user );
192 //return new AuthenticationResult( false, source.getUsername(), null, authnResultExceptionsMap );
195 catch ( UserNotFoundException e )
197 log.warn( "Login for user {} failed. user not found.", source.getUsername() );
199 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
200 "Login for user " + source.getUsername()
201 + " failed. user not found." ) );
203 catch ( Exception e )
205 log.warn( "Login for user {} failed, message: {}", source.getUsername(), e.getMessage() );
207 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_RUNTIME_EXCEPTION,
208 "Login for user " + source.getUsername()
209 + " failed, message: " + e.getMessage() ) );
212 return new AuthenticationResult( authenticationSuccess, username, resultException, authnResultErrors );
215 public boolean supportsDataSource( AuthenticationDataSource source )
217 return ( source instanceof PasswordBasedAuthenticationDataSource );
220 public String getId()
222 return "ArchivaUserManagerAuthenticator";