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.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
50
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
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
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
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
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
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
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 }