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