Improve documentation
[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 }
06675d2e 81}
82
7d0922d8 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
06675d2e 96sub prepare {
97 my $c = shift->NEXT::prepare(@_);
98
4fbe2e14 99 if ( $c->isa("Catalyst::Plugin::Session")
06675d2e 100 and !$c->user )
101 {
7bb06c91 102 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
e300c5b6 103 $c->_user($frozen_user);
06675d2e 104 }
105 }
106
107 return $c;
108}
109
7bb06c91 110sub auth_restore_user {
e300c5b6 111 my ( $c, $frozen_user, $store_name ) = @_;
7bb06c91 112
4fbe2e14 113 return
cde43a59 114 unless $c->isa("Catalyst::Plugin::Session")
4fbe2e14 115 and $c->config->{authentication}{use_session}
116 and $c->sessionid;
4402d92d 117
e300c5b6 118 $store_name ||= $c->session->{__user_store};
119 $frozen_user ||= $c->session->{__user};
7bb06c91 120
e300c5b6 121 my $store = $c->get_auth_store($store_name);
122 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
7bb06c91 123
e300c5b6 124 return $user;
7bb06c91 125
126}
127
06675d2e 128sub setup {
129 my $c = shift;
130
712a35bf 131 my $cfg = $c->config->{authentication} || {};
06675d2e 132
133 %$cfg = (
134 use_session => 1,
135 %$cfg,
136 );
b003080b 137
12dae309 138 $c->register_auth_stores(
139 default => $cfg->{store},
140 %{ $cfg->{stores} || {} },
141 );
96777f3a 142
b003080b 143 $c->NEXT::setup(@_);
06675d2e 144}
145
96777f3a 146sub get_auth_store {
12dae309 147 my ( $self, $name ) = @_;
148 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 149}
150
151sub get_auth_store_name {
12dae309 152 my ( $self, $store ) = @_;
153 $self->auth_store_names->{$store};
96777f3a 154}
155
156sub register_auth_stores {
12dae309 157 my ( $self, %new ) = @_;
96777f3a 158
12dae309 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 }
96777f3a 164}
165
166sub auth_stores {
12dae309 167 my $self = shift;
168 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 169}
170
171sub auth_store_names {
12dae309 172 my $self = shift;
96777f3a 173
4402d92d 174 $self->_auth_store_names || do {
12dae309 175 tie my %hash, 'Tie::RefHash';
176 $self->_auth_store_names( \%hash );
4fbe2e14 177 }
96777f3a 178}
179
180sub default_auth_store {
12dae309 181 my $self = shift;
96777f3a 182
12dae309 183 if ( my $new = shift ) {
184 $self->register_auth_stores( default => $new );
185 }
96777f3a 186
12dae309 187 $self->get_auth_store("default");
96777f3a 188}
189
06675d2e 190__PACKAGE__;
191
192__END__
193
194=pod
195
196=head1 NAME
197
55395841 198Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
199authentication framework.
06675d2e 200
201=head1 SYNOPSIS
202
189b5b0c 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;
06675d2e 214
215=head1 DESCRIPTION
216
189b5b0c 217The authentication plugin provides generic user support. It is the basis for both authentication (checking the user is who they claim to be), and authorization (allowing the user to do what the system authorises them to do).
06675d2e 218
189b5b0c 219Using authentication is split into two parts. A Store is used to actually store the user information, and can store any amount of data related to the user. Multiple stores can be accessed from within one application. Credentials are used to verify users, using the store, given data from the frontend.
220
221To implement authentication in a catalyst application you need to add this module, plus at least one store and one credential module.
222
223Authentication data can also be stored in a session, if the application is using the L<Catalyst::Plugin::Session> module.
06675d2e 224
225=head1 METHODS
226
227=over 4
228
06675d2e 229=item user
230
189b5b0c 231Returns the currently logged in user or undef if there is none.
06675d2e 232
ce0b058d 233=item user_exists
234
235Whether or not a user is logged in right now.
236
237The reason this method exists is that C<<$c->user>> may needlessly load the
238user from the auth store.
239
240If you're just going to say
241
242 if ( $c->user_user ) {
243 # foo
244 } else {
245 $c->forward("login");
246 }
247
248it should be more efficient than C<<$c->user>> when a user is marked in the session
249but C<<$c->user>> hasn't been called yet.
250
4402d92d 251=item logout
252
253Delete the currently logged in user from C<user> and the session.
254
7d0922d8 255=item get_user $uid
256
189b5b0c 257Fetch a particular users details, defined by the given ID, via the default store.
258
259=back
260
261=head1 CONFIGURATION
262
263=over 4
264
265=item use_session
266
267Whether or not to store the user's logged in state in the session, if the
268application is also using the L<Catalyst::Plugin::Session> plugin.
7d0922d8 269
4fbe2e14 270=back
271
272=head1 METHODS FOR STORE MANAGEMENT
273
fe4cf44a 274=over 4
275
7d0922d8 276=item default_auth_store
277
4fbe2e14 278Return the store whose name is 'default'.
7d0922d8 279
189b5b0c 280This is set to C<< $c->config->{authentication}{store} >> if that value exists,
4fbe2e14 281or by using a Store plugin:
282
283 use Catalyst qw/Authentication Authentication::Store::Minimal/;
284
285Sets the default store to
286L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
287
a1e5bd36 288
4fbe2e14 289=item get_auth_store $name
290
291Return the store whose name is $name.
292
293=item get_auth_store_name $store
294
295Return the name of the store $store.
296
297=item auth_stores
298
299A hash keyed by name, with the stores registered in the app.
300
301=item auth_store_names
302
303A ref-hash keyed by store, which contains the names of the stores.
304
305=item register_auth_stores %stores_by_name
306
307Register stores into the application.
06675d2e 308
fe4cf44a 309=back
310
06675d2e 311=head1 INTERNAL METHODS
312
313=over 4
314
315=item set_authenticated $user
316
317Marks a user as authenticated. Should be called from a
318C<Catalyst::Plugin::Authentication::Credential> plugin after successful
319authentication.
320
321This involves setting C<user> and the internal data in C<session> if
322L<Catalyst::Plugin::Session> is loaded.
323
e300c5b6 324=item auth_restore_user $user
325
326Used to restore a user from the session, by C<user> only when it's actually
327needed.
328
329=item save_user_in_session $user
330
331Used to save the user in a session.
332
06675d2e 333=item prepare
334
335Revives a user from the session object if there is one.
336
337=item setup
338
339Sets the default configuration parameters.
340
341=item
342
343=back
344
fbe577ac 345=head1 SEE ALSO
346
347L<Catalyst::Plugin::Authentication::Credential::Password>,
348L<Catalyst::Plugin::Authentication::Store::Minimal>,
349L<Catalyst::Plugin::Authorization::ACL>,
350L<Catalyst::Plugin::Authorization::Roles>.
351
352=head1 AUTHOR
353
354Yuval Kogman, C<nothingmuch@woobling.org>
06675d2e 355
fbe577ac 356=head1 COPYRIGHT & LICNESE
357
358 Copyright (c) 2005 the aforementioned authors. All rights
359 reserved. This program is free software; you can redistribute
360 it and/or modify it under the same terms as Perl itself.
361
362=cut
06675d2e 363