Version bump Auth, Auth::Store::DBIC, Authz::{ACL,Roles}
[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
237=head1 METHODS
238
239=over 4
240
06675d2e 241=item user
242
189b5b0c 243Returns the currently logged in user or undef if there is none.
06675d2e 244
ce0b058d 245=item user_exists
246
247Whether or not a user is logged in right now.
248
249The reason this method exists is that C<<$c->user>> may needlessly load the
250user from the auth store.
251
252If you're just going to say
253
254 if ( $c->user_user ) {
255 # foo
256 } else {
257 $c->forward("login");
258 }
259
260it should be more efficient than C<<$c->user>> when a user is marked in the session
1e055395 261but C<< $c->user >> hasn't been called yet.
ce0b058d 262
4402d92d 263=item logout
264
265Delete the currently logged in user from C<user> and the session.
266
7d0922d8 267=item get_user $uid
268
189b5b0c 269Fetch a particular users details, defined by the given ID, via the default store.
270
271=back
272
273=head1 CONFIGURATION
274
275=over 4
276
277=item use_session
278
279Whether or not to store the user's logged in state in the session, if the
e7522758 280application is also using the L<Catalyst::Plugin::Session> plugin. This
281value is set to true per default.
282
283=item store
284
1e055395 285If multiple stores are being used, set the module you want as default here.
7d0922d8 286
1e055395 287=item stores
288
289If multiple stores are being used, you need to provide a name for each store
290here, as a hash, the keys are the names you wish to use, and the values are
291the the names of the plugins.
292
293 # example
294 __PACKAGE__->config( authentication => {
295 store => 'Catalyst::Plugin::Authentication::Store::HtPasswd',
296 stores => {
297 'dbic' => 'Catalyst::Plugin::Authentication::Store::DBIC'
298 }
299 });
300
2bcde605 301=back
1e055395 302
4fbe2e14 303=head1 METHODS FOR STORE MANAGEMENT
304
fe4cf44a 305=over 4
306
7d0922d8 307=item default_auth_store
308
4fbe2e14 309Return the store whose name is 'default'.
7d0922d8 310
189b5b0c 311This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 312or by using a Store plugin:
313
314 use Catalyst qw/Authentication Authentication::Store::Minimal/;
315
316Sets the default store to
317L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
318
a1e5bd36 319
4fbe2e14 320=item get_auth_store $name
321
322Return the store whose name is $name.
323
324=item get_auth_store_name $store
325
326Return the name of the store $store.
327
328=item auth_stores
329
330A hash keyed by name, with the stores registered in the app.
331
332=item auth_store_names
333
334A ref-hash keyed by store, which contains the names of the stores.
335
336=item register_auth_stores %stores_by_name
337
338Register stores into the application.
06675d2e 339
fe4cf44a 340=back
341
06675d2e 342=head1 INTERNAL METHODS
343
344=over 4
345
346=item set_authenticated $user
347
348Marks a user as authenticated. Should be called from a
349C<Catalyst::Plugin::Authentication::Credential> plugin after successful
350authentication.
351
352This involves setting C<user> and the internal data in C<session> if
353L<Catalyst::Plugin::Session> is loaded.
354
e300c5b6 355=item auth_restore_user $user
356
357Used to restore a user from the session, by C<user> only when it's actually
358needed.
359
360=item save_user_in_session $user
361
362Used to save the user in a session.
363
06675d2e 364=item prepare
365
366Revives a user from the session object if there is one.
367
368=item setup
369
370Sets the default configuration parameters.
371
372=item
373
374=back
375
fbe577ac 376=head1 SEE ALSO
377
378L<Catalyst::Plugin::Authentication::Credential::Password>,
379L<Catalyst::Plugin::Authentication::Store::Minimal>,
380L<Catalyst::Plugin::Authorization::ACL>,
381L<Catalyst::Plugin::Authorization::Roles>.
382
2bcde605 383=head1 AUTHORS
fbe577ac 384
385Yuval Kogman, C<nothingmuch@woobling.org>
2bcde605 386
7d2f34eb 387Jess Robinson
2bcde605 388
7d2f34eb 389David Kamholz
06675d2e 390
fbe577ac 391=head1 COPYRIGHT & LICNESE
392
393 Copyright (c) 2005 the aforementioned authors. All rights
394 reserved. This program is free software; you can redistribute
395 it and/or modify it under the same terms as Perl itself.
396
397=cut
06675d2e 398