Simplify authentication
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 13 Oct 2015 19:01:10 +0000 (19:01 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 13 Oct 2015 19:01:10 +0000 (19:01 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8476 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

23 files changed:
org.argeo.cms/src/org/argeo/cms/AbstractCmsEntryPoint.java
org.argeo.cms/src/org/argeo/cms/CmsApplication.java [deleted file]
org.argeo.cms/src/org/argeo/cms/CmsView.java
org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java
org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/NodeContextLoginModule.java [deleted file]
org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg
org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java
org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java [deleted file]
org.argeo.cms/src/org/argeo/cms/util/UserMenu.java
org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java
org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/SingleSourcingException.java [new file with mode: 0644]
org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java [new file with mode: 0644]
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/RapLoginEntryPoint.java
org.argeo.security.ui/src/org/argeo/security/ui/login/WorkbenchLogin.java

index b5078696d4eae35cac32fb40b39ee0b89e50ac50..d27ed006e6f282065264a4c2b57fa13db510b1dc 100644 (file)
@@ -1,6 +1,5 @@
 package org.argeo.cms;
 
-import java.security.AccessControlContext;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Map;
@@ -12,16 +11,16 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.security.auth.Subject;
+import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.ArgeoException;
 import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.AbstractEntryPoint;
@@ -40,6 +39,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
        private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class);
 
        private final Subject subject;
+       private LoginContext loginContext;
 
        private final Repository repository;
        private final String workspace;
@@ -63,36 +63,26 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
                this.workspace = workspace;
                this.defaultPath = defaultPath;
                this.factoryProperties = new HashMap<String, String>(factoryProperties);
+               subject = new Subject();
 
-               // load context from session
-               HttpServletRequest httpRequest = RWT.getRequest();
-               final HttpSession httpSession = httpRequest.getSession();
-               AccessControlContext acc = (AccessControlContext) httpSession
-                               .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
-               if (acc != null
-                               && Subject.getSubject(acc).getPrincipals(X500Principal.class)
-                                               .size() == 1) {
-                       subject = Subject.getSubject(acc);
-               } else {
-                       subject = new Subject();
-
-                       // Initial login
+               // Initial login
+               try {
+                       loginContext = new LoginContext(AuthConstants.LOGIN_CONTEXT_USER,
+                                       subject, new HttpRequestCallbackHandler(
+                                                       UiContext.getHttpRequest()));
+                       loginContext.login();
+               } catch (CredentialNotFoundException e) {
                        try {
-                               new LoginContext(AuthConstants.LOGIN_CONTEXT_USER, subject)
-                                               .login();
-                       } catch (LoginException e) {
-                               // if (log.isTraceEnabled())
-                               // log.trace("Cannot authenticate user", e);
-                               try {
-                                       new LoginContext(AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
-                                                       subject).login();
-                               } catch (LoginException eAnonymous) {
-                                       throw new ArgeoException("Cannot initialize subject",
-                                                       eAnonymous);
-                               }
+                               loginContext = new LoginContext(
+                                               AuthConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+                               loginContext.login();
+                       } catch (LoginException e1) {
+                               throw new ArgeoException("Cannot log as anonymous", e);
                        }
+               } catch (LoginException e) {
+                       throw new ArgeoException("Cannot initialize subject", e);
                }
-               authChange();
+               authChange(loginContext);
 
                jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
                browserNavigation = RWT.getClient().getService(BrowserNavigation.class);
@@ -119,7 +109,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
 
        @Override
        protected final void createContents(final Composite parent) {
-               getShell().getDisplay().setData(CmsView.KEY, this);
+               UiContext.setData(CmsView.KEY, this);
                Subject.doAs(subject, new PrivilegedAction<Void>() {
                        @Override
                        public Void run() {
@@ -173,7 +163,25 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
        }
 
        @Override
-       public void authChange() {
+       public void logout() {
+               if (loginContext == null)
+                       throw new CmsException("Login context should not be null");
+               try {
+                       loginContext.logout();
+                       LoginContext anonymousLc = new LoginContext(
+                                       AuthConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+                       anonymousLc.login();
+                       authChange(anonymousLc);
+               } catch (LoginException e) {
+                       throw new CmsException("Cannot logout", e);
+               }
+       }
+
+       @Override
+       public void authChange(LoginContext loginContext) {
+               if (loginContext == null)
+                       throw new CmsException("Login context cannot be null");
+               this.loginContext = loginContext;
                Subject.doAs(subject, new PrivilegedAction<Void>() {
 
                        @Override
@@ -189,19 +197,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint
                                                try {
                                                        node = session.getNode(currentPath);
                                                } catch (Exception e) {
-                                                       try {
-                                                               // TODO find a less hacky way to log out
-                                                               new LoginContext(
-                                                                               AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
-                                                                               subject).logout();
-                                                               new LoginContext(
-                                                                               AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
-                                                                               subject).login();
-                                                       } catch (LoginException eAnonymous) {
-                                                               throw new ArgeoException(
-                                                                               "Cannot reset to anonymous", eAnonymous);
-                                                       }
-                                                       JcrUtils.logoutQuietly(session);
+                                                       logout();
                                                        session = repository.login(workspace);
                                                        navigateTo("~");
                                                        throw e;
diff --git a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java
deleted file mode 100644 (file)
index c428a0b..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-package org.argeo.cms;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.util.SimpleApp;
-
-/**
- * Configures an Argeo CMS RWT application.
- * 
- * @deprecated Use {@link SimpleApp} instead (same method signatures)
- */
-@Deprecated
-public class CmsApplication extends SimpleApp {
-       private final static Log log = LogFactory.getLog(CmsApplication.class);
-
-       public CmsApplication() {
-               super();
-               log.warn("org.argeo.cms.CmsApplication will be removed soon, use org.argeo.cms.util.SimpleApp");
-       }
-
-       //
-       // private Map<String, Map<String, String>> branding = new HashMap<String,
-       // Map<String, String>>();
-       // private Map<String, List<String>> styleSheets = new HashMap<String,
-       // List<String>>();
-       //
-       // private List<String> resources = new ArrayList<String>();
-       //
-       // private BundleContext bundleContext;
-       //
-       // private Repository repository;
-       // private String workspace = null;
-       // private String basePath = "/";
-       // private List<String> roPrincipals = Arrays.asList("anonymous",
-       // "everyone");
-       // private List<String> rwPrincipals = Arrays.asList("everyone");
-       //
-       // private CmsUiProvider header;
-       // private Map<String, CmsUiProvider> pages = new LinkedHashMap<String,
-       // CmsUiProvider>();
-       //
-       // private Integer headerHeight = 40;
-       //
-       // // Managers
-       // private CmsImageManager imageManager = new ImageManagerImpl();
-       //
-       // public void configure(Application application) {
-       // try {
-       // application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
-       // application.setExceptionHandler(new CmsExceptionHandler());
-       //
-       // // TODO load all pics under icons
-       // // loading animated gif
-       // application.addResource(LOADING_IMAGE,
-       // createResourceLoader(LOADING_IMAGE));
-       // // empty image
-       // application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
-       //
-       // for (String resource : resources) {
-       // application.addResource(resource, new BundleResourceLoader(
-       // bundleContext));
-       // if (log.isDebugEnabled())
-       // log.debug("Registered resource " + resource);
-       // }
-       //
-       // Map<String, String> defaultBranding = null;
-       // if (branding.containsKey("*"))
-       // defaultBranding = branding.get("*");
-       //
-       // // entry points
-       // for (String page : pages.keySet()) {
-       // Map<String, String> properties = defaultBranding != null ? new
-       // HashMap<String, String>(
-       // defaultBranding) : new HashMap<String, String>();
-       // if (branding.containsKey(page)) {
-       // properties.putAll(branding.get(page));
-       // }
-       // // favicon
-       // if (properties.containsKey(WebClient.FAVICON)) {
-       // String faviconRelPath = properties.get(WebClient.FAVICON);
-       // application.addResource(faviconRelPath,
-       // new BundleResourceLoader(bundleContext));
-       // if (log.isTraceEnabled())
-       // log.trace("Registered favicon " + faviconRelPath);
-       //
-       // }
-       //
-       // // page title
-       // if (!properties.containsKey(WebClient.PAGE_TITLE))
-       // properties.put(
-       // WebClient.PAGE_TITLE,
-       // Character.toUpperCase(page.charAt(0))
-       // + page.substring(1));
-       //
-       // // default body HTML
-       // if (!properties.containsKey(WebClient.BODY_HTML))
-       // properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
-       //
-       // //
-       // // ADD ENTRY POINT
-       // //
-       // application.addEntryPoint("/" + page, new CmsEntryPointFactory(
-       // pages.get(page), repository, workspace, properties),
-       // properties);
-       // log.info("Registered entry point /" + page);
-       // }
-       //
-       // // stylesheets
-       // for (String themeId : styleSheets.keySet()) {
-       // List<String> cssLst = styleSheets.get(themeId);
-       // for (String css : cssLst) {
-       // application.addStyleSheet(themeId, css,
-       // new BundleResourceLoader(bundleContext));
-       // }
-       //
-       // }
-       // } catch (RuntimeException e) {
-       // // Easier access to initialisation errors
-       // log.error("Unexpected exception when configuring RWT application.",
-       // e);
-       // throw e;
-       // }
-       // }
-       //
-       // public void init() throws RepositoryException {
-       // Session session = null;
-       // try {
-       // session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
-       // VersionManager vm = session.getWorkspace().getVersionManager();
-       // if (!vm.isCheckedOut("/"))
-       // vm.checkout("/");
-       // JcrUtils.mkdirs(session, basePath);
-       // for (String principal : rwPrincipals)
-       // JcrUtils.addPrivilege(session, basePath, principal,
-       // Privilege.JCR_WRITE);
-       // for (String principal : roPrincipals)
-       // JcrUtils.addPrivilege(session, basePath, principal,
-       // Privilege.JCR_READ);
-       //
-       // for (String pageName : pages.keySet()) {
-       // try {
-       // initPage(session, pages.get(pageName));
-       // session.save();
-       // } catch (Exception e) {
-       // throw new CmsException(
-       // "Cannot initialize page " + pageName, e);
-       // }
-       // }
-       //
-       // } finally {
-       // JcrUtils.logoutQuietly(session);
-       // }
-       // }
-       //
-       // protected void initPage(Session adminSession, CmsUiProvider page)
-       // throws RepositoryException {
-       // if (page instanceof LifeCycleUiProvider)
-       // ((LifeCycleUiProvider) page).init(adminSession);
-       // }
-       //
-       // public void destroy() {
-       // for (String pageName : pages.keySet()) {
-       // try {
-       // CmsUiProvider page = pages.get(pageName);
-       // if (page instanceof LifeCycleUiProvider)
-       // ((LifeCycleUiProvider) page).destroy();
-       // } catch (Exception e) {
-       // log.error("Cannot destroy page " + pageName, e);
-       // }
-       // }
-       // }
-       //
-       // public void setRepository(Repository repository) {
-       // this.repository = repository;
-       // }
-       //
-       // public void setWorkspace(String workspace) {
-       // this.workspace = workspace;
-       // }
-       //
-       // public void setCmsLogin(@SuppressWarnings("deprecation") CmsLogin
-       // cmsLogin) {
-       // // this.cmsLogin = cmsLogin;
-       // log.warn("cmsLogin"
-       // +
-       // " is deprecated and will be removed soon. Adapt your configuration ASAP.");
-       // }
-       //
-       // public void setHeader(CmsUiProvider header) {
-       // this.header = header;
-       // }
-       //
-       // public void setPages(Map<String, CmsUiProvider> pages) {
-       // this.pages = pages;
-       // }
-       //
-       // public void setBasePath(String basePath) {
-       // this.basePath = basePath;
-       // }
-       //
-       // public void setRoPrincipals(List<String> roPrincipals) {
-       // this.roPrincipals = roPrincipals;
-       // }
-       //
-       // public void setRwPrincipals(List<String> rwPrincipals) {
-       // this.rwPrincipals = rwPrincipals;
-       // }
-       //
-       // public void setHeaderHeight(Integer headerHeight) {
-       // this.headerHeight = headerHeight;
-       // }
-       //
-       // public void setBranding(Map<String, Map<String, String>> branding) {
-       // this.branding = branding;
-       // }
-       //
-       // public void setStyleSheets(Map<String, List<String>> styleSheets) {
-       // this.styleSheets = styleSheets;
-       // }
-       //
-       // public void setBundleContext(BundleContext bundleContext) {
-       // this.bundleContext = bundleContext;
-       // }
-       //
-       // public void setResources(List<String> resources) {
-       // this.resources = resources;
-       // }
-       //
-       // class CmsExceptionHandler implements ExceptionHandler {
-       //
-       // @Override
-       // public void handleException(Throwable throwable) {
-       // CmsSession.current.get().exception(throwable);
-       // }
-       //
-       // }
-       //
-       // private class CmsEntryPointFactory implements EntryPointFactory {
-       // private final CmsUiProvider page;
-       // private final Repository repository;
-       // private final String workspace;
-       // private final Map<String, String> properties;
-       //
-       // public CmsEntryPointFactory(CmsUiProvider page, Repository repository,
-       // String workspace, Map<String, String> properties) {
-       // this.page = page;
-       // this.repository = repository;
-       // this.workspace = workspace;
-       // this.properties = properties;
-       // }
-       //
-       // @Override
-       // public EntryPoint create() {
-       // CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace,
-       // page, properties);
-       // entryPoint.setState("");
-       // CmsSession.current.set(entryPoint);
-       // return entryPoint;
-       // }
-       //
-       // }
-       //
-       // private class CmsEntryPoint extends AbstractCmsEntryPoint {
-       // private Composite headerArea;
-       // private Composite bodyArea;
-       // private final CmsUiProvider uiProvider;
-       //
-       // public CmsEntryPoint(Repository repository, String workspace,
-       // CmsUiProvider uiProvider, Map<String, String> factoryProperties) {
-       // super(repository, workspace, factoryProperties);
-       // this.uiProvider = uiProvider;
-       // }
-       //
-       // @Override
-       // protected void createContents(Composite parent) {
-       // try {
-       // getShell().getDisplay().setData(CmsSession.KEY, this);
-       //
-       // parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-       // true));
-       // parent.setLayout(CmsUtils.noSpaceGridLayout());
-       //
-       // headerArea = new Composite(parent, SWT.NONE);
-       // headerArea.setLayout(new FillLayout());
-       // GridData headerData = new GridData(SWT.FILL, SWT.FILL, false,
-       // false);
-       // headerData.heightHint = headerHeight;
-       // headerArea.setLayoutData(headerData);
-       // refreshHeader();
-       //
-       // bodyArea = new Composite(parent, SWT.NONE);
-       // bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
-       // bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
-       // true));
-       // // Should not be set here: it then prevent all children
-       // // composite to define a background color via CSS
-       // // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
-       // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
-       // refreshBody();
-       // } catch (Exception e) {
-       // throw new CmsException("Cannot create entrypoint contents", e);
-       // }
-       // }
-       //
-       // @Override
-       // protected void refreshHeader() {
-       // if (headerArea == null)
-       // return;
-       // for (Control child : headerArea.getChildren())
-       // child.dispose();
-       // try {
-       // header.createUi(headerArea, getNode());
-       // } catch (RepositoryException e) {
-       // throw new CmsException("Cannot refresh header", e);
-       // }
-       // headerArea.layout(true, true);
-       // }
-       //
-       // @Override
-       // protected void refreshBody() {
-       // if (bodyArea == null)
-       // return;
-       // // Exception
-       // Throwable exception = getException();
-       // if (exception != null) {
-       // // new Label(bodyArea, SWT.NONE).setText("Unreachable state : "
-       // // + getState());
-       // // if (getNode() != null)
-       // // new Label(bodyArea, SWT.NONE).setText("Context : "
-       // // + getNode());
-       // //
-       // // Text errorText = new Text(bodyArea, SWT.MULTI | SWT.H_SCROLL
-       // // | SWT.V_SCROLL);
-       // // errorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
-       // // true,
-       // // true));
-       // // StringWriter sw = new StringWriter();
-       // // exception.printStackTrace(new PrintWriter(sw));
-       // // errorText.setText(sw.toString());
-       // // IOUtils.closeQuietly(sw);
-       // SystemNotifications systemNotifications = new SystemNotifications(
-       // bodyArea);
-       // systemNotifications.notifyException(exception);
-       // resetException();
-       // return;
-       // // TODO report
-       // }
-       //
-       // // clear
-       // for (Control child : bodyArea.getChildren())
-       // child.dispose();
-       // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
-       //
-       // String state = getState();
-       // try {
-       // if (state == null)
-       // throw new CmsException("State cannot be null");
-       // uiProvider.createUi(bodyArea, getNode());
-       // } catch (RepositoryException e) {
-       // throw new CmsException("Cannot refresh body", e);
-       // }
-       //
-       // bodyArea.layout(true, true);
-       // }
-       //
-       // @Override
-       // protected Node getDefaultNode(Session session)
-       // throws RepositoryException {
-       // if (!session.hasPermission(basePath, "read")) {
-       // if (session.getUserID().equals("anonymous"))
-       // throw new LoginRequiredException();
-       // else
-       // throw new CmsException("Unauthorized");
-       // }
-       // return session.getNode(basePath);
-       // }
-       //
-       // @Override
-       // public CmsImageManager getImageManager() {
-       // return imageManager;
-       // }
-       //
-       // }
-       //
-       // private static ResourceLoader createResourceLoader(final String
-       // resourceName) {
-       // return new ResourceLoader() {
-       // public InputStream getResourceAsStream(String resourceName)
-       // throws IOException {
-       // return getClass().getClassLoader().getResourceAsStream(
-       // resourceName);
-       // }
-       // };
-       // }
-       //
-       // /*
-       // * TEXTS
-       // */
-       // private static String DEFAULT_LOADING_BODY = "<div"
-       // +
-       // " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
-       // +
-       // "<img src=\"./rwt-resources/icons/loading.gif\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>"
-       // + "</div>";
-}
index ba960de33fedbf60c70e533a7da6dcf3fe1b8747..0ff1211b7d6a436d9bdad5e007bc61f65af5c5c7 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.cms;
 
 import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
 
 /** Provides interaction with the CMS system. UNSTABLE API at this stage. */
 public interface CmsView {
@@ -10,10 +11,12 @@ public interface CmsView {
        public void navigateTo(String state);
 
        // SECURITY
-       public void authChange();
+       public void authChange(LoginContext loginContext);
 
        public Subject getSubject();
 
+       public void logout();
+
        // SERVICES
        public void exception(Throwable e);
 
index b5b3c776cafca3b373877a0d7081e9b062aa2ab4..932b847e3849aa35f08a6f28dcbf4664910094d7 100644 (file)
@@ -9,6 +9,7 @@ public interface AuthConstants {
        final static String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER";
 
        // HTTP
+       @Deprecated
        final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext";
 
        // RESERVED ROLES
@@ -24,6 +25,6 @@ public interface AuthConstants {
        public final static String ROLE_ANONYMOUS = "cn=anonymous," + ROLES_BASEDN;
 
        // SHARED STATE KEYS
-       public final static String BUNDLE_CONTEXT_KEY = "org.argeo.security.bundleContext";
-       public final static String AUTHORIZATION_KEY = "org.argeo.security.authorization";
+       //public final static String BUNDLE_CONTEXT_KEY = "org.argeo.security.bundleContext";
+       //public final static String AUTHORIZATION_KEY = "org.argeo.security.authorization";
 }
index 5a65fcb112da76ce012f1f67f8e2771f5f2d36a4..11126014f2aba49e9a85a6ddf16f9242da8792a1 100644 (file)
@@ -43,6 +43,15 @@ public final class CurrentUser {
                return getDisplayName(currentSubject());
        }
 
+       public static boolean isAnonymous() {
+               return isAnonymous(currentSubject());
+       }
+
+       public static boolean isAnonymous(Subject subject) {
+               return getUsername(subject).equalsIgnoreCase(
+                               AuthConstants.ROLE_ANONYMOUS);
+       }
+
        private static Subject currentSubject() {
                Subject subject = Subject.getSubject(AccessController.getContext());
                if (subject != null)
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallback.java
new file mode 100644 (file)
index 0000000..eb3368d
--- /dev/null
@@ -0,0 +1,17 @@
+package org.argeo.cms.auth;
+
+import javax.security.auth.callback.Callback;
+import javax.servlet.http.HttpServletRequest;
+
+public class HttpRequestCallback implements Callback {
+       private HttpServletRequest request;
+
+       public HttpServletRequest getRequest() {
+               return request;
+       }
+
+       public void setRequest(HttpServletRequest request) {
+               this.request = request;
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpRequestCallbackHandler.java
new file mode 100644 (file)
index 0000000..0486d74
--- /dev/null
@@ -0,0 +1,29 @@
+package org.argeo.cms.auth;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Callback handler populating {@link HttpRequestCallback}s with the provided
+ * {@link HttpServletRequest}, and ignoring any other callback.
+ */
+public class HttpRequestCallbackHandler implements CallbackHandler {
+       final private HttpServletRequest request;
+
+       public HttpRequestCallbackHandler(HttpServletRequest request) {
+               this.request = request;
+       }
+
+       @Override
+       public void handle(Callback[] callbacks) throws IOException,
+                       UnsupportedCallbackException {
+               for (Callback callback : callbacks)
+                       if (callback instanceof HttpRequestCallback)
+                               ((HttpRequestCallback) callback).setRequest(request);
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/NodeContextLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/NodeContextLoginModule.java
deleted file mode 100644 (file)
index d898e6c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.argeo.cms.auth;
-
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
-
-import org.argeo.cms.internal.kernel.Activator;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.service.useradmin.Authorization;
-
-/** Populates the shared state with this node context. */
-public class NodeContextLoginModule implements LoginModule, AuthConstants {
-       private Subject subject;
-       private Map<String, Object> sharedState;
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public void initialize(Subject subject, CallbackHandler callbackHandler,
-                       Map<String, ?> sharedState, Map<String, ?> options) {
-               this.subject = subject;
-               this.sharedState = (Map<String, Object>) sharedState;
-       }
-
-       @Override
-       public boolean login() throws LoginException {
-               sharedState.put(AuthConstants.BUNDLE_CONTEXT_KEY, Activator.getBundleContext());
-               Display display = Display.getCurrent();
-               if (display != null) {
-                       Authorization authorization = (Authorization) display
-                                       .getData(AuthConstants.AUTHORIZATION_KEY);
-                       if (authorization != null)
-                               sharedState.put(AuthConstants.AUTHORIZATION_KEY, authorization);
-               }
-               return true;
-       }
-
-       @Override
-       public boolean commit() throws LoginException {
-               Display display = Display.getCurrent();
-               if (display != null) {
-                       Authorization authorization = subject
-                                       .getPrivateCredentials(Authorization.class).iterator()
-                                       .next();
-                       display.setData(AuthConstants.AUTHORIZATION_KEY, authorization);
-               }
-               return true;
-       }
-
-       @Override
-       public boolean abort() throws LoginException {
-               sharedState.remove(AuthConstants.BUNDLE_CONTEXT_KEY);
-               sharedState.remove(AuthConstants.AUTHORIZATION_KEY);
-               Display display = Display.getCurrent();
-               if (display != null)
-                       display.setData(AuthConstants.AUTHORIZATION_KEY, null);
-               return true;
-       }
-
-       @Override
-       public boolean logout() throws LoginException {
-               sharedState.remove(AuthConstants.BUNDLE_CONTEXT_KEY);
-               sharedState.remove(AuthConstants.AUTHORIZATION_KEY);
-               Display display = Display.getCurrent();
-               if (display != null)
-                       display.setData(AuthConstants.AUTHORIZATION_KEY, null);
-               return true;
-       }
-
-}
index 74fe4e421e747e0998b7e2763663ae0ab1be0f03..a2f5863cb434008cf06f8ba02b27e5d79525d2f8 100644 (file)
@@ -68,49 +68,48 @@ public class NodeUserLoginModule implements LoginModule {
 
        @Override
        public boolean commit() throws LoginException {
-               if (authorization != null) {
-                       Set<Principal> principals = subject.getPrincipals();
-                       try {
-                               String authName = authorization.getName();
-
-                               // determine user's principal
-                               final LdapName name;
-                               final Principal userPrincipal;
-                               if (authName == null) {
-                                       name = ROLE_ANONYMOUS_NAME;
-                                       userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
-                                       principals.add(userPrincipal);
-                                       principals.add(new AnonymousPrincipal());
+               if (authorization == null)
+                       throw new LoginException("Authorization should not be null");
+               Set<Principal> principals = subject.getPrincipals();
+               try {
+                       String authName = authorization.getName();
+
+                       // determine user's principal
+                       final LdapName name;
+                       final Principal userPrincipal;
+                       if (authName == null) {
+                               name = ROLE_ANONYMOUS_NAME;
+                               userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
+                               principals.add(userPrincipal);
+                               principals.add(new AnonymousPrincipal());
+                       } else {
+                               name = new LdapName(authName);
+                               checkUserName(name);
+                               userPrincipal = new X500Principal(name.toString());
+                               principals.add(userPrincipal);
+                               principals.add(new ImpliedByPrincipal(ROLE_USER_NAME,
+                                               userPrincipal));
+                       }
+
+                       // Add roles provided by authorization
+                       for (String role : authorization.getRoles()) {
+                               LdapName roleName = new LdapName(role);
+                               if (roleName.equals(name)) {
+                                       // skip
                                } else {
-                                       name = new LdapName(authName);
-                                       checkUserName(name);
-                                       userPrincipal = new X500Principal(name.toString());
-                                       principals.add(userPrincipal);
-                                       principals.add(new ImpliedByPrincipal(ROLE_USER_NAME,
+                                       checkImpliedPrincipalName(roleName);
+                                       principals.add(new ImpliedByPrincipal(roleName.toString(),
                                                        userPrincipal));
+                                       if (roleName.equals(ROLE_ADMIN_NAME))
+                                               principals.add(new AdminPrincipal(
+                                                               SecurityConstants.ADMIN_ID));
                                }
-
-                               // Add roles provided by authorization
-                               for (String role : authorization.getRoles()) {
-                                       LdapName roleName = new LdapName(role);
-                                       if (roleName.equals(name)) {
-                                               // skip
-                                       } else {
-                                               checkImpliedPrincipalName(roleName);
-                                               principals.add(new ImpliedByPrincipal(roleName
-                                                               .toString(), userPrincipal));
-                                               if (roleName.equals(ROLE_ADMIN_NAME))
-                                                       principals.add(new AdminPrincipal(
-                                                                       SecurityConstants.ADMIN_ID));
-                                       }
-                               }
-
-                               return true;
-                       } catch (InvalidNameException e) {
-                               throw new CmsException("Cannot commit", e);
                        }
-               } else
-                       return false;
+
+                       return true;
+               } catch (InvalidNameException e) {
+                       throw new CmsException("Cannot commit", e);
+               }
        }
 
        @Override
@@ -121,14 +120,14 @@ public class NodeUserLoginModule implements LoginModule {
 
        @Override
        public boolean logout() throws LoginException {
-               // TODO better deal with successive logout
                if (subject == null)
-                       return true;
-               // TODO make it less brutal
+                       throw new LoginException("Subject should not be null");
+               // Argeo
                subject.getPrincipals().removeAll(
                                subject.getPrincipals(X500Principal.class));
                subject.getPrincipals().removeAll(
                                subject.getPrincipals(ImpliedByPrincipal.class));
+               // Jackrabbit
                subject.getPrincipals().removeAll(
                                subject.getPrincipals(AdminPrincipal.class));
                subject.getPrincipals().removeAll(
index 3e44e65335bc9eb18e439b26e2722cbb4ea0241e..ea8821185d78d4badf8c4ea20d1c13a98f04e76d 100644 (file)
@@ -1,35 +1,42 @@
 package org.argeo.cms.auth;
 
+import java.io.IOException;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
 
 import org.argeo.ArgeoException;
+import org.argeo.cms.internal.kernel.Activator;
 import org.osgi.framework.BundleContext;
+import org.osgi.service.http.HttpContext;
 import org.osgi.service.useradmin.Authorization;
 import org.osgi.service.useradmin.User;
 import org.osgi.service.useradmin.UserAdmin;
 
 public class UserAdminLoginModule implements LoginModule, AuthConstants {
        private Subject subject;
-       private Map<String, Object> sharedState;
        private CallbackHandler callbackHandler;
        private boolean isAnonymous = false;
 
-       @SuppressWarnings("unchecked")
+       private HttpServletRequest request = null;
+
        @Override
        public void initialize(Subject subject, CallbackHandler callbackHandler,
                        Map<String, ?> sharedState, Map<String, ?> options) {
                try {
                        this.subject = subject;
-                       this.sharedState = (Map<String, Object>) sharedState;
                        this.callbackHandler = callbackHandler;
                        if (options.containsKey("anonymous"))
                                isAnonymous = Boolean.parseBoolean(options.get("anonymous")
@@ -41,55 +48,93 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants {
 
        @Override
        public boolean login() throws LoginException {
-               BundleContext bc = (BundleContext) sharedState
-                               .get(AuthConstants.BUNDLE_CONTEXT_KEY);
+               BundleContext bc = Activator.getBundleContext();
                UserAdmin userAdmin = bc.getService(bc
                                .getServiceReference(UserAdmin.class));
-               Authorization authorization = (Authorization) sharedState
-                               .get(AuthConstants.AUTHORIZATION_KEY);
-               if (authorization == null)
-                       if (!isAnonymous) {
-                               // ask for username and password
-                               NameCallback nameCallback = new NameCallback("User");
-                               PasswordCallback passwordCallback = new PasswordCallback(
-                                               "Password", false);
-
-                               // handle callbacks
-                               try {
-                                       callbackHandler.handle(new Callback[] { nameCallback,
-                                                       passwordCallback });
-                               } catch (Exception e) {
-                                       throw new ArgeoException("Cannot handle callbacks", e);
-                               }
+               Authorization authorization = null;
+               if (isAnonymous) {
+                       authorization = userAdmin.getAuthorization(null);
+               } else {
+                       HttpRequestCallback httpCallback = new HttpRequestCallback();
+                       // ask for username and password
+                       NameCallback nameCallback = new NameCallback("User");
+                       PasswordCallback passwordCallback = new PasswordCallback(
+                                       "Password", false);
+                       try {
+                               callbackHandler.handle(new Callback[] { httpCallback,
+                                               nameCallback, passwordCallback });
+                       } catch (IOException e) {
+                               throw new LoginException("Cannot handle http callback: "
+                                               + e.getMessage());
+                       } catch (UnsupportedCallbackException e) {
+                               return false;
+                       }
+                       request = httpCallback.getRequest();
+                       if (request != null) {
+                               authorization = (Authorization) request
+                                               .getAttribute(HttpContext.AUTHORIZATION);
+                               if (authorization == null)
+                                       authorization = (Authorization) request.getSession()
+                                                       .getAttribute(HttpContext.AUTHORIZATION);
+                       }
+                       // if (authorization == null || authorization.getName() == null)
+                       // if (!isAnonymous) {
+                       // // ask for username and password
+                       // NameCallback nameCallback = new NameCallback("User");
+                       // PasswordCallback passwordCallback = new PasswordCallback(
+                       // "Password", false);
+                       //
+                       // // handle callbacks
+                       // try {
+                       // callbackHandler.handle(new Callback[] { nameCallback,
+                       // passwordCallback });
+                       // } catch (Exception e) {
+                       // throw new ArgeoException("Cannot handle callbacks", e);
+                       // }
 
+                       if (authorization == null) {
                                // create credentials
                                final String username = nameCallback.getName();
-                               if (username == null || username.trim().equals(""))
-                                       throw new CredentialNotFoundException(
-                                                       "No credentials provided");
-
-                               char[] password = {};
-                               if (passwordCallback.getPassword() != null)
-                                       password = passwordCallback.getPassword();
-                               else
+                               if (username == null || username.trim().equals("")) {
+                                       // authorization = userAdmin.getAuthorization(null);
                                        throw new CredentialNotFoundException(
                                                        "No credentials provided");
+                               } else {
+                                       char[] password = {};
+                                       if (passwordCallback.getPassword() != null)
+                                               password = passwordCallback.getPassword();
+                                       else
+                                               throw new CredentialNotFoundException(
+                                                               "No credentials provided");
 
-                               User user = userAdmin.getUser(null, username);
-                               if (user == null)
-                                       return false;
-                               if (!user.hasCredential(null, password))
-                                       return false;
-                               authorization = userAdmin.getAuthorization(user);
-                       } else {
-                               authorization = userAdmin.getAuthorization(null);
+                                       User user = userAdmin.getUser(null, username);
+                                       if (user == null)
+                                               return false;
+                                       if (!user.hasCredential(null, password))
+                                               return false;
+                                       authorization = userAdmin.getAuthorization(user);
+                               }
                        }
+                       // } else {
+                       // authorization = userAdmin.getAuthorization(null);
+                       // }
+               }
                subject.getPrivateCredentials().add(authorization);
                return true;
        }
 
        @Override
        public boolean commit() throws LoginException {
+               Authorization authorization = subject
+                               .getPrivateCredentials(Authorization.class).iterator().next();
+               if (request != null) {
+                       request.setAttribute(HttpContext.REMOTE_USER,
+                                       authorization.getName());
+                       request.setAttribute(HttpContext.AUTHORIZATION, authorization);
+                       request.getSession().setAttribute(HttpContext.AUTHORIZATION,
+                                       authorization);
+                       subject.getPrivateCredentials().add(request.getSession());
+               }
                return true;
        }
 
@@ -101,6 +146,15 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants {
 
        @Override
        public boolean logout() throws LoginException {
+               Set<HttpSession> httpSession = subject
+                               .getPrivateCredentials(HttpSession.class);
+               Iterator<HttpSession> it = httpSession.iterator();
+               while (it.hasNext()) {
+                       HttpSession sess = it.next();
+                       sess.setAttribute(HttpContext.AUTHORIZATION, null);
+                       // sess.setMaxInactiveInterval(1);// invalidate session
+               }
+               subject.getPrivateCredentials().removeAll(httpSession);
                cleanUp();
                return true;
        }
index 8f95a3ef993077cc8071828f360079898f582058..ab9211a5439fc0ab02368107628ffe53d8a18fb8 100644 (file)
@@ -1,16 +1,12 @@
 package org.argeo.cms.internal.kernel;
 
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
+import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_USER;
 
 import java.io.IOException;
 import java.io.Serializable;
 import java.net.URL;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import java.security.cert.X509Certificate;
 import java.util.Properties;
 import java.util.StringTokenizer;
 
@@ -22,13 +18,13 @@ import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.logging.Log;
@@ -38,6 +34,8 @@ import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet;
 import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.HttpRequestCallback;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
 import org.argeo.jcr.ArgeoJcrConstants;
 import org.argeo.jcr.JcrUtils;
 import org.osgi.service.http.HttpContext;
@@ -52,11 +50,10 @@ import org.osgi.service.useradmin.Authorization;
 class DataHttp implements KernelConstants, ArgeoJcrConstants {
        private final static Log log = LogFactory.getLog(DataHttp.class);
 
-       private final static String ATTR_AUTH = "auth";
+       // private final static String ATTR_AUTH = "auth";
        private final static String HEADER_AUTHORIZATION = "Authorization";
        private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
 
-       // private final AuthenticationManager authenticationManager;
        private final HttpService httpService;
 
        // FIXME Make it more unique
@@ -129,82 +126,29 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants {
                                new DataHttpContext(anonymous));
        }
 
-       // private Boolean isSessionAuthenticated(HttpSession httpSession) {
-       // SecurityContext contextFromSession = (SecurityContext) httpSession
-       // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
-       // return contextFromSession != null;
-       // }
-
-       private void requestBasicAuth(HttpSession httpSession,
-                       HttpServletResponse response) {
-               response.setStatus(401);
-               response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
-                               + httpAuthRealm + "\"");
-               httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE);
-       }
-
-       private CallbackHandler basicAuth(String authHeader) {
-               if (authHeader != null) {
-                       StringTokenizer st = new StringTokenizer(authHeader);
-                       if (st.hasMoreTokens()) {
-                               String basic = st.nextToken();
-                               if (basic.equalsIgnoreCase("Basic")) {
-                                       try {
-                                               // TODO manipulate char[]
-                                               String credentials = new String(Base64.decodeBase64(st
-                                                               .nextToken()), "UTF-8");
-                                               // log.debug("Credentials: " + credentials);
-                                               int p = credentials.indexOf(":");
-                                               if (p != -1) {
-                                                       final String login = credentials.substring(0, p)
-                                                                       .trim();
-                                                       final char[] password = credentials
-                                                                       .substring(p + 1).trim().toCharArray();
-
-                                                       return new CallbackHandler() {
-                                                               public void handle(Callback[] callbacks) {
-                                                                       for (Callback cb : callbacks) {
-                                                                               if (cb instanceof NameCallback)
-                                                                                       ((NameCallback) cb).setName(login);
-                                                                               else if (cb instanceof PasswordCallback)
-                                                                                       ((PasswordCallback) cb)
-                                                                                                       .setPassword(password);
-                                                                       }
-                                                               }
-                                                       };
-                                               } else {
-                                                       throw new CmsException(
-                                                                       "Invalid authentication token");
-                                               }
-                                       } catch (Exception e) {
-                                               throw new CmsException(
-                                                               "Couldn't retrieve authentication", e);
-                                       }
-                               }
-                       }
-               }
-               throw new CmsException("Couldn't retrieve authentication");
-       }
-
-       private X509Certificate extractCertificate(HttpServletRequest req) {
-               X509Certificate[] certs = (X509Certificate[]) req
-                               .getAttribute("javax.servlet.request.X509Certificate");
-               if (null != certs && certs.length > 0) {
-                       return certs[0];
-               }
-               return null;
-       }
+//     private X509Certificate extractCertificate(HttpServletRequest req) {
+//             X509Certificate[] certs = (X509Certificate[]) req
+//                             .getAttribute("javax.servlet.request.X509Certificate");
+//             if (null != certs && certs.length > 0) {
+//                     return certs[0];
+//             }
+//             return null;
+//     }
 
        private Subject subjectFromRequest(HttpServletRequest request) {
-               HttpSession httpSession = request.getSession();
                Authorization authorization = (Authorization) request
                                .getAttribute(HttpContext.AUTHORIZATION);
                if (authorization == null)
                        throw new CmsException("Not authenticated");
-               AccessControlContext acc = (AccessControlContext) httpSession
-                               .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
-               Subject subject = Subject.getSubject(acc);
-               return subject;
+               try {
+                       LoginContext lc = new LoginContext(
+                                       AuthConstants.LOGIN_CONTEXT_USER,
+                                       new HttpRequestCallbackHandler(request));
+                       lc.login();
+                       return lc.getSubject();
+               } catch (LoginException e) {
+                       throw new CmsException("Cannot login", e);
+               }
        }
 
        private class DataHttpContext implements HttpContext {
@@ -215,56 +159,44 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants {
                }
 
                @Override
-               public boolean handleSecurity(HttpServletRequest request,
+               public boolean handleSecurity(final HttpServletRequest request,
                                HttpServletResponse response) throws IOException {
-                       final Subject subject;
 
                        if (anonymous) {
-                               subject = KernelUtils.anonymousLogin();
+                               Subject subject = KernelUtils.anonymousLogin();
                                Authorization authorization = subject
                                                .getPrivateCredentials(Authorization.class).iterator()
                                                .next();
+                               request.setAttribute(REMOTE_USER, AuthConstants.ROLE_ANONYMOUS);
                                request.setAttribute(AUTHORIZATION, authorization);
                                return true;
                        }
 
-                       final HttpSession httpSession = request.getSession();
-                       AccessControlContext acc = (AccessControlContext) httpSession
-                                       .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
-                       if (acc != null) {
-                               subject = Subject.getSubject(acc);
-                       } else {
-                               // Process basic auth
-                               String basicAuth = request.getHeader(HEADER_AUTHORIZATION);
-                               if (basicAuth != null) {
-                                       CallbackHandler token = basicAuth(basicAuth);
+                       KernelUtils.logRequestHeaders(log, request);
+                       try {
+                               new LoginContext(LOGIN_CONTEXT_USER,
+                                               new HttpRequestCallbackHandler(request)).login();
+                               return true;
+                       } catch (CredentialNotFoundException e) {
+                               CallbackHandler token = basicAuth(request);
+                               if (token != null) {
                                        try {
-                                               LoginContext lc = new LoginContext(
-                                                               AuthConstants.LOGIN_CONTEXT_USER, token);
+                                               LoginContext lc = new LoginContext(LOGIN_CONTEXT_USER,
+                                                               token);
                                                lc.login();
-                                               subject = lc.getSubject();
-                                       } catch (LoginException e) {
-                                               throw new CmsException("Could not login", e);
+                                               // Note: this is impossible to reliably clear the
+                                               // authorization header when access from a browser.
+                                               return true;
+                                       } catch (LoginException e1) {
+                                               throw new CmsException("Could not login", e1);
                                        }
-                                       Subject.doAs(subject, new PrivilegedAction<Void>() {
-                                               public Void run() {
-                                                       // add security context to session
-                                                       httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
-                                                                       AccessController.getContext());
-                                                       return null;
-                                               }
-                                       });
                                } else {
-                                       requestBasicAuth(httpSession, response);
+                                       requestBasicAuth(request, response);
                                        return false;
                                }
+                       } catch (LoginException e) {
+                               throw new CmsException("Could not login", e);
                        }
-                       // authenticate request
-                       Authorization authorization = subject
-                                       .getPrivateCredentials(Authorization.class).iterator()
-                                       .next();
-                       request.setAttribute(AUTHORIZATION, authorization);
-                       return true;
                }
 
                @Override
@@ -277,6 +209,62 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants {
                        return null;
                }
 
+               private void requestBasicAuth(HttpServletRequest request,
+                               HttpServletResponse response) {
+                       response.setStatus(401);
+                       response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
+                                       + httpAuthRealm + "\"");
+                       // request.getSession().setAttribute(ATTR_AUTH, Boolean.TRUE);
+               }
+
+               private CallbackHandler basicAuth(final HttpServletRequest httpRequest) {
+                       String authHeader = httpRequest.getHeader(HEADER_AUTHORIZATION);
+                       if (authHeader != null) {
+                               StringTokenizer st = new StringTokenizer(authHeader);
+                               if (st.hasMoreTokens()) {
+                                       String basic = st.nextToken();
+                                       if (basic.equalsIgnoreCase("Basic")) {
+                                               try {
+                                                       // TODO manipulate char[]
+                                                       String credentials = new String(
+                                                                       Base64.decodeBase64(st.nextToken()),
+                                                                       "UTF-8");
+                                                       // log.debug("Credentials: " + credentials);
+                                                       int p = credentials.indexOf(":");
+                                                       if (p != -1) {
+                                                               final String login = credentials
+                                                                               .substring(0, p).trim();
+                                                               final char[] password = credentials
+                                                                               .substring(p + 1).trim().toCharArray();
+                                                               return new CallbackHandler() {
+                                                                       public void handle(Callback[] callbacks) {
+                                                                               for (Callback cb : callbacks) {
+                                                                                       if (cb instanceof NameCallback)
+                                                                                               ((NameCallback) cb)
+                                                                                                               .setName(login);
+                                                                                       else if (cb instanceof PasswordCallback)
+                                                                                               ((PasswordCallback) cb)
+                                                                                                               .setPassword(password);
+                                                                                       else if (cb instanceof HttpRequestCallback)
+                                                                                               ((HttpRequestCallback) cb)
+                                                                                                               .setRequest(httpRequest);
+                                                                               }
+                                                                       }
+                                                               };
+                                                       } else {
+                                                               throw new CmsException(
+                                                                               "Invalid authentication token");
+                                                       }
+                                               } catch (Exception e) {
+                                                       throw new CmsException(
+                                                                       "Couldn't retrieve authentication", e);
+                                               }
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
        }
 
        /**
index 32672bef50aeb389a6d9c40681bc8523306e7e0b..68b3fa2891bf784ab5be47a33c254e1fa67fdc33 100644 (file)
@@ -106,6 +106,8 @@ final class Kernel implements KernelConstants, ServiceListener {
                                Kernel.class.getClassLoader());
                long begin = System.currentTimeMillis();
 
+               // KernelUtils.logFrameworkProperties(log);
+
                try {
                        // Initialise services
                        logger = new NodeLogger();
index c1e20892456fd26792956f3ce2532a3ddce9738c..28eb526952934937e075fe19fec6e4242c7eceb4 100644 (file)
@@ -16,6 +16,8 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.logging.Log;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.AuthConstants;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 
 /** Package utilities */
 class KernelUtils implements KernelConstants {
@@ -128,6 +130,19 @@ class KernelUtils implements KernelConstants {
                }
        }
 
+       static void logFrameworkProperties(Log log) {
+               BundleContext bc = Activator.getBundleContext();
+               String[] keys = { Constants.FRAMEWORK_STORAGE,
+                               Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION,
+                               Constants.FRAMEWORK_PROCESSOR, Constants.FRAMEWORK_SECURITY,
+                               Constants.FRAMEWORK_TRUST_REPOSITORIES,
+                               Constants.FRAMEWORK_WINDOWSYSTEM, Constants.FRAMEWORK_VENDOR,
+                               Constants.FRAMEWORK_VERSION, Constants.FRAMEWORK_STORAGE_CLEAN,
+                               Constants.FRAMEWORK_LANGUAGE, Constants.FRAMEWORK_UUID };
+               for (String key : keys)
+                       log.debug(key + "=" + bc.getProperty(key));
+       }
+
        private KernelUtils() {
 
        }
index bc74cf638722c3d8409e511f865ea28b34f0b442..5e1f39acb1f7a57d0651a0976a5c0cc786a781a1 100644 (file)
@@ -1,43 +1,20 @@
 package org.argeo.cms.internal.kernel;
 
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
-
 import java.io.IOException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.security.cert.X509Certificate;
 import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
 
-import javax.jcr.Repository;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
 import javax.servlet.FilterChain;
-import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.cms.CmsException;
-import org.argeo.cms.auth.AuthConstants;
-import org.argeo.jackrabbit.servlet.OpenInViewSessionProvider;
-import org.argeo.jackrabbit.servlet.RemotingServlet;
-import org.argeo.jackrabbit.servlet.WebdavServlet;
 import org.argeo.jcr.ArgeoJcrConstants;
 import org.eclipse.equinox.http.servlet.ExtendedHttpService;
-import org.osgi.service.http.NamespaceException;
 
 /**
  * Intercepts and enriches http access, mainly focusing on security and
@@ -47,159 +24,25 @@ import org.osgi.service.http.NamespaceException;
 class NodeHttp implements KernelConstants, ArgeoJcrConstants {
        private final static Log log = LogFactory.getLog(NodeHttp.class);
 
-       private final static String ATTR_AUTH = "auth";
-       private final static String HEADER_AUTHORIZATION = "Authorization";
-       private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
-       // private final AuthenticationManager authenticationManager;
-       private final ExtendedHttpService httpService;
-
-       // FIXME Make it more unique
-       private String httpAuthRealm = "Argeo";
-
        // Filters
        private final RootFilter rootFilter;
+
        // private final DoSFilter dosFilter;
        // private final QoSFilter qosFilter;
 
-       // WebDav / JCR remoting
-       private OpenInViewSessionProvider sessionProvider;
-
-       NodeHttp(ExtendedHttpService httpService, NodeRepository node) {
-               // this.bundleContext = bundleContext;
-               // this.authenticationManager = authenticationManager;
-
-               this.httpService = httpService;
-
-               // Filters
+       NodeHttp(ExtendedHttpService httpService) {
                rootFilter = new RootFilter();
                // dosFilter = new CustomDosFilter();
                // qosFilter = new QoSFilter();
 
-               // DAV
-               sessionProvider = new OpenInViewSessionProvider();
-
-               registerRepositoryServlets(ALIAS_NODE, node);
                try {
                        httpService.registerFilter("/", rootFilter, null, null);
                } catch (Exception e) {
-                       throw new CmsException("Could not register root filter", e);
+                       throw new CmsException("Cannot register filters", e);
                }
        }
 
        public void destroy() {
-               sessionProvider.destroy();
-               unregisterRepositoryServlets(ALIAS_NODE);
-       }
-
-       void registerRepositoryServlets(String alias, Repository repository) {
-               try {
-                       registerWebdavServlet(alias, repository, true);
-                       registerWebdavServlet(alias, repository, false);
-                       registerRemotingServlet(alias, repository, true);
-                       registerRemotingServlet(alias, repository, false);
-               } catch (Exception e) {
-                       throw new CmsException(
-                                       "Could not register servlets for repository " + alias, e);
-               }
-       }
-
-       void unregisterRepositoryServlets(String alias) {
-               // FIXME unregister servlets
-       }
-
-       void registerWebdavServlet(String alias, Repository repository,
-                       boolean anonymous) throws NamespaceException, ServletException {
-               WebdavServlet webdavServlet = new WebdavServlet(repository,
-                               sessionProvider);
-               String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE;
-               String path = pathPrefix + "/" + alias;
-               Properties ip = new Properties();
-               ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG);
-               ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
-               httpService.registerFilter(path, anonymous ? new AnonymousFilter()
-                               : new DavFilter(), null, null);
-               // Cast to servlet because of a weird behaviour in Eclipse
-               httpService.registerServlet(path, (Servlet) webdavServlet, ip, null);
-       }
-
-       void registerRemotingServlet(String alias, Repository repository,
-                       boolean anonymous) throws NamespaceException, ServletException {
-               String pathPrefix = anonymous ? REMOTING_PUBLIC : REMOTING_PRIVATE;
-               RemotingServlet remotingServlet = new RemotingServlet(repository,
-                               sessionProvider);
-               String path = pathPrefix + "/" + alias;
-               Properties ip = new Properties();
-               ip.setProperty(RemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
-
-               // Looks like a bug in Jackrabbit remoting init
-               ip.setProperty(RemotingServlet.INIT_PARAM_HOME,
-                               KernelUtils.getOsgiInstanceDir() + "/tmp/jackrabbit");
-               ip.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY, "remoting");
-               // in order to avoid annoying warning.
-               ip.setProperty(RemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG,
-                               "");
-               // Cast to servlet because of a weird behaviour in Eclipse
-               httpService.registerFilter(path, anonymous ? new AnonymousFilter()
-                               : new DavFilter(), null, null);
-               httpService.registerServlet(path, (Servlet) remotingServlet, ip, null);
-       }
-
-       // private Boolean isSessionAuthenticated(HttpSession httpSession) {
-       // SecurityContext contextFromSession = (SecurityContext) httpSession
-       // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
-       // return contextFromSession != null;
-       // }
-
-       private void requestBasicAuth(HttpSession httpSession,
-                       HttpServletResponse response) {
-               response.setStatus(401);
-               response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
-                               + httpAuthRealm + "\"");
-               httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE);
-       }
-
-       private CallbackHandler basicAuth(String authHeader) {
-               if (authHeader != null) {
-                       StringTokenizer st = new StringTokenizer(authHeader);
-                       if (st.hasMoreTokens()) {
-                               String basic = st.nextToken();
-                               if (basic.equalsIgnoreCase("Basic")) {
-                                       try {
-                                               // TODO manipulate char[]
-                                               String credentials = new String(Base64.decodeBase64(st
-                                                               .nextToken()), "UTF-8");
-                                               // log.debug("Credentials: " + credentials);
-                                               int p = credentials.indexOf(":");
-                                               if (p != -1) {
-                                                       final String login = credentials.substring(0, p)
-                                                                       .trim();
-                                                       final char[] password = credentials
-                                                                       .substring(p + 1).trim().toCharArray();
-
-                                                       return new CallbackHandler() {
-                                                               public void handle(Callback[] callbacks) {
-                                                                       for (Callback cb : callbacks) {
-                                                                               if (cb instanceof NameCallback)
-                                                                                       ((NameCallback) cb).setName(login);
-                                                                               else if (cb instanceof PasswordCallback)
-                                                                                       ((PasswordCallback) cb)
-                                                                                                       .setPassword(password);
-                                                                       }
-                                                               }
-                                                       };
-                                               } else {
-                                                       throw new CmsException(
-                                                                       "Invalid authentication token");
-                                               }
-                                       } catch (Exception e) {
-                                               throw new CmsException(
-                                                               "Couldn't retrieve authentication", e);
-                                       }
-                               }
-                       }
-               }
-               throw new CmsException("Couldn't retrieve authentication");
        }
 
        /** Intercepts all requests. Authenticates. */
@@ -293,96 +136,6 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants {
                return null;
        }
 
-       /** Intercepts all requests. Authenticates. */
-       private class AnonymousFilter extends HttpFilter {
-               @Override
-               public void doFilter(HttpSession httpSession,
-                               final HttpServletRequest request,
-                               final HttpServletResponse response,
-                               final FilterChain filterChain) throws IOException,
-                               ServletException {
-
-                       // Authenticate from session
-                       // if (isSessionAuthenticated(httpSession)) {
-                       // filterChain.doFilter(request, response);
-                       // return;
-                       // }
-
-                       Subject subject = KernelUtils.anonymousLogin();
-                       try {
-                               Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
-                                       public Void run() throws IOException, ServletException {
-                                               filterChain.doFilter(request, response);
-                                               return null;
-                                       }
-                               });
-                       } catch (PrivilegedActionException e) {
-                               if (e.getCause() instanceof ServletException)
-                                       throw (ServletException) e.getCause();
-                               else if (e.getCause() instanceof IOException)
-                                       throw (IOException) e.getCause();
-                               else
-                                       throw new CmsException("Unexpected exception", e.getCause());
-                       }
-               }
-       }
-
-       /** Intercepts all requests. Authenticates. */
-       private class DavFilter extends HttpFilter {
-
-               @Override
-               public void doFilter(final HttpSession httpSession,
-                               final HttpServletRequest request,
-                               final HttpServletResponse response,
-                               final FilterChain filterChain) throws IOException,
-                               ServletException {
-
-                       AccessControlContext acc = (AccessControlContext) httpSession
-                                       .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
-                       final Subject subject;
-                       if (acc != null) {
-                               subject = Subject.getSubject(acc);
-                       } else {
-                               // Process basic auth
-                               String basicAuth = request.getHeader(HEADER_AUTHORIZATION);
-                               if (basicAuth != null) {
-                                       CallbackHandler token = basicAuth(basicAuth);
-                                       try {
-                                               LoginContext lc = new LoginContext(
-                                                               AuthConstants.LOGIN_CONTEXT_USER, token);
-                                               lc.login();
-                                               subject = lc.getSubject();
-                                       } catch (LoginException e) {
-                                               throw new CmsException("Could not login", e);
-                                       }
-                               } else {
-                                       requestBasicAuth(httpSession, response);
-                                       return;
-                               }
-                       }
-                       // do filter as subject
-                       try {
-                               Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
-                                       public Void run() throws IOException, ServletException {
-                                               // add security context to session
-                                               httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
-                                                               AccessController.getContext());
-                                               filterChain.doFilter(request, response);
-                                               return null;
-                                       }
-                               });
-                       } catch (PrivilegedActionException e) {
-                               if (e.getCause() instanceof ServletException)
-                                       throw (ServletException) e.getCause();
-                               else if (e.getCause() instanceof IOException)
-                                       throw (IOException) e.getCause();
-                               else
-                                       throw new CmsException("Unexpected exception", e.getCause());
-                       }
-
-               }
-       }
-
        // class CustomDosFilter extends DoSFilter {
        // @Override
        // protected String extractUserId(ServletRequest request) {
index 90c68bd21dcaa5254478557c58e59a76cb8b1575..e5e3be5cdfcbcb60432452dbad765e8da485b928 100644 (file)
@@ -1,11 +1,9 @@
 USER {
-    org.argeo.cms.auth.NodeContextLoginModule requisite;
     org.argeo.cms.auth.UserAdminLoginModule requisite;
     org.argeo.cms.auth.NodeUserLoginModule requisite;
 };
 
 ANONYMOUS {
-    org.argeo.cms.auth.NodeContextLoginModule requisite;
     org.argeo.cms.auth.UserAdminLoginModule requisite anonymous=true;
     org.argeo.cms.auth.NodeUserLoginModule requisite;
 };
index 439f48af195c082193796f7a29ee276375238a1f..6e895818a35c34fd49bf736c146dc7813cb82f80 100644 (file)
@@ -11,6 +11,7 @@ import org.apache.commons.io.IOUtils;
 import org.argeo.cms.CmsConstants;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.CmsView;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.service.ResourceManager;
@@ -34,13 +35,7 @@ public class CmsUtils implements CmsConstants {
         * this call.
         */
        public static CmsView getCmsView() {
-               Display display = Display.getCurrent();
-               if (display == null)
-                       return null;
-               CmsView cmsView = (CmsView) display.getData(CmsView.KEY);
-               if (cmsView == null)
-                       return null;
-               return cmsView;
+               return UiContext.getData(CmsView.KEY);
        }
 
        /** @deprecated Use rowData16px() instead. GridData should not be reused. */
diff --git a/org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java b/org.argeo.cms/src/org/argeo/cms/util/CurrentUserUtils.java
deleted file mode 100644 (file)
index 0ebac9d..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.cms.util;
-
-import java.security.AccessController;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.security.auth.x500.X500Principal;
-
-import org.argeo.ArgeoException;
-
-/**
- * Retrieves information about the current user. Not an API, can change without
- * notice.
- */
-class CurrentUserUtils {
-       public final static String getUsername() {
-               Subject subject = getSubject();
-               if (subject == null)
-                       return null;
-               Principal principal = subject.getPrincipals(X500Principal.class)
-                               .iterator().next();
-               return principal.getName();
-
-       }
-
-       public final static Set<String> roles() {
-               Set<String> roles = Collections.synchronizedSet(new HashSet<String>());
-               // roles.add("ROLE_USER");
-               Subject subject = getSubject();
-               X500Principal userPrincipal = subject
-                               .getPrincipals(X500Principal.class).iterator().next();
-               roles.add(userPrincipal.getName());
-               for (Principal group : subject.getPrincipals(Group.class)) {
-                       roles.add(group.getName());
-               }
-               return roles;
-       }
-
-       public final static Subject getSubject() {
-               Subject subject = Subject.getSubject(AccessController.getContext());
-               if (subject == null) {
-                       subject = CmsUtils.getCmsView().getSubject();
-                       if (subject == null)
-                               throw new ArgeoException("Not authenticated.");
-               }
-               return subject;
-       }
-}
index 72289cb3e544783d1c6e3f490f15953e4db7e57b..ed8f20c0bcec5e349fa9a0f5613aea743825bb99 100644 (file)
@@ -1,12 +1,9 @@
 package org.argeo.cms.util;
 
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
 import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_ANONYMOUS;
 import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_USER;
 
 import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
@@ -16,8 +13,6 @@ import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
 import org.argeo.cms.CmsException;
 import org.argeo.cms.CmsMsg;
@@ -25,6 +20,7 @@ import org.argeo.cms.CmsStyles;
 import org.argeo.cms.CmsView;
 import org.argeo.cms.auth.AuthConstants;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.auth.HttpRequestCallback;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseAdapter;
@@ -59,8 +55,7 @@ public class UserMenu implements CmsStyles, CallbackHandler {
                cmsView = CmsUtils.getCmsView();
 
                if (cmsView != null) {
-                       String username = CurrentUser.getUsername(CmsUtils.getCmsView()
-                                       .getSubject());
+                       String username = CurrentUser.getUsername(cmsView.getSubject());
                        if (username == null
                                        || username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS)) {
                                username = null;
@@ -178,67 +173,42 @@ public class UserMenu implements CmsStyles, CallbackHandler {
 
        protected void login() {
                Subject subject = cmsView.getSubject();
+               LoginContext loginContext;
                try {
                        //
                        // LOGIN
                        //
                        new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).logout();
-                       LoginContext loginContext = new LoginContext(LOGIN_CONTEXT_USER,
-                                       subject, this);
+                       loginContext = new LoginContext(LOGIN_CONTEXT_USER, subject, this);
                        loginContext.login();
-
-                       // save context in session
-                       final HttpSession httpSession = RWT.getRequest().getSession();
-                       Subject.doAs(subject, new PrivilegedAction<Void>() {
-
-                               @Override
-                               public Void run() {
-                                       httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
-                                                       AccessController.getContext());
-                                       return null;
-                               }
-                       });
                } catch (LoginException e1) {
-                       try {
-                               new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).login();
-                       } catch (LoginException e) {
-                               throw new CmsException("Cannot authenticate anonymous", e1);
-                       }
                        throw new CmsException("Cannot authenticate", e1);
                }
                closeShell();
-               cmsView.authChange();
+               cmsView.authChange(loginContext);
        }
 
        protected void logout() {
-               Subject subject = cmsView.getSubject();
-               try {
-                       //
-                       // LOGOUT
-                       //
-                       new LoginContext(LOGIN_CONTEXT_USER, subject).logout();
-                       new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).login();
-
-                       HttpServletRequest httpRequest = RWT.getRequest();
-                       HttpSession httpSession = httpRequest.getSession();
-                       httpSession.setAttribute(ACCESS_CONTROL_CONTEXT, null);
-               } catch (LoginException e1) {
-                       throw new CmsException("Cannot authenticate anonymous", e1);
-               }
                closeShell();
+               cmsView.logout();
                cmsView.navigateTo("~");
-               cmsView.authChange();
        }
 
        @Override
        public void handle(Callback[] callbacks) throws IOException,
                        UnsupportedCallbackException {
-               ((NameCallback) callbacks[0]).setName(username.getText());
-               ((PasswordCallback) callbacks[1]).setPassword(password.getTextChars());
+               for (Callback callback : callbacks) {
+                       if (callback instanceof NameCallback)
+                               ((NameCallback) callback).setName(username.getText());
+                       else if (callback instanceof PasswordCallback)
+                               ((PasswordCallback) callback).setPassword(password
+                                               .getTextChars());
+                       else if (callback instanceof HttpRequestCallback)
+                               ((HttpRequestCallback) callback).setRequest(RWT.getRequest());
+               }
        }
 
        public Shell getShell() {
                return shell;
        }
-
 }
index afab928aa363cdc04d85d37876e4c8633ecf90c9..e8fd556bfe7f71302f16e40c20f7fe4751c239ff 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.cms.util;
 
 import javax.jcr.Node;
+import javax.security.auth.Subject;
 
 import org.argeo.cms.CmsMsg;
 import org.argeo.cms.CmsStyles;
@@ -23,13 +24,12 @@ public class UserMenuLink extends MenuLink {
 
        @Override
        public Control createUi(Composite parent, Node context) {
-               String username = CurrentUser.getUsername(CmsUtils.getCmsView()
-                               .getSubject());
+               Subject subject = CmsUtils.getCmsView().getSubject();
+               String username = CurrentUser.getUsername(subject);
                if (username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS))
                        setLabel(CmsMsg.login.lead());
                else {
-                       setLabel(CurrentUser.getDisplayName(CmsUtils.getCmsView()
-                                       .getSubject()));
+                       setLabel(CurrentUser.getDisplayName(subject));
                }
                Label link = (Label) ((Composite) super.createUi(parent, context))
                                .getChildren()[0];
diff --git a/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/SingleSourcingException.java b/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/SingleSourcingException.java
new file mode 100644 (file)
index 0000000..9b75690
--- /dev/null
@@ -0,0 +1,15 @@
+package org.argeo.eclipse.ui.specific;
+
+/** Exception related to SWT/RWT single sourcing. */
+public class SingleSourcingException extends RuntimeException {
+       private static final long serialVersionUID = -727700418055348468L;
+
+       public SingleSourcingException(String message, Throwable cause) {
+               super(message, cause);
+       }
+
+       public SingleSourcingException(String message) {
+               super(message);
+       }
+
+}
diff --git a/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java b/org.argeo.eclipse.ui.rap/src/org/argeo/eclipse/ui/specific/UiContext.java
new file mode 100644 (file)
index 0000000..ce50873
--- /dev/null
@@ -0,0 +1,39 @@
+package org.argeo.eclipse.ui.specific;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.swt.widgets.Display;
+
+/** Singleton class providing single sources infos about the UI context. */
+public class UiContext {
+
+       public static HttpServletRequest getHttpRequest() {
+               return RWT.getRequest();
+       }
+
+       /** Can always be null */
+       @SuppressWarnings("unchecked")
+       public static <T> T getData(String key) {
+               Display display = getDisplay();
+               if (display == null)
+                       return null;
+               return (T) display.getData(key);
+       }
+
+       public static void setData(String key, Object value) {
+               Display display = getDisplay();
+               if (display == null)
+                       throw new SingleSourcingException(
+                                       "Not display available in RAP context");
+               display.setData(key, value);
+       }
+
+       private static Display getDisplay() {
+               return Display.getCurrent();
+       }
+
+       private UiContext() {
+       }
+
+}
index 3fac3eba791d4941905b2195b6031353628ec9e0..bb97b6549ebaf3267289ea207db7a6d3278e4ceb 100644 (file)
@@ -1,6 +1,9 @@
 package org.argeo.security.ui.rap;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.argeo.security.ui.login.WorkbenchLogin;
+import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.ui.PlatformUI;
 
@@ -17,4 +20,7 @@ public class RapLoginEntryPoint extends WorkbenchLogin {
                return new RapWorkbenchAdvisor(username);
        }
 
+       protected HttpServletRequest getRequest() {
+               return RWT.getRequest();
+       }
 }
index 6a4e879e247708710ff7debaea978338e0132e2c..0eee6745cbd4cf11380e55cb1061d2d1c521fec3 100644 (file)
@@ -3,11 +3,20 @@ package org.argeo.security.ui.login;
 import java.security.PrivilegedAction;
 
 import javax.security.auth.Subject;
+import javax.security.auth.login.CredentialNotFoundException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
 
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
 import org.argeo.cms.CmsImageManager;
 import org.argeo.cms.CmsView;
+import org.argeo.cms.auth.AuthConstants;
 import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
 import org.argeo.cms.util.UserMenu;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.eclipse.rap.rwt.application.EntryPoint;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Display;
@@ -15,20 +24,31 @@ import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.PlatformUI;
 
 public abstract class WorkbenchLogin implements EntryPoint, CmsView {
+       // private final static Log log = LogFactory.getLog(WorkbenchLogin.class);
        private final Subject subject = new Subject();
+       private LoginContext loginContext;
 
        @Override
        public int createUI() {
                final Display display = PlatformUI.createDisplay();
-               display.setData(CmsView.KEY, this);
-               Shell shell = new Shell(display, SWT.NO_TRIM);
-               shell.setMaximized(true);
-               UserMenu userMenu = new UserMenu(shell, false);
-               shell.open();
-               while (!userMenu.getShell().isDisposed()) {
-                       if (!display.readAndDispatch()) {
-                               display.sleep();
+               UiContext.setData(CmsView.KEY, this);
+               try {
+                       loginContext = new LoginContext(AuthConstants.LOGIN_CONTEXT_USER,
+                                       subject, new HttpRequestCallbackHandler(getRequest()));
+                       loginContext.login();
+               } catch (CredentialNotFoundException e) {
+                       Shell shell = new Shell(display, SWT.NO_TRIM);
+                       shell.setMaximized(true);
+                       //shell.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
+                       UserMenu userMenu = new UserMenu(shell, false);
+                       shell.open();
+                       while (!userMenu.getShell().isDisposed()) {
+                               if (!display.readAndDispatch()) {
+                                       display.sleep();
+                               }
                        }
+               } catch (LoginException e) {
+                       throw new ArgeoException("Cannot log in", e);
                }
                //
                // RUN THE WORKBENCH
@@ -45,14 +65,36 @@ public abstract class WorkbenchLogin implements EntryPoint, CmsView {
                } finally {
                        display.dispose();
                }
+               // explicit workbench closing
+               logout();
                return returnCode;
-               // display.dispose();
-               // return 0;
        }
 
        protected abstract int createAndRunWorkbench(Display display,
                        String username);
 
+       // private void fullLogout() {
+       // String username = CurrentUser.getUsername(subject);
+       // try {
+       // LoginContext loginContext = new LoginContext(
+       // AuthConstants.LOGIN_CONTEXT_USER, subject);
+       // loginContext.logout();
+       // HttpServletRequest httpRequest = getRequest();
+       // httpRequest.setAttribute(HttpContext.AUTHORIZATION, null);
+       // HttpSession httpSession = httpRequest.getSession();
+       // httpSession.setAttribute(HttpContext.AUTHORIZATION, null);
+       // httpSession.setMaxInactiveInterval(1);
+       // log.info("Logged out " + (username != null ? username : "")
+       // + " (THREAD=" + Thread.currentThread().getId() + ")");
+       // } catch (LoginException e) {
+       // log.error("Error when logging out", e);
+       // }
+       // }
+
+       protected HttpServletRequest getRequest() {
+               return UiContext.getHttpRequest();
+       }
+
        @Override
        public void navigateTo(String state) {
                // TODO Auto-generated method stub
@@ -60,7 +102,19 @@ public abstract class WorkbenchLogin implements EntryPoint, CmsView {
        }
 
        @Override
-       public void authChange() {
+       public void authChange(LoginContext loginContext) {
+               this.loginContext = loginContext;
+       }
+
+       @Override
+       public void logout() {
+               if (loginContext == null)
+                       throw new CmsException("Login context should not bet null");
+               try {
+                       loginContext.logout();
+               } catch (LoginException e) {
+                       throw new CmsException("Cannot log out", e);
+               }
        }
 
        @Override