File Coverage

blib/lib/Catalyst/Plugin/Authentication.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::Authentication;
2              
3 1     1   53516 use Moose;
  0            
  0            
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.10023";
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