]> git.argeo.org Git - lgpl/argeo-commons.git/blob - HttpSessionLoginModule.java
491acf9bc4cbfc75863bdbc0a77401bbbd44751a
[lgpl/argeo-commons.git] / HttpSessionLoginModule.java
1 package org.argeo.cms.auth;
2
3 import java.io.IOException;
4 import java.util.Collection;
5 import java.util.Map;
6
7 import javax.security.auth.Subject;
8 import javax.security.auth.callback.Callback;
9 import javax.security.auth.callback.CallbackHandler;
10 import javax.security.auth.callback.UnsupportedCallbackException;
11 import javax.security.auth.login.LoginException;
12 import javax.security.auth.spi.LoginModule;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpSession;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.cms.CmsException;
19 import org.argeo.cms.internal.kernel.WebCmsSessionImpl;
20 import org.osgi.framework.BundleContext;
21 import org.osgi.framework.FrameworkUtil;
22 import org.osgi.framework.InvalidSyntaxException;
23 import org.osgi.framework.ServiceReference;
24 import org.osgi.service.http.HttpContext;
25 import org.osgi.service.useradmin.Authorization;
26
27 public class HttpSessionLoginModule implements LoginModule, AuthConstants {
28 private final static Log log = LogFactory.getLog(HttpSessionLoginModule.class);
29
30 private Subject subject = null;
31 private CallbackHandler callbackHandler = null;
32 private Map<String, Object> sharedState = null;
33
34 private HttpServletRequest request = null;
35
36 private BundleContext bc;
37
38 private Authorization authorization;
39
40 @SuppressWarnings("unchecked")
41 @Override
42 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
43 Map<String, ?> options) {
44 bc = FrameworkUtil.getBundle(HttpSessionLoginModule.class).getBundleContext();
45 assert bc != null;
46 this.subject = subject;
47 this.callbackHandler = callbackHandler;
48 this.sharedState = (Map<String, Object>) sharedState;
49 }
50
51 @Override
52 public boolean login() throws LoginException {
53 HttpRequestCallback httpCallback = new HttpRequestCallback();
54 try {
55 callbackHandler.handle(new Callback[] { httpCallback });
56 } catch (IOException e) {
57 throw new LoginException("Cannot handle http callback: " + e.getMessage());
58 } catch (UnsupportedCallbackException e) {
59 return false;
60 }
61 request = httpCallback.getRequest();
62 if (request == null)
63 return false;
64 authorization = checkHttp();
65 if (authorization == null)
66 return false;
67 sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
68 return true;
69 }
70
71 private Authorization checkHttp() {
72 Authorization authorization = null;
73 if (request != null) {
74 authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
75 if (authorization == null) {
76 String httpSessionId = request.getSession().getId();
77 authorization = (Authorization) request.getSession().getAttribute(HttpContext.AUTHORIZATION);
78 if (authorization == null) {
79 Collection<ServiceReference<WebCmsSession>> sr;
80 try {
81 sr = bc.getServiceReferences(WebCmsSession.class,
82 "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
83 } catch (InvalidSyntaxException e) {
84 throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
85 }
86 if (sr.size() == 1) {
87 WebCmsSession cmsSession = bc.getService(sr.iterator().next());
88 authorization = cmsSession.getAuthorization();
89 if (log.isTraceEnabled())
90 log.trace("Retrieved authorization from " + cmsSession);
91 } else if (sr.size() == 0)
92 return null;
93 else
94 throw new CmsException(
95 sr.size() + ">1 web sessions detected for http session " + httpSessionId);
96 }
97 }
98 }
99 return authorization;
100 }
101
102 @Override
103 public boolean commit() throws LoginException {
104 // TODO create CmsSession in another module
105 if (authorization == null) {
106 authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION);
107 } else { // this login module did the authorization
108 CmsAuthUtils.addAuthentication(subject, authorization);
109 }
110 if (authorization == null) {
111 return false;
112 }
113 if (request == null)
114 return false;
115 String httpSessionId = request.getSession().getId();
116 if (authorization.getName() != null) {
117 request.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
118 request.setAttribute(HttpContext.AUTHORIZATION, authorization);
119
120 HttpSession httpSession = request.getSession();
121 if (httpSession.getAttribute(HttpContext.AUTHORIZATION) == null) {
122
123 Collection<ServiceReference<WebCmsSession>> sr;
124 try {
125 sr = bc.getServiceReferences(WebCmsSession.class,
126 "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
127 } catch (InvalidSyntaxException e) {
128 throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
129 }
130 ServiceReference<WebCmsSession> cmsSessionRef;
131 if (sr.size() == 1) {
132 cmsSessionRef = sr.iterator().next();
133 } else if (sr.size() == 0) {
134 WebCmsSessionImpl cmsSessionImpl = new WebCmsSessionImpl(httpSessionId, authorization);
135 cmsSessionRef = cmsSessionImpl.getServiceRegistration().getReference();
136 if (log.isDebugEnabled())
137 log.debug("Initialized " + cmsSessionImpl + " for " + authorization.getName());
138 } else
139 throw new CmsException(sr.size() + " CMS sessions registered for " + httpSessionId);
140
141 WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(cmsSessionRef);
142 cmsSession.addHttpSession(request);
143 if (log.isTraceEnabled())
144 log.trace("Added " + request.getServletPath() + " to " + cmsSession + " (" + request.getRequestURI()
145 + ")");
146 httpSession.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
147 httpSession.setAttribute(HttpContext.AUTHORIZATION, authorization);
148 }
149 }
150 if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0)
151 subject.getPrivateCredentials().add(new HttpSessionId(httpSessionId));
152 else {
153 String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
154 if (storedSessionId.equals(httpSessionId))
155 throw new LoginException(
156 "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")");
157 }
158
159 if (authorization != null) {
160 CmsAuthUtils.addAuthentication(subject, authorization);
161 return true;
162 } else {
163 return false;
164 }
165 }
166
167 @Override
168 public boolean abort() throws LoginException {
169 return false;
170 }
171
172 @Override
173 public boolean logout() throws LoginException {
174 String httpSessionId;
175 if (subject.getPrivateCredentials(HttpSessionId.class).size() == 1)
176 httpSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
177 else
178 return false;
179 Collection<ServiceReference<WebCmsSession>> srs;
180 try {
181 srs = bc.getServiceReferences(WebCmsSession.class,
182 "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
183 } catch (InvalidSyntaxException e) {
184 throw new CmsException("Cannot retrieve CMS session #" + httpSessionId, e);
185 }
186
187 if (srs.size() == 0)
188 throw new CmsException("No CMS web session found for http session " + httpSessionId);
189 else if (srs.size() > 1)
190 throw new CmsException(srs.size() + " CMS web sessions found for http session " + httpSessionId);
191
192 WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(srs.iterator().next());
193 cmsSession.cleanUp();
194 subject.getPrivateCredentials().removeAll(subject.getPrivateCredentials(HttpSessionId.class));
195 if (log.isDebugEnabled())
196 log.debug("Cleaned up " + cmsSession);
197 return true;
198 }
199
200 }