]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/security/core/UserAdminLoginModule.java
Introduce ArgeoUser and ArgeoGroup
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / security / core / UserAdminLoginModule.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.argeo.security.core;
17
18 import java.util.Locale;
19 import java.util.Map;
20
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;
28
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;
37
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);
42
43 private CallbackHandler callbackHandler;
44
45 private Subject subject;
46
47 private Long waitBetweenFailedLoginAttempts = 5 * 1000l;
48
49 /** Comma separated list of locales */
50 private String availableLocales = "";
51
52 private AuthorizationPrincipal auth = null;
53 private Locale selectedLocale = null;
54
55 private LdapShaPasswordEncoder shaPasswordEncoder = new LdapShaPasswordEncoder();
56
57 public UserAdminLoginModule() {
58
59 }
60
61 @SuppressWarnings("rawtypes")
62 public void initialize(Subject subject, CallbackHandler callbackHandler,
63 Map sharedState, Map options) {
64 this.callbackHandler = callbackHandler;
65 this.subject = subject;
66 }
67
68 public boolean login() throws LoginException {
69 try {
70 // TODO thread already logged in
71 // AuthorizationPrincipal principal = subject
72 // .getPrincipals(AuthorizationPrincipal.class).iterator();
73
74 if (callbackHandler == null)
75 throw new LoginException("No call back handler available");
76
77 // ask for username and password
78 NameCallback nameCallback = new NameCallback("User");
79 PasswordCallback passwordCallback = new PasswordCallback(
80 "Password", false);
81 LocaleCallback localeCallback = new LocaleCallback(availableLocales);
82 BundleContextCallback bundleContextCallback = new BundleContextCallback();
83
84 callbackHandler.handle(new Callback[] { nameCallback,
85 passwordCallback, localeCallback, bundleContextCallback });
86
87 selectedLocale = localeCallback.getSelectedLocale();
88
89 // create credentials
90 final String username = nameCallback.getName();
91 if (username == null || username.trim().equals(""))
92 return false;
93
94 char[] password = {};
95 if (passwordCallback.getPassword() != null)
96 password = passwordCallback.getPassword();
97
98 BundleContext bc = bundleContextCallback.getBundleContext();
99 UserAdmin userAdmin = bc.getService(bc
100 .getServiceReference(UserAdmin.class));
101
102 User user = (User) userAdmin.getRole(username);
103 // TODO use hash
104 boolean authenticated = user.hasCredential(
105 ArgeoNames.ARGEO_PASSWORD, new String(password));
106
107 if (!authenticated) {
108 // wait between failed login attempts
109 Thread.sleep(waitBetweenFailedLoginAttempts);
110 return false;
111 }
112
113 Authorization authorization = userAdmin.getAuthorization(user);
114 auth = new AuthorizationPrincipal(authorization);
115 return true;
116 } catch (LoginException e) {
117 throw e;
118 } catch (ThreadDeath e) {
119 LoginException le = new LoginException(
120 "Spring Security login thread died");
121 le.initCause(e);
122 throw le;
123 } catch (Exception e) {
124 LoginException le = new LoginException(
125 "Spring Security login failed");
126 le.initCause(e);
127 throw le;
128 }
129 }
130
131 @Override
132 public boolean logout() throws LoginException {
133 subject.getPrincipals(AuthorizationPrincipal.class).remove(auth);
134 return true;
135 }
136
137 @Override
138 public boolean commit() throws LoginException {
139 subject.getPrincipals().add(auth);
140 if (selectedLocale != null)
141 LocaleUtils.threadLocale.set(selectedLocale);
142 return true;
143 }
144
145 @Override
146 public boolean abort() throws LoginException {
147 auth = null;
148 selectedLocale = null;
149 return true;
150 }
151
152 public void setAvailableLocales(String locales) {
153 this.availableLocales = locales;
154 }
155 }