Cookies are a great invention, allowing the web developer to maintain
the login status of their users. However, problems occur when your site or network
has more than one domain.
The cookie specification says that any cookie set for one domain, must
not be sent to any other domain. Therefore, if you set a cookie in your user's
browser on one domain, that cookie will not be available on any other domain.
This is a big problem, if you want your users to log in on one of your
sites and still be logged in on your other domains.
My solution will use the following general framework:
- A prepend script will be used that will accept the sessionid via GET or COOKIE.
It will preferentially choose a GET variable over a COOKIE. Therefore, whenever we need to
link across domains, we send the sessionid as a URL parameter.
- The Apache configuration will be modified to do rewrites on all cross-domain cookies.
The reason for this will soon become clear.
- Variables will be used whenever a cross-domain href appears.
Step 1: Setting Up A Prepend Script
Add the following code to a prepend script (or a function that appears at the top
of all scripts).
<?php
/* Support cross-domain cookies... */
// If the GET variable has been set, and it differs from the cookie
// variable, then use the get variable (and update the cookie)
global $HTTP_COOKIE_VARS, $HTTP_GET_VARS;
if (isset($sessionid) && isset($HTTP_GET_VARS['sessionid']) && ($HTTP_COOKIE_VARS['sessionid'] != $HTTP_GET_VARS['sessionid'])) {
SetCookie('sessionid', $HTTP_GET_VARS['sessionid'], 0, '/', '');
$HTTP_COOKIE_VARS['sessionid'] = $HTTP_GET_VARS['sessionid'];
$sessionid = $HTTP_GET_VARS['sessionid'];
}
?>
Once this code has been run, a global variable 'sessionid' will be available
to the script. It will contain the value of the sessionid from the users
cookie, or the value sent along with a GET request.
Step 2: Using Variables For All Cross-Domain Hrefs
Create a global configuration file that contains the base hrefs of the domains
you are switching between. For example, if we have domain1.com and domain2.com, set
the following:
<?php
$domains['domain1'] = "http://www.domain1.com/-$sessionid-";
$domains['domain2'] = "http://www.domain2.com/-$sessionid-";
?>
Now, if you do the following in your code...
<?php
echo "Click <a href=\"", $domains['domain2'], "/contact/?email=yes\">here</a> to contact us.";
?>
...you will produce the following output...
Click <a href="http://www.domain2.com/-66543afe6543asdf6asd-/contact/?email=yes\">here</a> to contact us.
...where the sessionid has been inserted into the URL.
At this point, you are probably thinking "this will try to open a subdirectory on
the webserver called dash, sessionid, dash?!?!?". However, the next step will provide the necessary
magic to make it all work - mod_rewrite!
Step 3: Configuring Apache
Now, the remaining step is to configure apache to rewrite this URL:
http://www.domain2.com/-66543afe6543asdf6asd-/contact/
...to this:
http://www.domain2.com/contact/?sessionid=66543afe6543asdf6asd
...and this kind of url:
http://www.domain2.com/-66543afe6543asdf6asd-/contact/?email=yes
...to this:
http://www.domain2.com/contact/?email=yes&sessionid=66543afe6543asdf6asd
To achieve this, simply configure your two virtual servers for domain1 and domain2 as
follows:
<VirtualHost ipaddress>
DocumentRoot /usr/local/www/domain1
ServerName www.domain1.com
RewriteEngine on
RewriteRule ^/-(.*)-(.*\?.*)$ $2&sessionid=$1 [L,R,QSA]
RewriteRule ^/-(.*)-(.*)$ $2?sessionid=$1 [L,R,QSA]
</VirtualHost>
<VirtualHost ipaddress>
DocumentRoot /usr/local/www/domain2
ServerName www.domain2.com
RewriteEngine on
RewriteRule ^/-(.*)-(.*\?.*)$ $2&sessionid=$1 [L,R,QSA]
RewriteRule ^/-(.*)-(.*)$ $2?sessionid=$1 [L,R,QSA]
</VirtualHost>
Those rewriting rules implement the above two URL rewriting requirements.
Conclusion
By using the combination of variables and apache rewriting, cross-domain cookies can
be implemented in a simple fashion. In order to maintain the system, your coders
need to do nothing more than use the domain variables whenever they link across domains.
Links within domains do not need to be modified, as the cookie will work properly.
If you are interested in seeing this system in action on a production network, please
visit
http://www.familyhealth.com.au/. Run
your mouse over some of the inter-domain links and see how they are rewritten when you
click on them.
Perhaps, the only problem with this technique is that it is impossible to delete the
cookie in the users browser for all the domains.
-- Chris