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