tags:

views:

515

answers:

3

On my site I have a simple login form. The page is served via HTTP, but the form's POST URL is HTTPS.

The normal method is that the user fills in their username/password, the form is submitted (to the fully qualified HTTPS URL, on the same site), and then the POST processing does a 303 redirect to the users' homepage. But sometimes this doesnt happen.

The cycle (and this is 100% repeatable) is this:

  1. visit login form, fillin details and submit
  2. On the servber the login script gets called, validates the data and then , if all is well, does a 303 redirect to the users home page.
  3. I then click logout and then click login, at which point im taken back to the login form
  4. I then fill in my details again, hit submit.
  5. This time, however, the login logic doesnt execute (the debug code that logged the login at step 2 doesnt get called), and yet im still redirected to the users homepage. But because i've not been logged in succesfully, I get kicked out to the front page...

SO why isnt the POST always calling the login form? I dont think the 303 is being cached (and it shouldnt be, according to the spec)...

Looking at the HTTPS logs in the server, login.phpo is being called the first time, but not the second....

Edit:

OK, we've solved the problem. For those that are interested:

The site is run on 2 webservers behind a load balancer. user sessions are 'sticky' - that is to say once a user is browsing on one web server the LB will keep them 'attached' to that server. This is done via a cookie. But once we switch to HTTPS the LB cant read the cookie, as the connection is encrypted between the browser and web server. So it was alternating between servers. WWe have code to propagate login authentications between webservers, but this wasnt happening fast enough. So whgat was happening was:

  1. User browsers to server A, gets a cookie saying 'keep me on A', fills in their login credentials and hits submit/
  2. The LB, being unable to decypher the HTTPS traffic (and thus the cookie), sends them 50% of the time to B
  3. B validates the login and sets the user to be authenticated in the session, before redirecting the user to the non https homepage
  4. Because the homepage is non https, the LB reads the cookie and sends them to A, which knows nothing of the authentication since it wasnt propagating fast enough from B...

The solution was to allow the LB to decrypt HTTPS traffic, thus ensuring that users really do stay on one web server, regardless of HTTP/HTTPS transitions.

A: 

Seems like it must be a caching issue, I would think. I'd set the headers on the pages so that you're explicitly not caching anything, and see how that works.

Second guess is that you have a session/ cookie issue (admittedly, I haven't thought through how this would work). In your logout page, do you explicitly destroy the session (and any non-permanent cookies on the client)?

Finally, are you using any server side caching? I don't think a PHP opcode cache would exhibit this behavior, but I've seen stranger things with memcache (and, if you're using a framework, each framework caches a little differently).

Travis Leleu
+1  A: 

How do you "log out" Have you tried clearing your cache to see if any leftover session variables are throwing it off?

In Firefox: Tools -> Clear Private Data -> Check Cache, Cookies, and Authenticated Sessions

St. John Johnson
+1  A: 

I dont think the 303 is being cached (and it shouldnt be, according to the spec)...

No, a 303 won't be cached by the browser, but some other level might be caching it or other pages in the sequence. Also, assuming you are using cookies to store login state, you need to ensure that you're setting ‘path’ and ‘domain’ so that the same cookie is being set and deleted, instead of multiple shadowed copies for different parts of the site.

More code needed to diagnose.

The page is served via HTTP, but the form's POST URL is HTTPS.

Don't do that. The user has no way of telling that the ‘action’ URL is going to be HTTPS without looking at the source manually (and checking every script referenced), which isn't going to happen.

So it's possible for a man-in-the-middle attacker to grab authentication details by simply altering the initial HTTP page with the login form. This makes any protection on the POST receiver entirely moot.

Every stage of the login process, including any page containing a login form, must be on HTTPS for you to get any benefit from it.

bobince