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.UserNotFoundException;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.springframework.context.ApplicationContext;
41 import org.springframework.stereotype.Service;
43 import javax.annotation.PostConstruct;
44 import javax.inject.Inject;
45 import java.util.ArrayList;
46 import java.util.List;
49 * @author Olivier Lamy
52 @Service("authenticator#archiva")
53 public class ArchivaUserManagerAuthenticator
54 extends AbstractAuthenticator
55 implements Authenticator
57 private Logger log = LoggerFactory.getLogger( getClass() );
60 private UserSecurityPolicy securityPolicy;
63 private ApplicationContext applicationContext;
66 private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
68 private List<UserManager> userManagers;
72 public void initialize()
73 throws AuthenticationException
77 List<String> userManagerImpls =
78 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls();
80 userManagers = new ArrayList<>( userManagerImpls.size() );
82 for ( String beanId : userManagerImpls )
84 userManagers.add( applicationContext.getBean( "userManager#" + beanId, UserManager.class ) );
87 catch ( RepositoryAdminException e )
89 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<>();
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() ).user( user ) );
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() + "." ).user( user ) );
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 {} and userManager {} failed. user not found.", source.getUsername(),
198 userManager.getId() );
200 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
201 "Login for user " + source.getUsername()
202 + " failed. user not found." ) );
204 catch ( Exception e )
206 log.warn( "Login for user {} and userManager {} failed, message: {}", source.getUsername(),
207 userManager.getId(), e.getMessage() );
209 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_RUNTIME_EXCEPTION,
210 "Login for user " + source.getUsername()
211 + " failed, message: " + e.getMessage() ) );
214 return new AuthenticationResult( authenticationSuccess, username, resultException, authnResultErrors );
218 public boolean supportsDataSource( AuthenticationDataSource source )
220 return ( source instanceof PasswordBasedAuthenticationDataSource );
224 public String getId()
226 return "ArchivaUserManagerAuthenticator";