1 package org
.argeo
.cms
.auth
;
3 import java
.io
.IOException
;
4 import java
.security
.cert
.X509Certificate
;
5 import java
.util
.Collection
;
7 import java
.util
.StringTokenizer
;
9 import javax
.security
.auth
.Subject
;
10 import javax
.security
.auth
.callback
.Callback
;
11 import javax
.security
.auth
.callback
.CallbackHandler
;
12 import javax
.security
.auth
.callback
.UnsupportedCallbackException
;
13 import javax
.security
.auth
.login
.LoginException
;
14 import javax
.security
.auth
.spi
.LoginModule
;
15 import javax
.servlet
.http
.HttpServletRequest
;
17 import org
.apache
.commons
.codec
.binary
.Base64
;
18 import org
.apache
.commons
.logging
.Log
;
19 import org
.apache
.commons
.logging
.LogFactory
;
20 import org
.argeo
.cms
.CmsException
;
21 import org
.osgi
.framework
.BundleContext
;
22 import org
.osgi
.framework
.FrameworkUtil
;
23 import org
.osgi
.framework
.InvalidSyntaxException
;
24 import org
.osgi
.framework
.ServiceReference
;
25 import org
.osgi
.service
.http
.HttpContext
;
26 import org
.osgi
.service
.useradmin
.Authorization
;
28 public class HttpSessionLoginModule
implements LoginModule
{
29 private final static Log log
= LogFactory
.getLog(HttpSessionLoginModule
.class);
31 private Subject subject
= null;
32 private CallbackHandler callbackHandler
= null;
33 private Map
<String
, Object
> sharedState
= null;
35 private HttpServletRequest request
= null;
37 private BundleContext bc
;
39 private Authorization authorization
;
41 @SuppressWarnings("unchecked")
43 public void initialize(Subject subject
, CallbackHandler callbackHandler
, Map
<String
, ?
> sharedState
,
44 Map
<String
, ?
> options
) {
45 bc
= FrameworkUtil
.getBundle(HttpSessionLoginModule
.class).getBundleContext();
47 this.subject
= subject
;
48 this.callbackHandler
= callbackHandler
;
49 this.sharedState
= (Map
<String
, Object
>) sharedState
;
53 public boolean login() throws LoginException
{
54 if (callbackHandler
== null)
56 HttpRequestCallback httpCallback
= new HttpRequestCallback();
58 callbackHandler
.handle(new Callback
[] { httpCallback
});
59 } catch (IOException e
) {
60 throw new LoginException("Cannot handle http callback: " + e
.getMessage());
61 } catch (UnsupportedCallbackException e
) {
64 request
= httpCallback
.getRequest();
67 authorization
= (Authorization
) request
.getAttribute(HttpContext
.AUTHORIZATION
);
68 if (authorization
== null) {// search by session ID
69 String httpSessionId
= request
.getSession().getId();
70 // authorization = (Authorization)
71 // request.getSession().getAttribute(HttpContext.AUTHORIZATION);
72 // if (authorization == null) {
73 Collection
<ServiceReference
<WebCmsSession
>> sr
;
75 sr
= bc
.getServiceReferences(WebCmsSession
.class,
76 "(" + WebCmsSession
.CMS_SESSION_ID
+ "=" + httpSessionId
+ ")");
77 } catch (InvalidSyntaxException e
) {
78 throw new CmsException("Cannot get CMS session for id " + httpSessionId
, e
);
81 WebCmsSession cmsSession
= bc
.getService(sr
.iterator().next());
82 authorization
= cmsSession
.getAuthorization();
83 if (log
.isTraceEnabled())
84 log
.trace("Retrieved authorization from " + cmsSession
);
85 } else if (sr
.size() == 0)
88 throw new CmsException(sr
.size() + ">1 web sessions detected for http session " + httpSessionId
);
91 sharedState
.put(CmsAuthUtils
.SHARED_STATE_HTTP_REQUEST
, request
);
92 extractHttpAuth(request
);
93 extractClientCertificate(request
);
94 if (authorization
== null)
96 sharedState
.put(CmsAuthUtils
.SHARED_STATE_AUTHORIZATION
, authorization
);
100 // private Authorization checkHttp() {
101 // Authorization authorization = null;
102 // if (request != null) {
103 // authorization = (Authorization)
104 // request.getAttribute(HttpContext.AUTHORIZATION);
105 // if (authorization == null) {
106 // String httpSessionId = request.getSession().getId();
107 // authorization = (Authorization)
108 // request.getSession().getAttribute(HttpContext.AUTHORIZATION);
109 // if (authorization == null) {
110 // Collection<ServiceReference<WebCmsSession>> sr;
112 // sr = bc.getServiceReferences(WebCmsSession.class,
113 // "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
114 // } catch (InvalidSyntaxException e) {
115 // throw new CmsException("Cannot get CMS session for id " + httpSessionId,
118 // if (sr.size() == 1) {
119 // WebCmsSession cmsSession = bc.getService(sr.iterator().next());
120 // authorization = cmsSession.getAuthorization();
121 // if (log.isTraceEnabled())
122 // log.trace("Retrieved authorization from " + cmsSession);
123 // } else if (sr.size() == 0)
126 // throw new CmsException(
127 // sr.size() + ">1 web sessions detected for http session " +
132 // return authorization;
136 public boolean commit() throws LoginException
{
137 // TODO create CmsSession in another module
138 Authorization authorizationToRegister
;
139 if (authorization
== null) {
140 authorizationToRegister
= (Authorization
) sharedState
.get(CmsAuthUtils
.SHARED_STATE_AUTHORIZATION
);
141 } else { // this login module did the authorization
142 CmsAuthUtils
.addAuthentication(subject
, authorization
);
143 authorizationToRegister
= authorization
;
145 if (authorizationToRegister
== null) {
150 CmsAuthUtils
.registerSessionAuthorization(bc
, request
, subject
, authorizationToRegister
);
152 if (authorization
!= null) {
153 // CmsAuthUtils.addAuthentication(subject, authorization);
163 public boolean abort() throws LoginException
{
168 private void cleanUp() {
169 authorization
= null;
174 public boolean logout() throws LoginException
{
175 return CmsAuthUtils
.logoutSession(bc
, subject
);
178 private void extractHttpAuth(final HttpServletRequest httpRequest
) {
179 String authHeader
= httpRequest
.getHeader(CmsAuthUtils
.HEADER_AUTHORIZATION
);
180 if (authHeader
!= null) {
181 StringTokenizer st
= new StringTokenizer(authHeader
);
182 if (st
.hasMoreTokens()) {
183 String basic
= st
.nextToken();
184 if (basic
.equalsIgnoreCase("Basic")) {
186 // TODO manipulate char[]
187 String credentials
= new String(Base64
.decodeBase64(st
.nextToken()), "UTF-8");
188 // log.debug("Credentials: " + credentials);
189 int p
= credentials
.indexOf(":");
191 final String login
= credentials
.substring(0, p
).trim();
192 final char[] password
= credentials
.substring(p
+ 1).trim().toCharArray();
193 sharedState
.put(CmsAuthUtils
.SHARED_STATE_NAME
, login
);
194 sharedState
.put(CmsAuthUtils
.SHARED_STATE_PWD
, password
);
196 throw new CmsException("Invalid authentication token");
198 } catch (Exception e
) {
199 throw new CmsException("Couldn't retrieve authentication", e
);
201 } else if (basic
.equalsIgnoreCase("Negotiate")) {
202 String spnegoToken
= st
.nextToken();
203 byte[] authToken
= Base64
.decodeBase64(spnegoToken
);
204 sharedState
.put(CmsAuthUtils
.SHARED_STATE_SPNEGO_TOKEN
, authToken
);
210 private X509Certificate
[] extractClientCertificate(HttpServletRequest req
) {
211 X509Certificate
[] certs
= (X509Certificate
[]) req
.getAttribute("javax.servlet.request.X509Certificate");
212 if (null != certs
&& certs
.length
> 0) {