Commit | Line | Data |
06675d2e |
1 | #!/usr/bin/perl |
2 | |
3 | package Catalyst::Plugin::Authentication; |
4 | |
b003080b |
5 | use base qw/Class::Accessor::Fast Class::Data::Inheritable/; |
06675d2e |
6 | |
b003080b |
7 | BEGIN { |
7bb06c91 |
8 | __PACKAGE__->mk_accessors(qw/_user/); |
96777f3a |
9 | __PACKAGE__->mk_classdata($_) for qw/_auth_stores _auth_store_names/; |
b003080b |
10 | } |
06675d2e |
11 | |
12 | use strict; |
13 | use warnings; |
14 | |
96777f3a |
15 | use Tie::RefHash; |
12dae309 |
16 | use Class::Inspector; |
96777f3a |
17 | |
c7c003d3 |
18 | our $VERSION = "0.01"; |
19 | |
06675d2e |
20 | sub 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 | |
4fbe2e14 |
33 | $c->NEXT::set_authenticated($user); |
06675d2e |
34 | } |
35 | |
7bb06c91 |
36 | sub 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 |
52 | sub 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 |
60 | sub 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 |
72 | sub 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 |
85 | sub prepare { |
86 | my $c = shift->NEXT::prepare(@_); |
87 | |
4fbe2e14 |
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 |
99 | sub auth_restore_user { |
e300c5b6 |
100 | my ( $c, $frozen_user, $store_name ) = @_; |
7bb06c91 |
101 | |
4fbe2e14 |
102 | return |
103 | unless $c->isa("Catalyst::PLugin::Session") |
104 | and $c->config->{authentication}{use_session} |
105 | and $c->sessionid; |
4402d92d |
106 | |
e300c5b6 |
107 | $store_name ||= $c->session->{__user_store}; |
108 | $frozen_user ||= $c->session->{__user}; |
7bb06c91 |
109 | |
e300c5b6 |
110 | my $store = $c->get_auth_store($store_name); |
111 | $c->_user( my $user = $store->from_session( $c, $frozen_user ) ); |
7bb06c91 |
112 | |
e300c5b6 |
113 | return $user; |
7bb06c91 |
114 | |
115 | } |
116 | |
06675d2e |
117 | sub setup { |
118 | my $c = shift; |
119 | |
712a35bf |
120 | my $cfg = $c->config->{authentication} || {}; |
06675d2e |
121 | |
122 | %$cfg = ( |
123 | use_session => 1, |
124 | %$cfg, |
125 | ); |
b003080b |
126 | |
12dae309 |
127 | $c->register_auth_stores( |
128 | default => $cfg->{store}, |
129 | %{ $cfg->{stores} || {} }, |
130 | ); |
96777f3a |
131 | |
b003080b |
132 | $c->NEXT::setup(@_); |
06675d2e |
133 | } |
134 | |
96777f3a |
135 | sub get_auth_store { |
12dae309 |
136 | my ( $self, $name ) = @_; |
137 | $self->auth_stores->{$name} || ( Class::Inspector->loaded($name) && $name ); |
96777f3a |
138 | } |
139 | |
140 | sub get_auth_store_name { |
12dae309 |
141 | my ( $self, $store ) = @_; |
142 | $self->auth_store_names->{$store}; |
96777f3a |
143 | } |
144 | |
145 | sub register_auth_stores { |
12dae309 |
146 | my ( $self, %new ) = @_; |
96777f3a |
147 | |
12dae309 |
148 | foreach my $name ( keys %new ) { |
149 | my $store = $new{$name} or next; |
150 | $self->auth_stores->{$name} = $store; |
151 | $self->auth_store_names->{$store} = $name; |
152 | } |
96777f3a |
153 | } |
154 | |
155 | sub auth_stores { |
12dae309 |
156 | my $self = shift; |
157 | $self->_auth_stores(@_) || $self->_auth_stores( {} ); |
96777f3a |
158 | } |
159 | |
160 | sub auth_store_names { |
12dae309 |
161 | my $self = shift; |
96777f3a |
162 | |
4402d92d |
163 | $self->_auth_store_names || do { |
12dae309 |
164 | tie my %hash, 'Tie::RefHash'; |
165 | $self->_auth_store_names( \%hash ); |
4fbe2e14 |
166 | } |
96777f3a |
167 | } |
168 | |
169 | sub default_auth_store { |
12dae309 |
170 | my $self = shift; |
96777f3a |
171 | |
12dae309 |
172 | if ( my $new = shift ) { |
173 | $self->register_auth_stores( default => $new ); |
174 | } |
96777f3a |
175 | |
12dae309 |
176 | $self->get_auth_store("default"); |
96777f3a |
177 | } |
178 | |
06675d2e |
179 | __PACKAGE__; |
180 | |
181 | __END__ |
182 | |
183 | =pod |
184 | |
185 | =head1 NAME |
186 | |
55395841 |
187 | Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst |
188 | authentication framework. |
06675d2e |
189 | |
190 | =head1 SYNOPSIS |
191 | |
192 | use Catalyst qw/ |
193 | Authentication |
194 | Authentication::Store::Foo |
195 | Authentication::Credential::Password |
196 | /; |
197 | |
198 | =head1 DESCRIPTION |
199 | |
200 | The authentication plugin is used by the various authentication and |
201 | authorization plugins in catalyst. |
202 | |
55395841 |
203 | It defines the notion of a logged in user, and provides integration with the |
204 | L<Catalyst::Plugin::Session> plugin, |
06675d2e |
205 | |
206 | =head1 METHODS |
207 | |
208 | =over 4 |
209 | |
06675d2e |
210 | =item user |
211 | |
212 | Returns the currently logged user or undef if there is none. |
213 | |
4402d92d |
214 | =item logout |
215 | |
216 | Delete the currently logged in user from C<user> and the session. |
217 | |
7d0922d8 |
218 | =item get_user $uid |
219 | |
220 | Delegate C<get_user> to the default store. |
221 | |
4fbe2e14 |
222 | =back |
223 | |
224 | =head1 METHODS FOR STORE MANAGEMENT |
225 | |
7d0922d8 |
226 | =item default_auth_store |
227 | |
4fbe2e14 |
228 | Return the store whose name is 'default'. |
7d0922d8 |
229 | |
4fbe2e14 |
230 | This is set to C<<$c->config->{authentication}{store}>> if that value exists, |
231 | or by using a Store plugin: |
232 | |
233 | use Catalyst qw/Authentication Authentication::Store::Minimal/; |
234 | |
235 | Sets the default store to |
236 | L<Catalyst::Plugin::Authentication::Store::Minimal::Backend>. |
237 | |
238 | =item get_auth_store $name |
239 | |
240 | Return the store whose name is $name. |
241 | |
242 | =item get_auth_store_name $store |
243 | |
244 | Return the name of the store $store. |
245 | |
246 | =item auth_stores |
247 | |
248 | A hash keyed by name, with the stores registered in the app. |
249 | |
250 | =item auth_store_names |
251 | |
252 | A ref-hash keyed by store, which contains the names of the stores. |
253 | |
254 | =item register_auth_stores %stores_by_name |
255 | |
256 | Register stores into the application. |
06675d2e |
257 | |
258 | =head1 INTERNAL METHODS |
259 | |
260 | =over 4 |
261 | |
262 | =item set_authenticated $user |
263 | |
264 | Marks a user as authenticated. Should be called from a |
265 | C<Catalyst::Plugin::Authentication::Credential> plugin after successful |
266 | authentication. |
267 | |
268 | This involves setting C<user> and the internal data in C<session> if |
269 | L<Catalyst::Plugin::Session> is loaded. |
270 | |
e300c5b6 |
271 | =item auth_restore_user $user |
272 | |
273 | Used to restore a user from the session, by C<user> only when it's actually |
274 | needed. |
275 | |
276 | =item save_user_in_session $user |
277 | |
278 | Used to save the user in a session. |
279 | |
06675d2e |
280 | =item prepare |
281 | |
282 | Revives a user from the session object if there is one. |
283 | |
284 | =item setup |
285 | |
286 | Sets the default configuration parameters. |
287 | |
288 | =item |
289 | |
290 | =back |
291 | |
292 | =head1 CONFIGURATION |
293 | |
294 | =over 4 |
295 | |
296 | =item use_session |
297 | |
298 | Whether or not to store the user's logged in state in the session, if the |
299 | application is also using the L<Catalyst::Plugin::Authentication> plugin. |
300 | |
301 | =back |
302 | |
303 | =cut |
304 | |
305 | |