When you click "remember me" on login, it doesn't seem to persist after you close the browser. Our users are complaining about this given our previous site would remember you until you logged out (even between browser sessions).
Is this behavior configurable?
Jeff, the remember me login cookie has an expiration date which I believe is set to a week or so. Are you users seeing this happen every time after closing a browser and subsequently opening a new one or does it seem to happen only after a set period of time? What version of Clearspace are you on?
We're running the latest - 2.5.3
Basically, it looks like the cookies are set to end at the end of session according to Firebug.
Is there a way I can configure this to end like in +1 month or something like that?
Also, looking at the source in JiveAuthenticationTranslationFilter the code is harded for this.. does this mean i need to recompile the code to change this.? please say no.......
protected void addLoginCookie(JiveAuthentication auth, HttpServletRequest request, HttpServletResponse response) {
if (JiveGlobals.getJiveBooleanProperty(COOKIE_LOGGED_IN + ".cookie", true)) {
if (auth == null || auth.isAnonymous()) {
Cookie cookie = CookieUtils.getCookie(request, COOKIE_LOGGED_IN);
if (cookie != null) {
CookieUtils.deleteCookie(request, response, cookie);
}
}
else {
Cookie existing = CookieUtils.getCookie(request, COOKIE_LOGGED_IN);
if (existing == null || !"true".equals(existing.getValue())) {
CookieUtils.setCookie(request, response, COOKIE_LOGGED_IN, "true", -1);
}
}
}
}
This is code that sets the timespan of the cookie that indicates whether you are logged in. The RememberMeProcessingFilter is what examines the remember me cookie. I'm investigating where this gets set and what the timespan is. This is the cookie that you are interested in, correct?
Thanks.
I'm not sure if this is the right cookie or not ... but it definitely expires upon session exit (that's what the HTTP headers indicate too).
Jeff,
Can you check your cookies for the expiration date of ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE? This should be two weeks from the time it was last set. When set (by selecting remember me at the login prompt), this should keep you logged in for up to two weeks. If this is not set, we'll need to check the security filters that are being applied for the URLs you are accessing to ensure that the RememberMeProcessingFilter is a part of the chain.
Thanks,
Austen
The only 3 cookies that are being sent are:
- JSESSIONID
- jive.server.info
- jive.recentHistory
We do have our own authentication filter that hits a different DB for login credentials. Are we suppose to set this cookie or call something else to make this work?
A couple of questions for you:
If you have simply modified the filter chain, you'll probably just need to add back in the rememberMeProcessingFilter. If you have SSO integration, it would be the responsibility of the SSO solution to set a cookie that Clearspace can consume (via custom code).
We're using the out-of-the-box clearspace installation. Looking the the web.xml in the WAR, there is no remember anything in the file. (see attached copy of web.xml we're running)
We are using the default jive login form. We have simply written a plugin that will talk with our DB to validate credentials and pass back to Jive the info.
The "Remeber Me" is in the default Jive login interface.
Is there something else we need to do to configure this?
Jeff,
Does your plugin have a spring.xml? If so, can you please post that as an attachment to the case? The security related changes would be contained in this file, not the web.xml.
here's our plugin.
Thanks, this is helpful. A couple more things:
I can confirm that the form is how you described it. I've also attached a copy of our AuthFilter. There are some odd bits in there, mostly because we want to authenticate users by their emails and not their usernames. Let me know if you have any questions.
You should have a copy of the Auth filter now. Also, I can confirm that there is an autoLogin field on the login form and the submit action is "cs_login".
-Kevin
Jeff, any update?
Hi Austen,
I am going to be trying to run this down for us - see my update to your last question. Are there other things I can be looking at that will be of assistance?
Also, as Jeff noted, we don't have any servlet filters defined for "rememberMeFilter" or anything along those lines.
Kevin,
The ACEGI security filters are a bit different in that they are defined in the spring.xml file, not the web.xml. As for the issue you are running across, we have apparently had several reports of the problem and it appears to be due to a recent change in the way Tomcat handles cookies when certain values are placed in the cookie. We have a defect filed for this (CS-9849) and the fix is currently scheduled for the 2.5.5 release.
Thank you all for your help on this issue!
Thanks for the update - is there are workaround available for the issue?
this is a real big problem for us and our users are constantly complaining about this -- especially our power users who stay on the forums all day.
we need a quick workaround -- do we need to downgrade tomcat or something? can we patch the source ourselves?
The bug report states that this started happening in Tomcat 6.0.18. If you downgrade to a version prior to that, you should see the remember me functionality start to function again.
Is a previous version of Tomcat 6 known to work, or are we talking a downgrade to 5.5?
Also, for the record, we're running Tomcat 6.0.14 - so the issue has likely been around a bit longer...
-Kevin
Kevin,
The comment from the assigned developer is that the change took place in the 6.0.18 release of Tomcat, but he could be mistaken. Can you please confirm that your users are not logging out ant the end of their session? If you log out, the remember me cookie will be cleared. Also, would it be possible to use Fire Cookie to get a dump of all of your cookies while you are logged in?
Thanks,
Austen
I have firecookie enabled - which cookie am I looking for?
-Kevin
I can also confirm that I (and others) are not logging out first before eding the session.
I have attached a screencap of the Firecookie info coming back - see attached, and let me know what further information I can provide on that front. Should another cookie be sent to the browser other than the ones shown?
-Kevin
It definitely looks like the ACEGI cookie is not being set. I'm going to run this by our development team to confirm the 6.0.18 release and see if they have any ideas about what the root cause might be.
Okay, so here is what I found:
There are two changes needed to make this work. First thing that you'll need to do is inject the rememberMeServices into your Filter. Second, after you have authenticated, you'll need to call the rememberMeServices.loginSuccess(HttpServletRequest, HttpServletResponse, Authentication). When you do this, you must make sure that the password hash that you store in the cookie is the same as is stored in the DB, otherwise the rememberMeProcessingFilter will fail to authenticate you from the stored cookie.
Please let me know if you have any questions about this.
Austen,
Thanks for the info. We are implementing your suggestions right away. Do you mind clarifying though, what you mean here:
At what point should be putting the password hash into a cookie? This wasn't previously part of our authentication filter and I don't see it happening in the code you just mentioned either. Thanks again.
When you call the rememberMeServices loginSuccess method, this is saving the cookie for you. To create the cookie, it extracts the username and password out of the Authentication object. Here's a copy of that method:
public void loginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
// Exit if the principal hasn't asked to be remembered
if (!rememberMeRequested(request, parameter)) {
if (logger.isDebugEnabled()) {
logger.debug("Did not send remember-me cookie (principal did not set parameter '" + this.parameter
+ "')");
}
return;
}
// Determine username and password, ensuring empty strings
Assert.notNull(successfulAuthentication.getPrincipal());
Assert.notNull(successfulAuthentication.getCredentials());
String username = retrieveUserName(successfulAuthentication);
String password = retrievePassword(successfulAuthentication);
// If unable to find a username and password, just abort as
// TokenBasedRememberMeServices unable to construct a valid token in
// this case
if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
return;
}
long expiryTime = System.currentTimeMillis() + (tokenValiditySeconds * 1000);
// construct token to put in cookie; format is:
// username + ":" + expiryTime + ":" + Md5Hex(username + ":" +
// expiryTime + ":" + password + ":" + key)
String signatureValue = DigestUtils.md5Hex(username + ":" + expiryTime + ":" + password + ":" + key);
String tokenValue = username + ":" + expiryTime + ":" + signatureValue;
String tokenValueBase64 = new String(Base64.encodeBase64(tokenValue.getBytes()));
response.addCookie(makeValidCookie(tokenValueBase64, request, tokenValiditySeconds));
if (logger.isDebugEnabled()) {
logger
.debug("Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime)
+ "'");
}
}
Once this cookie is established, the rememberMeProcessingFilter will attempt to log you in using the rememberMeServices autoLogin method. Under the covers, this method will load the password for the user and created a hashed cookie to compare to the hashed cookie that is passed along in the request. If the two match, you are authenticated and auto logged in.
I've run into a problem with your suggestion. In the snippet of code you listed above (in TokenBasedRememberMeServices from the acegi security package) there is:
// Determine username and password, ensuring empty strings
Assert.notNull(successfulAuthentication.getPrincipal());
Assert.notNull(successfulAuthentication.getCredentials());
Meanwhile in the JiveUserAuthentication class, which is type of Authentication instance I create in my plugin, I find this code:
public Object getCredentials() {
return null;
}
Unfortunately, the second assertion fails and the loginSuccess method throws an exception.
Martin,
Do you need to return null here? This is required to be non-null for the remember me services, as you have pointed out. In order to build the cookie, it is necessary to get the credentials. If your Authentication's principal is an instance of UserDetails, it will retrieve the password from there. However, credentials must still be a non-null Object for this to work. Does it create a problem in your code if you do not return null?
Thanks,
Austen
Just to clarify, I'm not actually returning null. It's happening inside Jive code (specifically the JiveUserAuthentication class). This is how the examples showed how to authenticate a user in my code:
Authentication authentication = new JiveUserAuthentication(jiveUser);
authentication.setAuthenticated(true);
context.setAuthentication(authentication);
The bit in my previous post where getCredentials is returning null is from the Jive JiveUserAuthentication class.
Perhaps I could extend that class, but I'm not sure what the appropriate thing to return instead of null would be.
Sorry, I must have read over that a little too fast. I spoke with a colleague on my team who is a bit more experienced with CS 2.5 SSO integrations and he recommended that you implement this as a AuthenticationProvider rather than an authentication filter. Most SSO integrations do not have the need for the TokenBasedRememberMeServices.
Since you are just going against an external DB for authentication and using the default login page, this would be more suited to a provider. You would want to override this spring bean and replace the first three providers with a custom rolled one. The daoAuthenticationProvider would be a good starting reference:
<!-- List of authentication providers used by the authentication manager beans.
Customized authentication providers can override this bean and re-define
this list as needed.-->
<bean id="authenticationProviderList" class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<ref bean="jiveLdapAuthenticationProvider"/>
<ref bean="daoAuthenticationProvider" />
<ref bean="jiveLegacyAuthenticationProvider"/>
<ref bean="rememberMeAuthenticationProvider"/>
<ref bean="openfireAuthenticationProvider"/>
</list>
</property>
</bean>
If you do decide to stick with the filter, you'll probably have to extend the JiveUserAuthentication to override that method to return a UsernamePasswordCredentials object.
How are things coming? Did you decide which route you plan on taking? Did you have any additional questions regarding my latest post?
The solutions that you mention above seem non-trivial. Sometime in the future we will be moving to an SSO, It's likely that that will remove the problems we're having with the RememberMeServices. We might have to wait for persisted logins until we finish the new SSO login.
Indeed, it is not a one line fixer and would require some testing effort. I am going to close this case for the time being. If you have additional questions about how the rememberMeServices works or about implementing this as a provider, feel free to reply to this thread to reopen the case or to open a new case.
Thanks,
Austen
Jive combines collaboration software, community software & social networking software into the leading SBS solution.
© Copyright 2000–2009 Jive Software. All rights reserved.
915 SW Stark St., Suite 400, Portland, OR 97205