File Coverage

blib/lib/Catalyst/Plugin/Authentication.pm
Criterion Covered Total %
statement 138 195 70.7
branch 41 82 50.0
condition 13 35 37.1
subroutine 23 30 76.6
pod 21 21 100.0
total 236 363 65.0


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