3 package Catalyst::Plugin::Authentication;
5 use base qw/Class::Accessor::Fast Class::Data::Inheritable/;
8 __PACKAGE__->mk_accessors(qw/_user/);
9 __PACKAGE__->mk_classdata($_) for qw/_auth_stores _auth_store_names/;
18 # this optimization breaks under Template::Toolkit
19 # use user_exists instead
22 # constant->import(have_want => eval { require Want });
25 our $VERSION = "0.04";
27 sub set_authenticated {
28 my ( $c, $user ) = @_;
31 $c->request->{user} = $user; # compatibility kludge
33 if ( $c->isa("Catalyst::Plugin::Session")
34 and $c->config->{authentication}{use_session}
35 and $user->supports("session") )
37 $c->save_user_in_session($user);
40 $c->NEXT::set_authenticated($user);
52 if ( $user and !Scalar::Util::blessed($user) ) {
53 # return 1 if have_want() && Want::want("BOOL");
54 return $c->auth_restore_user($user);
62 return defined($c->_user);
65 sub save_user_in_session {
66 my ( $c, $user ) = @_;
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;
78 if ( $c->isa("Catalyst::Plugin::Session")
79 and $c->config->{authentication}{use_session} )
81 delete @{ $c->session }{qw/__user __user_store/};
90 if ( my $store = $c->default_auth_store ) {
91 return $store->get_user($uid);
94 Catalyst::Exception->throw(
95 "The user id $uid was passed to an authentication "
96 . "plugin, but no default store was specified" );
101 my $c = shift->NEXT::prepare(@_);
103 if ( $c->isa("Catalyst::Plugin::Session")
106 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
107 $c->_user($frozen_user);
114 sub auth_restore_user {
115 my ( $c, $frozen_user, $store_name ) = @_;
118 unless $c->isa("Catalyst::Plugin::Session")
119 and $c->config->{authentication}{use_session}
122 $store_name ||= $c->session->{__user_store};
123 $frozen_user ||= $c->session->{__user};
125 my $store = $c->get_auth_store($store_name);
126 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
135 my $cfg = $c->config->{authentication} || {};
142 $c->register_auth_stores(
143 default => $cfg->{store},
144 %{ $cfg->{stores} || {} },
151 my ( $self, $name ) = @_;
152 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
155 sub get_auth_store_name {
156 my ( $self, $store ) = @_;
157 $self->auth_store_names->{$store};
160 sub register_auth_stores {
161 my ( $self, %new ) = @_;
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;
172 $self->_auth_stores(@_) || $self->_auth_stores( {} );
175 sub auth_store_names {
178 $self->_auth_store_names || do {
179 tie my %hash, 'Tie::RefHash';
180 $self->_auth_store_names( \%hash );
184 sub default_auth_store {
187 if ( my $new = shift ) {
188 $self->register_auth_stores( default => $new );
191 $self->get_auth_store("default");
202 Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
203 authentication framework.
209 Authentication::Store::Foo
210 Authentication::Credential::Password
214 # ->login is provided by the Credential::Password module
215 $c->login('myusername', 'mypassword');
216 my $age = $c->user->age;
221 The authentication plugin provides generic user support. It is the basis
222 for both authentication (checking the user is who they claim to be), and
223 authorization (allowing the user to do what the system authorises them to do).
225 Using authentication is split into two parts. A Store is used to actually
226 store the user information, and can store any amount of data related to
227 the user. Multiple stores can be accessed from within one application.
228 Credentials are used to verify users, using the store, given data from
231 To implement authentication in a catalyst application you need to add this
232 module, plus at least one store and one credential module.
234 Authentication data can also be stored in a session, if the application
235 is using the L<Catalyst::Plugin::Session> module.
243 Returns the currently logged in user or undef if there is none.
247 Whether or not a user is logged in right now.
249 The reason this method exists is that C<< $c->user >> may needlessly load the
250 user from the auth store.
252 If you're just going to say
254 if ( $c->user_user ) {
257 $c->forward("login");
260 it should be more efficient than C<< $c->user >> when a user is marked in the session
261 but C<< $c->user >> hasn't been called yet.
265 Delete the currently logged in user from C<user> and the session.
269 Fetch a particular users details, defined by the given ID, via the default store.
279 Whether or not to store the user's logged in state in the session, if the
280 application is also using the L<Catalyst::Plugin::Session> plugin. This
281 value is set to true per default.
285 If multiple stores are being used, set the module you want as default here.
289 If multiple stores are being used, you need to provide a name for each store
290 here, as a hash, the keys are the names you wish to use, and the values are
291 the the names of the plugins.
294 __PACKAGE__->config( authentication => {
295 store => 'Catalyst::Plugin::Authentication::Store::HtPasswd',
297 'dbic' => 'Catalyst::Plugin::Authentication::Store::DBIC'
303 =head1 METHODS FOR STORE MANAGEMENT
307 =item default_auth_store
309 Return the store whose name is 'default'.
311 This is set to C<< $c->config->{authentication}{store} >> if that value exists,
312 or by using a Store plugin:
314 use Catalyst qw/Authentication Authentication::Store::Minimal/;
316 Sets the default store to
317 L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>.
320 =item get_auth_store $name
322 Return the store whose name is $name.
324 =item get_auth_store_name $store
326 Return the name of the store $store.
330 A hash keyed by name, with the stores registered in the app.
332 =item auth_store_names
334 A ref-hash keyed by store, which contains the names of the stores.
336 =item register_auth_stores %stores_by_name
338 Register stores into the application.
342 =head1 INTERNAL METHODS
346 =item set_authenticated $user
348 Marks a user as authenticated. Should be called from a
349 C<Catalyst::Plugin::Authentication::Credential> plugin after successful
352 This involves setting C<user> and the internal data in C<session> if
353 L<Catalyst::Plugin::Session> is loaded.
355 =item auth_restore_user $user
357 Used to restore a user from the session, by C<user> only when it's actually
360 =item save_user_in_session $user
362 Used to save the user in a session.
366 Revives a user from the session object if there is one.
370 Sets the default configuration parameters.
378 L<Catalyst::Plugin::Authentication::Credential::Password>,
379 L<Catalyst::Plugin::Authentication::Store::Minimal>,
380 L<Catalyst::Plugin::Authorization::ACL>,
381 L<Catalyst::Plugin::Authorization::Roles>.
383 =head1 DON'T SEE ALSO
385 This module along with it's sub plugins deprecate a great number of other
386 modules. These include Catalyst::Plugin::Authentication::Simple,
387 Catalyst::Plugin::Authentication::CDBI.
389 At the time of writing these plugins have not yet been replaced or updated, but
390 should be eventually: Catalyst::Plugin::Authentication::OpenID,
391 Catalyst::Plugin::Authentication::LDAP,
392 Catalyst::Plugin::Authentication::CDBI::Basic,
393 Catalyst::Plugin::Authentication::Basic::Remote
397 Yuval Kogman, C<nothingmuch@woobling.org>
403 =head1 COPYRIGHT & LICNESE
405 Copyright (c) 2005 the aforementioned authors. All rights
406 reserved. This program is free software; you can redistribute
407 it and/or modify it under the same terms as Perl itself.