# $Id: AuthTypeKey.pm,v 1.4 2004/08/24 16:39:40 btrott Exp $
package Apache::AuthTypeKey;
use strict;
use Authen::TypeKey;
use Apache::Constants qw( REDIRECT SERVER_ERROR );
use base qw( Apache::AuthCookie );
use vars qw( $VERSION );
$VERSION = '0.01';
sub authen_cred {
my($self, $r, @cred) = @_;
my $token = $r->dir_config('TypeKeyToken');
unless ($token) {
$r->log_error('TypeKeyToken is required');
return;
}
my $tk = Authen::TypeKey->new;
$tk->token($token);
$tk->version(1.1);
my $key = $r->args;
my $q = Apache::AuthTypeKey::Query->new($key);
my $res = $tk->verify($q);
unless ($res) {
$r->log_error('TypeKey verification failed: ' . $tk->errstr);
}
$q->delete('destination');
$res ? $q->as_string : undef;
}
sub authen_ses_key {
my($self, $r, $key) = @_;
my $token = $r->dir_config('TypeKeyToken');
unless ($token) {
$r->log_reason('TypeKeyToken is required');
return SERVER_ERROR;
}
my $tk = Authen::TypeKey->new;
$tk->token($token);
$tk->version(1.1);
## When checking the validity of the session key, we need to skip the
## expiration check on the signature.
$tk->skip_expiry_check(1);
my $res = $tk->verify(Apache::AuthTypeKey::Query->new($key));
$res ? $res->{name} : undef;
}
## This is needed for 2 reasons:
## 1. Authen::TypeKey currently expects a Query-type object.
## 2. Apache->args breaks on '=' signs in the key/value pairs.
package Apache::AuthTypeKey::Query;
use Apache::Util qw( escape_uri unescape_uri );
sub new {
my $class = shift;
my($key) = @_;
my %p;
for my $p (split /&/, $key) {
my($k, $v) = split /=/, $p, 2;
$p{unescape_uri($k)} = unescape_uri($v);
}
bless \%p, $class;
}
sub param { $_[0]{$_[1]} }
sub delete { delete $_[0]{$_[1]} }
sub as_string {
my $q = shift;
my @s;
while (my($k, $v) = each %$q) {
push @s, escape_uri($k) . '=' . escape_uri($v);
}
join '&', @s;
}
1;
__END__
=head1 NAME
Apache::AuthTypeKey - Apache authorization handler using TypeKey
=head1 SYNOPSIS
## In httpd.conf or .htaccess:
PerlModule Apache::AuthTypeKey
PerlSetVar TypeKeyPath /
PerlSetVar TypeKeyLoginScript /login.pl
## These documents require user to be logged in.
AuthType Apache::AuthTypeKey
AuthName TypeKey
PerlAuthenHandler Apache::AuthTypeKey->authenticate
require valid-user
PerlSetVar TypeKeyToken your_token
## This is the _return URL that the login.pl script should point to.
AuthType Apache::AuthTypeKey
AuthName TypeKey
SetHandler perl-script
PerlHandler Apache::AuthTypeKey->login
PerlSetVar TypeKeyToken your_token
=head1 DESCRIPTION
I implements Apache authentication and authorization
handling using the TypeKey authentication service (I).
TypeKey is Six Apart's free, open service providing a central login for
people to comment on weblogs, get access to protected information, etc.
To use I, you'll need a TypeKey token that identifies
your site. So you'll need to sign up for a TypeKey account at
I, then fill out the Preferences
form to include the URI of your application. Specifically, this URI should be
the URI for the I area above, because that's the URI that
TypeKey will return to after a user logs in.
I is a subclass of I, so it inherits
all of that module's cookie-handling and authorization code. It also inherits
all of that module's configuration settings and options.
=head2 Authentication
Authentication is handled for you through TypeKey, and cookie handling is
handled by I. The value of the cookie will be the string
returned from TypeKey, including the username, email address, name, and a
DSA signature on those values, preventing users from forging the cookie.
=head2 Login Screen
The actual login form is on I; the login screen
that you'll be providing should be just a simple page linking people to that
login screen, along with your TypeKey token and return URI. An example login
screen is in F, but you'll probably wish to customize the HTML,
as it's fairly plain.
The login script functionality is inherited from I, so
it's implemented as a script that you must configure in your I
or I<.htaccess>. For example:
PerlSetVar TypeKeyLoginScript /login.pl
If you'd rather use a different mechanism for your login screen, you can
subclass I and override the I method. See
the L documentation for more details.
=head2 Authorization
I--coupled with TypeKey--will handle all of the
authentication for you, telling you whether someone is a valid TypeKey user.
For authorization, you have a couple of options:
=over 4
=item * Allow any TypeKey user
If you'd like to allow any valid TypeKey user, just use
require valid-user
as in the I above.
=item * Allow only certain TypeKey users
If you'd like to allow only certain TypeKey users, you can specify their
TypeKey usernames in standard I statements. For example:
require user foo
require user bar
This will allow only the TypeKey users C and C.
=item * Override the authorization phase and handle it yourself
If you'd like to do something more complex, like look up valid TypeKey
usernames in a database listing authorized users, you can subclass
I and override the I method. Note that
I doesn't actually provide its own I
method anyway--it merely inherits Iauthorize>.
=back
=head1 LICENSE
I is free software; you may redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR & COPYRIGHT
Except where otherwise noted, I is Copyright 2004 Six
Apart Ltd, cpan@sixapart.com. All rights reserved.
=head1 SEE ALSO
L, L
=cut