mostly doc fixes and a little Minimal Bug fix involving the hash passed in.
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication.pm
CommitLineData
06675d2e 1#!/usr/bin/perl
2
3package Catalyst::Plugin::Authentication;
4
b003080b 5use base qw/Class::Accessor::Fast Class::Data::Inheritable/;
06675d2e 6
b003080b 7BEGIN {
7bb06c91 8 __PACKAGE__->mk_accessors(qw/_user/);
54c8dc06 9 __PACKAGE__->mk_classdata($_) for qw/_auth_realms/;
b003080b 10}
06675d2e 11
12use strict;
13use warnings;
14
96777f3a 15use Tie::RefHash;
12dae309 16use Class::Inspector;
96777f3a 17
bbf1cb39 18# this optimization breaks under Template::Toolkit
19# use user_exists instead
e145babc 20#BEGIN {
21# require constant;
22# constant->import(have_want => eval { require Want });
23#}
a1e5bd36 24
54c8dc06 25our $VERSION = "0.10";
c7c003d3 26
06675d2e 27sub set_authenticated {
54c8dc06 28 my ( $c, $user, $realmname ) = @_;
06675d2e 29
30 $c->user($user);
e300c5b6 31 $c->request->{user} = $user; # compatibility kludge
06675d2e 32
54c8dc06 33 if (!$realmname) {
34 $realmname = 'default';
06675d2e 35 }
54c8dc06 36
37 if ( $c->isa("Catalyst::Plugin::Session")
38 and $c->config->{authentication}{use_session}
39 and $user->supports("session") )
40 {
41 $c->save_user_in_session($realmname, $user);
42 }
43 $user->_set_auth_realm($realmname);
44
45 $c->NEXT::set_authenticated($user, $realmname);
06675d2e 46}
47
488433fd 48sub _should_save_user_in_session {
49 my ( $c, $user ) = @_;
50
51 $c->_auth_sessions_supported
52 and $c->config->{authentication}{use_session}
53 and $user->supports("session");
54}
55
56sub _should_load_user_from_session {
57 my ( $c, $user ) = @_;
58
59 $c->_auth_sessions_supported
60 and $c->config->{authentication}{use_session}
61 and $c->session_is_valid;
62}
63
64sub _auth_sessions_supported {
65 my $c = shift;
66 $c->isa("Catalyst::Plugin::Session");
67}
68
7bb06c91 69sub user {
e300c5b6 70 my $c = shift;
7bb06c91 71
e300c5b6 72 if (@_) {
73 return $c->_user(@_);
74 }
7bb06c91 75
56e23e7a 76 if ( defined(my $user = $c->_user) ) {
77 return $user;
78 } else {
47c6643f 79 return $c->auth_restore_user;
e300c5b6 80 }
7bb06c91 81}
82
54c8dc06 83# change this to allow specification of a realm - to verify the user is part of that realm
84# in addition to verifying that they exist.
ce0b058d 85sub user_exists {
86 my $c = shift;
9deccb83 87 return defined($c->_user) || defined($c->_user_in_session);
56e23e7a 88}
89
54c8dc06 90
12dae309 91sub save_user_in_session {
54c8dc06 92 my ( $c, $realmname, $user ) = @_;
12dae309 93
54c8dc06 94 $c->session->{__user_realm} = $realmname;
95
96 # we want to ask the backend for a user prepared for the session.
97 # but older modules split this functionality between the user and the
98 # backend. We try the store first. If not, we use the old method.
99 my $realm = $c->get_auth_realm($realmname);
100 if ($realm->{'store'}->can('for_session')) {
101 $c->session->{__user} = $realm->{'store'}->for_session($c, $user);
102 } else {
103 $c->session->{__user} = $user->for_session;
104 }
12dae309 105}
106
06675d2e 107sub logout {
108 my $c = shift;
109
110 $c->user(undef);
b003080b 111
54c8dc06 112 if (
113 $c->isa("Catalyst::Plugin::Session")
114 and $c->config->{authentication}{use_session}
115 and $c->session_is_valid
116 ) {
117 delete @{ $c->session }{qw/__user __user_realm/};
b003080b 118 }
351e2a82 119
120 $c->NEXT::logout(@_);
06675d2e 121}
122
54c8dc06 123sub find_user {
124 my ( $c, $userinfo, $realmname ) = @_;
125
126 $realmname ||= 'default';
127 my $realm = $c->get_auth_realm($realmname);
128 if ( $realm->{'store'} ) {
129 return $realm->{'store'}->find_user($userinfo, $c);
130 } else {
131 $c->log->debug('find_user: unable to locate a store matching the requested realm');
7d0922d8 132 }
133}
134
54c8dc06 135
47c6643f 136sub _user_in_session {
137 my $c = shift;
138
488433fd 139 return unless $c->_should_load_user_from_session;
47c6643f 140
141 return $c->session->{__user};
488433fd 142}
47c6643f 143
488433fd 144sub _store_in_session {
145 my $c = shift;
146
147 # we don't need verification, it's only called if _user_in_session returned something useful
148
149 return $c->session->{__user_store};
47c6643f 150}
151
7bb06c91 152sub auth_restore_user {
54c8dc06 153 my ( $c, $frozen_user, $realmname ) = @_;
7bb06c91 154
47c6643f 155 $frozen_user ||= $c->_user_in_session;
156 return unless defined($frozen_user);
4402d92d 157
54c8dc06 158 $realmname ||= $c->session->{__user_realm};
159 return unless $realmname; # FIXME die unless? This is an internal inconsistency
7bb06c91 160
54c8dc06 161 my $realm = $c->get_auth_realm($realmname);
162 $c->_user( my $user = $realm->{'store'}->from_session( $c, $frozen_user ) );
163
164 # this sets the realm the user originated in.
165 $user->_set_auth_realm($realmname);
e300c5b6 166 return $user;
7bb06c91 167
168}
169
54c8dc06 170# we can't actually do our setup in setup because the model has not yet been loaded.
171# So we have to trigger off of setup_finished. :-(
06675d2e 172sub setup {
173 my $c = shift;
174
54c8dc06 175 $c->_authentication_initialize();
176 $c->NEXT::setup(@_);
177}
178
179## the actual initialization routine. whee.
180sub _authentication_initialize {
181 my $c = shift;
182
183 if ($c->_auth_realms) { return };
184
185 my $cfg = $c->config->{'authentication'} || {};
06675d2e 186
187 %$cfg = (
188 use_session => 1,
189 %$cfg,
190 );
b003080b 191
54c8dc06 192 my $realmhash = {};
193 $c->_auth_realms($realmhash);
194
195 ## BACKWARDS COMPATIBILITY - if realm is not defined - then we are probably dealing
196 ## with an old-school config. The only caveat here is that we must add a classname
197 if (exists($cfg->{'realms'})) {
198
199 foreach my $realm (keys %{$cfg->{'realms'}}) {
200 $c->setup_auth_realm($realm, $cfg->{'realms'}{$realm});
201 }
202
203 # if we have a 'default-realm' in the config hash and we don't already
204 # have a realm called 'default', we point default at the realm specified
205 if (exists($cfg->{'default_realm'}) && !$c->get_auth_realm('default')) {
206 $c->set_default_auth_realm($cfg->{'default_realm'});
207 }
208 } else {
209 foreach my $storename (keys %{$cfg->{'stores'}}) {
210 my $realmcfg = {
211 store => $cfg->{'stores'}{$storename},
212 };
213 $c->setup_auth_realm($storename, $realmcfg);
214 }
215 }
216
06675d2e 217}
218
54c8dc06 219
220# set up realmname.
221sub setup_auth_realm {
222 my ($app, $realmname, $config) = @_;
223
224 $app->log->debug("Setting up $realmname");
225 if (!exists($config->{'store'}{'class'})) {
226 Carp::croak "Couldn't setup the authentication realm named '$realmname', no class defined";
227 }
228
229 # use the
230 my $storeclass = $config->{'store'}{'class'};
231
232 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
233 ## taken to mean C::P::A::Store::(specifiedclass)::Backend
234 if ($storeclass !~ /^\+(.*)$/ ) {
235 $storeclass = "Catalyst::Plugin::Authentication::Store::${storeclass}::Backend";
236 } else {
237 $storeclass = $1;
238 }
239
240
241 # a little niceness - since most systems seem to use the password credential class,
242 # if no credential class is specified we use password.
243 $config->{credential}{class} ||= "Catalyst::Plugin::Authentication::Credential::Password";
244
245 my $credentialclass = $config->{'credential'}{'class'};
246
247 ## follow catalyst class naming - a + prefix means a fully qualified class, otherwise it's
248 ## taken to mean C::P::A::Credential::(specifiedclass)
249 if ($credentialclass !~ /^\+(.*)$/ ) {
250 $credentialclass = "Catalyst::Plugin::Authentication::Credential::${credentialclass}";
251 } else {
252 $credentialclass = $1;
253 }
254
255 # if we made it here - we have what we need to load the classes;
256 Catalyst::Utils::ensure_class_loaded( $credentialclass );
257 Catalyst::Utils::ensure_class_loaded( $storeclass );
258
259 # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms
260 # of get_user and add it to the class. this is because the auth routines use find_user,
261 # and rely on it being present. (this avoids per-call checks)
262 if (!$storeclass->can('find_user')) {
263 no strict 'refs';
264 *{"${storeclass}::find_user"} = sub {
265 my ($self, $info) = @_;
266 my @rest = @{$info->{rest}} if exists($info->{rest});
267 $self->get_user($info->{id}, @rest);
268 };
269 }
270
271 $app->auth_realms->{$realmname}{'store'} = $storeclass->new($config->{'store'}, $app);
272 if ($credentialclass->can('new')) {
273 $app->auth_realms->{$realmname}{'credential'} = $credentialclass->new($config->{'credential'}, $app);
274 } else {
275 # if the credential class is not actually a class - has no 'new' operator, we wrap it,
276 # once again - to allow our code to be simple at runtime and allow non-OO packages to function.
277 my $wrapperclass = 'Catalyst::Plugin::Authentication::Credential::Wrapper';
278 Catalyst::Utils::ensure_class_loaded( $wrapperclass );
279 $app->auth_realms->{$realmname}{'credential'} = $wrapperclass->new($config->{'credential'}, $app);
280 }
96777f3a 281}
282
54c8dc06 283sub auth_realms {
284 my $self = shift;
285 return($self->_auth_realms);
96777f3a 286}
287
54c8dc06 288sub get_auth_realm {
289 my ($app, $realmname) = @_;
290 return $app->auth_realms->{$realmname};
291}
96777f3a 292
54c8dc06 293sub set_default_auth_realm {
294 my ($app, $realmname) = @_;
295
296 if (exists($app->auth_realms->{$realmname})) {
297 $app->auth_realms->{'default'} = $app->auth_realms->{$realmname};
12dae309 298 }
54c8dc06 299 return $app->get_auth_realm('default');
96777f3a 300}
301
54c8dc06 302sub authenticate {
303 my ($app, $userinfo, $realmname) = @_;
304
305 if (!$realmname) {
306 $realmname = 'default';
307 }
308
309 my $realm = $app->get_auth_realm($realmname);
310
311 if ($realm && exists($realm->{'credential'})) {
312 my $user = $realm->{'credential'}->authenticate($app, $realm->{store}, $userinfo);
313 if ($user) {
314 $app->set_authenticated($user, $realmname);
315 return $user;
316 }
317 } else {
318 $app->log->debug("The realm requested, '$realmname' does not exist," .
319 " or there is no credential associated with it.")
320 }
321 return 0;
96777f3a 322}
323
54c8dc06 324## BACKWARDS COMPATIBILITY -- Warning: Here be monsters!
325#
326# What follows are backwards compatibility routines - for use with Stores and Credentials
327# that have not been updated to work with C::P::Authentication v0.10.
328# These are here so as to not break people's existing installations, but will go away
329# in a future version.
330#
331# The old style of configuration only supports a single store, as each store module
332# sets itself as the default store upon being loaded. This is the only supported
333# 'compatibility' mode.
334#
335
336sub get_user {
337 my ( $c, $uid, @rest ) = @_;
96777f3a 338
54c8dc06 339 return $c->find_user( {'id' => $uid, 'rest'=>\@rest }, 'default' );
96777f3a 340}
341
54c8dc06 342##
343## this should only be called when using old-style authentication plugins. IF this gets
344## called in a new-style config - it will OVERWRITE the store of your default realm. Don't do it.
345## also - this is a partial setup - because no credential is instantiated... in other words it ONLY
346## works with old-style auth plugins and C::P::Authentication in compatibility mode. Trying to combine
347## this with a realm-type config will probably crash your app.
96777f3a 348sub default_auth_store {
12dae309 349 my $self = shift;
96777f3a 350
12dae309 351 if ( my $new = shift ) {
54c8dc06 352 $self->auth_realms->{'default'}{'store'} = $new;
353 my $storeclass = ref($new);
354
355 # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms
356 # of get_user and add it to the class. this is because the auth routines use find_user,
357 # and rely on it being present. (this avoids per-call checks)
358 if (!$storeclass->can('find_user')) {
359 no strict 'refs';
360 *{"${storeclass}::find_user"} = sub {
361 my ($self, $info) = @_;
362 my @rest = @{$info->{rest}} if exists($info->{rest});
363 $self->get_user($info->{id}, @rest);
364 };
365 }
12dae309 366 }
96777f3a 367
54c8dc06 368 return $self->get_auth_realm('default')->{'store'};
96777f3a 369}
370
54c8dc06 371## BACKWARDS COMPATIBILITY
372## this only ever returns a hash containing 'default' - as that is the only
373## supported mode of calling this.
374sub auth_store_names {
375 my $self = shift;
376
377 my %hash = ( $self->get_auth_realm('default')->{'store'} => 'default' );
378}
379
380sub get_auth_store {
381 my ( $self, $name ) = @_;
382
383 if ($name ne 'default') {
384 Carp::croak "get_auth_store called on non-default realm '$name'. Only default supported in compatibility mode";
385 } else {
386 $self->default_auth_store();
387 }
388}
389
390sub get_auth_store_name {
391 my ( $self, $store ) = @_;
392 return 'default';
393}
394
395# sub auth_stores is only used internally - here for completeness
396sub auth_stores {
397 my $self = shift;
398
399 my %hash = ( 'default' => $self->get_auth_realm('default')->{'store'});
400}
401
402
403
404
405
406
06675d2e 407__PACKAGE__;
408
409__END__
410
411=pod
412
413=head1 NAME
414
55395841 415Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
416authentication framework.
06675d2e 417
418=head1 SYNOPSIS
419
189b5b0c 420 use Catalyst qw/
421 Authentication
189b5b0c 422 /;
423
424 # later on ...
54c8dc06 425 $c->authenticate({ username => 'myusername', password => 'mypassword' });
426 my $age = $c->user->get('age');
189b5b0c 427 $c->logout;
06675d2e 428
429=head1 DESCRIPTION
430
e7522758 431The authentication plugin provides generic user support. It is the basis
432for both authentication (checking the user is who they claim to be), and
433authorization (allowing the user to do what the system authorises them to do).
06675d2e 434
e7522758 435Using authentication is split into two parts. A Store is used to actually
436store the user information, and can store any amount of data related to
437the user. Multiple stores can be accessed from within one application.
62f27384 438Credentials are used to verify users, using information from the store,
439given data from the frontend.
189b5b0c 440
6a36933d 441To implement authentication in a Catalyst application you need to add this
e7522758 442module, plus at least one store and one credential module.
189b5b0c 443
e7522758 444Authentication data can also be stored in a session, if the application
445is using the L<Catalyst::Plugin::Session> module.
06675d2e 446
4bb9b01c 447=head1 INTRODUCTION
448
449=head2 The Authentication/Authorization Process
450
451Web applications typically need to identify a user - to tell the user apart
452from other users. This is usually done in order to display private information
453that is only that user's business, or to limit access to the application so
454that only certain entities can access certain parts.
455
456This process is split up into several steps. First you ask the user to identify
457themselves. At this point you can't be sure that the user is really who they
458claim to be.
459
6a36933d 460Then the user tells you who they are, and backs this claim with some piece of
4bb9b01c 461information that only the real user could give you. For example, a password is
462a secret that is known to both the user and you. When the user tells you this
463password you can assume they're in on the secret and can be trusted (ignore
464identity theft for now). Checking the password, or any other proof is called
465B<credential verification>.
466
467By this time you know exactly who the user is - the user's identity is
468B<authenticated>. This is where this module's job stops, and other plugins step
469in. The next logical step is B<authorization>, the process of deciding what a
470user is (or isn't) allowed to do. For example, say your users are split into
471two main groups - regular users and administrators. You should verify that the
472currently logged in user is indeed an administrator before performing the
6a36933d 473actions of an administrative part of your application. One way to do this is
4bb9b01c 474with role based access control.
475
476=head2 The Components In This Framework
477
62f27384 478=head3 Realms
479
480Configuration of the Catalyst::Plugin::Authentication framework is done in
481terms of realms. In simplest terms, a realm is a pairing of a Credential
482verifier and a User storage (Store) backend.
483
484An application can have any number of Realms, each of which operates
485independant of the others. Each realm has a name, which is used to identify it
486as the target of an authentication request. This name can be anything, such as
487'users' or 'members'. One realm must be defined as the default_realm, which is
488used when no realm name is specified. More about this in the configuration
489section.
490
4bb9b01c 491=head3 Credential Verifiers
492
493When user input is transferred to the L<Catalyst> application (typically via
62f27384 494form inputs) this authentication data then enters the authentication framework
495through the $c->authenticate() routine. From there, it is passed to the
496appropriate Credential verifier.
4bb9b01c 497
498These plugins check the data, and ensure that it really proves the user is who
499they claim to be.
500
501=head3 Storage Backends
502
62f27384 503The authentication data also identify a user, and the Storage Backend modules
504use this data to locate and return a standardized object-oriented
505representation of a user.
4bb9b01c 506
507When a user is retrieved from a store it is not necessarily authenticated.
62f27384 508Credential verifiers accept a set of authentication data and use this
509information to retrieve the user from the store they are paired with.
4bb9b01c 510
511=head3 The Core Plugin
512
62f27384 513This plugin on its own is the glue, providing realm configuration, session
4bb9b01c 514integration, and other goodness for the other plugins.
515
516=head3 Other Plugins
517
518More layers of plugins can be stacked on top of the authentication code. For
519example, L<Catalyst::Plugin::Session::PerUser> provides an abstraction of
520browser sessions that is more persistent per users.
521L<Catalyst::Plugin::Authorization::Roles> provides an accepted way to separate
522and group users into categories, and then check which categories the current
523user belongs to.
524
5e91c057 525=head1 EXAMPLE
526
62f27384 527Let's say we were storing users in an simple perl hash. Users are
6a36933d 528stored in that file, with a hashed password and some extra comments. Users are
529verified by supplying a password which is matched with the file.
5e91c057 530
531This means that our application will begin like this:
532
533 package MyApp;
534
535 use Catalyst qw/
536 Authentication
5e91c057 537 /;
538
62f27384 539 __PACKAGE__->config->{authentication} =
540 {
541 default_realm => 'members',
542 realms => {
543 members => {
544 credential => {
545 class => 'Password'
546 },
547 store => {
548 class => 'Minimal',
549 users = {
550 bob => {
551 password => "s3cr3t",
552 editor => 'yes',
553 roles => [qw/edit delete/],
554 },
555 william => {
556 password => "s00p3r",
557 roles => [qw/comment/],
558 }
559 }
560 }
561 }
562 }
563 };
564
5e91c057 565
62f27384 566This tells the authentication plugin what realms are available, which credential
567and store modules are used, and the configuration of each.
5e91c057 568
62f27384 569With this code loaded, we can now attempt to authenticate users.
5e91c057 570
62f27384 571To show an example of this, let's create an authentication controller:
5e91c057 572
573 package MyApp::Controller::Auth;
574
575 sub login : Local {
576 my ( $self, $c ) = @_;
577
578 if ( my $user = $c->req->param("user")
579 and my $password = $c->req->param("password") )
580 {
62f27384 581 if ( $c->authenticate( { username => $user,
582 password => $password } ) ) {
583 $c->res->body( "hello " . $c->user->get("name") );
5e91c057 584 } else {
585 # login incorrect
586 }
587 }
588 else {
589 # invalid form input
590 }
591 }
592
593This code should be very readable. If all the necessary fields are supplied,
62f27384 594call the L<Catalyst::Plugin::Authentication/authenticate> method in the
595controller. If it succeeds the user is logged in.
5e91c057 596
62f27384 597The credential verifier will attempt to retrieve the user whose details match
598the authentication information provided to $c->authenticate(). Once it fetches
599the user the password is checked and if it matches the user will be
600'authenticated' and C<< $c->user >> will contain the user object retrieved
601from the store.
5e91c057 602
62f27384 603In the above case, the default realm is checked, but we could just as easily
604check an alternate realm. If this were an admin login, for example, we could
605authenticate on the admin realm by simply changing the $c->authenticate()
606call:
5e91c057 607
62f27384 608 if ( $c->authenticate( { username => $user,
609 password => $password }, 'admin' )l ) {
610 $c->res->body( "hello " . $c->user->get("name") );
611 } ...
5e91c057 612
5e91c057 613
62f27384 614Now suppose we want to restrict the ability to edit to a user with 'edit'
615in it's roles list.
5e91c057 616
62f27384 617The restricted action might look like this:
5e91c057 618
62f27384 619 sub edit : Local {
5e91c057 620 my ( $self, $c ) = @_;
621
622 $c->detach("unauthorized")
623 unless $c->user_exists
62f27384 624 and $c->user->get('editor') == 'yes';
5e91c057 625
626 # do something restricted here
627 }
628
629This is somewhat similar to role based access control.
62f27384 630L<Catalyst::Plugin::Authentication::Store::Minimal> treats the roles field as
631an array of role names. Let's leverage this. Add the role authorization
632plugin:
5e91c057 633
634 use Catalyst qw/
635 ...
636 Authorization::Roles
637 /;
638
62f27384 639 sub edit : Local {
5e91c057 640 my ( $self, $c ) = @_;
641
62f27384 642 $c->detach("unauthorized") unless $c->check_roles("edit");
5e91c057 643
644 # do something restricted here
645 }
646
647This is somewhat simpler and will work if you change your store, too, since the
648role interface is consistent.
649
62f27384 650 .... This is the end of the updated documentation for v0.10 - more soon ....
651
5e91c057 652Let's say your app grew, and you now have 10000 users. It's no longer efficient
653to maintain an htpasswd file, so you move this data to a database.
654
655 use Catalyst qw/
656 Authentication
657 Authentication::Credential::Password
658 Authentication::Store::DBIC
659 Authorization::Roles
660 /;
661
662 __PACKAGE__->config->{authentication}{dbic} = ...; # see the DBIC store docs
663
664The rest of your code should be unchanged. Now let's say you are integrating
665typekey authentication to your system. For simplicity's sake we'll assume that
666the user's are still keyed in the same way.
667
668 use Catalyst qw/
669 Authentication
670 Authentication::Credential::Password
671 Authentication::Credential::TypeKey
672 Authentication::Store::DBIC
673 Authorization::Roles
674 /;
675
676And in your auth controller add a new action:
677
678 sub typekey : Local {
679 my ( $self, $c ) = @_;
680
681 if ( $c->authenticate_typekey) { # uses $c->req and Authen::TypeKey
682 # same stuff as the $c->login method
683 # ...
684 }
685 }
686
687You've now added a new credential verification mechanizm orthogonally to the
688other components. All you have to do is make sure that the credential verifiers
689pass on the same types of parameters to the store in order to retrieve user
690objects.
691
06675d2e 692=head1 METHODS
693
694=over 4
695
06675d2e 696=item user
697
189b5b0c 698Returns the currently logged in user or undef if there is none.
06675d2e 699
ce0b058d 700=item user_exists
701
702Whether or not a user is logged in right now.
703
8bcb3a4b 704The reason this method exists is that C<< $c->user >> may needlessly load the
ce0b058d 705user from the auth store.
706
707If you're just going to say
708
4359cfe3 709 if ( $c->user_exists ) {
ce0b058d 710 # foo
711 } else {
712 $c->forward("login");
713 }
714
4359cfe3 715it should be more efficient than C<< $c->user >> when a user is marked in the
716session but C<< $c->user >> hasn't been called yet.
ce0b058d 717
4402d92d 718=item logout
719
720Delete the currently logged in user from C<user> and the session.
721
7d0922d8 722=item get_user $uid
723
189b5b0c 724Fetch a particular users details, defined by the given ID, via the default store.
725
726=back
727
728=head1 CONFIGURATION
729
730=over 4
731
732=item use_session
733
734Whether or not to store the user's logged in state in the session, if the
e7522758 735application is also using the L<Catalyst::Plugin::Session> plugin. This
736value is set to true per default.
737
738=item store
739
1e055395 740If multiple stores are being used, set the module you want as default here.
7d0922d8 741
1e055395 742=item stores
743
744If multiple stores are being used, you need to provide a name for each store
745here, as a hash, the keys are the names you wish to use, and the values are
746the the names of the plugins.
747
748 # example
749 __PACKAGE__->config( authentication => {
750 store => 'Catalyst::Plugin::Authentication::Store::HtPasswd',
751 stores => {
752 'dbic' => 'Catalyst::Plugin::Authentication::Store::DBIC'
753 }
754 });
755
2bcde605 756=back
1e055395 757
4fbe2e14 758=head1 METHODS FOR STORE MANAGEMENT
759
fe4cf44a 760=over 4
761
7d0922d8 762=item default_auth_store
763
4fbe2e14 764Return the store whose name is 'default'.
7d0922d8 765
189b5b0c 766This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 767or by using a Store plugin:
768
769 use Catalyst qw/Authentication Authentication::Store::Minimal/;
770
771Sets the default store to
772L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
773
a1e5bd36 774
4fbe2e14 775=item get_auth_store $name
776
777Return the store whose name is $name.
778
779=item get_auth_store_name $store
780
781Return the name of the store $store.
782
783=item auth_stores
784
785A hash keyed by name, with the stores registered in the app.
786
787=item auth_store_names
788
789A ref-hash keyed by store, which contains the names of the stores.
790
791=item register_auth_stores %stores_by_name
792
793Register stores into the application.
06675d2e 794
fe4cf44a 795=back
796
06675d2e 797=head1 INTERNAL METHODS
798
799=over 4
800
801=item set_authenticated $user
802
803Marks a user as authenticated. Should be called from a
804C<Catalyst::Plugin::Authentication::Credential> plugin after successful
805authentication.
806
807This involves setting C<user> and the internal data in C<session> if
808L<Catalyst::Plugin::Session> is loaded.
809
e300c5b6 810=item auth_restore_user $user
811
812Used to restore a user from the session, by C<user> only when it's actually
813needed.
814
815=item save_user_in_session $user
816
817Used to save the user in a session.
818
06675d2e 819=item prepare
820
821Revives a user from the session object if there is one.
822
823=item setup
824
825Sets the default configuration parameters.
826
827=item
828
829=back
830
fbe577ac 831=head1 SEE ALSO
832
4bb9b01c 833This list might not be up to date.
834
835=head2 User Storage Backends
836
fbe577ac 837L<Catalyst::Plugin::Authentication::Store::Minimal>,
4bb9b01c 838L<Catalyst::Plugin::Authentication::Store::Htpasswd>,
839L<Catalyst::Plugin::Authentication::Store::DBIC> (also works with Class::DBI).
840
841=head2 Credential verification
842
843L<Catalyst::Plugin::Authentication::Credential::Password>,
844L<Catalyst::Plugin::Authentication::Credential::HTTP>,
845L<Catalyst::Plugin::Authentication::Credential::TypeKey>
846
847=head2 Authorization
848
fbe577ac 849L<Catalyst::Plugin::Authorization::ACL>,
4bb9b01c 850L<Catalyst::Plugin::Authorization::Roles>
851
5e91c057 852=head2 Internals Documentation
853
854L<Catalyst::Plugin::Authentication::Store>
855
4bb9b01c 856=head2 Misc
857
858L<Catalyst::Plugin::Session>,
859L<Catalyst::Plugin::Session::PerUser>
fbe577ac 860
93f08fb0 861=head1 DON'T SEE ALSO
862
1a05e6ed 863This module along with its sub plugins deprecate a great number of other
864modules. These include L<Catalyst::Plugin::Authentication::Simple>,
865L<Catalyst::Plugin::Authentication::CDBI>.
93f08fb0 866
867At the time of writing these plugins have not yet been replaced or updated, but
1a05e6ed 868should be eventually: L<Catalyst::Plugin::Authentication::OpenID>,
869L<Catalyst::Plugin::Authentication::LDAP>,
870L<Catalyst::Plugin::Authentication::CDBI::Basic>,
871L<Catalyst::Plugin::Authentication::Basic::Remote>.
93f08fb0 872
2bcde605 873=head1 AUTHORS
fbe577ac 874
875Yuval Kogman, C<nothingmuch@woobling.org>
2bcde605 876
7d2f34eb 877Jess Robinson
2bcde605 878
7d2f34eb 879David Kamholz
06675d2e 880
ff46c00b 881=head1 COPYRIGHT & LICENSE
fbe577ac 882
883 Copyright (c) 2005 the aforementioned authors. All rights
884 reserved. This program is free software; you can redistribute
885 it and/or modify it under the same terms as Perl itself.
886
887=cut
06675d2e 888