Doc + prereq 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/);
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
e145babc 18#BEGIN {
19# require constant;
20# constant->import(have_want => eval { require Want });
21#}
a1e5bd36 22
e09a839c 23our $VERSION = "0.02";
c7c003d3 24
06675d2e 25sub set_authenticated {
26 my ( $c, $user ) = @_;
27
28 $c->user($user);
e300c5b6 29 $c->request->{user} = $user; # compatibility kludge
06675d2e 30
31 if ( $c->isa("Catalyst::Plugin::Session")
96777f3a 32 and $c->config->{authentication}{use_session}
12dae309 33 and $user->supports("session") )
06675d2e 34 {
12dae309 35 $c->save_user_in_session($user);
06675d2e 36 }
55395841 37
4fbe2e14 38 $c->NEXT::set_authenticated($user);
06675d2e 39}
40
7bb06c91 41sub user {
e300c5b6 42 my $c = shift;
7bb06c91 43
e300c5b6 44 if (@_) {
45 return $c->_user(@_);
46 }
7bb06c91 47
e300c5b6 48 my $user = $c->_user;
7bb06c91 49
e300c5b6 50 if ( $user and !Scalar::Util::blessed($user) ) {
cde43a59 51# return 1 if have_want() && Want::want("BOOL");
e300c5b6 52 return $c->auth_restore_user($user);
53 }
7bb06c91 54
e300c5b6 55 return $user;
7bb06c91 56}
57
ce0b058d 58sub user_exists {
59 my $c = shift;
60 return defined($c->_user);
61}
62
12dae309 63sub save_user_in_session {
e300c5b6 64 my ( $c, $user ) = @_;
12dae309 65
66 my $store = $user->store || ref $user;
67 $c->session->{__user_store} = $c->get_auth_store_name($store) || $store;
68 $c->session->{__user} = $user->for_session;
69}
70
06675d2e 71sub logout {
72 my $c = shift;
73
74 $c->user(undef);
b003080b 75
76 if ( $c->isa("Catalyst::Plugin::Session")
77 and $c->config->{authentication}{use_session} )
78 {
96777f3a 79 delete @{ $c->session }{qw/__user __user_store/};
b003080b 80 }
351e2a82 81
82 $c->NEXT::logout(@_);
06675d2e 83}
84
7d0922d8 85sub get_user {
86 my ( $c, $uid ) = @_;
87
88 if ( my $store = $c->default_auth_store ) {
89 return $store->get_user($uid);
90 }
91 else {
92 Catalyst::Exception->throw(
93 "The user id $uid was passed to an authentication "
94 . "plugin, but no default store was specified" );
95 }
96}
97
06675d2e 98sub prepare {
99 my $c = shift->NEXT::prepare(@_);
100
4fbe2e14 101 if ( $c->isa("Catalyst::Plugin::Session")
06675d2e 102 and !$c->user )
103 {
7bb06c91 104 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
e300c5b6 105 $c->_user($frozen_user);
06675d2e 106 }
107 }
108
109 return $c;
110}
111
7bb06c91 112sub auth_restore_user {
e300c5b6 113 my ( $c, $frozen_user, $store_name ) = @_;
7bb06c91 114
4fbe2e14 115 return
cde43a59 116 unless $c->isa("Catalyst::Plugin::Session")
4fbe2e14 117 and $c->config->{authentication}{use_session}
118 and $c->sessionid;
4402d92d 119
e300c5b6 120 $store_name ||= $c->session->{__user_store};
121 $frozen_user ||= $c->session->{__user};
7bb06c91 122
e300c5b6 123 my $store = $c->get_auth_store($store_name);
124 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
7bb06c91 125
e300c5b6 126 return $user;
7bb06c91 127
128}
129
06675d2e 130sub setup {
131 my $c = shift;
132
712a35bf 133 my $cfg = $c->config->{authentication} || {};
06675d2e 134
135 %$cfg = (
136 use_session => 1,
137 %$cfg,
138 );
b003080b 139
12dae309 140 $c->register_auth_stores(
141 default => $cfg->{store},
142 %{ $cfg->{stores} || {} },
143 );
96777f3a 144
b003080b 145 $c->NEXT::setup(@_);
06675d2e 146}
147
96777f3a 148sub get_auth_store {
12dae309 149 my ( $self, $name ) = @_;
150 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 151}
152
153sub get_auth_store_name {
12dae309 154 my ( $self, $store ) = @_;
155 $self->auth_store_names->{$store};
96777f3a 156}
157
158sub register_auth_stores {
12dae309 159 my ( $self, %new ) = @_;
96777f3a 160
12dae309 161 foreach my $name ( keys %new ) {
162 my $store = $new{$name} or next;
163 $self->auth_stores->{$name} = $store;
164 $self->auth_store_names->{$store} = $name;
165 }
96777f3a 166}
167
168sub auth_stores {
12dae309 169 my $self = shift;
170 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 171}
172
173sub auth_store_names {
12dae309 174 my $self = shift;
96777f3a 175
4402d92d 176 $self->_auth_store_names || do {
12dae309 177 tie my %hash, 'Tie::RefHash';
178 $self->_auth_store_names( \%hash );
4fbe2e14 179 }
96777f3a 180}
181
182sub default_auth_store {
12dae309 183 my $self = shift;
96777f3a 184
12dae309 185 if ( my $new = shift ) {
186 $self->register_auth_stores( default => $new );
187 }
96777f3a 188
12dae309 189 $self->get_auth_store("default");
96777f3a 190}
191
06675d2e 192__PACKAGE__;
193
194__END__
195
196=pod
197
198=head1 NAME
199
55395841 200Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
201authentication framework.
06675d2e 202
203=head1 SYNOPSIS
204
189b5b0c 205 use Catalyst qw/
206 Authentication
207 Authentication::Store::Foo
208 Authentication::Credential::Password
209 /;
210
211 # later on ...
212 # ->login is provided by the Credential::Password module
213 $c->login('myusername', 'mypassword');
214 my $age = $c->user->age;
215 $c->logout;
06675d2e 216
217=head1 DESCRIPTION
218
e7522758 219The authentication plugin provides generic user support. It is the basis
220for both authentication (checking the user is who they claim to be), and
221authorization (allowing the user to do what the system authorises them to do).
06675d2e 222
e7522758 223Using authentication is split into two parts. A Store is used to actually
224store the user information, and can store any amount of data related to
225the user. Multiple stores can be accessed from within one application.
226Credentials are used to verify users, using the store, given data from
227the frontend.
189b5b0c 228
e7522758 229To implement authentication in a catalyst application you need to add this
230module, plus at least one store and one credential module.
189b5b0c 231
e7522758 232Authentication data can also be stored in a session, if the application
233is using the L<Catalyst::Plugin::Session> module.
06675d2e 234
235=head1 METHODS
236
237=over 4
238
06675d2e 239=item user
240
189b5b0c 241Returns the currently logged in user or undef if there is none.
06675d2e 242
ce0b058d 243=item user_exists
244
245Whether or not a user is logged in right now.
246
247The reason this method exists is that C<<$c->user>> may needlessly load the
248user from the auth store.
249
250If you're just going to say
251
252 if ( $c->user_user ) {
253 # foo
254 } else {
255 $c->forward("login");
256 }
257
258it should be more efficient than C<<$c->user>> when a user is marked in the session
1e055395 259but C<< $c->user >> hasn't been called yet.
ce0b058d 260
4402d92d 261=item logout
262
263Delete the currently logged in user from C<user> and the session.
264
7d0922d8 265=item get_user $uid
266
189b5b0c 267Fetch a particular users details, defined by the given ID, via the default store.
268
269=back
270
271=head1 CONFIGURATION
272
273=over 4
274
275=item use_session
276
277Whether or not to store the user's logged in state in the session, if the
e7522758 278application is also using the L<Catalyst::Plugin::Session> plugin. This
279value is set to true per default.
280
281=item store
282
1e055395 283If multiple stores are being used, set the module you want as default here.
7d0922d8 284
4fbe2e14 285=back
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
301
4fbe2e14 302=head1 METHODS FOR STORE MANAGEMENT
303
fe4cf44a 304=over 4
305
7d0922d8 306=item default_auth_store
307
4fbe2e14 308Return the store whose name is 'default'.
7d0922d8 309
189b5b0c 310This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 311or by using a Store plugin:
312
313 use Catalyst qw/Authentication Authentication::Store::Minimal/;
314
315Sets the default store to
316L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
317
a1e5bd36 318
4fbe2e14 319=item get_auth_store $name
320
321Return the store whose name is $name.
322
323=item get_auth_store_name $store
324
325Return the name of the store $store.
326
327=item auth_stores
328
329A hash keyed by name, with the stores registered in the app.
330
331=item auth_store_names
332
333A ref-hash keyed by store, which contains the names of the stores.
334
335=item register_auth_stores %stores_by_name
336
337Register stores into the application.
06675d2e 338
fe4cf44a 339=back
340
06675d2e 341=head1 INTERNAL METHODS
342
343=over 4
344
345=item set_authenticated $user
346
347Marks a user as authenticated. Should be called from a
348C<Catalyst::Plugin::Authentication::Credential> plugin after successful
349authentication.
350
351This involves setting C<user> and the internal data in C<session> if
352L<Catalyst::Plugin::Session> is loaded.
353
e300c5b6 354=item auth_restore_user $user
355
356Used to restore a user from the session, by C<user> only when it's actually
357needed.
358
359=item save_user_in_session $user
360
361Used to save the user in a session.
362
06675d2e 363=item prepare
364
365Revives a user from the session object if there is one.
366
367=item setup
368
369Sets the default configuration parameters.
370
371=item
372
373=back
374
fbe577ac 375=head1 SEE ALSO
376
377L<Catalyst::Plugin::Authentication::Credential::Password>,
378L<Catalyst::Plugin::Authentication::Store::Minimal>,
379L<Catalyst::Plugin::Authorization::ACL>,
380L<Catalyst::Plugin::Authorization::Roles>.
381
382=head1 AUTHOR
383
384Yuval Kogman, C<nothingmuch@woobling.org>
7d2f34eb 385Jess Robinson
386David Kamholz
06675d2e 387
fbe577ac 388=head1 COPYRIGHT & LICNESE
389
390 Copyright (c) 2005 the aforementioned authors. All rights
391 reserved. This program is free software; you can redistribute
392 it and/or modify it under the same terms as Perl itself.
393
394=cut
06675d2e 395