Here is another issue I alluded to in a previous post (on
groups.google.com/group/sproutcore). Again, I don't know whether this is the ideal forum to post it one, but I'm thinking that everyone here who does web-apps should encounter it at some time or another, so I'm going to go ahead. Besides, I can't find a more suitable group to post it on.
I'm developing a web app that asks users to submit personal financial information that they can return to later, but guarantees their anonymity. Moreover, I don't want my app and data server to have to deal with passwords and e-mails and all the use cases that maintaining authentication and privacy might involve. So I decided to use OpenId for authentication. Before displaying the Sproutcore app, the user must first initiate authentication with the data server, which redirects him to an OpenId provider, such as Google or Yahoo, which then returns his OpenId URL (essentially, a username). The server promptly obfuscates the OpenId URL/username with SHA-1. This then becomes the username for my SC app data server. So ultimately, even I would not be able to know who my users are, unless they explicitly contact me with their OpenId URL.
My next goal is to assure that the data server itself is secure from tampering. In particular, I want to assure that:
- An unauthenticated user cannot access or alter any data.
-
An authenticated user can only access and modify his own data.
So my data server creates a random session ID that it associates with the user-id in a database table. (I could have also done this in memory, but then a session would not survive a server-restart, which might be useful, and I would need a separate thread instead of a cron job to clean-up expired sessions.) Then it redirects the user's browser to the Sproutcore app.
My first problem was how to get the newly minted session-id to the SC app. I tried in vain to put it in a cookie. But each time I examined the response with Firebug, there was no sign of this cookie in the response. Instead, I find only the cookie 'rack.session'. Trying to decode it myself, I got:
$ irb
ruby-1.9.1-p243 > data="BAh7AA%3D%3D%0A"
=> "BAh7AA%3D%3D%0A"
ruby-1.9.1-p243 > data.unpack("m*")
=> ["\x04\b{\x00\r\xC3\xDC=\x00"]
ruby-1.9.1-p243 > unpacked = data.unpack("m*")
=> ["\x04\b{\x00\r\xC3\xDC=\x00"]
ruby-1.9.1-p243 > Marshal.load(unpacked)
TypeError: instance of IO needed
from (irb):4:in `load'
from (irb):4
from /home/lsiden/.rvm/ruby-1.9.1-p243/bin/irb:15:in `<main>'
I never figured out how to get Marshal.load it's IO instance that it wants, but I'm pretty sure that this is not the rack.session from my data server, but from the instance of sc-server that is supporting my SC app while it is still in development. I'm guessing, but not sure where to confirm, that Firefox (and other browsers) will ignore any cookie set from a different domain or even by a different port on the same domain.
So I'm left with the much uglier method of attaching the session id to my sproutcore app URL like so:
http://<my.domain.com/my-app?session_id=13245...
This works, but am I the only one who thinks this "smells" a little funny?
I should have mentioned sooner that this entire transaction will take place over HTTPS once it is deployed. So the session-id is secure and the session is safe from session-hijacking (at least as safe as HTTPS can provide).
This is my first experience building this kind of app, so I want to check with others whether I am taking the right approach or whether there might be a better way to do this.
One solution that comes to mind might be to deploy same port number to the Sproutcore app as the data server, so that the data server can plant the session cookie when it redirects to the SC app, but this has consequences. In particular, it means that now these two apps must be deployed together, when before they could be logically deployed separately. That, too, has a bad odor.
Larry Siden,
734-926-9614,
http://umich.edu/~lsidenThe United States is a nation of laws, badly written and randomly enforced.
--Frank Zappa 1940-1993