Don't attempt to restore in auth_restore_user unless there is already a session
[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
c7c003d3 18our $VERSION = "0.01";
19
06675d2e 20sub set_authenticated {
21 my ( $c, $user ) = @_;
22
23 $c->user($user);
e300c5b6 24 $c->request->{user} = $user; # compatibility kludge
06675d2e 25
26 if ( $c->isa("Catalyst::Plugin::Session")
96777f3a 27 and $c->config->{authentication}{use_session}
12dae309 28 and $user->supports("session") )
06675d2e 29 {
12dae309 30 $c->save_user_in_session($user);
06675d2e 31 }
55395841 32
33 $c->NEXT::set_authenticated( $user );
06675d2e 34}
35
7bb06c91 36sub user {
e300c5b6 37 my $c = shift;
7bb06c91 38
e300c5b6 39 if (@_) {
40 return $c->_user(@_);
41 }
7bb06c91 42
e300c5b6 43 my $user = $c->_user;
7bb06c91 44
e300c5b6 45 if ( $user and !Scalar::Util::blessed($user) ) {
46 return $c->auth_restore_user($user);
47 }
7bb06c91 48
e300c5b6 49 return $user;
7bb06c91 50}
51
12dae309 52sub save_user_in_session {
e300c5b6 53 my ( $c, $user ) = @_;
12dae309 54
55 my $store = $user->store || ref $user;
56 $c->session->{__user_store} = $c->get_auth_store_name($store) || $store;
57 $c->session->{__user} = $user->for_session;
58}
59
06675d2e 60sub logout {
61 my $c = shift;
62
63 $c->user(undef);
b003080b 64
65 if ( $c->isa("Catalyst::Plugin::Session")
66 and $c->config->{authentication}{use_session} )
67 {
96777f3a 68 delete @{ $c->session }{qw/__user __user_store/};
b003080b 69 }
06675d2e 70}
71
7d0922d8 72sub get_user {
73 my ( $c, $uid ) = @_;
74
75 if ( my $store = $c->default_auth_store ) {
76 return $store->get_user($uid);
77 }
78 else {
79 Catalyst::Exception->throw(
80 "The user id $uid was passed to an authentication "
81 . "plugin, but no default store was specified" );
82 }
83}
84
06675d2e 85sub prepare {
86 my $c = shift->NEXT::prepare(@_);
87
88 if ( $c->isa("Catalyst::Plugin::Session")
06675d2e 89 and !$c->user )
90 {
7bb06c91 91 if ( $c->sessionid and my $frozen_user = $c->session->{__user} ) {
e300c5b6 92 $c->_user($frozen_user);
06675d2e 93 }
94 }
95
96 return $c;
97}
98
7bb06c91 99sub auth_restore_user {
e300c5b6 100 my ( $c, $frozen_user, $store_name ) = @_;
7bb06c91 101
4402d92d 102 return unless $c->isa("Catalyst::PLugin::Session") and $c->config->{authentication}{use_session} and $c->sessionid;
103
e300c5b6 104 $store_name ||= $c->session->{__user_store};
105 $frozen_user ||= $c->session->{__user};
7bb06c91 106
e300c5b6 107 my $store = $c->get_auth_store($store_name);
108 $c->_user( my $user = $store->from_session( $c, $frozen_user ) );
7bb06c91 109
e300c5b6 110 return $user;
7bb06c91 111
112}
113
06675d2e 114sub setup {
115 my $c = shift;
116
712a35bf 117 my $cfg = $c->config->{authentication} || {};
06675d2e 118
119 %$cfg = (
120 use_session => 1,
121 %$cfg,
122 );
b003080b 123
12dae309 124 $c->register_auth_stores(
125 default => $cfg->{store},
126 %{ $cfg->{stores} || {} },
127 );
96777f3a 128
b003080b 129 $c->NEXT::setup(@_);
06675d2e 130}
131
96777f3a 132sub get_auth_store {
12dae309 133 my ( $self, $name ) = @_;
134 $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name );
96777f3a 135}
136
137sub get_auth_store_name {
12dae309 138 my ( $self, $store ) = @_;
139 $self->auth_store_names->{$store};
96777f3a 140}
141
142sub register_auth_stores {
12dae309 143 my ( $self, %new ) = @_;
96777f3a 144
12dae309 145 foreach my $name ( keys %new ) {
146 my $store = $new{$name} or next;
147 $self->auth_stores->{$name} = $store;
148 $self->auth_store_names->{$store} = $name;
149 }
96777f3a 150}
151
152sub auth_stores {
12dae309 153 my $self = shift;
154 $self->_auth_stores(@_) || $self->_auth_stores( {} );
96777f3a 155}
156
157sub auth_store_names {
12dae309 158 my $self = shift;
96777f3a 159
4402d92d 160 $self->_auth_store_names || do {
12dae309 161 tie my %hash, 'Tie::RefHash';
162 $self->_auth_store_names( \%hash );
163 }
96777f3a 164}
165
166sub default_auth_store {
12dae309 167 my $self = shift;
96777f3a 168
12dae309 169 if ( my $new = shift ) {
170 $self->register_auth_stores( default => $new );
171 }
96777f3a 172
12dae309 173 $self->get_auth_store("default");
96777f3a 174}
175
06675d2e 176__PACKAGE__;
177
178__END__
179
180=pod
181
182=head1 NAME
183
55395841 184Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst
185authentication framework.
06675d2e 186
187=head1 SYNOPSIS
188
189 use Catalyst qw/
190 Authentication
191 Authentication::Store::Foo
192 Authentication::Credential::Password
193 /;
194
195=head1 DESCRIPTION
196
197The authentication plugin is used by the various authentication and
198authorization plugins in catalyst.
199
55395841 200It defines the notion of a logged in user, and provides integration with the
201L<Catalyst::Plugin::Session> plugin,
06675d2e 202
203=head1 METHODS
204
205=over 4
206
06675d2e 207=item user
208
209Returns the currently logged user or undef if there is none.
210
4402d92d 211=item logout
212
213Delete the currently logged in user from C<user> and the session.
214
7d0922d8 215=item get_user $uid
216
217Delegate C<get_user> to the default store.
218
219=item default_auth_store
220
221Returns C<< $c->config->{authentication}{store} >>.
222
06675d2e 223=back
224
225=head1 INTERNAL METHODS
226
227=over 4
228
229=item set_authenticated $user
230
231Marks a user as authenticated. Should be called from a
232C<Catalyst::Plugin::Authentication::Credential> plugin after successful
233authentication.
234
235This involves setting C<user> and the internal data in C<session> if
236L<Catalyst::Plugin::Session> is loaded.
237
e300c5b6 238=item auth_restore_user $user
239
240Used to restore a user from the session, by C<user> only when it's actually
241needed.
242
243=item save_user_in_session $user
244
245Used to save the user in a session.
246
06675d2e 247=item prepare
248
249Revives a user from the session object if there is one.
250
251=item setup
252
253Sets the default configuration parameters.
254
255=item
256
257=back
258
259=head1 CONFIGURATION
260
261=over 4
262
263=item use_session
264
265Whether or not to store the user's logged in state in the session, if the
266application is also using the L<Catalyst::Plugin::Authentication> plugin.
267
268=back
269
270=cut
271
272