Cross domain sessions

02.18.2010

I have been racking my brain for some time on how to accomplish cross domain sessions.  It was especially puzzling at first since the application I was working on ran multiple sites.  So, the code base was the same, even though the domain might change.

I will not go too deep into security on this, I am just going to give you the tools to explore the concept.

The first step you will have to take is to create a services file on the original site providing the session, in this case I will be using rails.

  1. #Controller
  2. class ServiceController < ApplicationController
  3.   def sessioninfo
  4.     if session[:user]
  5.       @referrer = ‘var referrer=\’ + request.env[‘HTTP_REFERER’].to_s + \’;’
  6.       @user = ‘var user=’ + session[:user].to_json + ‘;’
  7.     else
  8.       #there was no session
  9.     end
  10.   end
  11. end

What ultimately gets outputted from this is the following:

  1. #output
  2. var referrer=‘http://www.thereferrer.com’;
  3. var user={"user"{"username":"joshmattvander"}}

Now the session is ultimately exposed on the original site.  But we need to get it from another site.  The only way to accomplish that I can find is to use javascript.  What you are going to do is add a script to the head of the document with your exposed service URL in my case (http://mysite.com/service/sessioninfo).  The reason we are doing this in javascript, is because if we did this on the server side, the session would be blank.  By doing this in javascript it is as if the user was returning to the URL themselves so the session is still alive and kicking.

  1.  
  2. $(document).ready(function(){
  3.         var scriptEl = $(‘<script type="text/javascript" src="http://mysite.com/service/sessioninfo"></script>’);
  4.         $(scriptEl).appendTo($(‘head’));
  5.         setTimeout(function(){
  6.                 try {
  7.                         if (referrer && user) {
  8.                         alert(‘The referring site is: ‘ + referrer + ‘.’)
  9.                         alert(‘The logged in user is: ‘ + user[‘user’].username + ‘.’)
  10.                         }
  11.                 } catch (e) {
  12.                         alert("The session did not transfer")
  13.                 }
  14.         }, 500);
  15. });
  16.  

This is the basic mechanism that allows this to happen, but the next step would be securing with some sort of key and adapting this to your needs.

As stated earlier - on my app there are multiple domains being run by a single application. So I can save the a generated key to a table, and then use that key to re-connect with ajax.

Ajaxifying your website

09.04.2009

This tutorial is intended to be a first look at the concept of “Ajaxifying” your website. That is, creating a progressive-enhancement to how users navigate from page to page. Traditionally when a user clicks a link, the new page in it’s entirety will be loaded. If your header / navigation / footer stays the same throughout, there is little need to re-download that content, furthermore to re-render that content after it downloaded.

This is a generic pattern that you can expand on and implement with your web application.

First the Javascript

  1.  
  2. var QuickLink = Class.create({
  3.  
  4.     currentPage : null,
  5.  
  6.     initialize : function() {
  7.         this.attachLinkEvents();
  8.         //Set an interval to check for changes in the URI
  9.         setInterval(function(){
  10.             this.refresh();
  11.         }.bind(this), 1000);
  12.     },
  13.    
  14.     refresh : function() {
  15.         //If a change has taken place, call the dispatch function
  16.         var url = window.location.hash.split(‘#’);
  17.         if (url.length > 1) {
  18.             this.dispatch(url[1]);
  19.         }
  20.     },
  21.  
  22.     attachLinkEvents : function() {
  23.         //Gather a list of links, and replace the default action
  24.         //With our javascript action
  25.         var links = $$(‘a’);
  26.         links.each(function(linkElement, index) {
  27.                 var href = linkElement.href;
  28.                 if(href.indexOf(‘http://www.yourdomain.com/’) != -1) {
  29.                     var uri = href.split(‘http://www.yourdomain.com’)[1];
  30.                     Event.observe(linkElement, ‘click’, function(e){
  31.                         window.location.hash = uri;
  32.                         //Disallow the default click to change pages
  33.                         Event.stop(e);
  34.                     });
  35.                 }
  36.  
  37.                 });
  38.         },
  39.        
  40.         dispatch : function(url) {
  41.         //Check to see if the page you are linking to is NOT the current URL
  42.         //If different, then send your request
  43.         if (this.currentPage != url) {
  44.             this.currentPage = url;
  45.             var myAjax = new Ajax.Updater(‘content’, url, {
  46.                 parameters : { ‘quick’ : true }
  47.             });
  48.         }
  49.  
  50.  
  51.         }
  52.  });
  53.  
  54. //initialize
  55.  
  56.  new QuickLink();
  57.  
  58.  

Your template

  1.  
  2. <? if ($_POST[‘quick’]!=true) { ?>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  4.         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  5. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  6. <head>
  7.         <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  8.         <title>Page Title</title>
  9. </head>
  10. <body>
  11. <div id="content">
  12. <? } ?> 
  13.         Some content here
  14. <? if ($_POST[‘quick’]!=true) { ?>
  15. </div>
  16. </body>
  17. </html>
  18. <? } ?>
  19.  

In conclusion

What we are doing is using AJAX just to refresh the content area. Your template checks to see if it was an AJAX request and if so, does not send the header and footer of your content back. This saves you in the following areas:

  • Does not have to re-download everything
  • If you have scripts that need to be initialized, the scripts will not need to be reparsed

Moving further

If using a more advanced setup like an MVC framework or if your app has different scripts or elements depending on the page I suggest on the server side you instead send back a payload including dependent scripts and maybe flags to highlight elements as well. Then you can use output buffering to store the HTML chunk in part of the payload. Return the response as a JSON object have your Javascript put things where they need to go and THEN write the innerHTML of the content part of the payload.

© Copyright 2009, JoshMattVander. Powered by Wordpress
Valid XHTML 1.0 Strict : Valid CSS 2