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