pod fix (RT #36063)
[catagits/Catalyst-Plugin-Authentication.git] / lib / Catalyst / Plugin / Authentication / Internals.pod
1
2 =head1 NAME
3
4 Catalyst::Plugin::Authentication::Internals - All about authentication Stores and Credentials
5
6 =head1 INTRODUCTION
7
8 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> provides
9 a standard authentication interface to application developers using the
10 Catalyst framework. It is designed to allow application developers to use
11 various methods of user storage and credential verification. It is also
12 designed to provide for minimal change to the application when switching
13 between different storage and credential verification methods.
14
15 While L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>
16 provides the interface to the application developer, the actual work of
17 verifying the credentials and retrieving users is delegated to separate
18 modules. These modules are called B<Credentials> and storage backends, or
19 B<Stores>, respectively. For authentication to function there must be at least
20 one credential and one store. A pairing of a store and a credential
21 is referred to as a B<Realm>. There may be any number of realms defined for an
22 application, though most applications will not require more than one or two.
23
24 The details of using this module can be found in the
25 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>
26 documentation.
27
28 What follows is an explanation of how the module functions internally and what
29 is required to implement a credential or a store.
30
31 =head1 OVERVIEW
32
33 There are two main entry points you need to be aware of when writing a store
34 or credential module. The first is initialization and the second is during the
35 actual call to the Catalyst application's authenticate method.  
36
37 A simplified description of the authentication process follows:
38
39
40
41 B<Initialization>
42
43 =over 4
44
45 B<Realm Setup> - for each realm:
46
47 =over 4
48
49 1) The Realm is instantiated using new() method
50
51 2) The Store is instantiated using new() method
52
53 3) The Credential Instantiated using new() method
54
55 4) Credential and Store objects tied to realm for use during requests
56
57 =back
58
59 =back
60
61 B<Authentication>
62
63 =over 4
64
65 C<< $c->authenticate( $userinfo, $realm ) >> called
66
67 =over 4
68
69 1) Credential object retrieved for realm provided
70
71 2) Credential's authenticate() method called with authinfo and realm object for current realm
72
73 =over 4 
74
75 The realm object and the authinfo hash are provided to the credential object's
76 authenticate call. In most cases the credential object will attempt to
77 retrieve a user using the realm's find_user() method, which by default relays
78 the call directly to the Store's find_user() method. It will then usually
79 compare the retrieved user's information with the information provided in the
80 $authinfo hash. This is how the default 'Password' credential functions. If
81 the credentials match, the authenticate() method should return a user object.
82
83 =back
84
85 3) User object stored in session
86
87 =over 4
88
89 If the user object supports session storage, the successfully authenticated
90 user will be placed in session storage. This is done by calling the realm
91 object's save_user_in_session() method. The save_user_in_session() routine by
92 default calls the Store's for_session() method, which should return serialized
93 data (IE a scalar). This serialized data is passed back to the store via the
94 from_session() method, so the data should contain enough information for the
95 store to recreate / reload the user.
96
97 =back
98
99 =back
100
101 =back
102
103 B<Sessions> - Per-Request operations
104
105 =over 4
106
107 When any user-related activity occurs, and $c->authenticate has not
108 yet been called, the Catalyst::Plugin::Authentication module will
109 attempt to restore the user from the session (if one is available).
110 There is only one step in this process: 
111
112 =over 4
113
114 1) Store object's from_session() is called
115
116 =back 
117     
118 The serialized data previously returned by the store's for_session()
119 method is provided to the from_session() method. The from_session()
120 method should return a valid user object.
121
122 Note that the for_session() is only called during the original
123 $c->authenticate() call, so if changes are made to the user that need
124 to be reflected in your session data, you will want to call the
125 $c->save_user_in_session() method - which will perform the session
126 storage process again (complete with call to for_session()).
127
128 =back
129
130 More detailed information about these processes is below.
131
132 =head2 INITIALIZATION
133
134 When the authentication module is loaded, it reads it's configuration to
135 determine the realms to set up for the application and which realm is to be
136 the default. For each realm defined in the application's config,
137 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>
138 instantiates both a new credential object and a new store object. See below
139 for the details of how credentials and stores are instantiated.
140
141 B<NOTE>: The instances created will remain active throughout the entire 
142 lifetime of the application, and so should be relatively lightweight. 
143 Care should be taken to ensure that they do not grow, or retain 
144 information per request, because they will be involved in each 
145 authentication request and could therefore substantially
146 hurt memory consumption over time.  
147
148 =head2 AUTHENTICATION
149
150 When C<$c-E<gt>authenticate()> is called from within an application, the
151 objects created in the initialization process come into play.
152 C<$c-E<gt>authenticate()> takes two arguments. The first is a hash reference
153 containing all the information available about the user. This will be used to
154 locate the user in the store and verify the user's credentials. The second
155 argument is the realm to authenticate against. If the second argument is
156 omitted, the default realm is assumed. 
157
158 The main authentication module then locates the credential and store objects
159 for the realm specified and calls the credential object's C<authenticate()>
160 method. It provides three arguments, first the application object, or C<$c>,
161 then a reference to the store object, and finally the hashref provided in the
162 C<$c-E<gt>authenticate> call. The main authentication module expects the
163 return value to be a reference to a user object upon successful
164 authentication. If it receives anything aside from a reference, it is
165 considered to be an authentication failure. Upon success, the returned user is
166 marked as authenticated and the application can act accordingly, using
167 C<$c-E<gt>user> to access the authenticated user, etc.
168
169 Astute readers will note that the main
170 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> module
171 does not interact with the store in any way, save for passing a reference to
172 it to the credential. This is correct. The credential object is responsible
173 for obtaining the user from the provided store using information from the
174 userinfo hashref and/or data obtained during the credential verification
175 process.
176
177 =head1 WRITING A STORE
178
179 There are two parts to an authentication store, the store object and the user object.
180
181 =head2 STORAGE BACKEND
182
183 Writing a store is actually quite simple.  There are only five methods
184 that must be implemented. They are:
185
186     new()           - instantiates the store object
187     find_user()     - locates a user using data contained in the hashref
188     for_session()   - prepares a user to be stored in the session
189     from_session()  - does any restoration required when obtaining a user from the session
190     user_supports() - provides information about what the user object supports
191
192 =head3 STORE METHODS
193
194 =over 4
195
196 =item new( $config, $app, $realm )
197
198 The C<new()> method is called only once, during the setup process of
199 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>. The
200 first argument, C<$config>, is a hash reference containing the configuration
201 information for the store module. The second argument is a reference to the
202 Catalyst application.
203
204 Note that when new() is called, Catalyst has not yet loaded 
205 the various controller and model classes, nor is it definite
206 that other plugins have been loaded, so your new() method 
207 must not rely on any of those being present.  If any of 
208 this is required for your store to function, you should
209 defer that part of initialization until the first method call. 
210
211 The C<new()> method should return a blessed reference to your store object.
212
213 =item find_user( $authinfo, $c ) 
214
215 This is the workhorse of any authentication store. It's job is to take the
216 information provided to it via the C<$authinfo> hashref and locate the user
217 that matches it. It should return a reference to a user object. A return value
218 of anything else is considered to mean no user was found that matched the
219 information provided.
220
221 How C<find_user()> accomplishes it's job is entirely up to you, the author, as
222 is what $authinfo is required to contain.  Many stores will simply use a 
223 username element in $authinfo to locate the user, but more advanced functionality
224 is possible and you may bend the $authinfo to your needs.  Be aware, however, that
225 both Credentials and Stores usually work with the same $authinfo hash, so take 
226 care to avoid overlapping element names.
227
228 Please note that this routine may be called numerous times in various
229 circumstances, and that a successful match for a user here does B<NOT>
230 necessarily constitute successful authentication. Your store class should
231 never assume this and in most cases C<$c> B<should not be modified> by your
232 store object.
233
234 =item for_session( $c, $user )
235
236 This method is responsible for preparing a user object for storage in the session.
237 It should return information that can be placed in the session and later used to 
238 restore a user object (using the C<from_session()> method).  It should therefore
239 ensure that whatever information provided can be used by the C<from_session()>
240 method to locate the unique user being saved.  Note that there is no guarantee
241 that the same Catalyst instance will receive both the C<for_session()> and 
242 C<from_session()> calls.  You should take care to provide information that can
243 be used to restore a user, regardless of the current state of the application. 
244 A good rule of thumb is that if C<from_session()> can revive the user with the
245 given information even if the Catalyst application has just started up, you are 
246 in good shape.
247
248 =item from_session( $c, $frozenuser )
249
250 This method is called whenever a user is being restored from the session.  
251 C<$frozenuser> contains the information that was stored in the session for the user.
252 This will under normal circumstances be the exact data your store returned from 
253 the previous call to C<for_session()>.  C<from_session()> should return a valid
254 user object.
255
256 =item user_supports( $feature, ...  )
257
258 This method allows credentials and other objects to inquire as to what the
259 underlying user object is capable of. This is pretty-well free-form and the
260 main purpose is to allow graceful integration with credentials and
261 applications that may provide advanced functionality based on whether the
262 underlying user object can do certain things. In most cases you will want to
263 pass this directly to the underlying user class' C<supports> method. Note that 
264 this is used as a B<class> method against the user class and therefore must 
265 be able to function without an instantiated user object. 
266
267 =back
268
269 =head2 USER OBJECT
270
271 The user object is an important piece of your store module. It will be the
272 part of the system that the application developer will interact with most. As
273 such, the API for the user object is very rigid. All user objects B<MUST>
274 inherit from
275 L<Catalyst::Authentication::User|Catalyst::Authentication::User>.
276
277 =head3 USER METHODS
278
279 The routines required by the
280 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> plugin
281 are below. Note that of these, only get_object is strictly required, as the
282 L<Catalyst::Authentication::User|Catalyst::Authentication::User>
283 base class contains reasonable implementations of the rest. If you do choose
284 to implement only the C<get_object()> routine, please read the base class code
285 and documentation so that you fully understand how the other routines will be
286 implemented for you.
287
288 Also, your user object can implement whatever additional methods you require
289 to provide the functionality you need. So long as the below are implemented,
290 and you don't overlap the base class' methods with incompatible routines, you
291 should experience no problems.
292
293 =over 4
294
295 =item id( )
296
297 The C<id()> method should return a unique id (scalar) that can be used to 
298 retreive this user from the store.  Often this will be provided to the store's
299 C<find_user()> routine as C<id =E<gt> $user-E<gt>id> so you should ensure that your 
300 store's C<find_user()> can cope with that. 
301
302 =item supports( $feature, $subfeature ... )
303
304 This method checks to see if the user class supports a particular feature.  It
305 is implemented such that each argument provides a subfeature of the previous 
306 argument. In other words, passing 'foo', 'bar'  would return true if the user
307 supported the 'foo' feature, and the 'bar' feature of 'foo'.   This is implemented
308 in Catalyst::Authentication::User, so if your class inherits from that, you
309 do not need to implement this and can instead implement supported_features(). 
310
311 B<Note:> If you want the authentication module to be able to save your user in
312 the session you must return true when presented with the feature 'session'.
313
314 =item supported_features( )
315
316 This method should return a hashref of features supported by the user class.
317 This is for more flexible integration with some Credentials / applications. It
318 is not required that you support anything, and returning C<undef> is perfectly
319 acceptable and in most cases what you will do.
320
321 =item get( $fieldname )
322
323 This method should return the value of the field matching fieldname provided,
324 or undef if there is no field matching that fieldname. In most cases this will
325 access the underlying storage mechanism for the user data and return the
326 information. This is used as a standard method of accessing an authenticated
327 user's data, and MUST be implemented by all user objects.  
328
329 B<Note>: There is no equivalent 'set' method. Each user class is 
330 likely to vary greatly in how data must be saved and it is 
331 therefore impractical to try to provide a standard way of 
332 accomplishing it. When an application developer needs to save 
333 data, they should obtain the underlying object / data by 
334 calling get_object, and work with it directly.
335     
336
337 =item get_object( )
338
339 This method returns the underlying user object. If your user object is backed
340 by another object class, this method should return that underlying object.
341 This allows the application developer to obtain an editable object. Generally
342 speaking this will only be done by developers who know what they are doing and
343 require advanced functionality which is either unforeseen or inconsistent
344 across user classes. If your object is not backed by another class, or you
345 need to provide additional intermediate functionality, it is perfectly
346 reasonable to return C<$self>.
347
348 =back 
349
350
351 =head1 WRITING A CREDENTIAL
352
353 Compared to writing a store, writing a credential is very simple.  There is only
354 one class to implement, and it consists of only two required routines. They are:
355
356     new()           - instantiates the credential object
357     authenticate()  - performs the authentication and returns a user object
358     
359 =head2 CREDENTIAL METHODS
360
361 =over 4
362
363 =item new( $config, $app, $realm )
364
365 Like the Store method of the same name, the C<new()> method is called only 
366 once, during the setup process of 
367 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>. The
368 first argument, C<$config>, is a hash reference containing the configuration
369 information for the credential module. The second argument is a reference 
370 to the Catalyst application.  $realm is the instantiated Realm object, which
371 you may use to access realm routines - such as find_user.
372
373 Again, when the credential's new() method is called, Catalyst 
374 has not yet loaded the various controller and model classes. 
375
376 The new method should perform any necessary setup required and instantiate 
377 your credential object.  It should return your instantiated credential.
378
379 =item authenticate( $c, $realm, $authinfo )
380
381 This is the workhorse of your credential.  When $c->authenticate() is called
382 the L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> module retrieves the
383 realm object and passes it, along with the $authinfo hash
384 to your credential's authenticate method.  Your module should use the 
385 $authinfo hash to obtain the user from the realm passed, and then perform 
386 any credential verification steps necessary to authenticate the user.  This
387 method should return the user object returned by the authentication store if
388 credential verification succeeded.  It should return undef on failure.  
389
390 How your credential module performs the credential verification is entirely
391 up to you.  In most cases, the credential will retrieve a user from the store
392 first (using the stores find_user() method), and then validate the user's 
393 information.  However, this does not have to be the case.  
394
395 It is perfectly acceptable for your credential to perform other tasks prior to
396 attempting to retrieve the user from the store. It may also make sense for
397 your credential to perform activities which help to locate the user in
398 question, for example, finding a user id based on an encrypted token.
399 In these scenarios, the $authinfo hash passed to find_user()
400 can be different than that which is passed in to $c->authenticate(). Once
401 again this is perfectly acceptable if it makes sense for your credential,
402 though you are strongly advised to note this behavior clearly in your 
403 credential's documentation - as application authors are almost 
404 certainly expecting the user to be found using the information provided 
405 to $c->authenticate().
406
407 Look at the L<Catalyst::Authentication::Credential::Password|Catalyst::Authentication::Credential::Password>
408 module source to see this in action.  In order to avoid possible 
409 mismatches between the encrypted and unencrypted passwords, the password 
410 credential actually removes the provided password from the authinfo 
411 array.  It does this because, in many cases, the store's password 
412 field will be encrypted in some way, and the password passed to 
413 $c->authenticate is almost certainly in plaintext. 
414
415 NOTE: You should always assume that a store is going to use all
416 the information passed to it to locate the user in question. 
417 If there are fields in the $authinfo hash that you are sure
418 are specific to your credential, you may want to consider 
419 removing them before user retrieval.  A better solution is to
420 place those arguments that are specific to your credential 
421 within their own subhash named after your module.
422  
423 The L<Catalyst::Authentication::Store::DBIx::Class|Catalyst::Authentication::Store::DBIx::Class> module does this
424 in order to encapsulate arguments intended specifically for 
425 that module. See the L<Catalyst::Authentication::Store::DBIx::Class::User|Catalyst::Authentication::Store::DBIx::Class::User>
426 source for details.
427
428 =back
429
430 =head1 AUTHORS
431
432 Jay Kuri, C<jayk@cpan.org>
433
434 =head1 COPYRIGHT & LICENSE
435
436 Copyright (c) 2005 the aforementioned authors. All rights
437 reserved. This program is free software; you can redistribute
438 it and/or modify it under the same terms as Perl itself.
439
440 =cut
441