Work on servlet securitxy integration.
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 3 Nov 2020 07:45:31 +0000 (08:45 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 3 Nov 2020 07:45:31 +0000 (08:45 +0100)
org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/ServletAuthUtils.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/integration/CmsPrivateServletContext.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg
org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java

index eb43ead247d13348ac027825c77a590d436b1fc2..acc0ba4e8ff58ee0a4fc437e24065bc5ab5873fc 100644 (file)
@@ -113,6 +113,7 @@ public class HttpSessionLoginModule implements LoginModule {
                } else {
                        if (log.isTraceEnabled())
                                log.trace("HTTP login: " + true);
+                       request.setAttribute(HttpContext.AUTHORIZATION, authorization);
                        return true;
                }
        }
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/ServletAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/ServletAuthUtils.java
new file mode 100644 (file)
index 0000000..9cb7fdc
--- /dev/null
@@ -0,0 +1,42 @@
+package org.argeo.cms.auth;
+
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.function.Supplier;
+
+import javax.security.auth.Subject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.osgi.service.http.HttpContext;
+
+/** Authentications utilities when using servlets. */
+public class ServletAuthUtils {
+       public final static <T> T doAs(Supplier<T> supplier, HttpServletRequest req) {
+               return Subject.doAs(
+                               Subject.getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())),
+                               new PrivilegedAction<T>() {
+
+                                       @Override
+                                       public T run() {
+                                               return supplier.get();
+                                       }
+
+                               });
+       }
+
+       public final static void configureRequestSecurity(HttpServletRequest req) {
+               if (req.getAttribute(AccessControlContext.class.getName()) != null)
+                       throw new IllegalStateException("Request already authenticated.");
+               AccessControlContext acc = AccessController.getContext();
+               req.setAttribute(HttpContext.REMOTE_USER, CurrentUser.getUsername());
+               req.setAttribute(AccessControlContext.class.getName(), acc);
+       }
+
+       public final static void clearRequestSecurity(HttpServletRequest req) {
+               if (req.getAttribute(AccessControlContext.class.getName()) == null)
+                       throw new IllegalStateException("Cannot clear non-authenticated request.");
+               req.setAttribute(HttpContext.REMOTE_USER, null);
+               req.setAttribute(AccessControlContext.class.getName(), null);
+       }
+}
index 9bdba4f170af9558b0085f7a153d84eb6fc6d496..54d328cc9787d329aa31ffc6512f3c4fa2036075 100644 (file)
@@ -44,7 +44,10 @@ import org.osgi.service.useradmin.Group;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
-/** Use the {@link UserAdmin} in the OSGi registry as the basis for authentication.*/
+/**
+ * Use the {@link UserAdmin} in the OSGi registry as the basis for
+ * authentication.
+ */
 public class UserAdminLoginModule implements LoginModule {
        private final static Log log = LogFactory.getLog(UserAdminLoginModule.class);
 
@@ -225,7 +228,7 @@ public class UserAdminLoginModule implements LoginModule {
                                if (authenticatedUser == null) {
                                        if (log.isTraceEnabled())
                                                log.trace("Neither kerberos nor user admin login succeeded. Login failed.");
-                                       return false;
+                                       throw new CredentialNotFoundException("Bad credentials.");
                                } else {
                                        authenticatingUser = authenticatedUser;
                                }
index 4c7c8997af3f2dfff96dfd81bd8e2451206f7ba3..a97f4133fdbdc2cd3191a6164136ef9a1d703e5f 100644 (file)
@@ -4,7 +4,6 @@ import static org.argeo.api.NodeConstants.LOGIN_CONTEXT_USER;
 
 import java.io.IOException;
 import java.security.AccessControlContext;
-import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Map;
 
@@ -15,6 +14,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.cms.auth.ServletAuthUtils;
 import org.osgi.service.http.context.ServletContextHelper;
 
 /** Manages security access to servlets. */
@@ -53,7 +53,8 @@ public class CmsPrivateServletContext extends ServletContextHelper {
 
                        @Override
                        public Void run() {
-                               request.setAttribute(REMOTE_USER, AccessController.getContext());
+                               // TODO also set login context in order to log out ?
+                               ServletAuthUtils.configureRequestSecurity(request);
                                return null;
                        }
 
@@ -62,6 +63,11 @@ public class CmsPrivateServletContext extends ServletContextHelper {
                return true;
        }
 
+       @Override
+       public void finishSecurity(HttpServletRequest request, HttpServletResponse response) {
+               ServletAuthUtils.clearRequestSecurity(request);
+       }
+
        protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
                try {
                        response.sendRedirect(loginPage);
index 9a59613e9d944610c829943d2408cc6562666172..0ebfb3a1306b06778e7cba69a96a9d491e67ca54 100644 (file)
@@ -1,12 +1,12 @@
 USER {
     org.argeo.cms.auth.HttpSessionLoginModule sufficient;
     org.argeo.cms.auth.IdentLoginModule optional;
-    org.argeo.cms.auth.UserAdminLoginModule sufficient;
+    org.argeo.cms.auth.UserAdminLoginModule requisite;
 };
 
 ANONYMOUS {
     org.argeo.cms.auth.HttpSessionLoginModule sufficient;
-    org.argeo.cms.auth.AnonymousLoginModule sufficient;
+    org.argeo.cms.auth.AnonymousLoginModule requisite;
 };
 
 DATA_ADMIN {
index 03a7551f01c568c84449fe3f44163c8600be4616..0d94ff3f10781d7aace56e9eafc8a1b9e64416d7 100644 (file)
@@ -2,8 +2,10 @@ package org.argeo.cms.servlet;
 
 import java.io.IOException;
 import java.net.URL;
+import java.security.PrivilegedAction;
 import java.util.Map;
 
+import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpServletRequest;
@@ -13,6 +15,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeConstants;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.cms.auth.ServletAuthUtils;
 import org.argeo.cms.internal.http.HttpUtils;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.FrameworkUtil;
@@ -50,9 +53,27 @@ public class CmsServletContext extends ServletContextHelper {
                        if (lc == null)
                                return false;
                }
+               
+               Subject subject = lc.getSubject();
+               //log.debug("SERVLET CONTEXT: "+subject);
+               Subject.doAs(subject, new PrivilegedAction<Void>() {
+
+                       @Override
+                       public Void run() {
+                               // TODO also set login context in order to log out ?
+                               ServletAuthUtils.configureRequestSecurity(request);
+                               return null;
+                       }
+
+               });
                return true;
        }
 
+       @Override
+       public void finishSecurity(HttpServletRequest request, HttpServletResponse response) {
+               ServletAuthUtils.clearRequestSecurity(request);
+       }
+
        protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
                // anonymous
                try {