*/
package org.argeo.security.ui.rap;
+import java.security.AccessControlContext;
+import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
+import javax.security.auth.login.CredentialNotFoundException;
+import javax.security.auth.login.FailedLoginException;
+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.eclipse.ui.ErrorFeedback;
-import org.argeo.util.LocaleUtils;
-import org.eclipse.equinox.security.auth.ILoginContext;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.ThreadDeathLoginException;
+import org.argeo.cms.widgets.auth.DefaultLoginDialog;
+import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.rap.rwt.RWT;
-import org.eclipse.rap.rwt.application.IEntryPoint;
+import org.eclipse.rap.rwt.application.EntryPoint;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
-import org.springframework.security.BadCredentialsException;
-import org.springframework.security.context.SecurityContext;
-import org.springframework.security.context.SecurityContextHolder;
/**
* RAP entry point with login capabilities. Once the user has been
* authenticated, the workbench is run as a privileged action by the related
* subject.
*/
-public class SecureEntryPoint implements IEntryPoint {
+@Deprecated
+public class SecureEntryPoint implements EntryPoint {
+ final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext";
private final static Log log = LogFactory.getLog(SecureEntryPoint.class);
- /**
- * From org.springframework.security.context.
- * HttpSessionContextIntegrationFilter
- */
- protected static final String SPRING_SECURITY_CONTEXT_KEY = "SPRING_SECURITY_CONTEXT";
-
/**
* How many seconds to wait before invalidating the session if the user has
* not yet logged in.
// around too long
RWT.getRequest().getSession().setMaxInactiveInterval(loginTimeout);
- // Try to load security context thanks to the session processing filter
- HttpServletRequest httpRequest = RWT.getRequest();
- HttpSession httpSession = httpRequest.getSession();
- Object contextFromSessionObject = httpSession
- .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
- if (contextFromSessionObject != null)
- SecurityContextHolder
- .setContext((SecurityContext) contextFromSessionObject);
-
-// if (log.isDebugEnabled())
-// log.debug("THREAD=" + Thread.currentThread().getId()
-// + ", sessionStore=" + RWT.getSessionStore().getId()
-// + ", remote user=" + httpRequest.getRemoteUser());
-
- // create display
final Display display = PlatformUI.createDisplay();
- // log in
- final ILoginContext loginContext = SecureRapActivator
- .createLoginContext(SecureRapActivator.CONTEXT_SPRING);
- Subject subject = null;
- tryLogin: while (subject == null && !display.isDisposed()) {
+ // load context from session
+ HttpServletRequest httpRequest = RWT.getRequest();
+ final HttpSession httpSession = httpRequest.getSession();
+ AccessControlContext acc = (AccessControlContext) httpSession
+ .getAttribute(ACCESS_CONTROL_CONTEXT);
+
+ final Subject subject;
+ if (acc != null
+ && Subject.getSubject(acc).getPrincipals(X500Principal.class)
+ .size() == 1) {
+ subject = Subject.getSubject(acc);
+ } else {
+ subject = new Subject();
+
+ final LoginContext loginContext;
+ DefaultLoginDialog callbackHandler;
try {
- loginContext.login();
- subject = loginContext.getSubject();
-
- // add security context to session
- if (httpSession.getAttribute(SPRING_SECURITY_CONTEXT_KEY) == null)
- httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY,
- SecurityContextHolder.getContext());
- // add thread locale to RWT session
- log.info("Locale "+LocaleUtils.threadLocale.get());
- RWT.setLocale(LocaleUtils.threadLocale.get());
-
- // Once the user is logged in, she can have a longer session
- // timeout
- RWT.getRequest().getSession()
- .setMaxInactiveInterval(sessionTimeout);
- if (log.isDebugEnabled())
- log.debug("Authenticated " + subject);
- } catch (LoginException e) {
- BadCredentialsException bce = wasCausedByBadCredentials(e);
- if (bce != null) {
+ callbackHandler = new DefaultLoginDialog(
+ display.getActiveShell());
+ loginContext = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_USER, subject,
+ callbackHandler);
+ } catch (LoginException e1) {
+ throw new CmsException("Cannot initialize login context", e1);
+ }
+
+ tryLogin: while (subject.getPrincipals(X500Principal.class).size() == 0) {
+ try {
+ loginContext.login();
+ if (subject.getPrincipals(X500Principal.class).size() == 0)
+ throw new CmsException("Login succeeded but no auth");// fatal
+
+ // add thread locale to RWT session
+ // if (log.isTraceEnabled())
+ // log.trace("Locale " + LocaleUtils.threadLocale.get());
+ // RWT.setLocale(LocaleUtils.threadLocale.get());
+
+ // once the user is logged in, longer session timeout
+ RWT.getRequest().getSession()
+ .setMaxInactiveInterval(sessionTimeout);
+
+ if (log.isDebugEnabled())
+ log.debug("Authenticated " + subject);
+ } catch (FailedLoginException e) {
MessageDialog.openInformation(display.getActiveShell(),
- "Bad Credentials", bce.getMessage());
+ "Bad Credentials", e.getMessage());
// retry login
continue tryLogin;
+ } catch (CredentialNotFoundException e) {
+ MessageDialog.openInformation(display.getActiveShell(),
+ "No Credentials", e.getMessage());
+ // retry login
+ continue tryLogin;
+ } catch (LoginException e) {
+ callbackHandler.getShell().dispose();
+ return processLoginDeath(display, e);
}
- return processLoginDeath(display, e);
}
}
-
- final String username = subject.getPrincipals().iterator().next()
- .getName();
+ final String username = subject.getPrincipals(X500Principal.class)
+ .iterator().next().getName();
// Logout callback when the display is disposed
display.disposeExec(new Runnable() {
public void run() {
- log.debug("Display disposed");
- logout(loginContext, username);
+ if (log.isTraceEnabled())
+ log.trace("Display disposed");
+ try {
+ LoginContext loginContext = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_USER, subject);
+ loginContext.logout();
+ } catch (LoginException e) {
+ log.error("Error when logging out", e);
+ }
}
});
try {
returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
public Integer run() {
+ // add security context to session
+ httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
+ AccessController.getContext());
+
+ // start workbench
RapWorkbenchAdvisor workbenchAdvisor = createRapWorkbenchAdvisor(username);
int result = PlatformUI.createAndRunWorkbench(display,
workbenchAdvisor);
return new Integer(result);
}
});
- // logout(loginContext, username);
+ // Explicit exit from workbench
+ fullLogout(subject, username);
} finally {
display.dispose();
}
return returnCode;
}
- private Integer processLoginDeath(Display display, LoginException e) {
+ private Integer processLoginDeath(Display display, Throwable e) {
// check thread death
ThreadDeath td = wasCausedByThreadDeath(e);
if (td != null) {
display.dispose();
return -1;
} else {
- throw new ArgeoException(
+ throw new CmsException(
"Unexpected exception during authentication", e);
}
}
- /** Recursively look for {@link BadCredentialsException} in the root causes. */
- private BadCredentialsException wasCausedByBadCredentials(Throwable t) {
- if (t instanceof BadCredentialsException)
- return (BadCredentialsException) t;
-
- if (t.getCause() != null)
- return wasCausedByBadCredentials(t.getCause());
- else
- return null;
- }
-
/**
* If there is a {@link ThreadDeath} in the root causes, rethrow it
* (important for RAP cleaning mechanism)
protected ThreadDeath wasCausedByThreadDeath(Throwable t) {
if (t instanceof ThreadDeath)
return (ThreadDeath) t;
-
+ if (t instanceof ThreadDeathLoginException)
+ return ((ThreadDeathLoginException) t).getThreadDeath();
if (t.getCause() != null)
return wasCausedByThreadDeath(t.getCause());
else
return null;
}
- protected void logout(ILoginContext secureContext, String username) {
+ private void fullLogout(Subject subject, String username) {
try {
+ LoginContext loginContext = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_USER, subject);
+ loginContext.logout();
HttpServletRequest httpRequest = RWT.getRequest();
HttpSession httpSession = httpRequest.getSession();
- httpSession.setAttribute(SPRING_SECURITY_CONTEXT_KEY, null);
+ httpSession.setAttribute(ACCESS_CONTROL_CONTEXT, null);
RWT.getRequest().getSession().setMaxInactiveInterval(1);
- SecurityContextHolder.clearContext();
- secureContext.logout();
log.info("Logged out " + (username != null ? username : "")
+ " (THREAD=" + Thread.currentThread().getId() + ")");
} catch (LoginException e) {
- log.error("Erorr when logging out", e);
+ log.error("Error when logging out", e);
}
}
}