how are you obtaining the user's credentials for the auto-login?
Technically speaking, I'm not obtaining the credentials for auto-login.
I have IIS configured with the ISAPI redirector sitting in front of Apache Tomcat. When IE is the browser, the Spring Security J2eePreAuthenticatedProcessingFilter will grab the AUTHORIZATION header put there by IIS, and populate the SpringSecurityContext with the user's authentication token. Here is some of my spring xml.
PHP Code:
<security:http auto-config="false" session-fixation-protection="none" >
<security:intercept-url pattern="/messagebroker/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<security:form-login />
<security:logout logout-url="/j_spring_security_logout"/>
</security:http>
<!-- Configuration for pre-authentication (e.g. User logged into Windows > IE > IIS > Tomcat) -->
<bean id="jeePreAuthenticatedFilter"
class="org.springframework.security.ui.preauth.j2ee.J2eePreAuthenticatedProcessingFilter">
<security:custom-filter position="PRE_AUTH_FILTER"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="preAuthAuthenticationProvider"
class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<security:custom-authentication-provider/>
<property name="preAuthenticatedUserDetailsService" ref="userDetailsService"/>
</bean>
And are trying to use ChannelSet.login() to authenticate at that time?
For pre-auth, I am not calling ChannelSet.login(). It is when I want to logout of my pre-authenticated session and login manually as another user that things fall apart. Because the ChannelSet.login() is passing through the Spring Security filters, the pre-auth filter populates the UserPrincipal into the HttpServletRequest again before SpringSecurityLoginCommand.doAuthentication() has a chance to run. In fact, the code in BlazeDS LoginManager.login() circumvents the LoginCommand altogether throwing the "cannot re-auth" error. Here's some of LoginManager code:
PHP Code:
/**
* Perform login with username and credentials.
*
* @param username Username to use to login.
* @param credentials Credentials to use to login.
*/
public void login(String username, Object credentials)
{
if (getCurrentPrincipal() == null)
{
if (loginCommand != null)
{
if (username != null && credentials != null)
{
Principal authenticated = loginCommand.doAuthentication(username, credentials);
if (authenticated == null)
{
// Invalid login.
SecurityException se = new SecurityException();
se.setMessage(INVALID_LOGIN);
se.setCode(SecurityException.CLIENT_AUTHENTICATION_CODE);
throw se;
}
setCurrentPrincipal(authenticated);
}
else
{
// Login is required but the client passed null principal and credentials.
SecurityException se = new SecurityException();
se.setMessage(LOGIN_REQ);
se.setCode(SecurityException.CLIENT_AUTHENTICATION_CODE);
throw se;
}
}
else
{
// Client needs to be externally authenticated via Basic Authentication or some other method.
SecurityException se = new SecurityException();
se.setMessage(NO_LOGIN_COMMAND);
se.setCode(SecurityException.SERVER_AUTHENTICATION_CODE);
throw se;
}
}
else
{
// It is possible that the username passed in from the client and that stored in the
// Principal on the session may be different. To facilitate this case a LoginCommand
// must implement LoginCommandExt and the user stored in the Principal is retrieved
// here for comparison
String comparisonUsername;
if(loginCommand instanceof LoginCommandExt)
{
comparisonUsername = ((LoginCommandExt)loginCommand).getPrincipalNameFromCredentials(username, credentials);
}
else
{
comparisonUsername = username;
}
// If we have a username and a different existing principal then we
// must raise an exception as we don't allow re-authentication for
// a given session...
if (comparisonUsername != null && !comparisonUsername.equals(getCurrentPrincipal().getName()))
{
// Cannot re-authenticate in the same session.
SecurityException se = new SecurityException();
se.setMessage(CANNOT_REAUTH);
se.setCode(SecurityException.CLIENT_AUTHENTICATION_CODE);
throw se;
}
}
}
FYI - I have a destination endpoint Flex calls when the client app is starting up: User getAuthenticatedUser().
If this call fails to return a User (e.g. the Windows user doesn't have an account in my application), the client app challenges the user with the login form; otherwise the main page of the application is presented.
I hope I'm getting closer to answering your questions.