Geoffrey Young

NAME

Apache::AuthDigest::API::Session - session-based Digest authentication

SYNOPSIS

  PerlModule Apache::AuthDigest::API::Session
  PerlModule My::SessionAuthenticator

  <Location /protected>
    PerlInitHandler My::SessionGenerator
    PerlAuthenHandler My::SessionAuthenticator
    Require valid-user
    AuthType Digest
    AuthName "cookbook"
    DigestSessionKey MYSESSION
  </Location>

DESCRIPTION

Apache::AuthDigest::API::Session is an experimental interface for using the "nonce" part of Digest authentication as a unique session identifier. For more information on Digest authentication, see RFC 2617: ftp://ftp.isi.edu/in-notes/rfc2617.txt

Apache::AuthDigest::API::Session is a subclass of Apache::AuthDigest::API, so see that manpage for details on the base API. where they differ is in the "nonce" key that is used to keep track of authentication sessions. Apache::AuthDigest::API uses the default Apache nonce (currently r->request_time). Apache::AuthDigest::API::Session uses whatever is stored in $r->notes($key), where $key is the notes key specified by the DigestSessionKey configuration directive (which defaults to 'SESSION').

How this all works together is still taking shape. the RFC says that a new nonce should be generated for each 401 sent by the server in order to prevent a replay attack. To me, that sounds rather like what we tend to do with cookies: initiate a session, store it on the client, retrieve the session on each request, then finally expire the session.

With Digest authentication, session initialization is taken care of with the initial 401 response, when the server generates a nonce. here, the session is initalized with the value in $r->notes('SESSION'). the session is stored on the client and sent along with every request to the same realm in the Authorization header. Apache::AuthDigest::API::Session provides the get_session() method for gleaning the session from the headers. So, all we're left with is expiring the session...

How I think this has to work is that $r->notes('SESSION') has to have a dual meaning. Prior to the PerlAuthenHandler, it needs to hold a _new_ session identifier - whatever the session would be if the user was coming in fresh with no session id. After the user authenticates, we can use $r->notes('SESSION') to store the session id of the authenticated user. this session can then be used by a PerlAuthzHandler (or other similar mechansim) to determine the validity of the session.

So, this means that the developer needs to do a few things. First, each request (via a PerlInitHandler or whatever) needs to populate $r->notes('SESSION') with a session to be used _if the user cannot authenticate_. If you think through how HTTP authentication and the Apache API works, you'll see why this needs to happen on every request (or correct me if you think I'm wrong). compare_digest_response() will then, if the user credentials check out, populate $r->notes('SESSION') with the session identifier that the user passed back via the headers.

So, when the PerlAuthzHandler, PerlFixupHandler and PerlHandler are run, $r->notes('SESSION') is the real session id, as gleaned from the headers, and _not_ what was placed into it by the user via a PerlInitHandler or whatever other mechanism one uses to generate a session.

an alternative interface is to have any handler that wants the current session identifier instantiate a new Apache::AuthDigest::API::Session object and call get_session() on it instead of diddling with $r->notes().

as this unfolds and people start to see what is going on, it will probably take more shape. There may very well be security implications here that I can't see, so beware. Hopefully if there are they will be flushed out through the community.

new()

creates a new Apache::AuthDigest::API::Session object. Apache::DigestAPI is a subclass of the Apache class so, with the exception of the addition of new methods, $r can be used the same as if it were a normal Apache object

  my $r = Apache::AuthDigest::API::Session->new(Apache->request);
get_session()

returns a list. the first element is the notes key as defined by DigestSessionKey. the second element is the session identifier (if obtainable).

  my ($key, $session) = $r->get_session;
set_session()

set the session. this actually is an interface that abstracts the notes() stuff I mentioned earlier.

  $r->set_session($session);
compare_digest_response()

same as Apache::AuthDigest::API, except that the nonce value is placed in $r->notes if the comparison is successful.

EXAMPLE

for a complete example, see the My/SessionAuthenticator.pm file in the test suite for this package.

SEE ALSO

perl(1), mod_perl(1), Apache(3)

AUTHORS

Geoffrey Young <geoff@modperlcookbook.org>

Paul Lindner <paul@modperlcookbook.org>

Randy Kobes <randy@modperlcookbook.org>

COPYRIGHT

Copyright (c) 2002, Geoffrey Young, Paul Lindner, Randy Kobes.

All rights reserved.

This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.

HISTORY

This code is derived from the Cookbook::DigestAPI module, available as part of "The mod_perl Developer's Cookbook".

For more information, visit http://www.modperlcookbook.org/