$user->store() should NOT be set by C::P::Auth - if it's needed - it
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication.pm
1 #!/usr/bin/perl
2
3 package Catalyst::Plugin::Authentication;
4
5 use base qw/Class::Accessor::Fast Class::Data::Inheritable/;
6
7 BEGIN {
8     __PACKAGE__->mk_accessors(qw/_user/);
9 }
10
11 use strict;
12 use warnings;
13
14 use Tie::RefHash;
15 use Class::Inspector;
16
17 # this optimization breaks under Template::Toolkit
18 # use user_exists instead
19 #BEGIN {
20 #       require constant;
21 #       constant->import(have_want => eval { require Want });
22 #}
23
24 our $VERSION = "0.10001";
25
26 sub set_authenticated {
27     my ( $c, $user, $realmname ) = @_;
28
29     $c->user($user);
30     $c->request->{user} = $user;    # compatibility kludge
31
32     if (!$realmname) {
33         $realmname = 'default';
34     }
35     
36     if (    $c->isa("Catalyst::Plugin::Session")
37         and $c->config->{authentication}{use_session}
38         and $user->supports("session") )
39     {
40         $c->save_user_in_session($user, $realmname);
41     }
42     $user->auth_realm($realmname);
43     
44     $c->NEXT::set_authenticated($user, $realmname);
45 }
46
47 sub user {
48     my $c = shift;
49
50     if (@_) {
51         return $c->_user(@_);
52     }
53
54     if ( defined($c->_user) ) {
55         return $c->_user;
56     } else {
57         return $c->auth_restore_user;
58     }
59 }
60
61 # change this to allow specification of a realm - to verify the user is part of that realm
62 # in addition to verifying that they exist. 
63 sub user_exists {
64         my $c = shift;
65         return defined($c->_user) || defined($c->_user_in_session);
66 }
67
68 # works like user_exists - except only returns true if user 
69 # exists AND is in the realm requested.
70 sub user_in_realm {
71     my ($c, $realmname) = @_;
72
73     if (defined($c->_user)) {
74         return ($c->_user->auth_realm eq $realmname);
75     } elsif (defined($c->_user_in_session)) {
76         return ($c->session->{__user_realm} eq $realmname);  
77     } else {
78         return undef;
79     }
80 }
81
82 sub save_user_in_session {
83     my ( $c, $user, $realmname ) = @_;
84
85     $c->session->{__user_realm} = $realmname;
86     
87     # we want to ask the store for a user prepared for the session.
88     # but older modules split this functionality between the user and the
89     # store.  We try the store first.  If not, we use the old method.
90     my $realm = $c->get_auth_realm($realmname);
91     if ($realm->{'store'}->can('for_session')) {
92         $c->session->{__user} = $realm->{'store'}->for_session($c, $user);
93     } else {
94         $c->session->{__user} = $user->for_session;
95     }
96 }
97
98 sub logout {
99     my $c = shift;
100
101     $c->user(undef);
102
103     if (
104         $c->isa("Catalyst::Plugin::Session")
105         and $c->config->{authentication}{use_session}
106         and $c->session_is_valid
107     ) {
108         delete @{ $c->session }{qw/__user __user_realm/};
109     }
110     
111     $c->NEXT::logout(@_);
112 }
113
114 sub find_user {
115     my ( $c, $userinfo, $realmname ) = @_;
116     
117     $realmname ||= 'default';
118     my $realm = $c->get_auth_realm($realmname);
119     if ( $realm->{'store'} ) {
120         return $realm->{'store'}->find_user($userinfo, $c);
121     } else {
122         $c->log->debug('find_user: unable to locate a store matching the requested realm');
123     }
124 }
125
126
127 sub _user_in_session {
128     my $c = shift;
129
130     return unless
131         $c->isa("Catalyst::Plugin::Session")
132         and $c->config->{authentication}{use_session}
133         and $c->session_is_valid;
134
135     return $c->session->{__user};
136 }
137
138 sub auth_restore_user {
139     my ( $c, $frozen_user, $realmname ) = @_;
140
141     $frozen_user ||= $c->_user_in_session;
142     return unless defined($frozen_user);
143
144     $realmname  ||= $c->session->{__user_realm};
145     return unless $realmname; # FIXME die unless? This is an internal inconsistency
146
147     my $realm = $c->get_auth_realm($realmname);
148     $c->_user( my $user = $realm->{'store'}->from_session( $c, $frozen_user ) );
149     
150     # this sets the realm the user originated in.
151     $user->auth_realm($realmname);
152         
153     return $user;
154
155 }
156
157 # we can't actually do our setup in setup because the model has not yet been loaded.  
158 # So we have to trigger off of setup_finished.  :-(
159 sub setup {
160     my $app = shift;
161
162     $app->_authentication_initialize();
163     $app->NEXT::setup(@_);
164 }
165
166 ## the actual initialization routine. whee.
167 sub _authentication_initialize {
168     my $app = shift;
169
170     ## let's avoid recreating / configuring everything if we have already done it, eh?
171     if ($app->can('_auth_realms')) { return };
172
173     ## make classdata where it is used.  
174     $app->mk_classdata( '_auth_realms' => {});
175     
176     my $cfg = $app->config->{'authentication'} ||= {};
177
178     $cfg->{use_session} = 1;
179     
180     if (exists($cfg->{'realms'})) {
181         foreach my $realm (keys %{$cfg->{'realms'}}) {
182             $app->setup_auth_realm($realm, $cfg->{'realms'}{$realm});
183         }
184         #  if we have a 'default-realm' in the config hash and we don't already 
185         # have a realm called 'default', we point default at the realm specified
186         if (exists($cfg->{'default_realm'}) && !$app->get_auth_realm('default')) {
187             $app->_set_default_auth_realm($cfg->{'default_realm'});
188         }
189     } else {
190         
191         ## BACKWARDS COMPATIBILITY - if realms is not defined - then we are probably dealing
192         ## with an old-school config.  The only caveat here is that we must add a classname
193         
194         ## also - we have to treat {store} as {stores}{default} - because 
195         ## while it is not a clear as a valid config in the docs, it 
196         ## is functional with the old api. Whee!
197         if (exists($cfg->{'store'}) && !exists($cfg->{'stores'}{'default'})) {
198             $cfg->{'stores'}{'default'} = $cfg->{'store'};
199         }
200
201         foreach my $storename (keys %{$cfg->{'stores'}}) {
202             my $realmcfg = {
203                 store => { class => $cfg->{'stores'}{$storename} },
204             };
205             $app->setup_auth_realm($storename, $realmcfg);
206         }
207     }
208     
209 }
210
211 # set up realmname.
212 sub setup_auth_realm {
213     my ($app, $realmname, $config) = @_;
214     
215     $app->log->debug("Setting up auth realm $realmname") if $app->debug;
216     if (!exists($config->{'store'}{'class'})) {
217         Carp::croak "Couldn't setup the authentication realm named '$realmname', no class defined";
218     } 
219         
220     # use the 
221     my $storeclass = $config->{'store'}{'class'};
222     
223     ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
224     ## taken to mean C::P::A::Store::(specifiedclass)
225     if ($storeclass !~ /^\+(.*)$/ ) {
226         $storeclass = "Catalyst::Plugin::Authentication::Store::${storeclass}";
227     } else {
228         $storeclass = $1;
229     }
230     
231
232     # a little niceness - since most systems seem to use the password credential class, 
233     # if no credential class is specified we use password.
234     $config->{credential}{class} ||= '+Catalyst::Plugin::Authentication::Credential::Password';
235
236     my $credentialclass = $config->{'credential'}{'class'};
237     
238     ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
239     ## taken to mean C::P::A::Credential::(specifiedclass)
240     if ($credentialclass !~ /^\+(.*)$/ ) {
241         $credentialclass = "Catalyst::Plugin::Authentication::Credential::${credentialclass}";
242     } else {
243         $credentialclass = $1;
244     }
245     
246     # if we made it here - we have what we need to load the classes;
247     Catalyst::Utils::ensure_class_loaded( $credentialclass );
248     Catalyst::Utils::ensure_class_loaded( $storeclass );
249     
250     # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
251     # of get_user and add it to the class.  this is because the auth routines use find_user, 
252     # and rely on it being present. (this avoids per-call checks)
253     if (!$storeclass->can('find_user')) {
254         no strict 'refs';
255         *{"${storeclass}::find_user"} = sub {
256                                                 my ($self, $info) = @_;
257                                                 my @rest = @{$info->{rest}} if exists($info->{rest});
258                                                 $self->get_user($info->{id}, @rest);
259                                             };
260     }
261     
262     ## a little cruft to stay compatible with some poorly written stores / credentials
263     ## we'll remove this soon.
264     if ($storeclass->can('new')) {
265         $app->auth_realms->{$realmname}{'store'} = $storeclass->new($config->{'store'}, $app);
266     } else {
267         $app->log->error("THIS IS DEPRECATED: $storeclass has no new() method - Attempting to use uninstantiated");
268         $app->auth_realms->{$realmname}{'store'} = $storeclass;
269     }
270     if ($credentialclass->can('new')) {
271         $app->auth_realms->{$realmname}{'credential'} = $credentialclass->new($config->{'credential'}, $app);
272     } else {
273         $app->log->error("THIS IS DEPRECATED: $credentialclass has no new() method - Attempting to use uninstantiated");
274         $app->auth_realms->{$realmname}{'credential'} = $credentialclass;
275     }
276 }
277
278 sub auth_realms {
279     my $self = shift;
280     return($self->_auth_realms);
281 }
282
283 sub get_auth_realm {
284     my ($app, $realmname) = @_;
285     return $app->auth_realms->{$realmname};
286 }
287
288
289 # Very internal method.  Vital Valuable Urgent, Do not touch on pain of death.
290 # Using this method just assigns the default realm to be the value associated
291 # with the realmname provided.  It WILL overwrite any real realm called 'default'
292 # so can be very confusing if used improperly.  It's used properly already. 
293 # Translation: don't use it.
294 sub _set_default_auth_realm {
295     my ($app, $realmname) = @_;
296     
297     if (exists($app->auth_realms->{$realmname})) {
298         $app->auth_realms->{'default'} = $app->auth_realms->{$realmname};
299     }
300     return $app->get_auth_realm('default');
301 }
302
303 sub authenticate {
304     my ($app, $userinfo, $realmname) = @_;
305     
306     if (!$realmname) {
307         $realmname = 'default';
308     }
309         
310     my $realm = $app->get_auth_realm($realmname);
311     
312     ## note to self - make authenticate throw an exception if realm is invalid.
313     
314     if ($realm && exists($realm->{'credential'})) {
315         my $user = $realm->{'credential'}->authenticate($app, $realm->{store}, $userinfo);
316         if (ref($user)) {
317             $app->set_authenticated($user, $realmname);
318             return $user;
319         }
320     } else {
321         $app->log->debug("The realm requested, '$realmname' does not exist," .
322                          " or there is no credential associated with it.")
323     }
324     return undef;
325 }
326
327 ## BACKWARDS COMPATIBILITY  -- Warning:  Here be monsters!
328 #
329 # What follows are backwards compatibility routines - for use with Stores and Credentials
330 # that have not been updated to work with C::P::Authentication v0.10.  
331 # These are here so as to not break people's existing installations, but will go away
332 # in a future version.
333 #
334 # The old style of configuration only supports a single store, as each store module
335 # sets itself as the default store upon being loaded.  This is the only supported 
336 # 'compatibility' mode.  
337 #
338
339 sub get_user {
340     my ( $c, $uid, @rest ) = @_;
341
342     return $c->find_user( {'id' => $uid, 'rest'=>\@rest }, 'default' );
343 }
344
345
346 ## this should only be called when using old-style authentication plugins.  IF this gets
347 ## called in a new-style config - it will OVERWRITE the store of your default realm.  Don't do it.
348 ## also - this is a partial setup - because no credential is instantiated... in other words it ONLY
349 ## works with old-style auth plugins and C::P::Authentication in compatibility mode.  Trying to combine
350 ## this with a realm-type config will probably crash your app.
351 sub default_auth_store {
352     my $self = shift;
353
354     if ( my $new = shift ) {
355         $self->auth_realms->{'default'}{'store'} = $new;
356         
357         my $storeclass;
358         if (ref($new)) {
359             $storeclass = ref($new);
360         } else {
361             $storeclass = $new;
362         }
363         
364         # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms 
365         # of get_user and add it to the class.  this is because the auth routines use find_user, 
366         # and rely on it being present. (this avoids per-call checks)
367         if (!$storeclass->can('find_user')) {
368             no strict 'refs';
369             *{"${storeclass}::find_user"} = sub {
370                                                     my ($self, $info) = @_;
371                                                     my @rest = @{$info->{rest}} if exists($info->{rest});
372                                                     $self->get_user($info->{id}, @rest);
373                                                 };
374         }
375     }
376
377     return $self->get_auth_realm('default')->{'store'};
378 }
379
380 ## BACKWARDS COMPATIBILITY
381 ## this only ever returns a hash containing 'default' - as that is the only
382 ## supported mode of calling this.
383 sub auth_store_names {
384     my $self = shift;
385
386     my %hash = (  $self->get_auth_realm('default')->{'store'} => 'default' );
387 }
388
389 sub get_auth_store {
390     my ( $self, $name ) = @_;
391     
392     if ($name ne 'default') {
393         Carp::croak "get_auth_store called on non-default realm '$name'. Only default supported in compatibility mode";        
394     } else {
395         $self->default_auth_store();
396     }
397 }
398
399 sub get_auth_store_name {
400     my ( $self, $store ) = @_;
401     return 'default';
402 }
403
404 # sub auth_stores is only used internally - here for completeness
405 sub auth_stores {
406     my $self = shift;
407
408     my %hash = ( 'default' => $self->get_auth_realm('default')->{'store'});
409 }
410
411 __PACKAGE__;
412
413 __END__
414
415 =pod
416
417 =head1 NAME
418
419 Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
420 authentication framework.
421
422 =head1 SYNOPSIS
423
424     use Catalyst qw/
425         Authentication
426     /;
427
428     # later on ...
429     $c->authenticate({ username => 'myusername', 
430                        password => 'mypassword' });
431     my $age = $c->user->get('age');
432     $c->logout;
433
434 =head1 DESCRIPTION
435
436 The authentication plugin provides generic user support for Catalyst apps. It
437 is the basis for both authentication (checking the user is who they claim to
438 be), and authorization (allowing the user to do what the system authorises
439 them to do).
440
441 Using authentication is split into two parts. A Store is used to actually
442 store the user information, and can store any amount of data related to the
443 user. Credentials are used to verify users, using information from the store,
444 given data from the frontend. A Credential and a Store are paired to form a
445 'Realm'. A Catalyst application using the authentication framework must have
446 at least one realm, and may have several.
447
448 To implement authentication in a Catalyst application you need to add this 
449 module, and specify at least one realm in the configuration. 
450
451 Authentication data can also be stored in a session, if the application 
452 is using the L<Catalyst::Plugin::Session> module.
453
454 B<NOTE> in version 0.10 of this module, the interface to this module changed.
455 Please see L</COMPATIBILITY ROUTINES> for more information.
456
457 =head1 INTRODUCTION
458
459 =head2 The Authentication/Authorization Process
460
461 Web applications typically need to identify a user - to tell the user apart
462 from other users. This is usually done in order to display private information
463 that is only that user's business, or to limit access to the application so
464 that only certain entities can access certain parts.
465
466 This process is split up into several steps. First you ask the user to identify
467 themselves. At this point you can't be sure that the user is really who they
468 claim to be.
469
470 Then the user tells you who they are, and backs this claim with some piece of
471 information that only the real user could give you. For example, a password is
472 a secret that is known to both the user and you. When the user tells you this
473 password you can assume they're in on the secret and can be trusted (ignore
474 identity theft for now). Checking the password, or any other proof is called
475 B<credential verification>.
476
477 By this time you know exactly who the user is - the user's identity is
478 B<authenticated>. This is where this module's job stops, and your application
479 or other plugins step in.  
480
481 The next logical step is B<authorization>, the process of deciding what a user
482 is (or isn't) allowed to do. For example, say your users are split into two
483 main groups - regular users and administrators. You want to verify that the
484 currently logged in user is indeed an administrator before performing the
485 actions in an administrative part of your application. These decisions may be
486 made within your application code using just the information available after
487 authentication, or it may be facilitated by a number of plugins.  
488
489 =head2 The Components In This Framework
490
491 =head3 Realms
492
493 Configuration of the Catalyst::Plugin::Authentication framework is done in
494 terms of realms. In simplest terms, a realm is a pairing of a Credential
495 verifier and a User storage (Store) backend.
496
497 An application can have any number of Realms, each of which operates
498 independant of the others. Each realm has a name, which is used to identify it
499 as the target of an authentication request. This name can be anything, such as
500 'users' or 'members'. One realm must be defined as the default_realm, which is
501 used when no realm name is specified. More information about configuring
502 realms is available in the configuration section.
503
504 =head3 Credential Verifiers
505
506 When user input is transferred to the L<Catalyst> application (typically via
507 form inputs) the application may pass this information into the authentication
508 system through the $c->authenticate() method.  From there, it is passed to the
509 appropriate Credential verifier.
510
511 These plugins check the data, and ensure that it really proves the user is who
512 they claim to be.
513
514 =head3 Storage Backends
515
516 The authentication data also identifies a user, and the Storage backend modules
517 use this data to locate and return a standardized object-oriented
518 representation of a user.
519
520 When a user is retrieved from a store it is not necessarily authenticated.
521 Credential verifiers accept a set of authentication data and use this
522 information to retrieve the user from the store they are paired with.
523
524 =head3 The Core Plugin
525
526 This plugin on its own is the glue, providing realm configuration, session
527 integration, and other goodness for the other plugins.
528
529 =head3 Other Plugins
530
531 More layers of plugins can be stacked on top of the authentication code. For
532 example, L<Catalyst::Plugin::Session::PerUser> provides an abstraction of
533 browser sessions that is more persistent per users.
534 L<Catalyst::Plugin::Authorization::Roles> provides an accepted way to separate
535 and group users into categories, and then check which categories the current
536 user belongs to.
537
538 =head1 EXAMPLE
539
540 Let's say we were storing users in a simple perl hash. Users are
541 verified by supplying a password which is matched within the hash.
542
543 This means that our application will begin like this:
544
545     package MyApp;
546
547     use Catalyst qw/
548         Authentication
549     /;
550
551     __PACKAGE__->config->{authentication} = 
552                 {  
553                     default_realm => 'members',
554                     realms => {
555                         members => {
556                             credential => {
557                                 class => 'Password',
558                                 password_field => 'password',
559                                 password_type => 'clear'
560                             },
561                             store => {
562                                 class => 'Minimal',
563                                 users = {
564                                     bob => {
565                                         password => "s00p3r",                                       
566                                         editor => 'yes',
567                                         roles => [qw/edit delete/],
568                                     },
569                                     william => {
570                                         password => "s3cr3t",
571                                         roles => [qw/comment/],
572                                     }
573                                 }                       
574                             }
575                         }
576                         }
577                 };
578     
579
580 This tells the authentication plugin what realms are available, which
581 credential and store modules are used, and the configuration of each. With
582 this code loaded, we can now attempt to authenticate users.
583
584 To show an example of this, let's create an authentication controller:
585
586     package MyApp::Controller::Auth;
587
588     sub login : Local {
589         my ( $self, $c ) = @_;
590
591         if (    my $user = $c->req->param("user")
592             and my $password = $c->req->param("password") )
593         {
594             if ( $c->authenticate( { username => $user, 
595                                      password => $password } ) ) {
596                 $c->res->body( "hello " . $c->user->get("name") );
597             } else {
598                 # login incorrect
599             }
600         }
601         else {
602             # invalid form input
603         }
604     }
605
606 This code should be very readable. If all the necessary fields are supplied,
607 call the "authenticate" method from the controller. If it succeeds the 
608 user is logged in.
609
610 The credential verifier will attempt to retrieve the user whose details match
611 the authentication information provided to $c->authenticate(). Once it fetches
612 the user the password is checked and if it matches the user will be
613 B<authenticated> and C<< $c->user >> will contain the user object retrieved
614 from the store.
615
616 In the above case, the default realm is checked, but we could just as easily
617 check an alternate realm. If this were an admin login, for example, we could
618 authenticate on the admin realm by simply changing the $c->authenticate()
619 call:
620
621     if ( $c->authenticate( { username => $user, 
622                              password => $password }, 'admin' )l ) {
623         $c->res->body( "hello " . $c->user->get("name") );
624     } ...
625
626
627 Now suppose we want to restrict the ability to edit to a user with an 
628 'editor' value of yes.
629
630 The restricted action might look like this:
631
632     sub edit : Local {
633         my ( $self, $c ) = @_;
634
635         $c->detach("unauthorized")
636           unless $c->user_exists
637           and $c->user->get('editor') eq 'yes';
638
639         # do something restricted here
640     }
641
642 (Note that if you have multiple realms, you can use $c->user_in_realm('realmname')
643 in place of $c->user_exists(); This will essentially perform the same 
644 verification as user_exists, with the added requirement that if there is a 
645 user, it must have come from the realm specified.)
646
647 The above example is somewhat similar to role based access control.  
648 L<Catalyst::Plugin::Authentication::Store::Minimal> treats the roles field as
649 an array of role names. Let's leverage this. Add the role authorization
650 plugin:
651
652     use Catalyst qw/
653         ...
654         Authorization::Roles
655     /;
656
657     sub edit : Local {
658         my ( $self, $c ) = @_;
659
660         $c->detach("unauthorized") unless $c->check_roles("edit");
661
662         # do something restricted here
663     }
664
665 This is somewhat simpler and will work if you change your store, too, since the
666 role interface is consistent.
667
668 Let's say your app grew, and you now have 10000 users. It's no longer
669 efficient to maintain a hash of users, so you move this data to a database.
670 You can accomplish this simply by installing the DBIx::Class Store and
671 changing your config:
672
673     __PACKAGE__->config->{authentication} = 
674                     {  
675                         default_realm => 'members',
676                         realms => {
677                             members => {
678                                 credential => {
679                                     class => 'Password',
680                                     password_field => 'password',
681                                     password_type => 'clear'
682                                 },
683                                 store => {
684                                     class => 'DBIx::Class',
685                                     user_class => 'MyApp::Users',
686                                     role_column => 'roles'                      
687                                 }
688                                 }
689                         }
690                     };
691
692 The authentication system works behind the scenes to load your data from the
693 new source. The rest of your application is completely unchanged.
694
695
696 =head1 CONFIGURATION
697
698 =over 4
699
700     # example
701     __PACKAGE__->config->{authentication} = 
702                 {  
703                     default_realm => 'members',
704                     realms => {
705                         members => {
706                             credential => {
707                                 class => 'Password',
708                                 password_field => 'password',
709                                 password_type => 'clear'
710                             },
711                             store => {
712                                 class => 'DBIx::Class',
713                                     user_class => 'MyApp::Users',
714                                     role_column => 'roles'                      
715                                 }
716                         },
717                         admins => {
718                             credential => {
719                                 class => 'Password',
720                                 password_field => 'password',
721                                 password_type => 'clear'
722                             },
723                             store => {
724                                 class => '+MyApp::Authentication::Store::NetAuth',
725                                 authserver => '192.168.10.17'
726                             }
727                         }
728                         
729                         }
730                 };
731
732 =item use_session
733
734 Whether or not to store the user's logged in state in the session, if the
735 application is also using L<Catalyst::Plugin::Session>. This 
736 value is set to true per default.
737
738 =item default_realm
739
740 This defines which realm should be used as when no realm is provided to methods
741 that require a realm such as authenticate or find_user.
742
743 =item realms
744
745 This contains the series of realm configurations you want to use for your app.
746 The only rule here is that there must be at least one.  A realm consists of a
747 name, which is used to reference the realm, a credential and a store.  
748
749 Each realm config contains two hashes, one called 'credential' and one called 
750 'store', each of which provide configuration details to the respective modules.
751 The contents of these hashes is specific to the module being used, with the 
752 exception of the 'class' element, which tells the core Authentication module the
753 classname to instantiate.  
754
755 The 'class' element follows the standard Catalyst mechanism of class
756 specification. If a class is prefixed with a +, it is assumed to be a complete
757 class name. Otherwise it is considered to be a portion of the class name. For
758 credentials, the classname 'B<Password>', for example, is expanded to
759 Catalyst::Plugin::Authentication::Credential::B<Password>. For stores, the
760 classname 'B<storename>' is expanded to:
761 Catalyst::Plugin::Authentication::Store::B<storename>.
762
763
764 =back
765
766
767 =head1 METHODS
768
769 =over 4 
770
771 =item authenticate( $userinfo, $realm )
772
773 Attempts to authenticate the user using the information in the $userinfo hash
774 reference using the realm $realm. $realm may be omitted, in which case the
775 default realm is checked.
776
777 =item user
778
779 Returns the currently logged in user or undef if there is none.
780
781 =item user_exists
782
783 Returns true if a user is logged in right now. The difference between
784 user_exists and user is that user_exists will return true if a user is logged
785 in, even if it has not been yet retrieved from the storage backend. If you only
786 need to know if the user is logged in, depending on the storage mechanism this
787 can be much more efficient.
788
789 =item user_in_realm ( $realm )
790
791 Works like user_exists, except that it only returns true if a user is both 
792 logged in right now and was retrieved from the realm provided.  
793
794 =item logout
795
796 Logs the user out, Deletes the currently logged in user from $c->user and the session.
797
798 =item find_user( $userinfo, $realm )
799
800 Fetch a particular users details, matching the provided user info, from the realm 
801 specified in $realm.
802
803 =back
804
805 =head1 INTERNAL METHODS
806
807 These methods are for Catalyst::Plugin::Authentication B<INTERNAL USE> only.
808 Please do not use them in your own code, whether application or credential /
809 store modules. If you do, you will very likely get the nasty shock of having
810 to fix / rewrite your code when things change. They are documented here only
811 for reference.
812
813 =over 4
814
815 =item set_authenticated ( $user, $realmname )
816
817 Marks a user as authenticated. This is called from within the authenticate
818 routine when a credential returns a user. $realmname defaults to 'default'
819
820 =item auth_restore_user ( $user, $realmname )
821
822 Used to restore a user from the session. In most cases this is called without
823 arguments to restore the user via the session. Can be called with arguments
824 when restoring a user from some other method.  Currently not used in this way.
825
826 =item save_user_in_session ( $user, $realmname )
827
828 Used to save the user in a session. Saves $user in session, marked as
829 originating in $realmname. Both arguments are required.
830
831 =item auth_realms
832
833 Returns a hashref containing realmname -> realm instance pairs. Realm
834 instances contain an instantiated store and credential object as the 'store'
835 and 'credential' elements, respectively
836
837 =item get_auth_realm ( $realmname )
838
839 Retrieves the realm instance for the realmname provided.
840
841 =item 
842
843 =back
844
845 =head1 SEE ALSO
846
847 This list might not be up to date.  Below are modules known to work with the updated
848 API of 0.10 and are therefore compatible with realms.  
849
850 =head2 User Storage Backends
851
852 L<Catalyst::Plugin::Authentication::Store::Minimal>,
853 L<Catalyst::Plugin::Authentication::Store::DBIx::Class>,
854
855 =head2 Credential verification
856
857 L<Catalyst::Plugin::Authentication::Credential::Password>,
858
859 =head2 Authorization
860
861 L<Catalyst::Plugin::Authorization::ACL>,
862 L<Catalyst::Plugin::Authorization::Roles>
863
864 =head2 Internals Documentation
865
866 L<Catalyst::Plugin::Authentication::Internals>
867
868 =head2 Misc
869
870 L<Catalyst::Plugin::Session>,
871 L<Catalyst::Plugin::Session::PerUser>
872
873 =head1 DON'T SEE ALSO
874
875 This module along with its sub plugins deprecate a great number of other
876 modules. These include L<Catalyst::Plugin::Authentication::Simple>,
877 L<Catalyst::Plugin::Authentication::CDBI>.
878
879 At the time of writing these plugins have not yet been replaced or updated, but
880 should be eventually: L<Catalyst::Plugin::Authentication::OpenID>,
881 L<Catalyst::Plugin::Authentication::LDAP>,
882 L<Catalyst::Plugin::Authentication::CDBI::Basic>,
883 L<Catalyst::Plugin::Authentication::Basic::Remote>.
884
885 =head1 INCOMPATABILITIES
886
887 The realms based configuration and functionality of the 0.10 update 
888 of L<Catalyst::Plugin::Authentication> required a change in the API used by
889 credentials and stores.  It has a compatibility mode which allows use of
890 modules that have not yet been updated. This, however, completely mimics the
891 older api and disables the new realm-based features. In other words you can
892 not mix the older credential and store modules with realms, or realm-based
893 configs. The changes required to update modules are relatively minor and are
894 covered in L<Catalyst::Plugin::Authentication::Internals>.  We hope that most
895 modules will move to the compatible list above very quickly.
896
897 =head1 COMPATIBILITY ROUTINES
898
899 In version 0.10 of L<Catalyst::Plugin::Authentication>, the API
900 changed. For app developers, this change is fairly minor, but for
901 Credential and Store authors, the changes are significant. 
902
903 Please see the documentation in version 0.09 of
904 Catalyst::Plugin::Authentication for a better understanding of how the old API
905 functioned.
906
907 The items below are still present in the plugin, though using them is
908 deprecated. They remain only as a transition tool, for those sites which can
909 not yet be upgraded to use the new system due to local customizations or use
910 of Credential / Store modules that have not yet been updated to work with the 
911 new API.
912
913 These routines should not be used in any application using realms
914 functionality or any of the methods described above. These are for reference
915 purposes only.
916
917 =over 4
918
919 =item login
920
921 This method is used to initiate authentication and user retrieval. Technically
922 this is part of the old Password credential module and it still resides in the
923 L<Password|Catalyst::Plugin::Authentication::Credential::Password> class. It is
924 included here for reference only.
925
926 =item default_auth_store
927
928 Return the store whose name is 'default'.
929
930 This is set to C<< $c->config->{authentication}{store} >> if that value exists,
931 or by using a Store plugin:
932
933     # load the Minimal authentication store.
934         use Catalyst qw/Authentication Authentication::Store::Minimal/;
935
936 Sets the default store to
937 L<Catalyst::Plugin::Authentication::Store::Minimal>.
938
939 =item get_auth_store $name
940
941 Return the store whose name is $name.
942
943 =item get_auth_store_name $store
944
945 Return the name of the store $store.
946
947 =item auth_stores
948
949 A hash keyed by name, with the stores registered in the app.
950
951 =item register_auth_stores %stores_by_name
952
953 Register stores into the application.
954
955 =back
956
957
958
959 =head1 AUTHORS
960
961 Yuval Kogman, C<nothingmuch@woobling.org>
962
963 Jay Kuri, C<jayk@cpan.org>
964
965 Jess Robinson
966
967 David Kamholz
968
969
970 =head1 COPYRIGHT & LICENSE
971
972         Copyright (c) 2005 the aforementioned authors. All rights
973         reserved. This program is free software; you can redistribute
974         it and/or modify it under the same terms as Perl itself.
975
976 =cut
977