modperl-two_token_session_authentication_scheme

This is part of The Pile, a partial archive of some open source mailing lists and newsgroups.



To: modperl@apache.org
From: DeWitt Clinton <dewitt@unto.net>
Subject: Re: Doing Authorization using mod_perl from a
programmers perspective
Date: Mon, 19 Nov 2001 11:41:32 -0500

On Mon, Nov 19, 2001 at 07:51:55AM -0800, Randal L. Schwartz wrote:

> But this is obvious.  I'm confused about why I'd have to explain it. :(

I posted this a year or two back:

http://mathforum.org/epigone/modperl/jytwortwor/20000420121516.B31518@eziba.com


Here is the relevant part of that post:


It makes sense to start with the requirements for what it means to 
implement those secure features.  My requirements have an obvious 
e-commerce bias, and should probably be heavily reviewed by anyone 
thinking of using this design for online banking or government work. 

First, I'd like to introduce the notion of a secure session.  Secure
sessions have some subtle differences from the traditional notion of
the session, and I'll point those out when they appear.

The secure session has the following properties:

*) The user is able to initiate a secure session by providing proper
credentials (i.e., a username and password pair) via a login process.

*) The user is able to terminate the secure session via a logout
process.

*) Secure sessions must be able to time out automatically.

*) Secure sessions must *never* transmit sensitive data (such as the
password) over insecure channels.

*) The secure session, while it requires the use of a secure protocol
(such as HTTPS), should not require the use of cookies.  Cookies,
however, can be employed to extend the functionality of the system.  

Additionally, I feel that one of the essential requirements to any
enterprise quality, highly scalable, and fault-tolerant system is the
ability to store session state on a tier other than the front-end.
This usually means storing state in a shared database, but there are
other options.

A very effective method of meeting the requirements above is to use a
two token architecture.  The first token is a user identifier, which
can be passed over insecure channels.  This user identification token
can be used to restore state that isn't particularly sensitive, such
as a shopping cart or user preferences.  The second token is a secure
identifier, which is never passed over insecure channels.  The secure
identifier is required to access sensitive data, such as credit card
data. (It is possible to create an architecture that uses *only* the
secure token, but there are significant benefits in terms of
flexibility afforded by using two tokens, so I won't go into the one
token model here.)

The fundamental goal of the secure token is to a) keep it safe from
prying eyes, and b) use it is a requirement for accessing secure data.

Tokens can be passed in one of two ways.  First, the token can be
passed as part of the URL.  Second, the token can be passed in a
cookie.  I've found it very useful to create an initialization
procedure inside applications that check both places for these tokens,
and abstract the particular mechanism used to pass them.  Note,
however, that is important to remember how the token was passed -- if
it came from a cookie, it is cosmetic to not pass it around in the
URL.  I also recommend creating a library used in your templates that
has a function to build URLs that automatically append the tokens if
necessary.  Since it is critical that secure tokens are never passed
in the clear, it really helps to have that function, because it can
prevent the secure token from being sent via an insecure page in a URL
(i.e., only setting secure tokens in URLs that contain "https").

The user identification token is typically used to restore state from
the database.  It is created whenever a page is viewed and the client 
has either not provided one (via the URL or a cookie), or the token
they provide doesn't exist in the database.  This token should then be 
set in both the URL and in a cookie.  On the subsequent page request,
if the user identification token is found in a cookie, it is probably
safe to stop putting it in the URL.  However, if the token is found
only in the URL (probably meaning the client does not use cookies) the 
server should not try writing the cookie again.  

The advantage of the cookie is such that the user can insecurely
identify themselves across browser sessions.  This is perfectly
acceptable when used to restore some insensitive state data (such as a
name or shopping cart).  However, the system still functions without
the cookie.  The user can now login to associate their client with
particular stored user information.

The login process is as follows:

1) The client connects to a secure page that presents a form
requesting a username and password.  (There has been much discussion
about whether a HTTP form that POSTS to a secure page will encrypt the 
posted data.  There is too much ambiguity here -- I recommend using
HTTPS on the login form as well.)  The ACTION of the form must also
be a secure page.

2) On receiving the username and password, the server compares an
encrypted version of the password with the stored encrypted password
associated with that customer.  If the passwords do not match, the
user is returned to the login page. (For highly secure sites, storing
a count of the number of failed logins may be desirable.)

3) The server compares the client supplied user identification token
with the one associated with that username in the database.  If they
are different, the server should use the procedure outline above to set
the new user identification token in the URL and cookie.  

4) The server now generates a unique secure token.  Using the
techniques I mentioned, this should be appended to all links from the
page that use HTTPS, as well as set in the cookie.  *Important* --
when setting this in the cookie, use the "secure" flag in the cookie
string.  This will tell the browser never to send the cookie over
insecure channels.  (I don't know whether to trust the browser here,
but it seems there is little choice if you want to use cookies.)

5) The secure token is associated on the server side (preferably on
another tier, such as a database) with the user identification token.
Additionally, to support secure session timeouts, the current time
must be recorded.


The customer is now technically logged in, and will be able to access
sensitive pages, providing they provide the proper tokens, and certain 
other requirements are met.  When a sensitive page is accessed, the
following requirements must be met:

1) The page must be viewed over a secure protocol (i.e., HTTPS).  

2) The client must present a valid user identification token.  

3) The client must present a valid secure token that matches secure
token that is stored associated with that user identification token.  

4) To implement secure session timeouts, the last access time of the
stored secure token is compared with the current time.  The delta must 
be less than some predetermined value (such as 15 minutes or one
hour).  

5) The current time must be stored as the last access time for the
stored secure token.

6) If the secure token was not found in a cookie, then all the exit
links for that sensitive page should contain the secure token, if and
only if they point at another secured page (similar to the login
procedure).


If any of these requirements are not met, the user can *not* access
the sensitive page.  The server can then display the login page
instead (or redirect to it over a secure protocol, in the case that
requirement #1 was not met).

Obviously, it helps to encapsulate all of those steps inside a simple
routine that each page or module can call at the beginning of the
process.  Even better, enforce some external control that won't even
let the particular page's code run unless those requirements are met.


To explicitly logout, the user should simple be presented with a URL
that requests that the secure session end.  When this happens:

1) The server then erases the stored secure token identified with the
user identification token.  (Now, step #3 of the sensitive page view
requirements will fail on future requests.)

2) As a courtesy, the server should set the secure token in a cookie
to null.  (This isn't required for security, but it makes the user
feel they have logged out.  Do this even if you think the client isn't 
accepting cookies -- some users are manually accepting/declining
cookies to test your system.)

3) Optionally, generate a new user identification token and set this
in the cookie and URL.  (I prefer this approach, because it is very
useful for someone accessing your site from a shared computer.)

There are occasions in which it makes sense to clear the secure cookie
without being asked to.  For example, after a customer on an
e-commerce site makes a purchase, you may want to assume that the
secure session is over.  You  can leave the user identification token
in effect, however.  Additionally, you can clear the stored secure
token after a secure session timeout.


Briefly, the advantage to using cookies is that:

a) The user identification token can persist between browser sessions,
provided they don't explicitly log out.  

b) The user can move between viewing secured and insecured pages.
Recall that if the user access an insecure page, the secure token will 
*not* be passed along in the URL.  When they return to a secure page,
they will fail check #3, and need to log in again.  Cookies, however,
will still contain the secure token (which is okay, because they will 
only be passed to secure pages) and will pass check #3, but perhaps
not check #4 (if the timeout has occurred). 


Well, that about sums it up.  Obviously there is a lot of work
involved in correctly supporting secure authentication in a flexible
fashion.  I've found that most other approaches, even on high profile
e-commerce sites, don't come anywhere close to doing it correctly (or
securely!).   Apologies if I forgot something important here.  I
welcome any comments on this technique, and how to improve it.


===





the rest of The Pile (a partial mailing list archive)

doom@kzsu.stanford.edu