Improve IPA
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 5 Feb 2017 21:46:45 +0000 (22:46 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 5 Feb 2017 21:46:45 +0000 (22:46 +0100)
demo/argeo_node_rap.properties
demo/init/node/.gitignore [new file with mode: 0644]
org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java
org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java
org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java
org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg
org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java

index 3e7ec66518173db14abda17eb9bb984c87303a33..88ab23abf87da8e216cac95be2df903fd9174b61 100644 (file)
@@ -72,4 +72,5 @@ log4j.configuration=file:../../log4j.properties
 
 # DON'T CHANGE BELOW
 org.eclipse.rap.workbenchAutostart=false
-org.eclipse.equinox.http.jetty.autostart=false
\ No newline at end of file
+org.eclipse.equinox.http.jetty.autostart=false
+javax.security.auth.useSubjectCredsOnly=false
diff --git a/demo/init/node/.gitignore b/demo/init/node/.gitignore
new file mode 100644 (file)
index 0000000..288267a
--- /dev/null
@@ -0,0 +1 @@
+/krb5.keytab
index f310f31e2b907c3b6a8b939eb578a911a2291eab..22a2ba3e1dbec9f6c74fe922b822c9845eb0256d 100644 (file)
@@ -72,7 +72,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                // Initial login
                try {
                        loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
-                                       new HttpRequestCallbackHandler(UiContext.getHttpRequest()));
+                                       new HttpRequestCallbackHandler(UiContext.getHttpRequest(), UiContext.getHttpResponse()));
                        loginContext.login();
                } catch (LoginException e) {
                        try {
index 1809998070bc5e2a724a90b34b4e02a58cfd93fb..54f0ac395251e08e143d91caf455138d58edc402 100644 (file)
@@ -284,8 +284,10 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                                ((NameCallback) callback).setName(usernameT.getText());
                        else if (callback instanceof PasswordCallback && passwordT != null)
                                ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
-                       else if (callback instanceof HttpRequestCallback)
+                       else if (callback instanceof HttpRequestCallback){
                                ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
+                               ((HttpRequestCallback) callback).setResponse(UiContext.getHttpResponse());
+                       }
                        else if (callback instanceof LanguageCallback && localeChoice != null)
                                ((LanguageCallback) callback).setLocale(localeChoice.getSelectedLocale());
                }
index 1562d5cd0f8cad6d345e861977ad40a8d174f9f6..2432d9c0a45b5a1947e8b0d2d38deb184d07140e 100644 (file)
@@ -32,18 +32,19 @@ class CmsAuthUtils {
        private final static Log log = LogFactory.getLog(CmsAuthUtils.class);
 
        /** Shared HTTP request */
-       static final String SHARED_STATE_HTTP_REQUEST = "org.argeo.cms.auth.http.request";
+       final static String SHARED_STATE_HTTP_REQUEST = "org.argeo.cms.auth.http.request";
        /** From org.osgi.service.http.HttpContext */
-       static final String SHARED_STATE_AUTHORIZATION = "org.osgi.service.useradmin.authorization";
+       final static String SHARED_STATE_AUTHORIZATION = "org.osgi.service.useradmin.authorization";
        /** From com.sun.security.auth.module.*LoginModule */
-       static final String SHARED_STATE_NAME = "javax.security.auth.login.name";
+       final static String SHARED_STATE_NAME = "javax.security.auth.login.name";
        /** From com.sun.security.auth.module.*LoginModule */
-       static final String SHARED_STATE_PWD = "javax.security.auth.login.password";
+       final static String SHARED_STATE_PWD = "javax.security.auth.login.password";
 
-       static final String SHARED_STATE_SPNEGO_TOKEN = "org.argeo.cms.auth.spnegoToken";
-       static final String SHARED_STATE_SPNEGO_OUT_TOKEN = "org.argeo.cms.auth.spnegoOutToken";
+       final static String SHARED_STATE_SPNEGO_TOKEN = "org.argeo.cms.auth.spnegoToken";
+       final static String SHARED_STATE_SPNEGO_OUT_TOKEN = "org.argeo.cms.auth.spnegoOutToken";
 
-       static final String HEADER_AUTHORIZATION = "Authorization";
+       final static String HEADER_AUTHORIZATION = "Authorization";
+       final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
 
        static void addAuthentication(Subject subject, Authorization authorization) {
                assert subject != null;
index d87e70474175b1b5b94369dbfaf018e2c9936227..611b324d54fb88d81f900f2f3ecb0b25a42e0de1 100644 (file)
@@ -2,9 +2,11 @@ package org.argeo.cms.auth;
 
 import javax.security.auth.callback.Callback;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 public class HttpRequestCallback implements Callback {
        private HttpServletRequest request;
+       private HttpServletResponse response;
 
        public HttpServletRequest getRequest() {
                return request;
@@ -13,4 +15,13 @@ public class HttpRequestCallback implements Callback {
        public void setRequest(HttpServletRequest request) {
                this.request = request;
        }
+
+       public HttpServletResponse getResponse() {
+               return response;
+       }
+
+       public void setResponse(HttpServletResponse response) {
+               this.response = response;
+       }
+
 }
index 0486d7479daa1ddbc14925b61e966ab427e08fdb..191a114523fd595c054df750b96d8c67169b6ebd 100644 (file)
@@ -6,6 +6,7 @@ import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 /**
  * Callback handler populating {@link HttpRequestCallback}s with the provided
@@ -13,17 +14,20 @@ import javax.servlet.http.HttpServletRequest;
  */
 public class HttpRequestCallbackHandler implements CallbackHandler {
        final private HttpServletRequest request;
+       final private HttpServletResponse response;
 
-       public HttpRequestCallbackHandler(HttpServletRequest request) {
+       public HttpRequestCallbackHandler(HttpServletRequest request, HttpServletResponse response) {
                this.request = request;
+               this.response = response;
        }
 
        @Override
-       public void handle(Callback[] callbacks) throws IOException,
-                       UnsupportedCallbackException {
+       public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (Callback callback : callbacks)
-                       if (callback instanceof HttpRequestCallback)
+                       if (callback instanceof HttpRequestCallback) {
                                ((HttpRequestCallback) callback).setRequest(request);
+                               ((HttpRequestCallback) callback).setResponse(response);
+                       }
        }
 
 }
index b450401ff015bd5aaf268f9b000b065f5e87296f..382d8fe4add66aba512eb1305485d1efeaf512ed 100644 (file)
@@ -13,6 +13,7 @@ import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.logging.Log;
@@ -33,6 +34,7 @@ public class HttpSessionLoginModule implements LoginModule {
        private Map<String, Object> sharedState = null;
 
        private HttpServletRequest request = null;
+       private HttpServletResponse response = null;
 
        private BundleContext bc;
 
@@ -97,41 +99,6 @@ public class HttpSessionLoginModule implements LoginModule {
                return true;
        }
 
-       // private Authorization checkHttp() {
-       // Authorization authorization = null;
-       // if (request != null) {
-       // authorization = (Authorization)
-       // request.getAttribute(HttpContext.AUTHORIZATION);
-       // if (authorization == null) {
-       // String httpSessionId = request.getSession().getId();
-       // authorization = (Authorization)
-       // request.getSession().getAttribute(HttpContext.AUTHORIZATION);
-       // if (authorization == null) {
-       // Collection<ServiceReference<WebCmsSession>> sr;
-       // try {
-       // sr = bc.getServiceReferences(WebCmsSession.class,
-       // "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
-       // } catch (InvalidSyntaxException e) {
-       // throw new CmsException("Cannot get CMS session for id " + httpSessionId,
-       // e);
-       // }
-       // if (sr.size() == 1) {
-       // WebCmsSession cmsSession = bc.getService(sr.iterator().next());
-       // authorization = cmsSession.getAuthorization();
-       // if (log.isTraceEnabled())
-       // log.trace("Retrieved authorization from " + cmsSession);
-       // } else if (sr.size() == 0)
-       // return null;
-       // else
-       // throw new CmsException(
-       // sr.size() + ">1 web sessions detected for http session " +
-       // httpSessionId);
-       // }
-       // }
-       // }
-       // return authorization;
-       // }
-
        @Override
        public boolean commit() throws LoginException {
                // TODO create CmsSession in another module
@@ -149,6 +116,12 @@ public class HttpSessionLoginModule implements LoginModule {
                        return false;
                CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorizationToRegister);
 
+               byte[] outToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_OUT_TOKEN);
+               if (outToken != null) {
+                       response.setHeader(CmsAuthUtils.HEADER_WWW_AUTHENTICATE,
+                                       "Negotiate " + java.util.Base64.getEncoder().encodeToString(outToken));
+               }
+
                if (authorization != null) {
                        // CmsAuthUtils.addAuthentication(subject, authorization);
                        cleanUp();
index c9b44aa8e64e15d5c640cd9ad5338eae5d12d92e..bd444466871bcf3d8be4c9efc2e4f30c20e6b6a5 100644 (file)
@@ -149,13 +149,13 @@ class DataHttp implements KernelConstants {
                return NodeConstants.PATH_FILES + "/" + alias;
        }
 
-       private Subject subjectFromRequest(HttpServletRequest request) {
+       private Subject subjectFromRequest(HttpServletRequest request, HttpServletResponse response) {
                Authorization authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
                if (authorization == null)
                        throw new CmsException("Not authenticated");
                try {
                        LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
-                                       new HttpRequestCallbackHandler(request));
+                                       new HttpRequestCallbackHandler(request, response));
                        lc.login();
                        return lc.getSubject();
                } catch (LoginException e) {
@@ -165,18 +165,18 @@ class DataHttp implements KernelConstants {
 
        private void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) {
                response.setStatus(401);
-                response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\"" +
-                httpAuthRealm + "\"");
-               
+               response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\"" + httpAuthRealm + "\"");
+
                // SPNEGO
-//             response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate");
-//             response.setDateHeader("Date", System.currentTimeMillis());
-//             response.setDateHeader("Expires", System.currentTimeMillis() + (24 * 60 * 60 * 1000));
-//             response.setHeader("Accept-Ranges", "bytes");
-//             response.setHeader("Connection", "Keep-Alive");
-//             response.setHeader("Keep-Alive", "timeout=5, max=97");
-//             response.setContentType("text/html; charset=UTF-8");
-               
+               // response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate");
+               // response.setDateHeader("Date", System.currentTimeMillis());
+               // response.setDateHeader("Expires", System.currentTimeMillis() + (24 *
+               // 60 * 60 * 1000));
+               // response.setHeader("Accept-Ranges", "bytes");
+               // response.setHeader("Connection", "Keep-Alive");
+               // response.setHeader("Keep-Alive", "timeout=5, max=97");
+               // response.setContentType("text/html; charset=UTF-8");
+
        }
 
        private CallbackHandler extractHttpAuth(final HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
@@ -201,8 +201,10 @@ class DataHttp implements KernelConstants {
                                                                                        ((NameCallback) cb).setName(login);
                                                                                else if (cb instanceof PasswordCallback)
                                                                                        ((PasswordCallback) cb).setPassword(password);
-                                                                               else if (cb instanceof HttpRequestCallback)
+                                                                               else if (cb instanceof HttpRequestCallback) {
                                                                                        ((HttpRequestCallback) cb).setRequest(httpRequest);
+                                                                                       ((HttpRequestCallback) cb).setResponse(httpResponse);
+                                                                               }
                                                                        }
                                                                }
                                                        };
@@ -231,7 +233,7 @@ class DataHttp implements KernelConstants {
                                                        while (!gContext.isEstablished()) {
                                                                byte[] outToken = gContext.acceptSecContext(authToken, 0, authToken.length);
                                                                String outTokenStr = Base64.encodeBase64String(outToken);
-                                                               httpResponse.setHeader("WWW-Authenticate","Negotiate "+ outTokenStr);
+                                                               httpResponse.setHeader("WWW-Authenticate", "Negotiate " + outTokenStr);
                                                        }
                                                        if (gContext.isEstablished()) {
                                                                String clientName = gContext.getSrcName().toString();
@@ -241,13 +243,13 @@ class DataHttp implements KernelConstants {
                                                                log.debug("Client Principal is: " + gContext.getSrcName());
                                                                log.debug("Server Principal is: " + gContext.getTargName());
                                                                log.debug("Client Default Role: " + role);
-                                                               
+
                                                                // TODO log in
                                                        }
                                                }
 
                                        } catch (GSSException gsse) {
-                                               log.warn(gsse,gsse);
+                                               log.warn(gsse, gsse);
                                        }
 
                                }
@@ -292,11 +294,12 @@ class DataHttp implements KernelConstants {
                                KernelUtils.logRequestHeaders(log, request);
                        LoginContext lc;
                        try {
-                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request));
+                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
+                                               new HttpRequestCallbackHandler(request, response));
                                lc.login();
                                // return true;
                        } catch (LoginException e) {
-                               CallbackHandler token = extractHttpAuth(request,response);
+                               CallbackHandler token = extractHttpAuth(request, response);
                                if (token != null) {
                                        try {
                                                lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token);
@@ -344,11 +347,12 @@ class DataHttp implements KernelConstants {
                                KernelUtils.logRequestHeaders(log, request);
                        LoginContext lc;
                        try {
-                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request));
+                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
+                                               new HttpRequestCallbackHandler(request, response));
                                lc.login();
                                // return true;
                        } catch (LoginException e) {
-                               CallbackHandler token = extractHttpAuth(request,response);
+                               CallbackHandler token = extractHttpAuth(request, response);
                                if (token != null) {
                                        try {
                                                lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token);
@@ -404,10 +408,11 @@ class DataHttp implements KernelConstants {
                                KernelUtils.logRequestHeaders(log, request);
                        LoginContext lc;
                        try {
-                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request));
+                               lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
+                                               new HttpRequestCallbackHandler(request, response));
                                lc.login();
                        } catch (CredentialNotFoundException e) {
-                               CallbackHandler token = extractHttpAuth(request,response);
+                               CallbackHandler token = extractHttpAuth(request, response);
                                if (token != null) {
                                        try {
                                                lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token);
@@ -558,7 +563,7 @@ class DataHttp implements KernelConstants {
                protected void service(final HttpServletRequest request, final HttpServletResponse response)
                                throws ServletException, IOException {
                        try {
-                               Subject subject = subjectFromRequest(request);
+                               Subject subject = subjectFromRequest(request, response);
                                Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
                                        @Override
                                        public Void run() throws Exception {
index 38fe3705f26b2f4c4b942dd47d9b1adf50f2a733..52bf4c37567456048d55a19d441dd27d21ae6d09 100644 (file)
@@ -13,7 +13,8 @@ NODE {
     com.sun.security.auth.module.Krb5LoginModule optional
      keyTab="${osgi.instance.area}node/krb5.keytab" 
      useKeyTab=true
-     storeKey=true;
+     storeKey=true
+     debug=true;
     org.argeo.cms.auth.DataAdminLoginModule requisite;
 };
 
index ec3b2e96a62eb18cd162a25b167625223e03e984..dac270026311815f71d8cd5b20c358c03546a310 100644 (file)
@@ -3,6 +3,7 @@ package org.argeo.eclipse.ui.specific;
 import java.util.Locale;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.widgets.Display;
@@ -14,6 +15,10 @@ public class UiContext {
                return RWT.getRequest();
        }
 
+       public static HttpServletResponse getHttpResponse() {
+               return RWT.getResponse();
+       }
+
        public static Locale getLocale() {
                if (Display.getCurrent() != null)
                        return RWT.getUISession().getLocale();
@@ -40,8 +45,7 @@ public class UiContext {
        public static void setData(String key, Object value) {
                Display display = getDisplay();
                if (display == null)
-                       throw new SingleSourcingException(
-                                       "Not display available in RAP context");
+                       throw new SingleSourcingException("Not display available in RAP context");
                display.setData(key, value);
        }