I have a rather annoying problem in the last few days, after lots of
debugging I found it was a problem with the way php handles sessions
and how cakephp handles links coming in from external websites.
I created a bug in Trac here: https://trac.cakephp.org/ticket/5782
Here is the issue:
I have a link to: http://127.0.0.1/cmhr/websites/browse/11/Drug_and_alcohol
cmhr is where cakephp is installed.
The websites controller is using the Auth component so then user is
redirected to an authentication page, but during the process the
session is lost again and cakephp no longer knows where it's supposed
to redirect to because Auth.redirect is gone so it redirects to the
HTTP_REFERER which is http://locahost/test.html after the user logs
I did extensive debugging both using a PHP debugger, wireshark and
reading the php source code for sessions and I found out some
1. Go to http://locahost/test.html
2. Click on http://127.0.0.1/cmhr/websites/browse/11/Drug_and_alcohol
(with session cookie CAKEPHP=750c5ad36000dc5c773b3419e922aff1)
3. Cake php saves /websites/browse/11/Drug_and_alcohol into
Auth.redirect and sends a HTTP redirect (HTTP 1/1 302 Found, with
Location header) to http://127.0.0.1/cmhr/users/login (Server sets
Session cookie CAKEPHP=1f537fb5f5a1cdb3065920f05b128314)
4. Browser requests http://127.0.0.1/cmhr/users/login (with session
cookie CAKEPHP=1f537fb5f5a1cdb3065920f05b128314) Referer: http://localhost/test.html
5. Server sends back login page amd saves http://localhost/test.html
into Auth.redirect (Server sets Session cookie
6. Browser posts response to http://127.0.0.1/cmhr/users/login (with
session cookie CAKEPHP=5ee7d212148b93f5ca6c343808b9690d) Referer:
7. Server (CakePHP) sends back HTTP redirect to http://locahost/test.html
And the user is back where they started.
If you look above you'll notice that on step 5 php has changed the
session key and because it did that the original Auth.redirect was
lost, so when cakephp realises that it decides to use the http referer
instead which happens to be the external website.
I also verified this bug on book.cakephp.org, if you create a link
from an external site eg http://localhost/test.html to
http://book.cakephp.org/edit/526/How-it-Works you should be presented
with a login box, and then after you login you will be redirected
where you came from. I confirmed this with my delicious account too.
Eg I bookmarked http://book.cakephp.org/edit/526/How-it-Works and then
click on the link, logged in and was redirected back to delicious.
I tried all sorts of things, but couldn't get around it, and in the
end I went as far as read php source code.
In ext/session/session.c I found the following comment:
/* check whether the current request was referred to by
an external site which invalidates the previously found id */
Which explains why the session changes on steps 3 and 5.
So to retain the Auth.redirect we have to work around php killing the
I had 3 ideas off the top of my head:
1. We set an auth_redirect cookie when we detect that the referer
hostname is different to currrent hostname. But the problem with this
is that we then loose the session flash message that says "You are not
authorized to access that location." or whatever is in $this-
>authError. But we could probably get around it easily enough by
adding the authError message back in when we see the auth_redirect
2. We append the auth redirect to the login url, ie: users/login?
authRedirect=/edit/526/How-it-Works. This would probably be more
reliable especially if cookies are disabled, but it doesn't look as
good. I don't think you would need the ?authRedirect in the form
action because the auth component could just add authRedirect back
into the session when the browser requests the login page after it
sends the 302 redirect.
3. Remove the http_referer, unfortunately I tried this and it didn't
seem to work for me. It seems that php can still get access to the
http_referer even if we unset it from $_SERVER.