updates to auth draft
Yuval Kogman [Fri, 4 Nov 2005 01:35:32 +0000 (01:35 +0000)]
lib/Catalyst/Plugin/Authentication.pm
lib/Catalyst/Plugin/Authentication/Credential/Password.pm [new file with mode: 0644]
lib/Catalyst/Plugin/Authentication/Store.pm [deleted file]
lib/Catalyst/Plugin/Authentication/Store/Minimal.pm

index 2a67859..8f78848 100644 (file)
@@ -9,6 +9,11 @@ BEGIN { __PACKAGE__->mk_accessors(qw/user/) }
 use strict;
 use warnings;
 
+sub default_auth_store {
+       my $c = shift;
+       $c->config->{authentication}{store};
+}
+
 sub set_authenticated {
     my ( $c, $user ) = @_;
 
@@ -17,7 +22,8 @@ sub set_authenticated {
     if (    $c->isa("Catalyst::Plugin::Session")
         and $c->config->{authentication}{use_session} )
     {
-        $c->session->{__user} = $user->for_session if $user->supperts("session");
+        $c->session->{__user} = $user->for_session
+          if $user->supperts("session");
         $c->session->{__user_class} = ref $user;
     }
 }
@@ -29,6 +35,19 @@ sub logout {
     delete @{ $c->session }{qw/__user __user_class/};
 }
 
+sub get_user {
+    my ( $c, $uid ) = @_;
+
+    if ( my $store = $c->default_auth_store ) {
+        return $store->get_user($uid);
+    }
+    else {
+        Catalyst::Exception->throw(
+                "The user id $uid was passed to an authentication "
+              . "plugin, but no default store was specified" );
+    }
+}
+
 sub prepare {
     my $c = shift->NEXT::prepare(@_);
 
@@ -92,6 +111,14 @@ Delete the currently logged in user from C<user> and the session.
 
 Returns the currently logged user or undef if there is none.
 
+=item get_user $uid
+
+Delegate C<get_user> to the default store.
+
+=item default_auth_store
+
+Returns C<< $c->config->{authentication}{store} >>.
+
 =back
 
 =head1 INTERNAL METHODS
diff --git a/lib/Catalyst/Plugin/Authentication/Credential/Password.pm b/lib/Catalyst/Plugin/Authentication/Credential/Password.pm
new file mode 100644 (file)
index 0000000..f3c0934
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/perl
+
+package Catalyst::Plugin::Authentication::Credential::Password;
+
+use strict;
+use warnings;
+
+use Scalar::Util        ();
+use Catalyst::Exception ();
+use Digest              ();
+
+sub login {
+    my ( $self, $c, $user, $password ) = @_;
+    $user = $c->get_user($user)
+      unless Scalar::Util::blessed($user)
+      and $user->isa("Catalyst:::Plugin::Authentication::User");
+
+    if ( $c->_check_password( $user, $password ) ) {
+        $c->set_authenticated($user);
+        return 1;
+    }
+    else {
+        return undef;
+    }
+}
+
+sub _check_password {
+    my ( $c, $user, $password ) = @_;
+
+    if ( $user->supports(qw/password clear/) ) {
+        return $user->password eq $password;
+    }
+    elsif ( $user->supports(qw/password crypted/) ) {
+        my $crypted = $user->crypted_password;
+        return $crypted eq crypt( $password, $crypted );
+    }
+    elsif ( $user->supports(qw/password hashed/) ) {
+        my $d = Digest->new( $user->hash_algorithm );
+        $d->add( $user->password_pre_salt || '' );
+        $d->add($password);
+        $d->add( $user->password_post_salt || '' );
+        return $c->digest eq $user->hashed_password;
+    }
+    else {
+        Catalyst::Exception->throw(
+                "The user object $user does not support any "
+              . "known password authentication mechanism." );
+    }
+}
+
+__PACKAGE__;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+Catalyst:::Plugin::Authentication::Credential::Password - Authenticate a user
+with a password.
+
+=head1 SYNOPSIS
+
+    use Catalyst qw/
+      Authentication
+      Authentication::Store::Foo
+      Authentication::Credential::Password
+      /;
+
+    sub login : Local {
+        my ( $self, $c ) = @_;
+
+        $c->login( $c->req->param('login'), $c->req->param('password') );
+    }
+
+=head1 DESCRIPTION
+
+This authentication credential checker takes a user and a password, and tries
+various methods of comparing a password based on what the user supports:
+
+=over 4
+
+=item clear text password
+
+If the user has clear a clear text password it will be compared directly.
+
+=item crypted password
+
+If UNIX crypt hashed passwords are supported, they will be compared using
+perl's builtin C<crypt> function.
+
+=item hashed password
+
+If the user object supports hashed passwords, they will be used in conjunction
+with L<Digest>.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item login $user, $password
+
+Try to log a user in.
+
+$user can be an ID or object. If it isa
+L<Catalyst:::Plugin::Authentication::User> it will be used as is. Otherwise
+C<< $c->get_user >> is used to retrieve it.
+
+$password is a string.
+
+=back
+
+=cut
+
+
diff --git a/lib/Catalyst/Plugin/Authentication/Store.pm b/lib/Catalyst/Plugin/Authentication/Store.pm
deleted file mode 100644 (file)
index f47b24a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/perl
-
-package Catalyst::Plugin::Authentication::Store;
-
-use strict;
-use warnings;
-
-sub get_user { die "virtual" }
-
-sub user_supports { die "virtual" }
-
-__PACKAGE__;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-Catalyst::Plugin::Authentication::Store - 
-
-=head1 SYNOPSIS
-
-       use Catalyst::Plugin::Authentication::Store;
-
-=head1 DESCRIPTION
-
-=cut
-
-
index a5477a1..af17d4b 100644 (file)
@@ -1,7 +1,6 @@
 #!/usr/bin/perl
 
 package Catalyst::Plugin::Authentication::Store::Minimal;
-use base qw/Catalyst::Plugin::Authentication::Store/;
 
 use strict;
 use warnings;
@@ -61,8 +60,6 @@ more "serious" store for production.
 The hash in the config, as well as the user objects/hashes are freely mutable
 at runtime.
 
-This plugin inherits L<Catalyst::Plugin::Authentication::Store>.
-
 =head1 METHODS
 
 =over 4
@@ -70,7 +67,7 @@ This plugin inherits L<Catalyst::Plugin::Authentication::Store>.
 =item setup
 
 This method will popultate C<< $c->config->{authentication}{store} >> so that
-L<Catalyst::Plugin::Authentication::Store> can use it.
+L<Catalyst::Plugin::Authentication/default_auth_store> can use it.
 
 =back