Forum OpenACS Development: Login/Security tokens without cookies

In Japan there are a couple of reasons why it would
be useful to have the ACS support  some kind of authentication
or login without using Cookies.

the iMode phones don't support cookies, and also apparently
many people disable cookies in their browsers for security
reasons  (so I've been told).

Anyway, I'm pondering if there is an easy way to put the session
tokens into the URL someplace if the browser doesn't handle
cookies, rather than just giving up. It seems that with
the request processor centralizing all URL handling it should
be possible to stuff and unstuff a session ID into the
start or end of the URL.  Many ACS3 modules do their
own cookie juggling, but ACS4 pretty much
relies on the session mechanism, as I recall.

Does anyone have recent experience with this
technique, i.e.,  know what the "state of the art" is in
passing session id tokens in URLs? I.e., what is the best
encoding mechanism, where is the best place to put
them in a URL, to prevent tripping over browser bugs, what
does the Java servlet standard do, what does PHP do,  etc..

Collapse
Posted by Steve Crossan on
I agree, it would be good to have an alternative. One thing to watch out for is that the session token doesn't become too large - I can remember doing this a few years ago and having a lot of problems with a URL size limit in (I think) IE 4.
Collapse
Posted by Pascal Scheffers on
Basic Authentication is the simplest way to go I think. It is,
AFAIK, supported in every browser. For most
OpenACS applications this would suffice, I think. It should not be
too hard to implement, and with some checking the authentication
mechanism could even be smart enough to use the forms/cookie
authentication for those that support it (i.e. give cookies back) or
use basic authentication (which pops up a dialog in the browser.)
Collapse
Posted by Jerry Asher on
Henry,

Can you describe a bit more about what you mean by authentication and login? I can see how session ids can be easily encoded into the URL, but I would worry about placing a permanent, bookmarkable, user id representing an authenticated user into the URL.

The nice feature of cookies is that you can put a great deal of data in them (so that makes it hard for users to just try random cookies) and they are invisible: ignoring any security through obscurity benefits, that makes them a friendly UI.

I notice that Amazon has taken to moving query parameters, including session ids, into some odd lookings URLs:

http://www.amazon.com/exec/obidos/ASIN/0140067485/o/qid=987113900/sr=2-1/107-1497231-4480558

And Tom Jackson has a tcl module for AOLserver that can be used to do something similar for AOLserver sites. I believe Saleonall.com is using his VAT module. If you visit http://saleonall.com/cat/input/keyboards/7063/onemfg.html you can see how his catalog is encoded into the URL and doesn't use the query field.

I am not sure what servlets are doing, but I hope to rsn.... And I would love to see this placed into the 4.x request processor and security handler....

Collapse
Posted by Tom Jackson on

Putting session ids in the url is a great way to make your site difficult to bookmark, email to friends and to index with a search engine. At least that is what I thought until I read Jerry's post.

He is right that I use the url to encode variables. The main reason I do that is because I want AltaVista to index the site.

I have done this encoding several different ways so I can tell you that there is one good way that would allow you to encode the session_id without messing up any of the above three important features of static urls.

I wrote a simple little adp tag, I like it so much that I even use it on tcl pages. Here is the code:

proc set_url_vars_adptag {tagset} {
    set size [ns_set size $tagset]
    set urlv [ns_conn urlv]
    set urlc [ns_conn urlc]
    for {set i 0} {$i < $size } {incr i} {
	set key   [ns_set key $tagset $i]
	set value [ns_set value $tagset $i]
	upvar $key $key
	set $key [lindex $urlv [expr $urlc - $value - 1]]
	
    }
    return ""
}
ns_register_adptag urlvars  set_url_vars_adptag

Then you can put this adp tag on your page and set variables from the url:
<urlvars letter="2" mfg_id="1">
or use code like this on your tcl page to get the same effect:
set tagset [ns_set create]
ns_set put $tagset letter 2
ns_set put $tagset mfg_id 1
set_url_vars_adptag $tagset

The key to this is that you count from the tail end of the url back toward the http part. This is much more desireable than hard coded positions, which is really the same as counting from the left.

Using my VAT module which is available at http://zmbh.com/discussion/vat/ you could include a session id in the url. Imagine that I wanted to do this. Go to this url: http://dev.saleonall.com/cat/accessories/cables/onesub.html. Now insert some random letters between the first directory 'cat' and the second 'accessories'. Try for instance: http://dev.saleonall.com/cat/1234/accessories/cables/onesub.html.

You still need to worry about identifying users. Basic authentication is you only other option. Usually this requires sending a base 64 encoded clear text string of the user name and password. It isn't less secure than using a cookie, but with session tokens, there is less opportunity to steal a password. It isn't likly to happen, but just good to remember that it can.

Collapse
Posted by David Eison on
Patrick McNeill did this sort of modification to ACS for Voxtime (apparently some phone stuff doesn't do cookies right so they needed things to work without cookies).  Basically one session-id-getting procedure was modified to check the first "directory" in the URL for the session ID if no session ID was found, and all URLs were modified to include the session ID.  The hard part is the "all URLs were modified" part, simply because there are a lot of hard-coded links.  I'm sure he could provide more details if you need them.

This would probably be easier on ACS-Java because I did a modification to support different mount points; required replacing all hard-coded links and using a "get context path" method to get the context path.  So you're down to just the include-session-id-in-get-context-path-method and check-context-path-for-session-id steps.  The standard Java session handling won't work for ACS-Java because
a) It isn't database backed,
b) it requires you to call a method around every URL, and the system wasn't written that way,
c) it uses a URL variable rather than a directory, so it doesn't work "for free" on relative links (see b)

Finally, you'd want to make sure the session ID encodes & checks at least part of the IP, and probably have faster timeouts than normal, so that people don't accidentally e-mail their login to their friend.

It's an easy enough change that I think it should really be done, it's a nice feature and can reduce frustration/customer support "your site is broken" requests.

Collapse
Posted by Patrick McNeill on
In ACS4-based systems, aside from modifying the hard-coded links, this is fairly easy to do.  The concept is that you copy the ad_token_id cookie into the front of the URL (index 0 of ns_conn urlv).  ad_conn is modified to strip off the session information when ad_conn url is called (vs just passing it through to ns_conn).  A new function is needed to create the URL string -- it needs to be signed in some way -- I used SHA1 hashing.

We have the basics now, so we modify the request processor and security system to redirect users without the URL session information to a URL with session information.  The cookie-reading functions are modified to read the URL session information when the ad_token_id doesn't exist.  That's about it (IIRC) for a basic functional system.

Now for the trickier part -- making it work nicely.  First, you can't detect whether a user does or does not have cookie support until the second page load so the first page visited always has to have the session information in the URL.  However, after that first page, the session information should be omitted for users that support cookies.  This can be done with another redirect in the security system.  The downside is that this method requires something that can be recognized by ad_conn, so it can decide if the urlv0 needs to be stripped.  I would simply prepend some random combination of letters that isn't likely to be used at the front of a URL.  It's also wise to make this a package parameter.  The other way to make this work nicely is to maintain the session information even when the user finds an absolute link.  This is done by reading session information from the referrer header when its not present in the URL or cookie.

I'm planning on redoing this system for ACS Java when I get some time, and possibly writing an ASJ article about it.

Collapse
Posted by Henry Minsky on
For handling the i-mode cell phone browsers, I think it is
probably sufficient to use "manually assisted" methods, which would mean just adding a little support in the form of functions to shove some form of the session id into a URL var, and to parse it out.

What I mean is that for i-mode, you have to design new pages anyway, so it won't ever be transparent to handle both desktop and cell phone browsers with the same pages.

For the users who won't enable cookies, I'm not quite as concerned about that. But it would be nice if the request processor made it
as easy as possible to handle this option should it be desired.

Collapse
Posted by Jerry Asher on
As folks legitimately navigate a site, they often perform URL hacking, which means that a) we should support URL hacking and b) it's a good thing to make the URL's semiunderstandable in structure.  I would recommend the session id not be urlv0 or urlvsmall, but would think it better belongs as urlend or urlvlarge.

We want to encourage folks to email and bookmark urls.  That means that the system should be able to determine when a session has timed out and create a new session id.

Collapse
Posted by Patrick McNeill on
Jerry -- I didn't make this clear in my first posting.  By making the session code look in both the cookie and URL for session information, session timeouts work correctly.  With a redirect, the user can be given a new session completely invisibly to the user.  This allows bookmarks to function completely normally -- the user just may have to log in again (which they'd have to do anyways).

As for URL hacking, if someone wants to do it, IMHO, they'll do it regardless of where the session information is.  From my experience, the best place to put it is at the front -- anywhere else would require much more extensive changes to the ACS.  As long as it's not 100s of bytes long, it shouldn't be a problem.

Collapse
Posted by David Eison on
I like it at the front because URL hackers tend to work from the right to the left - nuke the current page to get to the current directory, nuke that directory to go up a level, etc.  And because relative links work well/easily.