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