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