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