From d4cd517a9ff39f08ab28c129775de19c5c0ec02a Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 3 Nov 2020 08:45:31 +0100 Subject: [PATCH] Work on servlet securitxy integration. --- .../cms/auth/HttpSessionLoginModule.java | 1 + .../org/argeo/cms/auth/ServletAuthUtils.java | 42 +++++++++++++++++++ .../argeo/cms/auth/UserAdminLoginModule.java | 7 +++- .../integration/CmsPrivateServletContext.java | 10 ++++- .../org/argeo/cms/internal/kernel/jaas.cfg | 4 +- .../argeo/cms/servlet/CmsServletContext.java | 21 ++++++++++ 6 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 org.argeo.cms/src/org/argeo/cms/auth/ServletAuthUtils.java diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java index eb43ead24..acc0ba4e8 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java @@ -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 index 000000000..9cb7fdcbe --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/auth/ServletAuthUtils.java @@ -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 doAs(Supplier supplier, HttpServletRequest req) { + return Subject.doAs( + Subject.getSubject((AccessControlContext) req.getAttribute(AccessControlContext.class.getName())), + new PrivilegedAction() { + + @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); + } +} diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 9bdba4f17..54d328cc9 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -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; } diff --git a/org.argeo.cms/src/org/argeo/cms/integration/CmsPrivateServletContext.java b/org.argeo.cms/src/org/argeo/cms/integration/CmsPrivateServletContext.java index 4c7c8997a..a97f4133f 100644 --- a/org.argeo.cms/src/org/argeo/cms/integration/CmsPrivateServletContext.java +++ b/org.argeo.cms/src/org/argeo/cms/integration/CmsPrivateServletContext.java @@ -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); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index 9a59613e9..0ebfb3a13 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -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 { diff --git a/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java b/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java index 03a7551f0..0d94ff3f1 100644 --- a/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java +++ b/org.argeo.cms/src/org/argeo/cms/servlet/CmsServletContext.java @@ -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() { + + @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 { -- 2.30.2