TypeKey: $store->get_user( \%params, \%result ) made into $store->get( $username...
[catagits/Catalyst-Authentication-Credential-HTTP-Proxy.git] / lib / Catalyst / Plugin / Authentication / Credential / TypeKey.pm
index ba4511c..afdc39a 100644 (file)
 package Catalyst::Plugin::Authentication::Credential::TypeKey;
 
 use strict;
+use warnings;
+
 use Authen::TypeKey;
-use Carp ();
 use File::Spec;
+use Catalyst::Utils ();
+use NEXT;
+use UNIVERSAL::require;
+use Scalar::Util ();
 
-our $VERSION = '0.1';
+our $VERSION = '0.2';
 
-our $PARAMETERS = qw[
-    email
-    name
-    nick
-    ts
-    sig
-];
+sub setup {
+    my $c = shift;
 
-sub authenticate_typekey {
-    my ( $c, $email, $name, $nick, $ts, $sig, $options ) = @_;
+    my $config = $c->config->{authentication}{typekey} ||= {};
 
-    unless ( @_ == 6 || ( @_ == 7 && ref($options) eq 'HASH' ) ) {
-        Carp::croak('usage: $c->authenticate_typekey( $email, $name, $nick, $ts, $sig [, \%options ] )');
-    }
+    $config->{typekey_object} ||= do {
+        ( $config->{user_class} ||=
+              "Catalyst::Plugin::Authentication::User::Hash" )->require;
 
-    unless ( @_ == 7 ) {
-        $options = {};
-    }
+        $config->{key_cache} ||=
+          File::Spec->catfile( Catalyst::Utils::class2tempdir( $c, 1 ),
+            'regkeys.txt' );
 
-    my $config = $c->config->{authenticate}->{typekey};
-
-    my $token   = $options->{token}   || $config->{token}   || undef;
-    my $expires = $options->{expires} || $config->{expires} || 0;
-    my $version = $options->{version} || $config->{version} || 1.1;
-    my $cache   = $options->{cache}   || $config->{cache}   || File::Spec->catfile( File::Spec->tmpdir, 'regkeys.txt' );
-    my $keys    = $options->{keys}    || $config->{keys}    || 'http://www.typekey.com/extras/regkeys.txt';
-
-    my $typekey = Authen::TypeKey->new;
-    $typekey->expires($expires);
-    $typekey->key_cache($cache);
-    $typekey->key_url($keys);
-    $typekey->token($token);
-    $typekey->version($version);
-
-    my $parameters = {
-        email => $email,
-        name  => $name,
-        nick  => $nick,
-        ts    => $ts,
-        sig   => $sig
+        my $typekey = Authen::TypeKey->new;
+
+        for ( grep { exists $config->{$_} }
+            qw/expires key_cache key_url token version skip_expiry_check/ )
+        {
+            $typekey->$_( $config->{$_} );
+        }
+
+        $typekey;
     };
 
-    unless ( $typekey->verify($parameters) ) {
-        my $error = $typekey->errstr;
-        $c->log->debug(qq/Failed to authenticate user '$name'. Reason: '$error'/);
-        return 0;
+    $c->NEXT::setup(@_);
+}
+
+sub authenticate_typekey {
+    my ( $c, @p ) = @_;
+
+    my ( $user, $p );
+    if ( @p == 1 ) {
+        if ( Scalar::Util::blessed( $p[0] ) ) {
+            $user = $p[0];
+            Catalyst::Exception->throw(
+                    "Attempted to authenticate user object, but "
+                  . "user doesnt't support 'typekey_credentials'" )
+              unless $user->supports(qw/typekey_credentials/);
+            $p = $user->typekey_credentials;
+        }
+        else {
+            $p = $p[0];
+        }
+    }
+    else {
+        $p = @p ? {@p} : undef;
     }
 
-    $c->log->debug( qq/Successfully authenticated user '$name'./);
-    return 1;
+    my $config = $c->config->{authentication}{typekey};
+
+    my $typekey = $p && delete( $p->{typekey_object} )
+      || $config->{typekey_object};
+
+    $p ||= $c->req;
+
+    if ( my $res = $typekey->verify($p) ) {
+        $c->log->debug("Successfully authenticated user '$res->{name}'.")
+          if $c->debug;
+
+        if ( !$user and my $store = $config->{auth_store} ) {
+            $store = $c->get_auth_store($store) unless ref $store;
+            $user = $store->get_user( $res->{name}, $p, $res );
+        }
+
+        if ( !$user ) {
+            my $user_class = $config->{user_class};
+            $user = $user_class->new($res);
+        }
+
+        $c->set_authenticated($user);
+
+        return 1;
+    }
+    else {
+        $c->log->debug(
+            sprintf "Failed to authenticate user '%s'. Reason: '%s'",
+            $p->{name} || $p->param("name"),
+            $typekey->errstr
+          )
+          if $c->debug;
+
+        return;
+    }
 }
 
 1;
@@ -66,30 +104,120 @@ __END__
 =head1 NAME
 
 Catalyst::Plugin::Authentication::Credential::TypeKey - TypeKey Authentication
+for Catalyst.
 
 =head1 SYNOPSIS
 
-    use Catalyst qw[Authentication::Credential::TypeKey];
+    use Catalyst qw/Authentication::Credential::TypeKey/;
 
-    MyApp->config->{authenticate}->{typekey} = {
-        token => 'xxxxxxxxxxxxxxxxxxxx'
+    MyApp->config->{authentication}{typekey} = {
+        token => 'xxxxxxxxxxxxxxxxxxxx',
     };
 
-    if ( $c->authenticate_typekey( $email, $name, $nick, $ts, $sig ) ) {
-        # successful autentication
-    }
+    sub foo : Local {
+               my ( $self, $c ) = @_;
+
+               if ( $c->authenticate_typekey ) {
+
+               # you can also specify the params manually: $c->authenticate_typekey(
+               #       name => $name,
+               #       email => $email,
+               #       ...
+               #)
+
+                       # successful autentication
+
+                       $c->user; # this is set
+               }
+       }
+
+
+       sub auto : Private {
+               my ( $self, $c ) = @_;
+
+               $c->authenticate_typekey; # uses $c->req
+
+               return 1;
+       }
 
 =head1 DESCRIPTION
 
-TypeKey Authentication.
+This module integrates L<Authen::TypeKey> with
+L<Catalyst::Plugin::Authentication>.
+
+=head1 METHODS
+
+=head3 authenticate_typekey %parameters
+
+=head3 authenticate_typekey
+
+=head3 EXTENDED METHODS
+
+=head3 setup
+
+Fills the config with defaults.
+
+=head1 CONFIGURATION
+
+C<<$c->config->{autentication}{typekey}>> is a hash with these fields (all can
+be left out):
+
+=over 4
+
+=item typekey_object
+
+If this field does not exist an L<Authen::TypeKey> object will be created based
+on the other param and put here.
+
+=item expires
+
+=item key_url
+
+=item token
+
+=item version
+
+See L<Authen::TypeKey> for all of these. If they aren't specified
+L<Authen::TypeKey>'s defaults will be used.
+
+=item key_cache
+
+Also see L<Authen::TypeKey>.
+
+Defaults to C<regkeys.txt> under L<Catalyst::Utils/class2tempdir>.
+
+=item auth_store
+
+A store (or store name) to retrieve the user from.
+
+When a user is successfully authenticated it will call this:
+
+       $store->get_user( $name, $parameters, $result_of_verify );
+
+Where C<$parameters> is a the hash reference passed to
+L<Authen::TypeKey/verify>, and C<$result_of_verify> is the value returned by
+L<Authen::TypeKey/verify>.
+
+If this is unset, L<Catalyst::Plugin::Authentication/default_auth_store> will
+be used instead.
+
+=item user_class
+
+If C<auth_store> or the default store returns nothing from get_user, this class
+will be used to instantiate an object by calling C<new> on the class with the
+return value from L<Authen::TypeKey/verify>.
+
+=back
 
 =head1 SEE ALSO
 
-L<Authen::TypeKey>, L<Catalyst>.
+L<Authen::TypeKey>, L<Catalyst>, L<Catalyst::Plugin::Authentication>.
 
 =head1 AUTHOR
 
-Christian Hansen, C<ch@ngmedia.com>
+Christian Hansen
+
+Yuval Kogman, C<nothingmuch@woobling.org>
 
 =head1 LICENSE