Commit | Line | Data |
06675d2e |
1 | package Catalyst::Plugin::Authentication; |
2 | |
c7b6526a |
3 | use base qw/Class::Accessor::Fast/; |
06675d2e |
4 | |
9c469e37 |
5 | __PACKAGE__->mk_accessors(qw/_user/); |
06675d2e |
6 | |
7 | use strict; |
8 | use warnings; |
9 | |
47cede3d |
10 | use MRO::Compat; |
96777f3a |
11 | use Tie::RefHash; |
12dae309 |
12 | use Class::Inspector; |
5c5af345 |
13 | use Catalyst::Authentication::Realm; |
96777f3a |
14 | |
6f5a33ae |
15 | our $VERSION = "0.10016"; |
c7c003d3 |
16 | |
06675d2e |
17 | sub set_authenticated { |
54c8dc06 |
18 | my ( $c, $user, $realmname ) = @_; |
06675d2e |
19 | |
20 | $c->user($user); |
e300c5b6 |
21 | $c->request->{user} = $user; # compatibility kludge |
06675d2e |
22 | |
54c8dc06 |
23 | if (!$realmname) { |
24 | $realmname = 'default'; |
06675d2e |
25 | } |
646ea5b1 |
26 | my $realm = $c->get_auth_realm($realmname); |
c7b6526a |
27 | |
646ea5b1 |
28 | if (!$realm) { |
29 | Catalyst::Exception->throw( |
30 | "set_authenticated called with nonexistant realm: '$realmname'."); |
31 | } |
646ea5b1 |
32 | $user->auth_realm($realm->name); |
8a7bd676 |
33 | |
c7b6526a |
34 | $c->persist_user(); |
35 | |
47cede3d |
36 | $c->maybe::next::method($user, $realmname); |
06675d2e |
37 | } |
38 | |
7bb06c91 |
39 | sub user { |
e300c5b6 |
40 | my $c = shift; |
7bb06c91 |
41 | |
e300c5b6 |
42 | if (@_) { |
43 | return $c->_user(@_); |
44 | } |
7bb06c91 |
45 | |
45c7644b |
46 | if ( defined($c->_user) ) { |
47 | return $c->_user; |
56e23e7a |
48 | } else { |
47c6643f |
49 | return $c->auth_restore_user; |
e300c5b6 |
50 | } |
7bb06c91 |
51 | } |
52 | |
54c8dc06 |
53 | # change this to allow specification of a realm - to verify the user is part of that realm |
8a7bd676 |
54 | # in addition to verifying that they exist. |
ce0b058d |
55 | sub user_exists { |
99747fe1 |
56 | my $c = shift; |
57 | return defined($c->_user) || defined($c->find_realm_for_persisted_user); |
56e23e7a |
58 | } |
59 | |
c7b6526a |
60 | # works like user_exists - except only returns true if user |
45c7644b |
61 | # exists AND is in the realm requested. |
62 | sub user_in_realm { |
63 | my ($c, $realmname) = @_; |
64 | |
65 | if (defined($c->_user)) { |
66 | return ($c->_user->auth_realm eq $realmname); |
45c7644b |
67 | } else { |
bf4d93a4 |
68 | my $realm = $c->find_realm_for_persisted_user; |
8a7bd676 |
69 | if ($realm) { |
70 | return ($realm->name eq $realmname); |
71 | } else { |
72 | return undef; |
73 | } |
45c7644b |
74 | } |
75 | } |
54c8dc06 |
76 | |
646ea5b1 |
77 | sub __old_save_user_in_session { |
e8919861 |
78 | my ( $c, $user, $realmname ) = @_; |
12dae309 |
79 | |
54c8dc06 |
80 | $c->session->{__user_realm} = $realmname; |
c7b6526a |
81 | |
45c7644b |
82 | # we want to ask the store for a user prepared for the session. |
54c8dc06 |
83 | # but older modules split this functionality between the user and the |
45c7644b |
84 | # store. We try the store first. If not, we use the old method. |
54c8dc06 |
85 | my $realm = $c->get_auth_realm($realmname); |
86 | if ($realm->{'store'}->can('for_session')) { |
87 | $c->session->{__user} = $realm->{'store'}->for_session($c, $user); |
88 | } else { |
89 | $c->session->{__user} = $user->for_session; |
90 | } |
12dae309 |
91 | } |
92 | |
8a7bd676 |
93 | sub persist_user { |
94 | my $c = shift; |
95 | |
96 | if ($c->user_exists) { |
c7b6526a |
97 | |
98 | ## if we have a valid session handler - we store the |
99 | ## realm in the session. If not - we have to hope that |
5812e0a3 |
100 | ## the realm can recognize its frozen user somehow. |
c7b6526a |
101 | if ($c->can('session') && |
102 | $c->config->{'Plugin::Authentication'}{'use_session'} && |
8a7bd676 |
103 | $c->session_is_valid) { |
c7b6526a |
104 | |
105 | $c->session->{'__user_realm'} = $c->_user->auth_realm; |
8a7bd676 |
106 | } |
c7b6526a |
107 | |
8a7bd676 |
108 | my $realm = $c->get_auth_realm($c->_user->auth_realm); |
c7b6526a |
109 | |
8a7bd676 |
110 | # used to call $realm->save_user_in_session |
111 | $realm->persist_user($c, $c->user); |
112 | } |
113 | } |
114 | |
115 | |
c7b6526a |
116 | ## this was a short lived method to update user information - |
8a7bd676 |
117 | ## you should use persist_user instead. |
118 | sub update_user_in_session { |
119 | my $c = shift; |
120 | |
121 | return $c->persist_user; |
122 | } |
123 | |
06675d2e |
124 | sub logout { |
125 | my $c = shift; |
126 | |
127 | $c->user(undef); |
b003080b |
128 | |
bf4d93a4 |
129 | my $realm = $c->find_realm_for_persisted_user; |
8a7bd676 |
130 | if ($realm) { |
131 | $realm->remove_persisted_user($c); |
b003080b |
132 | } |
c7b6526a |
133 | |
47cede3d |
134 | $c->maybe::next::method(@_); |
06675d2e |
135 | } |
136 | |
54c8dc06 |
137 | sub find_user { |
138 | my ( $c, $userinfo, $realmname ) = @_; |
c7b6526a |
139 | |
54c8dc06 |
140 | $realmname ||= 'default'; |
141 | my $realm = $c->get_auth_realm($realmname); |
c7b6526a |
142 | |
646ea5b1 |
143 | if (!$realm) { |
144 | Catalyst::Exception->throw( |
145 | "find_user called with nonexistant realm: '$realmname'."); |
7d0922d8 |
146 | } |
646ea5b1 |
147 | return $realm->find_user($userinfo, $c); |
7d0922d8 |
148 | } |
149 | |
c7b6526a |
150 | ## Consider making this a public method. - would make certain things easier when |
bf4d93a4 |
151 | ## dealing with things pre-auth restore. |
152 | sub find_realm_for_persisted_user { |
47c6643f |
153 | my $c = shift; |
c7b6526a |
154 | |
8a7bd676 |
155 | my $realm; |
622e71d9 |
156 | if ($c->can('session') |
7c4d44af |
157 | and $c->config->{'Plugin::Authentication'}{'use_session'} |
c7b6526a |
158 | and $c->session_is_valid |
8a7bd676 |
159 | and exists($c->session->{'__user_realm'})) { |
c7b6526a |
160 | |
8a7bd676 |
161 | $realm = $c->auth_realms->{$c->session->{'__user_realm'}}; |
162 | if ($realm->user_is_restorable($c)) { |
c7b6526a |
163 | return $realm; |
8a7bd676 |
164 | } |
165 | } else { |
166 | ## we have no choice but to ask each realm whether it has a persisted user. |
167 | foreach my $realmname (@{$c->_auth_realm_restore_order}) { |
9172af6d |
168 | my $realm = $c->auth_realms->{$realmname} |
169 | || Catalyst::Exception->throw("Could not find authentication realm '$realmname'"); |
170 | return $realm |
171 | if $realm->user_is_restorable($c); |
8a7bd676 |
172 | } |
173 | } |
174 | return undef; |
488433fd |
175 | } |
47c6643f |
176 | |
7bb06c91 |
177 | sub auth_restore_user { |
54c8dc06 |
178 | my ( $c, $frozen_user, $realmname ) = @_; |
7bb06c91 |
179 | |
8a7bd676 |
180 | my $realm; |
181 | if (defined($realmname)) { |
c7b6526a |
182 | $realm = $c->get_auth_realm($realmname); |
8a7bd676 |
183 | } else { |
bf4d93a4 |
184 | $realm = $c->find_realm_for_persisted_user; |
8a7bd676 |
185 | } |
bf4d93a4 |
186 | return undef unless $realm; # FIXME die unless? This is an internal inconsistency |
c7b6526a |
187 | |
8a7bd676 |
188 | $c->_user( my $user = $realm->restore_user( $c, $frozen_user ) ); |
c7b6526a |
189 | |
54c8dc06 |
190 | # this sets the realm the user originated in. |
9c469e37 |
191 | $user->auth_realm($realm->name) if $user; |
c7b6526a |
192 | |
e300c5b6 |
193 | return $user; |
7bb06c91 |
194 | |
195 | } |
196 | |
c7b6526a |
197 | # we can't actually do our setup in setup because the model has not yet been loaded. |
54c8dc06 |
198 | # So we have to trigger off of setup_finished. :-( |
06675d2e |
199 | sub setup { |
c5fbff80 |
200 | my $app = shift; |
06675d2e |
201 | |
c5fbff80 |
202 | $app->_authentication_initialize(); |
47cede3d |
203 | $app->next::method(@_); |
54c8dc06 |
204 | } |
205 | |
206 | ## the actual initialization routine. whee. |
207 | sub _authentication_initialize { |
c5fbff80 |
208 | my $app = shift; |
54c8dc06 |
209 | |
d6209239 |
210 | ## let's avoid recreating / configuring everything if we have already done it, eh? |
211 | if ($app->can('_auth_realms')) { return }; |
c5fbff80 |
212 | |
c7b6526a |
213 | ## make classdata where it is used. |
d6209239 |
214 | $app->mk_classdata( '_auth_realms' => {}); |
c7b6526a |
215 | |
216 | ## the order to attempt restore in - If we don't have session - we have |
217 | ## no way to be sure where a frozen user came from - so we have to |
218 | ## ask each realm if it can restore the user. Unfortunately it is possible |
219 | ## that multiple realms could restore the user from the data we have - |
220 | ## So we have to determine at setup time what order to ask the realms in. |
8a7bd676 |
221 | ## The default is to use the user_restore_priority values defined in the realm |
c7b6526a |
222 | ## config. if they are not defined - we go by alphabetical order. Note that |
8a7bd676 |
223 | ## the 'default' realm always gets first chance at it unless it is explicitly |
224 | ## placed elsewhere by user_restore_priority. Remember this only comes |
c7b6526a |
225 | ## into play if session is disabled. |
226 | |
8a7bd676 |
227 | $app->mk_classdata( '_auth_realm_restore_order' => []); |
bf4d93a4 |
228 | |
7c4d44af |
229 | my $cfg = $app->config->{'Plugin::Authentication'}; |
99747fe1 |
230 | my $realmshash; |
7c4d44af |
231 | if (!defined($cfg)) { |
232 | if (exists($app->config->{'authentication'})) { |
233 | $cfg = $app->config->{'authentication'}; |
234 | $app->config->{'Plugin::Authentication'} = $app->config->{'authentication'}; |
235 | } else { |
236 | $cfg = {}; |
237 | } |
bf4d93a4 |
238 | } else { |
99747fe1 |
239 | # the realmshash contains the various configured realms. By default this is |
240 | # the main $app->config->{'Plugin::Authentication'} hash - but if that is |
241 | # not defined, or there is a subkey {'realms'} then we use that. |
242 | $realmshash = $cfg; |
243 | } |
c7b6526a |
244 | |
99747fe1 |
245 | ## If we have a sub-key of {'realms'} then we use that for realm configuration |
246 | if (exists($cfg->{'realms'})) { |
247 | $realmshash = $cfg->{'realms'}; |
248 | } |
06675d2e |
249 | |
7c4d44af |
250 | # old default was to force use_session on. This must remain for that |
5812e0a3 |
251 | # reason - but if use_session is already in the config, we respect its setting. |
7c4d44af |
252 | if (!exists($cfg->{'use_session'})) { |
253 | $cfg->{'use_session'} = 1; |
254 | } |
c7b6526a |
255 | |
256 | ## if we have a realms hash |
bf4d93a4 |
257 | if (ref($realmshash) eq 'HASH') { |
c7b6526a |
258 | |
8a7bd676 |
259 | my %auth_restore_order; |
260 | my $authcount = 2; |
261 | my $defaultrealm = 'default'; |
c7b6526a |
262 | |
bf4d93a4 |
263 | foreach my $realm (sort keys %{$realmshash}) { |
264 | if (ref($realmshash->{$realm}) eq 'HASH' && |
99747fe1 |
265 | (exists($realmshash->{$realm}{credential}) || exists($realmshash->{$realm}{class}))) { |
c7b6526a |
266 | |
99747fe1 |
267 | $app->setup_auth_realm($realm, $realmshash->{$realm}); |
c7b6526a |
268 | |
99747fe1 |
269 | if (exists($realmshash->{$realm}{'user_restore_priority'})) { |
270 | $auth_restore_order{$realm} = $realmshash->{$realm}{'user_restore_priority'}; |
271 | } else { |
272 | $auth_restore_order{$realm} = $authcount++; |
273 | } |
274 | } |
54c8dc06 |
275 | } |
c7b6526a |
276 | |
277 | # if we have a 'default_realm' in the config hash and we don't already |
54c8dc06 |
278 | # have a realm called 'default', we point default at the realm specified |
c5fbff80 |
279 | if (exists($cfg->{'default_realm'}) && !$app->get_auth_realm('default')) { |
8a7bd676 |
280 | if ($app->_set_default_auth_realm($cfg->{'default_realm'})) { |
281 | $defaultrealm = $cfg->{'default_realm'}; |
282 | $auth_restore_order{'default'} = $auth_restore_order{$cfg->{'default_realm'}}; |
283 | delete($auth_restore_order{$cfg->{'default_realm'}}); |
284 | } |
54c8dc06 |
285 | } |
c7b6526a |
286 | |
5812e0a3 |
287 | ## if the default realm did not have a defined priority in its config - we put it at the front. |
bf4d93a4 |
288 | if (!exists($realmshash->{$defaultrealm}{'user_restore_priority'})) { |
8a7bd676 |
289 | $auth_restore_order{'default'} = 1; |
290 | } |
c7b6526a |
291 | |
8a7bd676 |
292 | @{$app->_auth_realm_restore_order} = sort { $auth_restore_order{$a} <=> $auth_restore_order{$b} } keys %auth_restore_order; |
c7b6526a |
293 | |
54c8dc06 |
294 | } else { |
c7b6526a |
295 | |
58db3441 |
296 | ## BACKWARDS COMPATIBILITY - if realms is not defined - then we are probably dealing |
c5fbff80 |
297 | ## with an old-school config. The only caveat here is that we must add a classname |
c7b6526a |
298 | |
299 | ## also - we have to treat {store} as {stores}{default} - because |
300 | ## while it is not a clear as a valid config in the docs, it |
58db3441 |
301 | ## is functional with the old api. Whee! |
302 | if (exists($cfg->{'store'}) && !exists($cfg->{'stores'}{'default'})) { |
303 | $cfg->{'stores'}{'default'} = $cfg->{'store'}; |
304 | } |
305 | |
8a7bd676 |
306 | push @{$app->_auth_realm_restore_order}, 'default'; |
54c8dc06 |
307 | foreach my $storename (keys %{$cfg->{'stores'}}) { |
308 | my $realmcfg = { |
58db3441 |
309 | store => { class => $cfg->{'stores'}{$storename} }, |
54c8dc06 |
310 | }; |
c5fbff80 |
311 | $app->setup_auth_realm($storename, $realmcfg); |
54c8dc06 |
312 | } |
c7b6526a |
313 | } |
314 | |
06675d2e |
315 | } |
316 | |
54c8dc06 |
317 | # set up realmname. |
318 | sub setup_auth_realm { |
319 | my ($app, $realmname, $config) = @_; |
c7b6526a |
320 | |
e05c457e |
321 | my $realmclass = $config->{class}; |
322 | |
323 | if( !$realmclass ) { |
5c5af345 |
324 | $realmclass = 'Catalyst::Authentication::Realm'; |
e05c457e |
325 | } elsif ($realmclass !~ /^\+(.*)$/ ) { |
5c5af345 |
326 | $realmclass = "Catalyst::Authentication::Realm::${realmclass}"; |
e05c457e |
327 | } else { |
328 | $realmclass = $1; |
54c8dc06 |
329 | } |
e05c457e |
330 | |
331 | Catalyst::Utils::ensure_class_loaded( $realmclass ); |
332 | |
646ea5b1 |
333 | my $realm = $realmclass->new($realmname, $config, $app); |
334 | if ($realm) { |
335 | $app->auth_realms->{$realmname} = $realm; |
58db3441 |
336 | } else { |
646ea5b1 |
337 | $app->log->debug("realm initialization for '$realmname' failed."); |
58db3441 |
338 | } |
646ea5b1 |
339 | return $realm; |
96777f3a |
340 | } |
341 | |
54c8dc06 |
342 | sub auth_realms { |
343 | my $self = shift; |
3fd45491 |
344 | $self->_authentication_initialize(); # Ensure _auth_realms created! |
54c8dc06 |
345 | return($self->_auth_realms); |
96777f3a |
346 | } |
347 | |
54c8dc06 |
348 | sub get_auth_realm { |
349 | my ($app, $realmname) = @_; |
350 | return $app->auth_realms->{$realmname}; |
351 | } |
96777f3a |
352 | |
e8919861 |
353 | |
354 | # Very internal method. Vital Valuable Urgent, Do not touch on pain of death. |
355 | # Using this method just assigns the default realm to be the value associated |
356 | # with the realmname provided. It WILL overwrite any real realm called 'default' |
c7b6526a |
357 | # so can be very confusing if used improperly. It's used properly already. |
e8919861 |
358 | # Translation: don't use it. |
359 | sub _set_default_auth_realm { |
54c8dc06 |
360 | my ($app, $realmname) = @_; |
c7b6526a |
361 | |
54c8dc06 |
362 | if (exists($app->auth_realms->{$realmname})) { |
363 | $app->auth_realms->{'default'} = $app->auth_realms->{$realmname}; |
12dae309 |
364 | } |
54c8dc06 |
365 | return $app->get_auth_realm('default'); |
96777f3a |
366 | } |
367 | |
54c8dc06 |
368 | sub authenticate { |
369 | my ($app, $userinfo, $realmname) = @_; |
c7b6526a |
370 | |
54c8dc06 |
371 | if (!$realmname) { |
372 | $realmname = 'default'; |
373 | } |
c7b6526a |
374 | |
54c8dc06 |
375 | my $realm = $app->get_auth_realm($realmname); |
c7b6526a |
376 | |
45c7644b |
377 | ## note to self - make authenticate throw an exception if realm is invalid. |
c7b6526a |
378 | |
646ea5b1 |
379 | if ($realm) { |
380 | return $realm->authenticate($app, $userinfo); |
54c8dc06 |
381 | } else { |
646ea5b1 |
382 | Catalyst::Exception->throw( |
383 | "authenticate called with nonexistant realm: '$realmname'."); |
384 | |
54c8dc06 |
385 | } |
0cc778ab |
386 | return undef; |
96777f3a |
387 | } |
388 | |
54c8dc06 |
389 | ## BACKWARDS COMPATIBILITY -- Warning: Here be monsters! |
390 | # |
391 | # What follows are backwards compatibility routines - for use with Stores and Credentials |
c7b6526a |
392 | # that have not been updated to work with C::P::Authentication v0.10. |
54c8dc06 |
393 | # These are here so as to not break people's existing installations, but will go away |
394 | # in a future version. |
395 | # |
396 | # The old style of configuration only supports a single store, as each store module |
c7b6526a |
397 | # sets itself as the default store upon being loaded. This is the only supported |
398 | # 'compatibility' mode. |
54c8dc06 |
399 | # |
400 | |
401 | sub get_user { |
402 | my ( $c, $uid, @rest ) = @_; |
96777f3a |
403 | |
54c8dc06 |
404 | return $c->find_user( {'id' => $uid, 'rest'=>\@rest }, 'default' ); |
96777f3a |
405 | } |
406 | |
e8919861 |
407 | |
54c8dc06 |
408 | ## this should only be called when using old-style authentication plugins. IF this gets |
409 | ## called in a new-style config - it will OVERWRITE the store of your default realm. Don't do it. |
410 | ## also - this is a partial setup - because no credential is instantiated... in other words it ONLY |
411 | ## works with old-style auth plugins and C::P::Authentication in compatibility mode. Trying to combine |
412 | ## this with a realm-type config will probably crash your app. |
96777f3a |
413 | sub default_auth_store { |
12dae309 |
414 | my $self = shift; |
96777f3a |
415 | |
646ea5b1 |
416 | my $realm = $self->get_auth_realm('default'); |
417 | if (!$realm) { |
e05c457e |
418 | $realm = $self->setup_auth_realm('default', { class => 'Compatibility' }); |
646ea5b1 |
419 | } |
12dae309 |
420 | if ( my $new = shift ) { |
646ea5b1 |
421 | $realm->store($new); |
c7b6526a |
422 | |
58db3441 |
423 | my $storeclass; |
424 | if (ref($new)) { |
425 | $storeclass = ref($new); |
426 | } else { |
427 | $storeclass = $new; |
428 | } |
c7b6526a |
429 | |
430 | # BACKWARDS COMPATIBILITY - if the store class does not define find_user, we define it in terms |
431 | # of get_user and add it to the class. this is because the auth routines use find_user, |
54c8dc06 |
432 | # and rely on it being present. (this avoids per-call checks) |
433 | if (!$storeclass->can('find_user')) { |
434 | no strict 'refs'; |
435 | *{"${storeclass}::find_user"} = sub { |
436 | my ($self, $info) = @_; |
437 | my @rest = @{$info->{rest}} if exists($info->{rest}); |
438 | $self->get_user($info->{id}, @rest); |
439 | }; |
440 | } |
12dae309 |
441 | } |
96777f3a |
442 | |
646ea5b1 |
443 | return $self->get_auth_realm('default')->store; |
96777f3a |
444 | } |
445 | |
54c8dc06 |
446 | ## BACKWARDS COMPATIBILITY |
447 | ## this only ever returns a hash containing 'default' - as that is the only |
448 | ## supported mode of calling this. |
449 | sub auth_store_names { |
450 | my $self = shift; |
451 | |
646ea5b1 |
452 | my %hash = ( $self->get_auth_realm('default')->store => 'default' ); |
54c8dc06 |
453 | } |
454 | |
455 | sub get_auth_store { |
456 | my ( $self, $name ) = @_; |
c7b6526a |
457 | |
54c8dc06 |
458 | if ($name ne 'default') { |
c7b6526a |
459 | Carp::croak "get_auth_store called on non-default realm '$name'. Only default supported in compatibility mode"; |
54c8dc06 |
460 | } else { |
461 | $self->default_auth_store(); |
462 | } |
463 | } |
464 | |
465 | sub get_auth_store_name { |
466 | my ( $self, $store ) = @_; |
467 | return 'default'; |
468 | } |
469 | |
470 | # sub auth_stores is only used internally - here for completeness |
471 | sub auth_stores { |
472 | my $self = shift; |
473 | |
646ea5b1 |
474 | my %hash = ( 'default' => $self->get_auth_realm('default')->store); |
54c8dc06 |
475 | } |
476 | |
06675d2e |
477 | __PACKAGE__; |
478 | |
479 | __END__ |
480 | |
481 | =pod |
482 | |
483 | =head1 NAME |
484 | |
55395841 |
485 | Catalyst::Plugin::Authentication - Infrastructure plugin for the Catalyst |
486 | authentication framework. |
06675d2e |
487 | |
488 | =head1 SYNOPSIS |
489 | |
189b5b0c |
490 | use Catalyst qw/ |
491 | Authentication |
189b5b0c |
492 | /; |
493 | |
494 | # later on ... |
c7b6526a |
495 | $c->authenticate({ username => 'myusername', |
c5fbff80 |
496 | password => 'mypassword' }); |
54c8dc06 |
497 | my $age = $c->user->get('age'); |
189b5b0c |
498 | $c->logout; |
06675d2e |
499 | |
500 | =head1 DESCRIPTION |
501 | |
16ef3eb8 |
502 | The authentication plugin provides generic user support for Catalyst apps. It |
503 | is the basis for both authentication (checking the user is who they claim to |
504 | be), and authorization (allowing the user to do what the system authorises |
505 | them to do). |
506 | |
507 | Using authentication is split into two parts. A Store is used to actually |
508 | store the user information, and can store any amount of data related to the |
509 | user. Credentials are used to verify users, using information from the store, |
510 | given data from the frontend. A Credential and a Store are paired to form a |
e8919861 |
511 | 'Realm'. A Catalyst application using the authentication framework must have |
512 | at least one realm, and may have several. |
189b5b0c |
513 | |
c7b6526a |
514 | To implement authentication in a Catalyst application you need to add this |
515 | module, and specify at least one realm in the configuration. |
189b5b0c |
516 | |
c7b6526a |
517 | Authentication data can also be stored in a session, if the application |
e7522758 |
518 | is using the L<Catalyst::Plugin::Session> module. |
06675d2e |
519 | |
30e90c6f |
520 | B<NOTE> in version 0.10 of this module, the interface to this module changed. |
521 | Please see L</COMPATIBILITY ROUTINES> for more information. |
e8919861 |
522 | |
4bb9b01c |
523 | =head1 INTRODUCTION |
524 | |
525 | =head2 The Authentication/Authorization Process |
526 | |
527 | Web applications typically need to identify a user - to tell the user apart |
528 | from other users. This is usually done in order to display private information |
529 | that is only that user's business, or to limit access to the application so |
530 | that only certain entities can access certain parts. |
531 | |
532 | This process is split up into several steps. First you ask the user to identify |
533 | themselves. At this point you can't be sure that the user is really who they |
534 | claim to be. |
535 | |
6a36933d |
536 | Then the user tells you who they are, and backs this claim with some piece of |
4bb9b01c |
537 | information that only the real user could give you. For example, a password is |
538 | a secret that is known to both the user and you. When the user tells you this |
539 | password you can assume they're in on the secret and can be trusted (ignore |
540 | identity theft for now). Checking the password, or any other proof is called |
541 | B<credential verification>. |
542 | |
543 | By this time you know exactly who the user is - the user's identity is |
16ef3eb8 |
544 | B<authenticated>. This is where this module's job stops, and your application |
c7b6526a |
545 | or other plugins step in. |
16ef3eb8 |
546 | |
547 | The next logical step is B<authorization>, the process of deciding what a user |
548 | is (or isn't) allowed to do. For example, say your users are split into two |
549 | main groups - regular users and administrators. You want to verify that the |
4bb9b01c |
550 | currently logged in user is indeed an administrator before performing the |
c5fbff80 |
551 | actions in an administrative part of your application. These decisions may be |
16ef3eb8 |
552 | made within your application code using just the information available after |
c7b6526a |
553 | authentication, or it may be facilitated by a number of plugins. |
4bb9b01c |
554 | |
555 | =head2 The Components In This Framework |
556 | |
62f27384 |
557 | =head3 Realms |
558 | |
559 | Configuration of the Catalyst::Plugin::Authentication framework is done in |
560 | terms of realms. In simplest terms, a realm is a pairing of a Credential |
5afc0dde |
561 | verifier and a User storage (Store) backend. As of version 0.10003, realms are |
562 | now objects that you can create and customize. |
62f27384 |
563 | |
564 | An application can have any number of Realms, each of which operates |
34088132 |
565 | independent of the others. Each realm has a name, which is used to identify it |
62f27384 |
566 | as the target of an authentication request. This name can be anything, such as |
567 | 'users' or 'members'. One realm must be defined as the default_realm, which is |
16ef3eb8 |
568 | used when no realm name is specified. More information about configuring |
569 | realms is available in the configuration section. |
62f27384 |
570 | |
4bb9b01c |
571 | =head3 Credential Verifiers |
572 | |
4e86cf54 |
573 | When user input is transferred to the L<Catalyst> application |
574 | (typically via form inputs) the application may pass this information |
e979170b |
575 | into the authentication system through the C<< $c->authenticate() >> |
4e86cf54 |
576 | method. From there, it is passed to the appropriate Credential |
577 | verifier. |
4bb9b01c |
578 | |
579 | These plugins check the data, and ensure that it really proves the user is who |
580 | they claim to be. |
581 | |
4e86cf54 |
582 | Credential verifiers compatible with versions of this module 0.10x and |
583 | upwards should be in the namespace |
584 | C<Catalyst::Authentication::Credential>. |
585 | |
4bb9b01c |
586 | =head3 Storage Backends |
587 | |
45c7644b |
588 | The authentication data also identifies a user, and the Storage backend modules |
62f27384 |
589 | use this data to locate and return a standardized object-oriented |
590 | representation of a user. |
4bb9b01c |
591 | |
592 | When a user is retrieved from a store it is not necessarily authenticated. |
62f27384 |
593 | Credential verifiers accept a set of authentication data and use this |
594 | information to retrieve the user from the store they are paired with. |
4bb9b01c |
595 | |
34088132 |
596 | Storage backends compatible with versions of this module 0.10x and |
4e86cf54 |
597 | upwards should be in the namespace |
598 | C<Catalyst::Authentication::Store>. |
599 | |
4bb9b01c |
600 | =head3 The Core Plugin |
601 | |
62f27384 |
602 | This plugin on its own is the glue, providing realm configuration, session |
4bb9b01c |
603 | integration, and other goodness for the other plugins. |
604 | |
605 | =head3 Other Plugins |
606 | |
607 | More layers of plugins can be stacked on top of the authentication code. For |
608 | example, L<Catalyst::Plugin::Session::PerUser> provides an abstraction of |
4e86cf54 |
609 | browser sessions that is more persistent per user. |
4bb9b01c |
610 | L<Catalyst::Plugin::Authorization::Roles> provides an accepted way to separate |
611 | and group users into categories, and then check which categories the current |
612 | user belongs to. |
613 | |
5e91c057 |
614 | =head1 EXAMPLE |
615 | |
34088132 |
616 | Let's say we were storing users in a simple Perl hash. Users are |
16ef3eb8 |
617 | verified by supplying a password which is matched within the hash. |
5e91c057 |
618 | |
619 | This means that our application will begin like this: |
620 | |
621 | package MyApp; |
622 | |
623 | use Catalyst qw/ |
624 | Authentication |
5e91c057 |
625 | /; |
626 | |
c7b6526a |
627 | __PACKAGE__->config( 'Plugin::Authentication' => |
628 | { |
bf4d93a4 |
629 | default => { |
630 | credential => { |
631 | class => 'Password', |
632 | password_field => 'password', |
633 | password_type => 'clear' |
634 | }, |
635 | store => { |
636 | class => 'Minimal', |
99747fe1 |
637 | users => { |
638 | bob => { |
639 | password => "s00p3r", |
640 | editor => 'yes', |
641 | roles => [qw/edit delete/], |
642 | }, |
643 | william => { |
644 | password => "s3cr3t", |
645 | roles => [qw/comment/], |
646 | } |
647 | } |
648 | } |
649 | } |
c83ea211 |
650 | } |
651 | ); |
5e91c057 |
652 | |
16ef3eb8 |
653 | This tells the authentication plugin what realms are available, which |
654 | credential and store modules are used, and the configuration of each. With |
655 | this code loaded, we can now attempt to authenticate users. |
5e91c057 |
656 | |
62f27384 |
657 | To show an example of this, let's create an authentication controller: |
5e91c057 |
658 | |
659 | package MyApp::Controller::Auth; |
660 | |
661 | sub login : Local { |
662 | my ( $self, $c ) = @_; |
663 | |
4e143b06 |
664 | if ( my $user = $c->req->params->{user} |
34088132 |
665 | and my $password = $c->req->params->{password} ) |
5e91c057 |
666 | { |
c7b6526a |
667 | if ( $c->authenticate( { username => $user, |
62f27384 |
668 | password => $password } ) ) { |
669 | $c->res->body( "hello " . $c->user->get("name") ); |
5e91c057 |
670 | } else { |
671 | # login incorrect |
672 | } |
673 | } |
674 | else { |
675 | # invalid form input |
676 | } |
677 | } |
678 | |
4e86cf54 |
679 | This code should be self-explanatory. If all the necessary fields are supplied, |
c7b6526a |
680 | call the C<authenticate> method on the context object. If it succeeds the |
c5fbff80 |
681 | user is logged in. |
5e91c057 |
682 | |
4e86cf54 |
683 | The credential verifier will attempt to retrieve the user whose |
684 | details match the authentication information provided to |
e979170b |
685 | C<< $c->authenticate() >>. Once it fetches the user the password is |
4e86cf54 |
686 | checked and if it matches the user will be B<authenticated> and |
e979170b |
687 | C<< $c->user >> will contain the user object retrieved from the store. |
5e91c057 |
688 | |
62f27384 |
689 | In the above case, the default realm is checked, but we could just as easily |
690 | check an alternate realm. If this were an admin login, for example, we could |
e979170b |
691 | authenticate on the admin realm by simply changing the C<< $c->authenticate() >> |
62f27384 |
692 | call: |
5e91c057 |
693 | |
c7b6526a |
694 | if ( $c->authenticate( { username => $user, |
4e86cf54 |
695 | password => $password }, 'admin' ) ) { |
62f27384 |
696 | $c->res->body( "hello " . $c->user->get("name") ); |
697 | } ... |
5e91c057 |
698 | |
5e91c057 |
699 | |
c7b6526a |
700 | Now suppose we want to restrict the ability to edit to a user with an |
c5fbff80 |
701 | 'editor' value of yes. |
5e91c057 |
702 | |
62f27384 |
703 | The restricted action might look like this: |
5e91c057 |
704 | |
62f27384 |
705 | sub edit : Local { |
5e91c057 |
706 | my ( $self, $c ) = @_; |
707 | |
708 | $c->detach("unauthorized") |
709 | unless $c->user_exists |
c5fbff80 |
710 | and $c->user->get('editor') eq 'yes'; |
5e91c057 |
711 | |
712 | # do something restricted here |
713 | } |
714 | |
4e86cf54 |
715 | (Note that if you have multiple realms, you can use |
e979170b |
716 | C<< $c->user_in_realm('realmname') >> in place of |
717 | C<< $c->user_exists(); >> This will essentially perform the same |
4e86cf54 |
718 | verification as user_exists, with the added requirement that if there |
719 | is a user, it must have come from the realm specified.) |
c5fbff80 |
720 | |
c7b6526a |
721 | The above example is somewhat similar to role based access control. |
5c5af345 |
722 | L<Catalyst::Authentication::Store::Minimal> treats the roles field as |
62f27384 |
723 | an array of role names. Let's leverage this. Add the role authorization |
724 | plugin: |
5e91c057 |
725 | |
726 | use Catalyst qw/ |
727 | ... |
728 | Authorization::Roles |
729 | /; |
730 | |
62f27384 |
731 | sub edit : Local { |
5e91c057 |
732 | my ( $self, $c ) = @_; |
733 | |
128321cc |
734 | $c->detach("unauthorized") unless $c->check_user_roles("edit"); |
5e91c057 |
735 | |
736 | # do something restricted here |
737 | } |
738 | |
739 | This is somewhat simpler and will work if you change your store, too, since the |
740 | role interface is consistent. |
741 | |
34088132 |
742 | Let's say your app grows, and you now have 10,000 users. It's no longer |
0cc778ab |
743 | efficient to maintain a hash of users, so you move this data to a database. |
4e86cf54 |
744 | You can accomplish this simply by installing the L<DBIx::Class|Catalyst::Authentication::Store::DBIx::Class> Store and |
0cc778ab |
745 | changing your config: |
5e91c057 |
746 | |
47074ecb |
747 | __PACKAGE__->config( 'Plugin::Authentication' => |
c7b6526a |
748 | { |
0cc778ab |
749 | default_realm => 'members', |
0cc778ab |
750 | members => { |
751 | credential => { |
c5fbff80 |
752 | class => 'Password', |
753 | password_field => 'password', |
754 | password_type => 'clear' |
0cc778ab |
755 | }, |
756 | store => { |
757 | class => 'DBIx::Class', |
99747fe1 |
758 | user_model => 'MyApp::Users', |
759 | role_column => 'roles', |
760 | } |
761 | } |
c83ea211 |
762 | } |
763 | ); |
bf4d93a4 |
764 | |
765 | The authentication system works behind the scenes to load your data from the |
766 | new source. The rest of your application is completely unchanged. |
767 | |
768 | |
769 | =head1 CONFIGURATION |
770 | |
771 | # example |
c7b6526a |
772 | __PACKAGE__->config( 'Plugin::Authentication' => |
773 | { |
bf4d93a4 |
774 | default_realm => 'members', |
775 | |
776 | members => { |
777 | credential => { |
778 | class => 'Password', |
779 | password_field => 'password', |
780 | password_type => 'clear' |
781 | }, |
782 | store => { |
783 | class => 'DBIx::Class', |
99747fe1 |
784 | user_model => 'MyApp::Users', |
785 | role_column => 'roles', |
786 | } |
787 | }, |
788 | admins => { |
789 | credential => { |
790 | class => 'Password', |
791 | password_field => 'password', |
bf4d93a4 |
792 | password_type => 'clear' |
99747fe1 |
793 | }, |
794 | store => { |
795 | class => '+MyApp::Authentication::Store::NetAuth', |
796 | authserver => '192.168.10.17' |
797 | } |
798 | } |
c83ea211 |
799 | } |
800 | ); |
0cc778ab |
801 | |
03a89311 |
802 | NOTE: Until version 0.10008 of this module, you would need to put all the |
c7b6526a |
803 | realms inside a "realms" key in the configuration. Please see |
ff87fb62 |
804 | L</COMPATIBILITY CONFIGURATION> for more information |
03a89311 |
805 | |
078c2289 |
806 | =over 4 |
807 | |
189b5b0c |
808 | =item use_session |
809 | |
810 | Whether or not to store the user's logged in state in the session, if the |
0c4fbc79 |
811 | application is also using L<Catalyst::Plugin::Session>. This |
e7522758 |
812 | value is set to true per default. |
813 | |
0c4fbc79 |
814 | However, even if use_session is disabled, if any code touches $c->session, a session |
815 | object will be auto-vivified and session Cookies will be sent in the headers. To |
816 | prevent accidental session creation, check if a session already exists with |
817 | if ($c->sessionid) { ... }. If the session doesn't exist, then don't place |
818 | anything in the session to prevent an unecessary session from being created. |
819 | |
0cc778ab |
820 | =item default_realm |
fe4cf44a |
821 | |
0cc778ab |
822 | This defines which realm should be used as when no realm is provided to methods |
823 | that require a realm such as authenticate or find_user. |
7d0922d8 |
824 | |
bf4d93a4 |
825 | =item realm refs |
7d0922d8 |
826 | |
c7b6526a |
827 | The Plugin::Authentication config hash contains the series of realm |
828 | configurations you want to use for your app. The only rule here is |
829 | that there must be at least one. A realm consists of a name, which is used |
830 | to reference the realm, a credential and a store. You may also put your |
831 | realm configurations within a subelement called 'realms' if you desire to |
bf4d93a4 |
832 | separate them from the remainder of your configuration. Note that if you use |
c7b6526a |
833 | a 'realms' subelement, you must put ALL of your realms within it. |
4fbe2e14 |
834 | |
7c3d201d |
835 | You can also specify a realm class to instantiate instead of the default |
836 | L<Catalyst::Authentication::Realm> class using the 'class' element within the |
837 | realm config. |
5afc0dde |
838 | |
c7b6526a |
839 | Each realm config contains two hashes, one called 'credential' and one called |
0cc778ab |
840 | 'store', each of which provide configuration details to the respective modules. |
c7b6526a |
841 | The contents of these hashes is specific to the module being used, with the |
0cc778ab |
842 | exception of the 'class' element, which tells the core Authentication module the |
c7b6526a |
843 | classname to instantiate. |
4fbe2e14 |
844 | |
0cc778ab |
845 | The 'class' element follows the standard Catalyst mechanism of class |
846 | specification. If a class is prefixed with a +, it is assumed to be a complete |
847 | class name. Otherwise it is considered to be a portion of the class name. For |
e8919861 |
848 | credentials, the classname 'B<Password>', for example, is expanded to |
5c5af345 |
849 | Catalyst::Authentication::Credential::B<Password>. For stores, the |
e8919861 |
850 | classname 'B<storename>' is expanded to: |
5c5af345 |
851 | Catalyst::Authentication::Store::B<storename>. |
4fbe2e14 |
852 | |
fe4cf44a |
853 | =back |
854 | |
e8919861 |
855 | =head1 METHODS |
856 | |
34088132 |
857 | =head2 $c->authenticate( $userinfo [, $realm ]) |
e8919861 |
858 | |
859 | Attempts to authenticate the user using the information in the $userinfo hash |
860 | reference using the realm $realm. $realm may be omitted, in which case the |
861 | default realm is checked. |
862 | |
4e86cf54 |
863 | =head2 $c->user( ) |
e8919861 |
864 | |
34088132 |
865 | Returns the currently logged in user, or undef if there is none. |
e8919861 |
866 | |
4e86cf54 |
867 | =head2 $c->user_exists( ) |
e8919861 |
868 | |
869 | Returns true if a user is logged in right now. The difference between |
870 | user_exists and user is that user_exists will return true if a user is logged |
45c7644b |
871 | in, even if it has not been yet retrieved from the storage backend. If you only |
e8919861 |
872 | need to know if the user is logged in, depending on the storage mechanism this |
873 | can be much more efficient. |
874 | |
4e86cf54 |
875 | =head2 $c->user_in_realm( $realm ) |
45c7644b |
876 | |
c7b6526a |
877 | Works like user_exists, except that it only returns true if a user is both |
878 | logged in right now and was retrieved from the realm provided. |
45c7644b |
879 | |
4e86cf54 |
880 | =head2 $c->logout( ) |
e8919861 |
881 | |
18b5ff80 |
882 | Logs the user out. Deletes the currently logged in user from C<< $c->user >> |
883 | and the session. It does not delete the session. |
e8919861 |
884 | |
4e86cf54 |
885 | =head2 $c->find_user( $userinfo, $realm ) |
e8919861 |
886 | |
c7b6526a |
887 | Fetch a particular users details, matching the provided user info, from the realm |
e8919861 |
888 | specified in $realm. |
889 | |
8a7bd676 |
890 | =head2 persist_user() |
891 | |
892 | Under normal circumstances the user data is only saved to the session during |
c7b6526a |
893 | initial authentication. This call causes the auth system to save the |
34088132 |
894 | currently authenticated user's data across requests. Useful if you have |
8a7bd676 |
895 | changed the user data and want to ensure that future requests reflect the |
c7b6526a |
896 | most current data. Assumes that at the time of this call, $c->user |
8a7bd676 |
897 | contains the most current data. |
898 | |
95114c34 |
899 | =head2 find_realm_for_persisted_user() |
900 | |
901 | Private method, do not call from user code! |
902 | |
06675d2e |
903 | =head1 INTERNAL METHODS |
904 | |
e8919861 |
905 | These methods are for Catalyst::Plugin::Authentication B<INTERNAL USE> only. |
906 | Please do not use them in your own code, whether application or credential / |
907 | store modules. If you do, you will very likely get the nasty shock of having |
908 | to fix / rewrite your code when things change. They are documented here only |
909 | for reference. |
06675d2e |
910 | |
4e86cf54 |
911 | =head2 $c->set_authenticated( $user, $realmname ) |
06675d2e |
912 | |
e8919861 |
913 | Marks a user as authenticated. This is called from within the authenticate |
914 | routine when a credential returns a user. $realmname defaults to 'default' |
06675d2e |
915 | |
4e86cf54 |
916 | =head2 $c->auth_restore_user( $user, $realmname ) |
e300c5b6 |
917 | |
e8919861 |
918 | Used to restore a user from the session. In most cases this is called without |
919 | arguments to restore the user via the session. Can be called with arguments |
920 | when restoring a user from some other method. Currently not used in this way. |
e300c5b6 |
921 | |
4e86cf54 |
922 | =head2 $c->auth_realms( ) |
06675d2e |
923 | |
e8919861 |
924 | Returns a hashref containing realmname -> realm instance pairs. Realm |
925 | instances contain an instantiated store and credential object as the 'store' |
926 | and 'credential' elements, respectively |
06675d2e |
927 | |
4e86cf54 |
928 | =head2 $c->get_auth_realm( $realmname ) |
06675d2e |
929 | |
e8919861 |
930 | Retrieves the realm instance for the realmname provided. |
06675d2e |
931 | |
96671824 |
932 | =head2 $c->update_user_in_session |
933 | |
34088132 |
934 | This was a short-lived method to update user information - you should use persist_user instead. |
96671824 |
935 | |
eda12589 |
936 | =head2 $c->setup_auth_realm( ) |
937 | |
938 | =head1 OVERRIDDEN METHODS |
939 | |
940 | =head2 $c->setup( ) |
941 | |
fbe577ac |
942 | =head1 SEE ALSO |
943 | |
649de93b |
944 | This list might not be up to date. Below are modules known to work with the updated |
c7b6526a |
945 | API of 0.10 and are therefore compatible with realms. |
4bb9b01c |
946 | |
5afc0dde |
947 | =head2 Realms |
948 | |
5c5af345 |
949 | L<Catalyst::Authentication::Realm> |
5afc0dde |
950 | |
4bb9b01c |
951 | =head2 User Storage Backends |
952 | |
eda12589 |
953 | =over |
954 | |
955 | =item L<Catalyst::Authentication::Store::Minimal> |
956 | |
957 | =item L<Catalyst::Authentication::Store::DBIx::Class> |
958 | |
959 | =item L<Catalyst::Authentication::Store::LDAP> |
960 | |
961 | =item L<Catalyst::Authentication::Store::RDBO> |
962 | |
963 | =item L<Catalyst::Authentication::Store::Model::KiokuDB> |
964 | |
965 | =item L<Catalyst::Authentication::Store::Jifty::DBI> |
966 | |
967 | =item L<Catalyst::Authentication::Store::Htpasswd> |
968 | |
969 | =back |
4bb9b01c |
970 | |
971 | =head2 Credential verification |
972 | |
eda12589 |
973 | =over |
974 | |
975 | =item L<Catalyst::Authentication::Credential::Password> |
976 | |
977 | =item L<Catalyst::Authentication::Credential::HTTP> |
978 | |
979 | =item L<Catalyst::Authentication::Credential::OpenID> |
980 | |
981 | =item L<Catalyst::Authentication::Credential::Authen::Simple> |
982 | |
983 | =item L<Catalyst::Authentication::Credential::Flickr> |
984 | |
985 | =item L<Catalyst::Authentication::Credential::Testing> |
986 | |
987 | =item L<Catalyst::Authentication::Credential::AuthTkt> |
988 | |
989 | =item L<Catalyst::Authentication::Credential::Kerberos> |
4bb9b01c |
990 | |
fdf33503 |
991 | =back |
992 | |
4bb9b01c |
993 | =head2 Authorization |
994 | |
fbe577ac |
995 | L<Catalyst::Plugin::Authorization::ACL>, |
4bb9b01c |
996 | L<Catalyst::Plugin::Authorization::Roles> |
997 | |
5e91c057 |
998 | =head2 Internals Documentation |
999 | |
649de93b |
1000 | L<Catalyst::Plugin::Authentication::Internals> |
5e91c057 |
1001 | |
4bb9b01c |
1002 | =head2 Misc |
1003 | |
1004 | L<Catalyst::Plugin::Session>, |
1005 | L<Catalyst::Plugin::Session::PerUser> |
fbe577ac |
1006 | |
93f08fb0 |
1007 | =head1 DON'T SEE ALSO |
1008 | |
1a05e6ed |
1009 | This module along with its sub plugins deprecate a great number of other |
1010 | modules. These include L<Catalyst::Plugin::Authentication::Simple>, |
1011 | L<Catalyst::Plugin::Authentication::CDBI>. |
93f08fb0 |
1012 | |
649de93b |
1013 | =head1 INCOMPATABILITIES |
1014 | |
c7b6526a |
1015 | The realms-based configuration and functionality of the 0.10 update |
649de93b |
1016 | of L<Catalyst::Plugin::Authentication> required a change in the API used by |
1017 | credentials and stores. It has a compatibility mode which allows use of |
1018 | modules that have not yet been updated. This, however, completely mimics the |
c7b6526a |
1019 | older api and disables the new realm-based features. In other words you cannot |
34088132 |
1020 | mix the older credential and store modules with realms, or realm-based |
649de93b |
1021 | configs. The changes required to update modules are relatively minor and are |
1022 | covered in L<Catalyst::Plugin::Authentication::Internals>. We hope that most |
1023 | modules will move to the compatible list above very quickly. |
0cc778ab |
1024 | |
ff87fb62 |
1025 | =head1 COMPATIBILITY CONFIGURATION |
1026 | |
1027 | Until version 0.10008 of this module, you needed to put all the |
c7b6526a |
1028 | realms inside a "realms" key in the configuration. |
ff87fb62 |
1029 | |
1030 | # example |
47074ecb |
1031 | __PACKAGE__->config( 'Plugin::Authentication' => |
c7b6526a |
1032 | { |
ff87fb62 |
1033 | default_realm => 'members', |
1034 | realms => { |
1035 | members => { |
1036 | ... |
1037 | }, |
1038 | }, |
c83ea211 |
1039 | } |
1040 | ); |
ff87fb62 |
1041 | |
c83ea211 |
1042 | If you use the old, deprecated C<< __PACKAGE__->config( 'authentication' ) >> |
ff87fb62 |
1043 | configuration key, then the realms key is still required. |
1044 | |
0cc778ab |
1045 | =head1 COMPATIBILITY ROUTINES |
1046 | |
e8919861 |
1047 | In version 0.10 of L<Catalyst::Plugin::Authentication>, the API |
1048 | changed. For app developers, this change is fairly minor, but for |
c7b6526a |
1049 | Credential and Store authors, the changes are significant. |
e8919861 |
1050 | |
1051 | Please see the documentation in version 0.09 of |
30e90c6f |
1052 | Catalyst::Plugin::Authentication for a better understanding of how the old API |
e8919861 |
1053 | functioned. |
1054 | |
1055 | The items below are still present in the plugin, though using them is |
1056 | deprecated. They remain only as a transition tool, for those sites which can |
30e90c6f |
1057 | not yet be upgraded to use the new system due to local customizations or use |
c7b6526a |
1058 | of Credential / Store modules that have not yet been updated to work with the |
45c7644b |
1059 | new API. |
e8919861 |
1060 | |
1061 | These routines should not be used in any application using realms |
1062 | functionality or any of the methods described above. These are for reference |
1063 | purposes only. |
0cc778ab |
1064 | |
4e86cf54 |
1065 | =head2 $c->login( ) |
e8919861 |
1066 | |
1067 | This method is used to initiate authentication and user retrieval. Technically |
649de93b |
1068 | this is part of the old Password credential module and it still resides in the |
1069 | L<Password|Catalyst::Plugin::Authentication::Credential::Password> class. It is |
1070 | included here for reference only. |
e8919861 |
1071 | |
4e86cf54 |
1072 | =head2 $c->default_auth_store( ) |
0cc778ab |
1073 | |
1074 | Return the store whose name is 'default'. |
1075 | |
c83ea211 |
1076 | This is set to C<< $c->config( 'Plugin::Authentication' => { store => # Store} ) >> if that value exists, |
0cc778ab |
1077 | or by using a Store plugin: |
1078 | |
30e90c6f |
1079 | # load the Minimal authentication store. |
99747fe1 |
1080 | use Catalyst qw/Authentication Authentication::Store::Minimal/; |
0cc778ab |
1081 | |
1082 | Sets the default store to |
45c7644b |
1083 | L<Catalyst::Plugin::Authentication::Store::Minimal>. |
0cc778ab |
1084 | |
4e86cf54 |
1085 | =head2 $c->get_auth_store( $name ) |
0cc778ab |
1086 | |
1087 | Return the store whose name is $name. |
1088 | |
4e86cf54 |
1089 | =head2 $c->get_auth_store_name( $store ) |
0cc778ab |
1090 | |
1091 | Return the name of the store $store. |
1092 | |
4e86cf54 |
1093 | =head2 $c->auth_stores( ) |
0cc778ab |
1094 | |
1095 | A hash keyed by name, with the stores registered in the app. |
1096 | |
4e86cf54 |
1097 | =head2 $c->register_auth_stores( %stores_by_name ) |
0cc778ab |
1098 | |
1099 | Register stores into the application. |
1100 | |
4e86cf54 |
1101 | =head2 $c->auth_store_names( ) |
078c2289 |
1102 | |
4e86cf54 |
1103 | =head2 $c->get_user( ) |
078c2289 |
1104 | |
2bcde605 |
1105 | =head1 AUTHORS |
fbe577ac |
1106 | |
1107 | Yuval Kogman, C<nothingmuch@woobling.org> |
2bcde605 |
1108 | |
649de93b |
1109 | Jay Kuri, C<jayk@cpan.org> |
1110 | |
7d2f34eb |
1111 | Jess Robinson |
2bcde605 |
1112 | |
7d2f34eb |
1113 | David Kamholz |
06675d2e |
1114 | |
7289cea0 |
1115 | Tomas Doran (t0m), C<bobtfish@bobtfish.net> |
1116 | |
1117 | kmx |
1118 | |
1119 | Nigel Metheringham |
36540b6c |
1120 | |
44bb43eb |
1121 | Florian Ragwitz C<rafl@debian.org> |
1122 | |
1123 | Stephan Jauernick C<stephanj@cpan.org> |
1124 | |
ff46c00b |
1125 | =head1 COPYRIGHT & LICENSE |
fbe577ac |
1126 | |
87d186b1 |
1127 | Copyright (c) 2005 - 2009 |
1128 | the Catalyst::Plugin::Authentication L</AUTHORS> |
1129 | as listed above. |
1130 | |
1131 | This program is free software; you can redistribute |
1132 | it and/or modify it under the same terms as Perl itself. |
fbe577ac |
1133 | |
1134 | =cut |
06675d2e |
1135 | |