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