More documentation fixes.
[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 }
0cc778ab 321 return undef;
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
16ef3eb8 431The authentication plugin provides generic user support for Catalyst apps. It
432is the basis for both authentication (checking the user is who they claim to
433be), and authorization (allowing the user to do what the system authorises
434them to do).
435
436Using authentication is split into two parts. A Store is used to actually
437store the user information, and can store any amount of data related to the
438user. Credentials are used to verify users, using information from the store,
439given data from the frontend. A Credential and a Store are paired to form a
440'Realm'. A Catalyst applicaiton using the authentication framework must have
441at least one realm, and may have multiple.
189b5b0c 442
6a36933d 443To implement authentication in a Catalyst application you need to add this
16ef3eb8 444module, and specify at least one realm in the configuration.
189b5b0c 445
e7522758 446Authentication data can also be stored in a session, if the application
447is using the L<Catalyst::Plugin::Session> module.
06675d2e 448
4bb9b01c 449=head1 INTRODUCTION
450
451=head2 The Authentication/Authorization Process
452
453Web applications typically need to identify a user - to tell the user apart
454from other users. This is usually done in order to display private information
455that is only that user's business, or to limit access to the application so
456that only certain entities can access certain parts.
457
458This process is split up into several steps. First you ask the user to identify
459themselves. At this point you can't be sure that the user is really who they
460claim to be.
461
6a36933d 462Then the user tells you who they are, and backs this claim with some piece of
4bb9b01c 463information that only the real user could give you. For example, a password is
464a secret that is known to both the user and you. When the user tells you this
465password you can assume they're in on the secret and can be trusted (ignore
466identity theft for now). Checking the password, or any other proof is called
467B<credential verification>.
468
469By this time you know exactly who the user is - the user's identity is
16ef3eb8 470B<authenticated>. This is where this module's job stops, and your application
471or other plugins step in.
472
473The next logical step is B<authorization>, the process of deciding what a user
474is (or isn't) allowed to do. For example, say your users are split into two
475main groups - regular users and administrators. You want to verify that the
4bb9b01c 476currently logged in user is indeed an administrator before performing the
16ef3eb8 477actions in an administrative part of your application. These decisionsmay be
478made within your application code using just the information available after
479authentication, or it may be facilitated by a number of plugins.
4bb9b01c 480
481=head2 The Components In This Framework
482
62f27384 483=head3 Realms
484
485Configuration of the Catalyst::Plugin::Authentication framework is done in
486terms of realms. In simplest terms, a realm is a pairing of a Credential
487verifier and a User storage (Store) backend.
488
489An application can have any number of Realms, each of which operates
490independant of the others. Each realm has a name, which is used to identify it
491as the target of an authentication request. This name can be anything, such as
492'users' or 'members'. One realm must be defined as the default_realm, which is
16ef3eb8 493used when no realm name is specified. More information about configuring
494realms is available in the configuration section.
62f27384 495
4bb9b01c 496=head3 Credential Verifiers
497
498When user input is transferred to the L<Catalyst> application (typically via
16ef3eb8 499form inputs) the application may pass this information into the authentication
500system through the $c->authenticate() method. From there, it is passed to the
62f27384 501appropriate Credential verifier.
4bb9b01c 502
503These plugins check the data, and ensure that it really proves the user is who
504they claim to be.
505
506=head3 Storage Backends
507
16ef3eb8 508The authentication data also identifies a user, and the Storage Backend modules
62f27384 509use this data to locate and return a standardized object-oriented
510representation of a user.
4bb9b01c 511
512When a user is retrieved from a store it is not necessarily authenticated.
62f27384 513Credential verifiers accept a set of authentication data and use this
514information to retrieve the user from the store they are paired with.
4bb9b01c 515
516=head3 The Core Plugin
517
62f27384 518This plugin on its own is the glue, providing realm configuration, session
4bb9b01c 519integration, and other goodness for the other plugins.
520
521=head3 Other Plugins
522
523More layers of plugins can be stacked on top of the authentication code. For
524example, L<Catalyst::Plugin::Session::PerUser> provides an abstraction of
525browser sessions that is more persistent per users.
526L<Catalyst::Plugin::Authorization::Roles> provides an accepted way to separate
527and group users into categories, and then check which categories the current
528user belongs to.
529
5e91c057 530=head1 EXAMPLE
531
16ef3eb8 532Let's say we were storing users in a simple perl hash. Users are
533verified by supplying a password which is matched within the hash.
5e91c057 534
535This means that our application will begin like this:
536
537 package MyApp;
538
539 use Catalyst qw/
540 Authentication
5e91c057 541 /;
542
62f27384 543 __PACKAGE__->config->{authentication} =
544 {
545 default_realm => 'members',
546 realms => {
547 members => {
548 credential => {
549 class => 'Password'
550 },
551 store => {
0cc778ab 552 class => 'Minimal',
62f27384 553 users = {
554 bob => {
16ef3eb8 555 password => "s00p3r",
62f27384 556 editor => 'yes',
557 roles => [qw/edit delete/],
558 },
559 william => {
16ef3eb8 560 password => "s3cr3t",
62f27384 561 roles => [qw/comment/],
562 }
563 }
564 }
565 }
566 }
567 };
568
5e91c057 569
16ef3eb8 570This tells the authentication plugin what realms are available, which
571credential and store modules are used, and the configuration of each. With
572this code loaded, we can now attempt to authenticate users.
5e91c057 573
62f27384 574To show an example of this, let's create an authentication controller:
5e91c057 575
576 package MyApp::Controller::Auth;
577
578 sub login : Local {
579 my ( $self, $c ) = @_;
580
581 if ( my $user = $c->req->param("user")
582 and my $password = $c->req->param("password") )
583 {
62f27384 584 if ( $c->authenticate( { username => $user,
585 password => $password } ) ) {
586 $c->res->body( "hello " . $c->user->get("name") );
5e91c057 587 } else {
588 # login incorrect
589 }
590 }
591 else {
592 # invalid form input
593 }
594 }
595
596This code should be very readable. If all the necessary fields are supplied,
62f27384 597call the L<Catalyst::Plugin::Authentication/authenticate> method in the
598controller. If it succeeds the user is logged in.
5e91c057 599
62f27384 600The credential verifier will attempt to retrieve the user whose details match
601the authentication information provided to $c->authenticate(). Once it fetches
602the user the password is checked and if it matches the user will be
16ef3eb8 603B<authenticated> and C<< $c->user >> will contain the user object retrieved
62f27384 604from the store.
5e91c057 605
62f27384 606In the above case, the default realm is checked, but we could just as easily
607check an alternate realm. If this were an admin login, for example, we could
608authenticate on the admin realm by simply changing the $c->authenticate()
609call:
5e91c057 610
62f27384 611 if ( $c->authenticate( { username => $user,
612 password => $password }, 'admin' )l ) {
613 $c->res->body( "hello " . $c->user->get("name") );
614 } ...
5e91c057 615
5e91c057 616
62f27384 617Now suppose we want to restrict the ability to edit to a user with 'edit'
618in it's roles list.
5e91c057 619
62f27384 620The restricted action might look like this:
5e91c057 621
62f27384 622 sub edit : Local {
5e91c057 623 my ( $self, $c ) = @_;
624
625 $c->detach("unauthorized")
626 unless $c->user_exists
62f27384 627 and $c->user->get('editor') == 'yes';
5e91c057 628
629 # do something restricted here
630 }
631
632This is somewhat similar to role based access control.
62f27384 633L<Catalyst::Plugin::Authentication::Store::Minimal> treats the roles field as
634an array of role names. Let's leverage this. Add the role authorization
635plugin:
5e91c057 636
637 use Catalyst qw/
638 ...
639 Authorization::Roles
640 /;
641
62f27384 642 sub edit : Local {
5e91c057 643 my ( $self, $c ) = @_;
644
62f27384 645 $c->detach("unauthorized") unless $c->check_roles("edit");
5e91c057 646
647 # do something restricted here
648 }
649
650This is somewhat simpler and will work if you change your store, too, since the
651role interface is consistent.
652
0cc778ab 653Let's say your app grew, and you now have 10000 users. It's no longer
654efficient to maintain a hash of users, so you move this data to a database.
655You can accomplish this simply by installing the DBIx::Class Store and
656changing your config:
5e91c057 657
0cc778ab 658 __PACKAGE__->config->{authentication} =
659 {
660 default_realm => 'members',
661 realms => {
662 members => {
663 credential => {
664 class => 'Password'
665 },
666 store => {
667 class => 'DBIx::Class',
668 user_class => 'MyApp::Users',
669 role_column => 'roles'
670 }
671 }
672 }
673 };
5e91c057 674
0cc778ab 675The authentication system works behind the scenes to load your data from the
676new source. The rest of your application is completely unchanged.
5e91c057 677
0cc778ab 678=head1 METHODS
5e91c057 679
0cc778ab 680=over 4
5e91c057 681
5e91c057 682
16ef3eb8 683=item authenticate( $userinfo, $realm )
06675d2e 684
16ef3eb8 685Attempts to authenticate the user using the information in the $userinfo hash
0cc778ab 686reference using the realm $realm. $realm may be omitted, in which case the
687default realm is checked.
06675d2e 688
06675d2e 689=item user
690
189b5b0c 691Returns the currently logged in user or undef if there is none.
06675d2e 692
ce0b058d 693=item user_exists
694
0cc778ab 695Returns true if a user is logged in right now. The difference between
696user_exists and user is that user_exists will return true if a user is logged
697in, even if it has not been retrieved from the storage backend. If you only
698need to know if the user is logged in, depending on the storage mechanism this
699can be much more efficient.
ce0b058d 700
4402d92d 701=item logout
702
16ef3eb8 703Logs the user out, Deletes the currently logged in user from $c->user and the session.
4402d92d 704
0cc778ab 705=item find_user( $userinfo, $realm )
7d0922d8 706
0cc778ab 707Fetch a particular users details, matching the provided user info, from the realm
708specified in $realm.
189b5b0c 709
710=back
711
712=head1 CONFIGURATION
713
714=over 4
715
0cc778ab 716 # example
717 __PACKAGE__->config->{authentication} =
718 {
719 default_realm => 'members',
720 realms => {
721 members => {
722 credential => {
723 class => 'Password'
724 },
725 store => {
726 class => 'DBIx::Class',
727 user_class => 'MyApp::Users',
728 role_column => 'roles'
729 }
730 },
731 admins => {
732 credential => {
733 class => 'Password'
734 },
735 store => {
736 class => '+MyApp::Authentication::Store::NetAuth',
737 authserver => '192.168.10.17'
738 }
739 }
740
741 }
742 };
743
189b5b0c 744=item use_session
745
746Whether or not to store the user's logged in state in the session, if the
e7522758 747application is also using the L<Catalyst::Plugin::Session> plugin. This
748value is set to true per default.
749
0cc778ab 750=item default_realm
fe4cf44a 751
0cc778ab 752This defines which realm should be used as when no realm is provided to methods
753that require a realm such as authenticate or find_user.
7d0922d8 754
0cc778ab 755=item realms
7d0922d8 756
0cc778ab 757This contains the series of realm configurations you want to use for your app.
758The only rule here is that there must be at least one. A realm consists of a
759name, which is used to reference the realm, a credential and a store.
4fbe2e14 760
0cc778ab 761Each realm config contains two hashes, one called 'credential' and one called
762'store', each of which provide configuration details to the respective modules.
763The contents of these hashes is specific to the module being used, with the
764exception of the 'class' element, which tells the core Authentication module the
765classname to use for that entry.
4fbe2e14 766
0cc778ab 767The 'class' element follows the standard Catalyst mechanism of class
768specification. If a class is prefixed with a +, it is assumed to be a complete
769class name. Otherwise it is considered to be a portion of the class name. For
770credentials, the classname 'Password', for example, is expanded to
771Catalyst::Plugin::Authentication::Credential::Password. For stores, the
772classname 'storename' is expanded to:
773Catalyst::Plugin::Authentication::Store::storename::Backend.
4fbe2e14 774
a1e5bd36 775
fe4cf44a 776=back
777
16ef3eb8 778 ... this is where the documentation fairy got distracted and moved on to other things ...
0cc778ab 779
06675d2e 780=head1 INTERNAL METHODS
781
782=over 4
783
784=item set_authenticated $user
785
786Marks a user as authenticated. Should be called from a
787C<Catalyst::Plugin::Authentication::Credential> plugin after successful
788authentication.
789
790This involves setting C<user> and the internal data in C<session> if
791L<Catalyst::Plugin::Session> is loaded.
792
e300c5b6 793=item auth_restore_user $user
794
795Used to restore a user from the session, by C<user> only when it's actually
796needed.
797
798=item save_user_in_session $user
799
800Used to save the user in a session.
801
06675d2e 802=item prepare
803
804Revives a user from the session object if there is one.
805
806=item setup
807
808Sets the default configuration parameters.
809
810=item
811
812=back
813
fbe577ac 814=head1 SEE ALSO
815
4bb9b01c 816This list might not be up to date.
817
818=head2 User Storage Backends
819
fbe577ac 820L<Catalyst::Plugin::Authentication::Store::Minimal>,
4bb9b01c 821L<Catalyst::Plugin::Authentication::Store::Htpasswd>,
822L<Catalyst::Plugin::Authentication::Store::DBIC> (also works with Class::DBI).
823
824=head2 Credential verification
825
826L<Catalyst::Plugin::Authentication::Credential::Password>,
827L<Catalyst::Plugin::Authentication::Credential::HTTP>,
828L<Catalyst::Plugin::Authentication::Credential::TypeKey>
829
830=head2 Authorization
831
fbe577ac 832L<Catalyst::Plugin::Authorization::ACL>,
4bb9b01c 833L<Catalyst::Plugin::Authorization::Roles>
834
5e91c057 835=head2 Internals Documentation
836
837L<Catalyst::Plugin::Authentication::Store>
838
4bb9b01c 839=head2 Misc
840
841L<Catalyst::Plugin::Session>,
842L<Catalyst::Plugin::Session::PerUser>
fbe577ac 843
93f08fb0 844=head1 DON'T SEE ALSO
845
1a05e6ed 846This module along with its sub plugins deprecate a great number of other
847modules. These include L<Catalyst::Plugin::Authentication::Simple>,
848L<Catalyst::Plugin::Authentication::CDBI>.
93f08fb0 849
850At the time of writing these plugins have not yet been replaced or updated, but
1a05e6ed 851should be eventually: L<Catalyst::Plugin::Authentication::OpenID>,
852L<Catalyst::Plugin::Authentication::LDAP>,
853L<Catalyst::Plugin::Authentication::CDBI::Basic>,
854L<Catalyst::Plugin::Authentication::Basic::Remote>.
93f08fb0 855
0cc778ab 856
857=head1 COMPATIBILITY ROUTINES
858
859=over 4
860
861In version 0.10 of the L<Catalyst::Plugin::Authentication> plugin, the API
862used changed. For app developers, this change is fairly minor, but for
863Credential and Store authors, the changes are significant. The items below are
864still present in the plugin, though using them is deprecated. They remain only
865as a transition tool, for those sites which can not be upgraded to use the new
866system due to local customizations, or use of Credential / store modules that
867have not yet been updated.
868
869=head1 METHODS FOR STORE MANAGEMENT
870
871=over 4
872
873=item default_auth_store
874
875Return the store whose name is 'default'.
876
877This is set to C<< $c->config->{authentication}{store} >> if that value exists,
878or by using a Store plugin:
879
880 use Catalyst qw/Authentication Authentication::Store::Minimal/;
881
882Sets the default store to
883L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
884
885
886=item get_auth_store $name
887
888Return the store whose name is $name.
889
890=item get_auth_store_name $store
891
892Return the name of the store $store.
893
894=item auth_stores
895
896A hash keyed by name, with the stores registered in the app.
897
898=item auth_store_names
899
900A ref-hash keyed by store, which contains the names of the stores.
901
902=item register_auth_stores %stores_by_name
903
904Register stores into the application.
905
906=back
907
908
909
2bcde605 910=head1 AUTHORS
fbe577ac 911
912Yuval Kogman, C<nothingmuch@woobling.org>
2bcde605 913
7d2f34eb 914Jess Robinson
2bcde605 915
7d2f34eb 916David Kamholz
06675d2e 917
ff46c00b 918=head1 COPYRIGHT & LICENSE
fbe577ac 919
920 Copyright (c) 2005 the aforementioned authors. All rights
921 reserved. This program is free software; you can redistribute
922 it and/or modify it under the same terms as Perl itself.
923
924=cut
06675d2e 925