2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.security
.core
;
18 import java
.util
.Locale
;
21 import javax
.security
.auth
.Subject
;
22 import javax
.security
.auth
.callback
.Callback
;
23 import javax
.security
.auth
.callback
.CallbackHandler
;
24 import javax
.security
.auth
.callback
.NameCallback
;
25 import javax
.security
.auth
.callback
.PasswordCallback
;
26 import javax
.security
.auth
.login
.LoginException
;
27 import javax
.security
.auth
.spi
.LoginModule
;
29 import org
.argeo
.jcr
.ArgeoNames
;
30 import org
.argeo
.util
.LocaleCallback
;
31 import org
.argeo
.util
.LocaleUtils
;
32 import org
.osgi
.framework
.BundleContext
;
33 import org
.osgi
.service
.useradmin
.Authorization
;
34 import org
.osgi
.service
.useradmin
.User
;
35 import org
.osgi
.service
.useradmin
.UserAdmin
;
36 import org
.springframework
.security
.authentication
.encoding
.LdapShaPasswordEncoder
;
38 /** Login module which caches one subject per thread. */
39 public class UserAdminLoginModule
implements LoginModule
{
40 // private final static Log log = LogFactory
41 // .getLog(UserAdminLoginModule.class);
43 private CallbackHandler callbackHandler
;
45 private Subject subject
;
47 private Long waitBetweenFailedLoginAttempts
= 5 * 1000l;
49 /** Comma separated list of locales */
50 private String availableLocales
= "";
52 private AuthorizationPrincipal auth
= null;
53 private Locale selectedLocale
= null;
55 private LdapShaPasswordEncoder shaPasswordEncoder
= new LdapShaPasswordEncoder();
57 public UserAdminLoginModule() {
61 @SuppressWarnings("rawtypes")
62 public void initialize(Subject subject
, CallbackHandler callbackHandler
,
63 Map sharedState
, Map options
) {
64 this.callbackHandler
= callbackHandler
;
65 this.subject
= subject
;
68 public boolean login() throws LoginException
{
70 // TODO thread already logged in
71 // AuthorizationPrincipal principal = subject
72 // .getPrincipals(AuthorizationPrincipal.class).iterator();
74 if (callbackHandler
== null)
75 throw new LoginException("No call back handler available");
77 // ask for username and password
78 NameCallback nameCallback
= new NameCallback("User");
79 PasswordCallback passwordCallback
= new PasswordCallback(
81 LocaleCallback localeCallback
= new LocaleCallback(availableLocales
);
82 BundleContextCallback bundleContextCallback
= new BundleContextCallback();
84 callbackHandler
.handle(new Callback
[] { nameCallback
,
85 passwordCallback
, localeCallback
, bundleContextCallback
});
87 selectedLocale
= localeCallback
.getSelectedLocale();
90 final String username
= nameCallback
.getName();
91 if (username
== null || username
.trim().equals(""))
95 if (passwordCallback
.getPassword() != null)
96 password
= passwordCallback
.getPassword();
98 BundleContext bc
= bundleContextCallback
.getBundleContext();
99 UserAdmin userAdmin
= bc
.getService(bc
100 .getServiceReference(UserAdmin
.class));
102 User user
= (User
) userAdmin
.getRole(username
);
104 boolean authenticated
= user
.hasCredential(
105 ArgeoNames
.ARGEO_PASSWORD
, new String(password
));
107 if (!authenticated
) {
108 // wait between failed login attempts
109 Thread
.sleep(waitBetweenFailedLoginAttempts
);
113 Authorization authorization
= userAdmin
.getAuthorization(user
);
114 auth
= new AuthorizationPrincipal(authorization
);
116 } catch (LoginException e
) {
118 } catch (ThreadDeath e
) {
119 LoginException le
= new LoginException(
120 "Spring Security login thread died");
123 } catch (Exception e
) {
124 LoginException le
= new LoginException(
125 "Spring Security login failed");
132 public boolean logout() throws LoginException
{
133 subject
.getPrincipals(AuthorizationPrincipal
.class).remove(auth
);
138 public boolean commit() throws LoginException
{
139 subject
.getPrincipals().add(auth
);
140 if (selectedLocale
!= null)
141 LocaleUtils
.threadLocale
.set(selectedLocale
);
146 public boolean abort() throws LoginException
{
148 selectedLocale
= null;
152 public void setAvailableLocales(String locales
) {
153 this.availableLocales
= locales
;