views:

573

answers:

3

I have a weird quirk with cookies in IE. When a user logs into the site, I'm generating a new session id and hence need to overwrite the cookie. The flow is basically:

  1. Client goes to https://secure.example.com/users/login page, automatically receiving a session id
  2. Client POSTs login credentials to same address
  3. Client receives the following set-cookie headers together with a 302 redirect to https://secure.example.com/users/mypage:

    CAKEPHP=deleted; expires=Sun, 05-Apr-2009 04:50:35 GMT; path=/
    CAKEPHP=98hnIO23...; expires=Mon, 12 Apr 2010 04:50:36 GMT; path=/; secure

  4. Client is supposed to visit https://secure.example.com/users/mypage, presenting the new session id.

This works in all browsers, except IE (tested in 7 & 8). IE retains the old, unauthenticated session id, and is redirected back to the login page. It works on my local test environment (using a self-signed certificate at https://localhost:8443/...), but not on the live server.

I'm using CakePHP and simply issue a $this->Session->renew(), which produces the above cookie headers.

Any ideas how to get IE to accept the new cookie?


Here's the complete header:

HTTP/1.0 302 Moved Temporarily
Date: Thu, 08 Apr 2010 02:54:30 GMT
Server: Apache
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Set-Cookie: CAKEPHP=deleted; expires=Wed, 08-Apr-2009 02:54:30 GMT; path=/
Set-Cookie: CAKEPHP=d55c...; expires=Thu, 15 Apr 2010 02:54:31 GMT; path=/; secure
Last-Modified: Thu, 08 Apr 2010 02:54:30 GMT
Location: https://secure.example.com/users/mypage
Vary: Accept-Encoding
Content-Length: 0
Connection: close
Content-Type: text/html; charset=utf-8

I think I have found the problem: IE is sending two cookies of identical name. Here's the next request to the server:

GET /users/mypage HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-silverlight, */ *
Referer: https://secure.example.com/users/login
Accept-Language: en-gb
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322)
Accept-Encoding: gzip, deflate
Host: secure.example.com
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: CAKEPHP=19c6...; CAKEPHP=d55c...

Notice that it sends two cookies, the one it received after logging in, but also the old one. It received the old one at the main page example.com, set with path=/. It's also sending it for requests to secure.example.com. It doesn't get replaced by the above header, instead it adds it as additional cookie. How can I stop it from doing that?

+2  A: 

A common problem is that the second attempt to set the cookie lacks a proper P3P header and thus the attempt to touch the cookie is ignored.

It would be helpful if you posted the headers of the overall flow (e.g. use Fiddler to capture and look)

EricLaw -MSFT-
After fiddling around with Fiddler I think I found the root of the problem, please have a look at the question again.
deceze
The typical problem when you have two cookies of the same name is that you either set the same cookie with two different PATH attributes, or you set the same cookie with two different DOMAIN attributes. The latter often occurs when a user visits your site as //example.com and later revisits as //www.example.com. If your site isn't careful to always redirect to www.example.com without setting a cookie, you end up with two. Due to the nature of cookie domain inheritence, both are sent when you visit www.example.com. Simplest way to check? Visit //example.com and check!
EricLaw -MSFT-
As I read your question more closely, it sounds to me like you already know that this is the problem.To fix it, add the DOMAIN=example.com attribute to all of your SET-COOKIE response headers.
EricLaw -MSFT-
+2  A: 

Make sure the cookies are emitted for your base domain.

That's v. likely the problem, since this behavior certainly varies in different browsers.

I haven't done it in cakephp, but this should work

eglasius
Yep, that was the problem. I added `ini_set('session.cookie_domain', '.example.com')` via the linked method. Thanks!
deceze
+1  A: 

You might have two issues here. First, give the link in @freddy-rios posting a shot. If that doesn't do it, then you might experience the IE "redirection cookie bug."

IE doesn't always honor cookie modification during redirection. If you assign a session ID on the login form, and do not change it, then the redirect should work fine. If you are altering a cookie on redirect, then you'll probably end up with the old session... the browser will simply submit the old cookie to the new URL (arguably, what it's supposed to do... redirect the original request).

There are a handful of ways to deal with this. The ugliest, by far, is to use a Javascript or META tag redirect. As long as you pass a non-300 with those cookies, the browser will almost always accept them.

If you are using $this->Session->renew(), simply removing it may solve all of your problems... especially if it's calling session_regenerate_id() under the hood.

I'd suggest removing the redirect and seeing if it's still a problem. If it is, then you can ignore everything I said. :)

Pestilence