This project has retired. For details please refer to its
Attic page.
ArchivaUserManagerAuthenticator xref
1 package org.apache.archiva.web.security;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.archiva.admin.model.RepositoryAdminException;
22 import org.apache.archiva.admin.model.runtime.RedbackRuntimeConfigurationAdmin;
23 import org.apache.archiva.metadata.model.facets.AuditEvent;
24 import org.apache.archiva.redback.authentication.AbstractAuthenticator;
25 import org.apache.archiva.redback.authentication.AuthenticationConstants;
26 import org.apache.archiva.redback.authentication.AuthenticationDataSource;
27 import org.apache.archiva.redback.authentication.AuthenticationException;
28 import org.apache.archiva.redback.authentication.AuthenticationFailureCause;
29 import org.apache.archiva.redback.authentication.AuthenticationResult;
30 import org.apache.archiva.redback.authentication.Authenticator;
31 import org.apache.archiva.redback.authentication.PasswordBasedAuthenticationDataSource;
32 import org.apache.archiva.redback.policy.AccountLockedException;
33 import org.apache.archiva.redback.policy.MustChangePasswordException;
34 import org.apache.archiva.redback.policy.PasswordEncoder;
35 import org.apache.archiva.redback.policy.UserSecurityPolicy;
36 import org.apache.archiva.redback.users.User;
37 import org.apache.archiva.redback.users.UserManager;
38 import org.apache.archiva.redback.users.UserNotFoundException;
39 import org.apache.archiva.repository.events.AuditListener;
40 import org.apache.archiva.rest.services.interceptors.AuditInfoFilter;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.springframework.context.ApplicationContext;
44 import org.springframework.stereotype.Service;
45
46 import javax.annotation.PostConstruct;
47 import javax.inject.Inject;
48 import java.util.ArrayList;
49 import java.util.List;
50
51
52
53
54
55 @Service("authenticator#archiva")
56 public class ArchivaUserManagerAuthenticator
57 extends AbstractAuthenticator
58 implements Authenticator
59 {
60 private Logger log = LoggerFactory.getLogger( getClass() );
61
62 @Inject
63 private UserSecurityPolicy securityPolicy;
64
65 @Inject
66 private ApplicationContext applicationContext;
67
68 @Inject
69 private RedbackRuntimeConfigurationAdmin redbackRuntimeConfigurationAdmin;
70
71 @Inject
72 private List<AuditListener> auditListeners = new ArrayList<>();
73
74 private List<UserManager> userManagers;
75
76 private boolean valid = false;
77
78 @PostConstruct
79 @Override
80 public void initialize()
81 throws AuthenticationException
82 {
83 try
84 {
85 List<String> userManagerImpls =
86 redbackRuntimeConfigurationAdmin.getRedbackRuntimeConfiguration().getUserManagerImpls();
87
88 userManagers = new ArrayList<>( userManagerImpls.size() );
89
90 for ( String beanId : userManagerImpls )
91 {
92 userManagers.add( applicationContext.getBean( "userManager#" + beanId, UserManager.class ) );
93 }
94 valid=true;
95 }
96 catch ( RepositoryAdminException e )
97 {
98 log.error("Error during repository initialization "+e.getMessage(),e);
99
100 }
101 }
102
103 protected AuditInfoFilter.AuditInfo getAuditInformation()
104 {
105 return AuditInfoFilter.getAuditInfo( );
106 }
107
108 public List<AuditListener> getAuditListeners()
109 {
110 return auditListeners;
111 }
112
113 protected void triggerAuditEvent( String repositoryId, String filePath, String action, String user )
114 {
115 AuditEvent auditEvent = new AuditEvent( repositoryId, user, filePath, action );
116 AuditInfoFilter.AuditInfo auditInformation = getAuditInformation();
117 auditEvent.setUserId( user );
118 auditEvent.setRemoteIP( auditInformation.getRemoteHost() + ":" + auditInformation.getRemotePort() );
119 for ( AuditListener auditListener : getAuditListeners() )
120 {
121 auditListener.auditEvent( auditEvent );
122 }
123 }
124
125 @Override
126 public AuthenticationResult authenticate( AuthenticationDataSource ds )
127 throws AuthenticationException, AccountLockedException, MustChangePasswordException
128 {
129 boolean authenticationSuccess = false;
130 String username = null;
131 Exception resultException = null;
132 PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) ds;
133 List<AuthenticationFailureCause> authnResultErrors = new ArrayList<>();
134 final String loginUserId = source.getUsername( );
135
136 for ( UserManager userManager : userManagers )
137 {
138 try
139 {
140 log.debug( "Authenticate: {} with userManager: {}", source, userManager.getId() );
141 User user = userManager.findUser( loginUserId );
142 username = user.getUsername();
143
144 if ( user.isLocked() )
145 {
146
147 AccountLockedException e =
148 new AccountLockedException( "Account " + loginUserId + " is locked.", user );
149 log.warn( "{}", e.getMessage() );
150 triggerAuditEvent( "", "", "login-account-locked", loginUserId );
151 resultException = e;
152 authnResultErrors.add(
153 new AuthenticationFailureCause( AuthenticationConstants.AUTHN_LOCKED_USER_EXCEPTION,
154 e.getMessage() ) );
155 }
156
157 if ( user.isPasswordChangeRequired() && source.isEnforcePasswordChange() )
158 {
159
160 MustChangePasswordException e = new MustChangePasswordException( "Password expired.", user );
161 log.warn( "{}", e.getMessage() );
162 resultException = e;
163 triggerAuditEvent( "", "", "login-password-change-required", loginUserId );
164 authnResultErrors.add(
165 new AuthenticationFailureCause( AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION,
166 e.getMessage() ) );
167 }
168
169 PasswordEncoder encoder = securityPolicy.getPasswordEncoder();
170 log.debug( "PasswordEncoder: {}", encoder.getClass().getName() );
171
172 boolean isPasswordValid = encoder.isPasswordValid( user.getEncodedPassword(), source.getPassword() );
173 if ( isPasswordValid )
174 {
175 log.debug( "User {} provided a valid password", loginUserId );
176
177 try
178 {
179 securityPolicy.extensionPasswordExpiration( user );
180
181 authenticationSuccess = true;
182 triggerAuditEvent( "", "", "login-success", loginUserId );
183
184
185
186 if ( user.getCountFailedLoginAttempts() > 0 )
187 {
188 user.setCountFailedLoginAttempts( 0 );
189 if ( !userManager.isReadOnly() )
190 {
191 userManager.updateUser( user );
192 }
193 }
194
195 return new AuthenticationResult( true, loginUserId, null );
196 }
197 catch ( MustChangePasswordException e )
198 {
199 user.setPasswordChangeRequired( true );
200 triggerAuditEvent( "", "", "login-password-change-required", loginUserId );
201
202 resultException = e;
203 authnResultErrors.add( new AuthenticationFailureCause(
204 AuthenticationConstants.AUTHN_MUST_CHANGE_PASSWORD_EXCEPTION, e.getMessage() ).user( user ) );
205 }
206 }
207 else
208 {
209 log.warn( "Password is Invalid for user {} and userManager '{}'.", source.getUsername(),
210 userManager.getId() );
211 triggerAuditEvent( "", "", "login-authentication-failed", loginUserId );
212
213 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
214 "Password is Invalid for user "
215 + source.getUsername() + "." ).user( user ) );
216
217 try
218 {
219
220 securityPolicy.extensionExcessiveLoginAttempts( user );
221
222 }
223 finally
224 {
225 if ( !userManager.isReadOnly() )
226 {
227 userManager.updateUser( user );
228 }
229 }
230
231
232 }
233 }
234 catch ( UserNotFoundException e )
235 {
236 log.warn( "Login for user {} and userManager {} failed. user not found.", loginUserId,
237 userManager.getId() );
238 resultException = e;
239 triggerAuditEvent( "", "", "login-user-unknown", loginUserId );
240 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_NO_SUCH_USER,
241 "Login for user " + source.getUsername()
242 + " failed. user not found." ) );
243 }
244 catch ( Exception e )
245 {
246 log.warn( "Login for user {} and userManager {} failed, message: {}", loginUserId,
247 userManager.getId(), e.getMessage() );
248 resultException = e;
249 triggerAuditEvent( "", "", "login-error", loginUserId );
250 authnResultErrors.add( new AuthenticationFailureCause( AuthenticationConstants.AUTHN_RUNTIME_EXCEPTION,
251 "Login for user " + source.getUsername()
252 + " failed, message: " + e.getMessage() ) );
253 }
254 }
255 return new AuthenticationResult( authenticationSuccess, username, resultException, authnResultErrors );
256 }
257
258 @Override
259 public boolean supportsDataSource( AuthenticationDataSource source )
260 {
261 return ( source instanceof PasswordBasedAuthenticationDataSource );
262 }
263
264 @Override
265 public String getId()
266 {
267 return "ArchivaUserManagerAuthenticator";
268 }
269
270 public boolean isValid() {
271 return valid;
272 }
273 }