Joel Pearson
Joel Pearson

Reputation: 1631

JBoss EAP 6.3 / AS 7 Clustered SSO with unsecured pages

I am trying to get Clustered SSO working in JBoss EAP 6.3.2 (equivalent to JBoss AS 7.4.x), I have session replication working fine, however SSO (user principal replication) is not working in all cases.

It works properly when I use servlets that are secured inside a <security-contraint> that has an <auth-constraint> with an appropriate role.

However for servlets that are not protected, SSO doesn't work until I first access a protected page, which seemes to kickstart the SSO and infinispan then finds the User Principal in the cluster.

This is a problem, because I have a number of pages that behave differently whether you are logged in or not.

I have a dodgy workaround where I call reauthenticateFromSSO inside a valve, however that doesn't work until a subsequent request (I presume I am too late in the chain). I could probably do a servlet FORWARD to work around this, but it just seems dodgy.

Inside the standalone.xml I tried setting reauthenticate=true in the <sso cache-container="web" cache-name="sso" reauthenticate="true"/> line, however that just seemed to cause it to logout everytime I ended up on a different server in the cluster.

Is there some magic setting inside JBoss to make it reauthenticate SSO on pages that don't require authentication?

Upvotes: 2

Views: 793

Answers (1)

Joel Pearson
Joel Pearson

Reputation: 1631

Thanks to some clarifications by @FedericoSierra, calling super.reauthenticateFromSSO before super.invoke(request, response); solved my problem. I have attached the code below.

In theory checking for request.getPrincipal() == null && ssoID != null might have been sufficient also.

ClusteredSSOFailoverValve.java

package com.mycompany.valve;

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

import org.jboss.as.web.security.ExtendedFormAuthenticator;
import com.yourcompany.framework.Loggers;

/**
 * Enables Clustered Single Sign On session failover for servlets that don't have any security defined in the web.xml
 */
public class ClusteredSSOFailoverValve extends ExtendedFormAuthenticator {

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        if (request.getSession(false) != null && request.getPrincipal() == null) {
            // Try to find the session from Infinispan
            // The REQ_SSOID_NOTE is set by org.jboss.as.web.sso.ClusteredSingleSignOn.invoke(Request, Response)
            Object ssoID = request.getNote(Constants.REQ_SSOID_NOTE);
            if (ssoID != null && ssoID instanceof String) {
                if (Loggers.securityLogger.isDebugEnabled()) {
                    Loggers.securityLogger
                            .debug("Found SSO Session ID ["
                                    + ssoID
                                    + "] with a null principal, so will attempt a re-authenticate from SSO to try and retrieve the user principal from the cluster");
                }
                super.reauthenticateFromSSO((String) ssoID, request);
                if (Loggers.securityLogger.isDebugEnabled()) {
                    Loggers.securityLogger.debug("After re-authenticate from SSO with ssoID [" + ssoID + "], principal is now ["
                            + request.getPrincipal() + "]");
                }
            }
        }
        super.invoke(request, response);
    }
}

WEB-INF/jboss-web.xml

<?xml version='1.0' encoding='UTF-8' ?>
<jboss-web>
   <security-domain>sso</security-domain>
   <valve>
      <class-name>com.mycompany.valve.ClusteredSSOFailoverValve</class-name>
   </valve>
</jboss-web>

Upvotes: 2

Related Questions