Some docs for Auth
[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/);
96777f3a 9 __PACKAGE__->mk_classdata($_) for qw/_auth_stores _auth_store_names/;
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
bbf1cb39 25our $VERSION = "0.04";
c7c003d3 26
06675d2e 27sub set_authenticated {
28 my ( $c, $user ) = @_;
29
30 $c->user($user);
e300c5b6 31 $c->request->{user} = $user; # compatibility kludge
06675d2e 32
33 if ( $c->isa("Catalyst::Plugin::Session")
96777f3a 34 and $c->config->{authentication}{use_session}
12dae309 35 and $user->supports("session") )
06675d2e 36 {
12dae309 37 $c->save_user_in_session($user);
06675d2e 38 }
55395841 39
4fbe2e14 40 $c->NEXT::set_authenticated($user);
06675d2e 41}
42
7bb06c91 43sub user {
e300c5b6 44 my $c = shift;
7bb06c91 45
e300c5b6 46 if (@_) {
47 return $c->_user(@_);
48 }
7bb06c91 49
e300c5b6 50 my $user = $c->_user;
7bb06c91 51
e300c5b6 52 if ( $user and !Scalar::Util::blessed($user) ) {
cde43a59 53# return 1 if have_want() && Want::want("BOOL");
e300c5b6 54 return $c->auth_restore_user($user);
55 }
7bb06c91 56
e300c5b6 57 return $user;
7bb06c91 58}
59
ce0b058d 60sub user_exists {
61 my $c = shift;
62 return defined($c->_user);
63}
64
12dae309 65sub save_user_in_session {
e300c5b6 66 my ( $c, $user ) = @_;
12dae309 67
68 my $store = $user->store || ref $user;
69 $c->session->{__user_store} = $c->get_auth_store_name($store) || $store;
70 $c->session->{__user} = $user->for_session;
71}
72
06675d2e 73sub logout {
74 my $c = shift;
75
76 $c->user(undef);
b003080b 77
78 if ( $c->isa("Catalyst::Plugin::Session")
79 and $c->config->{authentication}{use_session} )
80 {
96777f3a 81 delete @{ $c->session }{qw/__user __user_store/};
b003080b 82 }
351e2a82 83
84 $c->NEXT::logout(@_);
06675d2e 85}
86
7d0922d8 87sub get_user {
88 my ( $c, $uid ) = @_;
89
90 if ( my $store = $c->default_auth_store ) {
91 return $store->get_user($uid);
92 }
93 else {
94 Catalyst::Exception->throw(
95 "The user id $uid was passed to an authentication "
96 . "plugin, but no default store was specified" );
97 }
98}
99
06675d2e 100sub prepare {
101 my $c = shift->NEXT::prepare(@_);
102
4fbe2e14 103 if ( $c->isa("Catalyst::Plugin::Session")
06675d2e 104 and !$c->user )
105 {
7bb06c91 106 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
e300c5b6 107 $c->_user($frozen_user);
06675d2e 108 }
109 }
110
111 return $c;
112}
113
7bb06c91 114sub auth_restore_user {
e300c5b6 115 my ( $c, $frozen_user, $store_name ) = @_;
7bb06c91 116
4fbe2e14 117 return
cde43a59 118 unless $c->isa("Catalyst::Plugin::Session")
4fbe2e14 119 and $c->config->{authentication}{use_session}
120 and $c->sessionid;
4402d92d 121
e300c5b6 122 $store_name ||= $c->session->{__user_store};
123 $frozen_user ||= $c->session->{__user};
7bb06c91 124
e300c5b6 125 my $store = $c->get_auth_store($store_name);
126 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
7bb06c91 127
e300c5b6 128 return $user;
7bb06c91 129
130}
131
06675d2e 132sub setup {
133 my $c = shift;
134
712a35bf 135 my $cfg = $c->config->{authentication} || {};
06675d2e 136
137 %$cfg = (
138 use_session => 1,
139 %$cfg,
140 );
b003080b 141
12dae309 142 $c->register_auth_stores(
143 default => $cfg->{store},
144 %{ $cfg->{stores} || {} },
145 );
96777f3a 146
b003080b 147 $c->NEXT::setup(@_);
06675d2e 148}
149
96777f3a 150sub get_auth_store {
12dae309 151 my ( $self, $name ) = @_;
152 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 153}
154
155sub get_auth_store_name {
12dae309 156 my ( $self, $store ) = @_;
157 $self->auth_store_names->{$store};
96777f3a 158}
159
160sub register_auth_stores {
12dae309 161 my ( $self, %new ) = @_;
96777f3a 162
12dae309 163 foreach my $name ( keys %new ) {
164 my $store = $new{$name} or next;
165 $self->auth_stores->{$name} = $store;
166 $self->auth_store_names->{$store} = $name;
167 }
96777f3a 168}
169
170sub auth_stores {
12dae309 171 my $self = shift;
172 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 173}
174
175sub auth_store_names {
12dae309 176 my $self = shift;
96777f3a 177
4402d92d 178 $self->_auth_store_names || do {
12dae309 179 tie my %hash, 'Tie::RefHash';
180 $self->_auth_store_names( \%hash );
4fbe2e14 181 }
96777f3a 182}
183
184sub default_auth_store {
12dae309 185 my $self = shift;
96777f3a 186
12dae309 187 if ( my $new = shift ) {
188 $self->register_auth_stores( default => $new );
189 }
96777f3a 190
12dae309 191 $self->get_auth_store("default");
96777f3a 192}
193
06675d2e 194__PACKAGE__;
195
196__END__
197
198=pod
199
200=head1 NAME
201
55395841 202Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
203authentication framework.
06675d2e 204
205=head1 SYNOPSIS
206
189b5b0c 207 use Catalyst qw/
208 Authentication
209 Authentication::Store::Foo
210 Authentication::Credential::Password
211 /;
212
213 # later on ...
214 # ->login is provided by the Credential::Password module
215 $c->login('myusername', 'mypassword');
216 my $age = $c->user->age;
217 $c->logout;
06675d2e 218
219=head1 DESCRIPTION
220
e7522758 221The authentication plugin provides generic user support. It is the basis
222for both authentication (checking the user is who they claim to be), and
223authorization (allowing the user to do what the system authorises them to do).
06675d2e 224
e7522758 225Using authentication is split into two parts. A Store is used to actually
226store the user information, and can store any amount of data related to
227the user. Multiple stores can be accessed from within one application.
228Credentials are used to verify users, using the store, given data from
229the frontend.
189b5b0c 230
e7522758 231To implement authentication in a catalyst application you need to add this
232module, plus at least one store and one credential module.
189b5b0c 233
e7522758 234Authentication data can also be stored in a session, if the application
235is using the L<Catalyst::Plugin::Session> module.
06675d2e 236
4bb9b01c 237=head1 INTRODUCTION
238
239=head2 The Authentication/Authorization Process
240
241Web applications typically need to identify a user - to tell the user apart
242from other users. This is usually done in order to display private information
243that is only that user's business, or to limit access to the application so
244that only certain entities can access certain parts.
245
246This process is split up into several steps. First you ask the user to identify
247themselves. At this point you can't be sure that the user is really who they
248claim to be.
249
250Then the user tells you who they are, and backs this claim with some peice of
251information that only the real user could give you. For example, a password is
252a secret that is known to both the user and you. When the user tells you this
253password you can assume they're in on the secret and can be trusted (ignore
254identity theft for now). Checking the password, or any other proof is called
255B<credential verification>.
256
257By this time you know exactly who the user is - the user's identity is
258B<authenticated>. This is where this module's job stops, and other plugins step
259in. The next logical step is B<authorization>, the process of deciding what a
260user is (or isn't) allowed to do. For example, say your users are split into
261two main groups - regular users and administrators. You should verify that the
262currently logged in user is indeed an administrator before performing the
263actions of an administrative part of your apploication. One way to do this is
264with role based access control.
265
266=head2 The Components In This Framework
267
268=head3 Credential Verifiers
269
270When user input is transferred to the L<Catalyst> application (typically via
271form inputs) this data then enters the authentication framework through these
272plugins.
273
274These plugins check the data, and ensure that it really proves the user is who
275they claim to be.
276
277=head3 Storage Backends
278
279The credentials also identify a user, and this family of modules is supposed to
280take this identification data and return a standardized object oriented
281representation of users.
282
283When a user is retrieved from a store it is not necessarily authenticated.
284Credential verifiers can either accept a user object, or fetch the object
285themselves from the default store.
286
287=head3 The Core Plugin
288
289This plugin on it's own is the glue, providing store registration, session
290integration, and other goodness for the other plugins.
291
292=head3 Other Plugins
293
294More layers of plugins can be stacked on top of the authentication code. For
295example, L<Catalyst::Plugin::Session::PerUser> provides an abstraction of
296browser sessions that is more persistent per users.
297L<Catalyst::Plugin::Authorization::Roles> provides an accepted way to separate
298and group users into categories, and then check which categories the current
299user belongs to.
300
06675d2e 301=head1 METHODS
302
303=over 4
304
06675d2e 305=item user
306
189b5b0c 307Returns the currently logged in user or undef if there is none.
06675d2e 308
ce0b058d 309=item user_exists
310
311Whether or not a user is logged in right now.
312
8bcb3a4b 313The reason this method exists is that C<< $c->user >> may needlessly load the
ce0b058d 314user from the auth store.
315
316If you're just going to say
317
318 if ( $c->user_user ) {
319 # foo
320 } else {
321 $c->forward("login");
322 }
323
8bcb3a4b 324it should be more efficient than C<< $c->user >> when a user is marked in the session
1e055395 325but C<< $c->user >> hasn't been called yet.
ce0b058d 326
4402d92d 327=item logout
328
329Delete the currently logged in user from C<user> and the session.
330
7d0922d8 331=item get_user $uid
332
189b5b0c 333Fetch a particular users details, defined by the given ID, via the default store.
334
335=back
336
337=head1 CONFIGURATION
338
339=over 4
340
341=item use_session
342
343Whether or not to store the user's logged in state in the session, if the
e7522758 344application is also using the L<Catalyst::Plugin::Session> plugin. This
345value is set to true per default.
346
347=item store
348
1e055395 349If multiple stores are being used, set the module you want as default here.
7d0922d8 350
1e055395 351=item stores
352
353If multiple stores are being used, you need to provide a name for each store
354here, as a hash, the keys are the names you wish to use, and the values are
355the the names of the plugins.
356
357 # example
358 __PACKAGE__->config( authentication => {
359 store => 'Catalyst::Plugin::Authentication::Store::HtPasswd',
360 stores => {
361 'dbic' => 'Catalyst::Plugin::Authentication::Store::DBIC'
362 }
363 });
364
2bcde605 365=back
1e055395 366
4fbe2e14 367=head1 METHODS FOR STORE MANAGEMENT
368
fe4cf44a 369=over 4
370
7d0922d8 371=item default_auth_store
372
4fbe2e14 373Return the store whose name is 'default'.
7d0922d8 374
189b5b0c 375This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 376or by using a Store plugin:
377
378 use Catalyst qw/Authentication Authentication::Store::Minimal/;
379
380Sets the default store to
381L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
382
a1e5bd36 383
4fbe2e14 384=item get_auth_store $name
385
386Return the store whose name is $name.
387
388=item get_auth_store_name $store
389
390Return the name of the store $store.
391
392=item auth_stores
393
394A hash keyed by name, with the stores registered in the app.
395
396=item auth_store_names
397
398A ref-hash keyed by store, which contains the names of the stores.
399
400=item register_auth_stores %stores_by_name
401
402Register stores into the application.
06675d2e 403
fe4cf44a 404=back
405
06675d2e 406=head1 INTERNAL METHODS
407
408=over 4
409
410=item set_authenticated $user
411
412Marks a user as authenticated. Should be called from a
413C<Catalyst::Plugin::Authentication::Credential> plugin after successful
414authentication.
415
416This involves setting C<user> and the internal data in C<session> if
417L<Catalyst::Plugin::Session> is loaded.
418
e300c5b6 419=item auth_restore_user $user
420
421Used to restore a user from the session, by C<user> only when it's actually
422needed.
423
424=item save_user_in_session $user
425
426Used to save the user in a session.
427
06675d2e 428=item prepare
429
430Revives a user from the session object if there is one.
431
432=item setup
433
434Sets the default configuration parameters.
435
436=item
437
438=back
439
fbe577ac 440=head1 SEE ALSO
441
4bb9b01c 442This list might not be up to date.
443
444=head2 User Storage Backends
445
fbe577ac 446L<Catalyst::Plugin::Authentication::Store::Minimal>,
4bb9b01c 447L<Catalyst::Plugin::Authentication::Store::Htpasswd>,
448L<Catalyst::Plugin::Authentication::Store::DBIC> (also works with Class::DBI).
449
450=head2 Credential verification
451
452L<Catalyst::Plugin::Authentication::Credential::Password>,
453L<Catalyst::Plugin::Authentication::Credential::HTTP>,
454L<Catalyst::Plugin::Authentication::Credential::TypeKey>
455
456=head2 Authorization
457
fbe577ac 458L<Catalyst::Plugin::Authorization::ACL>,
4bb9b01c 459L<Catalyst::Plugin::Authorization::Roles>
460
461=head2 Misc
462
463L<Catalyst::Plugin::Session>,
464L<Catalyst::Plugin::Session::PerUser>
fbe577ac 465
93f08fb0 466=head1 DON'T SEE ALSO
467
468This module along with it's sub plugins deprecate a great number of other
469modules. These include Catalyst::Plugin::Authentication::Simple,
470Catalyst::Plugin::Authentication::CDBI.
471
472At the time of writing these plugins have not yet been replaced or updated, but
473should be eventually: Catalyst::Plugin::Authentication::OpenID,
474Catalyst::Plugin::Authentication::LDAP,
475Catalyst::Plugin::Authentication::CDBI::Basic,
476Catalyst::Plugin::Authentication::Basic::Remote
477
2bcde605 478=head1 AUTHORS
fbe577ac 479
480Yuval Kogman, C<nothingmuch@woobling.org>
2bcde605 481
7d2f34eb 482Jess Robinson
2bcde605 483
7d2f34eb 484David Kamholz
06675d2e 485
ff46c00b 486=head1 COPYRIGHT & LICENSE
fbe577ac 487
488 Copyright (c) 2005 the aforementioned authors. All rights
489 reserved. This program is free software; you can redistribute
490 it and/or modify it under the same terms as Perl itself.
491
492=cut
06675d2e 493