Improve Jetty integration in order to support consistent HTTP sessions.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / RemoteSessionLoginModule.java
index 4d3617eefc4150e01fdc07075b87d61ae03ce252..772531ede5f53f213a10c8cbc510d275542809f4 100644 (file)
@@ -15,14 +15,14 @@ import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 
 import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.CmsDeployProperty;
 import org.argeo.cms.internal.auth.CmsSessionImpl;
-import org.argeo.cms.internal.kernel.Activator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.service.http.HttpContext;
+import org.argeo.cms.internal.runtime.CmsContextImpl;
+import org.argeo.cms.internal.runtime.CmsStateImpl;
+import org.argeo.util.http.HttpHeader;
 import org.osgi.service.useradmin.Authorization;
 
-/** Use the HTTP session as the basis for authentication. */
+/** Use a remote session as the basis for authentication. */
 public class RemoteSessionLoginModule implements LoginModule {
        private final static CmsLog log = CmsLog.getLog(RemoteSessionLoginModule.class);
 
@@ -33,8 +33,6 @@ public class RemoteSessionLoginModule implements LoginModule {
        private RemoteAuthRequest request = null;
        private RemoteAuthResponse response = null;
 
-       private BundleContext bc;
-
        private Authorization authorization;
        private Locale locale;
 
@@ -42,8 +40,6 @@ public class RemoteSessionLoginModule implements LoginModule {
        @Override
        public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
                        Map<String, ?> options) {
-               bc = FrameworkUtil.getBundle(RemoteSessionLoginModule.class).getBundleContext();
-               assert bc != null;
                this.subject = subject;
                this.callbackHandler = callbackHandler;
                this.sharedState = (Map<String, Object>) sharedState;
@@ -53,49 +49,43 @@ public class RemoteSessionLoginModule implements LoginModule {
        public boolean login() throws LoginException {
                if (callbackHandler == null)
                        return false;
-               RemoteAuthCallback httpCallback = new RemoteAuthCallback();
+               RemoteAuthCallback remoteAuthCallback = new RemoteAuthCallback();
                try {
-                       callbackHandler.handle(new Callback[] { httpCallback });
+                       callbackHandler.handle(new Callback[] { remoteAuthCallback });
                } catch (IOException e) {
                        throw new LoginException("Cannot handle http callback: " + e.getMessage());
                } catch (UnsupportedCallbackException e) {
                        return false;
                }
-               request = httpCallback.getRequest();
+               request = remoteAuthCallback.getRequest();
                if (request == null) {
-                       RemoteAuthSession httpSession = httpCallback.getHttpSession();
+                       RemoteAuthSession httpSession = remoteAuthCallback.getHttpSession();
                        if (httpSession == null)
                                return false;
                        // TODO factorize with below
                        String httpSessionId = httpSession.getId();
-//                     if (log.isTraceEnabled())
-//                             log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
-                       CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
-                       if (cmsSession != null) {
+                       CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
+                       if (cmsSession != null && !cmsSession.isAnonymous()) {
                                authorization = cmsSession.getAuthorization();
                                locale = cmsSession.getLocale();
                                if (log.isTraceEnabled())
                                        log.trace("Retrieved authorization from " + cmsSession);
                        }
                } else {
-                       authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
+                       authorization = (Authorization) request.getAttribute(RemoteAuthRequest.AUTHORIZATION);
                        if (authorization == null) {// search by session ID
                                RemoteAuthSession httpSession = request.getSession();
-                               if (httpSession == null) {
-                                       // TODO make sure this is always safe
-                                       if (log.isTraceEnabled())
-                                               log.trace("Create http session");
-                                       httpSession = request.createSession();
-                               }
-                               String httpSessionId = httpSession.getId();
-//                             if (log.isTraceEnabled())
-//                                     log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
-                               CmsSessionImpl cmsSession = CmsAuthUtils.cmsSessionFromHttpSession(bc, httpSessionId);
-                               if (cmsSession != null) {
-                                       authorization = cmsSession.getAuthorization();
-                                       locale = cmsSession.getLocale();
-                                       if (log.isTraceEnabled())
-                                               log.trace("Retrieved authorization from " + cmsSession);
+                               if (httpSession != null) {
+                                       String httpSessionId = httpSession.getId();
+                                       CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
+                                       if (cmsSession != null && !cmsSession.isAnonymous()) {
+                                               authorization = cmsSession.getAuthorization();
+                                               locale = cmsSession.getLocale();
+                                               if (log.isTraceEnabled())
+                                                       log.trace("Retrieved authorization from " + cmsSession);
+                                       }
+                               }else {
+                                       request.createSession();
                                }
                        }
                        sharedState.put(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST, request);
@@ -109,7 +99,7 @@ public class RemoteSessionLoginModule implements LoginModule {
                } else {
                        if (log.isTraceEnabled())
                                log.trace("HTTP login: " + true);
-                       request.setAttribute(HttpContext.AUTHORIZATION, authorization);
+                       request.setAttribute(RemoteAuthRequest.AUTHORIZATION, authorization);
                        return true;
                }
        }
@@ -118,7 +108,7 @@ public class RemoteSessionLoginModule implements LoginModule {
        public boolean commit() throws LoginException {
                byte[] outToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN);
                if (outToken != null) {
-                       response.setHeader(CmsAuthUtils.HEADER_WWW_AUTHENTICATE,
+                       response.setHeader(HttpHeader.WWW_AUTHENTICATE.getHeaderName(),
                                        "Negotiate " + java.util.Base64.getEncoder().encodeToString(outToken));
                }
 
@@ -156,7 +146,7 @@ public class RemoteSessionLoginModule implements LoginModule {
        }
 
        private void extractHttpAuth(final RemoteAuthRequest httpRequest) {
-               String authHeader = httpRequest.getHeader(CmsAuthUtils.HEADER_AUTHORIZATION);
+               String authHeader = httpRequest.getHeader(HttpHeader.AUTHORIZATION.getHeaderName());
                extractHttpAuth(authHeader);
        }
 
@@ -165,7 +155,7 @@ public class RemoteSessionLoginModule implements LoginModule {
                        StringTokenizer st = new StringTokenizer(authHeader);
                        if (st.hasMoreTokens()) {
                                String basic = st.nextToken();
-                               if (basic.equalsIgnoreCase("Basic")) {
+                               if (basic.equalsIgnoreCase(HttpHeader.BASIC)) {
                                        try {
                                                // TODO manipulate char[]
                                                Base64.Decoder decoder = Base64.getDecoder();
@@ -183,7 +173,7 @@ public class RemoteSessionLoginModule implements LoginModule {
                                        } catch (Exception e) {
                                                throw new IllegalStateException("Couldn't retrieve authentication", e);
                                        }
-                               } else if (basic.equalsIgnoreCase("Negotiate")) {
+                               } else if (basic.equalsIgnoreCase(HttpHeader.NEGOTIATE)) {
                                        String spnegoToken = st.nextToken();
                                        Base64.Decoder decoder = Base64.getDecoder();
                                        byte[] authToken = decoder.decode(spnegoToken);
@@ -191,15 +181,6 @@ public class RemoteSessionLoginModule implements LoginModule {
                                }
                        }
                }
-
-               // auth token
-               // String mail = request.getParameter(LdapAttrs.mail.name());
-               // String authPassword = request.getParameter(LdapAttrs.authPassword.name());
-               // if (authPassword != null) {
-               // sharedState.put(CmsAuthUtils.SHARED_STATE_PWD, authPassword);
-               // if (mail != null)
-               // sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, mail);
-               // }
        }
 
        private void extractClientCertificate(RemoteAuthRequest req) {
@@ -211,7 +192,8 @@ public class RemoteSessionLoginModule implements LoginModule {
                        if (log.isDebugEnabled())
                                log.debug("Client certificate " + certDn + " verified by servlet container");
                } // Reverse proxy verified the client certificate
-               String clientDnHttpHeader = Activator.getHttpProxySslHeader();
+               String clientDnHttpHeader = CmsStateImpl.getDeployProperty(CmsContextImpl.getCmsContext().getCmsState(),
+                               CmsDeployProperty.HTTP_PROXY_SSL_HEADER_DN);
                if (clientDnHttpHeader != null) {
                        String certDn = req.getHeader(clientDnHttpHeader);
                        // TODO retrieve more cf. https://httpd.apache.org/docs/current/mod/mod_ssl.html