This document is out of date.
ACS Documentation : ACS Kernel Documentation : Security Documentation : Session Tracking
HTTP is a stateless protocol, but nearly all nontrivial Web services are stateful. We need to provide a way to maintain state within a session. Such state includes the user's preferences, login information if any (although the solution needs to be general enough to handle anonymous sessions), and an identifier for the session itself. This session identifier absolutely must remain constant from the moment a user enters to the site to the moment he or she is done (even if the user logs in or switches to HTTPS in the meantime) so our clickstreaming software can ably analyze the users' behavior.
We need to provide different levels of security for different parts of this state:
The new security and session-tracking subsystem needs to consolidate the myriad ways in place now for maintaining and securing session and persistent state (including login information). It must remember the last time the user visited the site, so we can determine which material on the site is new since the user's last visit.
In reality, the session system has no way of knowing the identity of a person, but it makes the assumption that a series of requests from one browser, each within a specified interval, is from one person. The system recognizes session data by issuing and retrieving cookies from the client's browser. Included in the cookie is a token, a randomly generated string that acts like the password for the session. It verifies the information using the database, so someone cannot log in, get a session, muck with the cookie, then get access as someone else.
Because this system is instantiated upon every request made to the server, efficiency is crucial to the system. In order to achieve speed, we utilize global variables and AOL server caching mechanisms.
To provide the specifications, the system uses the global variable ad_conn to pass user session information between various procs. Though this makes the code more complex and harder to read, it allows for a cleaner implementation because we don't have to worry about passing all the variables from one part of the session to another. The global variable ad_conn in AOL Server exists from the beginning of the request to when the connection is closed, so the system can access the variables in any step of the way.
To fully show the API, we will go through a user session experience.
The user information is stored in the database and also set in the global environment
It checks whether the token and session_id match the database. It then realizes that the user_id is null, so it returns 0 to the tcl page.
The tcl page then redirects to a login page.
Since the -forever flag is set, it then goes to assign a login_token inside the sec_login_token table. It then assigns the ad_user_login cookie to Richard's browser
----------------
| Page Request |
----------------
|
| ---------------------
|------------| Request Processor | Handles all redirects and url mappings
---------------------
|
|
---------------
| Sec_Handler | sets ad_conn and cookies to the browser
---------------
|
-----------------------
|
|
|
------------ -----------------------------
| TCL page |---| ad_verify_and_get_user_id |
------------ -----------------------------
|
|
-----------------------------
| ad_validate_security_info | checks global variables against database.
-----------------------------
|
|
-----------------------------
| ad_verify_and_get_user_id | returns the user_id if security passed, 0 otherwise.
-----------------------------
|
|
-----------------------
|
|
------------
| TCL page |
------------
|
| --------
--------------| User |
--------
sec_handler:
sec_handler, which
gains control from the request processor and makes sure the global
variable ad_conn is set correctly. If the handler recognizes a cookie, it
sets the information appropriately. Otherwise, it goes through a
process to create a session_id and set the cookie with the appropriate
information.
ad_validate_security_info
The semantics of ad_get_user_id and ad_verify_and_get_user_id remain the same: ad_get_user_id does absolutely no checking that the user ID isn't forged, while ad_verify_and_get_user_id makes sure the user is properly logged in. Correspondingly, the new routine ad_get_session_id returns a session ID (which may be forged), whereas the new routine ad_verify_and_get_session_id first verifies that the token is valid. Both verify routines take an optional -secure switch, taking a Boolean (t/f) argument defaulting to f; if true, only secure (HTTPS) connections will be considered valid.
ad_verify_and_get_user_id
ad_get_user_id
ad_set_client_property
ad_get_client_property
sec_sessions : holds information for regular sessions
sec_login_tokens : holds information for permanent
logins.
sec_session_properties : properties for this session
sec_browser_properties : properties for this browser
(multiple sessions)
create table sec_sessions (
-- Unique ID (don't care if everyone knows this)
session_id integer primary key,
user_id references users,
-- A secret used for unencrypted connections
token varchar(50) not null,
-- A secret used for encrypted connections only. not generated until needed
secure_token varchar(50),
browser_id integer not null,
-- Make sure all hits in this session are from same host
last_ip varchar(50) not null,
-- When was the last hit from this session? (seconds since the epoch)
last_hit integer not null
);
We populate secure_token only when we issue a secure token (the first time the client
makes an access to the site over HTTPS).
In order to let programmers write code to preserve state on a per-session or per-browser basis without sending lots of cookies, we maintain the following tables:
create table sec_session_properties (
session_id references sec_sessions not null,
module varchar2(50) not null,
property_name varchar2(50) not null,
property_value varchar2(4000),
-- transmitted only across secure connections?
secure_p char(1) check(secure_p in ('t','f')),
primary key(session_id, module, property_name),
foreign key(session_id) references sec_sessions on delete cascade
);
create table sec_browser_properties (
browser_id integer not null,
module varchar2(50) not null,
property_name varchar2(50) not null,
property_value varchar2(4000),
-- transmitted only across secure connections?
secure_p char(1) check(secure_p in ('t','f')),
primary key(browser_id, module, property_name)
);
A client module needing to save or restore session- or browser-specific state uses the new
ad_get_client_property and ad_set_client_property routines, which manage access to the
table (caching as appropriate). This way they don't have to set their own cookies, and as a
bonus they don't have to worry about users tampering with contents!
In general, use session-level properties when you want the properties to expire when the current session ceases (e.g., items in a shopping cart). Use browser-level properties which the properties should never expire (e.g., user preferences).
One really neat thing about properties is that if secure_p
is true (i.e., the secure_p flag was passed to
ad_set_client_property - see above) the
ad_get_client_property routine will refuse to access the
information except when the connection is secure (HTTPS) and the
secure token is correct. So the user can switch back and forth between
HTTP and HTTPS without giving anything away, and hijackers cannot
tamper with any state marked secure (even if they're sniffing for
tokens). Note that this only works for session-level state for the
moment - browser-level state isn't protected by any kind of token.
ad_session_id := session-id,user-id,token-string,last-issue
Note that TokenLength and SessionCookieReissue are parameters configurable in the local .ini file.
We issue ad_session_id, like ad_browser_id, whenever we receive an HTTP request from a client that doesn't already have it set. We keep this cookie set to expire SessionTimeout seconds in the future (plus or minus SessionCookieReissue seconds).
This cookie is only ever sent to a client once, so there's positively no way we could make the mistake of sending it to two users (one masquerading as the other). Furthermore, when the secure token is issued (typically on a client's first access to the site via HTTPS) we reissue the insecure token as well. This way, if Gus sniffs Mary's insecure token and proceeds to make a secure access to the site (receiving her secure token), Mary's insecure session will stop working, limiting Gus's ability to mess with her.
ad_user_login := user-id,permanent-login-token
permanent-login-token is a TokenLength-character random string stored in the login_token field of a row in sec_login_tokens. This cookie is persistent, and allows the user to log into ACS without having to explicitly type a login name and password. If the user logged in securely (over SSL), this cookie is only ever transmitted over SSL; otherwise, we assume the user doesn't care about security anyway and let it be transmitted in the clear.
All inside of [ns/server/yourservername/security]
Parameter Description AllowPersistentLoginPAllow a person to be logged in forever? TokenLengthLength of Security Tokens SessionTimeouthow long can a session be inactive for before it times out? (in seconds) SessionCookieReissuethe period, in seconds, after which we should reissue the session_id cookie and update last_hit in the sessions table. SessionInfoCacheIntervalhow long should we cache session information (using util_memoize)? SessionLifetimehow long after the last hit should we save information in the SessionLifetime table? PreallocatedSessionPoolSizehow many preallocated session should we store in the database? PreallocatedSessionPoolUpdateIntervalhow often should we reallocate pooled sessions? SessionSweepIntervalhow often should we sweep the sessions pool for old stale sessions? PoolSequence.sec_id_seqpool values in the sec_id_seq sequence
Document Revision # Action Taken, Notes When? By Whom? 0.1 Creation 08/30/2000 Hiro Iwashima 0.2 ad_conn moved to request processor docs 09/16/2000 Rafael Schloming
Last Modified: sessions.html,v 1.1 2001/01/21 01:39:49 bquinn Exp