Various minor adjustments to code and a WHOLE lot of documentation
[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 storage backend. 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 =head2 INITIALIZATION
38
39 When the authentication module is loaded, it reads it's configuration to
40 determine the realms to set up for the application and which realm is to be
41 the default. For each realm defined in the application's config,
42 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>
43 instantiates both a new credential object and a new store object. See below
44 for the details of how credentials and stores are instantiated.
45
46     NOTE: The instances created will remain active throughout the entire 
47     lifetime of the application, and so should be relatively lightweight. 
48     Care should be taken to ensure that they do not grow, or retain 
49     information per request, because they will be involved in each 
50     authentication request and could therefore substantially
51     hurt memory consumption over time.  
52
53 =head2 AUTHENTICATION
54
55 When C<$c-E<gt>authenticate()> is called from within an application, the
56 objects created in the initialization process come into play.
57 C<$c-E<gt>authenticate()> takes two arguments. The first is a hash reference
58 containing all the information available about the user. This will be used to
59 locate the user in the store and verify the user's credentials. The second
60 argument is the realm to authenticate against. If the second argument is
61 omitted, the default realm is assumed. 
62
63 The main authentication module then locates the credential and store objects
64 for the realm specified and calls the credential object's C<authenticate()>
65 method. It provides three arguments, first the application object, or C<$c>,
66 then a reference to the store object, and finally the hashref provided in the
67 C<$c-E<gt>authenticate> call. The main authentication module expects the
68 return value to be a reference to a user object upon successful
69 authentication. If it receives anything aside from a reference, it is
70 considered to be an authentication failure. Upon success, the returned user is
71 marked as authenticated and the application can act accordingly, using
72 C<$c-E<gt>user> to access the authenticated user, etc.
73
74 Astute readers will note that the main
75 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> module
76 does not interact with the store in any way, save for passing a reference to
77 it to the credential. This is correct. The credential object is responsible
78 for obtaining the user from the provided store using information from the
79 userinfo hashref and/or data obtained during the credential verification
80 process.
81
82 =head1 WRITING A STORE
83
84 There are two parts to an authentication store, the backend and the user object.
85
86 =head2 STORAGE BACKEND
87
88 Writing a storage backend is actually quite simple.  There are only five methods
89 that must be implemented. They are:
90
91     new()           - instantiates the store object
92     find_user()     - locates a user using data contained in the hashref
93     for_session()   - prepares a user to be stored in the session
94     from_session()  - does any restoration required when obtaining a user from the session
95     user_supports() - provides information about what the user object supports
96
97 =head3 STORE METHODS
98
99 =over 4
100
101 =item new( $config, $app )
102
103 The C<new()> method is called only once, during the setup process of
104 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>. The
105 first argument, C<$config>, is a hash reference containing the configuration
106 information for the store module. The second argument is a reference to the
107 Catalyst application.
108
109     Note that when new() is called, Catalyst has not yet loaded the various 
110     controller and model classes, nor is it definite that other plugins have 
111     been loaded, so your new() method must not rely on any of those being 
112     present.  If any of this is required for your store to function, you should
113     defer that part of initialization until the first method call. 
114     
115 The C<new()> method should return a blessed reference to your store object.
116
117 =item find_user( $authinfo, $c ) 
118
119 This is the workhorse of any authentication store. It's job is to take the
120 information provided to it via the C<$authinfo> hashref and locate the user
121 that matches it. It should return a reference to a user object. A return value
122 of anything else is considered to mean no user was found that matched the
123 information provided.
124
125 How C<find_user()> accomplishes it's job is entirely up to you, the author, as
126 is what $authinfo is required to contain.  Many stores will simply use a 
127 username element in $authinfo to locate the user, but more advanced functionality
128 is possible and you may bend the $authinfo to your needs.  Be aware, however, that
129 both Credentials and Stores work with the same $authinfo hash, so take care to
130 avoid overlapping element names.
131
132 Please note that this routine may be called numerous times in various
133 circumstances, and that a successful match for a user here does B<NOT>
134 necessarily constitute successful authentication. Your store class should
135 never assume this and in most cases C<$c> B<should not be modified> by your
136 store object.
137
138 =item for_session( $c, $user )
139
140 This method is responsible for preparing a user object for storage in the session.
141 It should return information that can be placed in the session and later used to 
142 restore a user object (using the C<from_session()> method).  It should therefore
143 ensure that whatever information provided can be used by the C<from_session()>
144 method to locate the unique user being saved.  Note that there is no guarantee
145 that the same Catalyst instance will receive both the C<for_session()> and 
146 C<from_session()> calls.  You should take care to provide information that can
147 be used to restore a user, regardless of the current state of the application. 
148 A good rule of thumb is that if C<from_session()> can revive the user with the
149 given information even if the Catalyst application has just started up, you are 
150 in good shape.
151
152 =item from_session( $c, $frozenuser )
153
154 This method is called whenever a user is being restored from the session.  
155 C<$frozenuser> contains the information that was stored in the session for the user.
156 This will under normal circumstances be the exact data your store returned from 
157 the previous call to C<for_session()>.  C<from_session()> should return a valid
158 user object.
159
160 =item user_supports( $feature, ...  )
161
162 This method allows credentials and other objects to inquire as to what the
163 underlying user object is capable of. This is pretty-well free-form and the
164 main purpose is to allow graceful integration with credentials and
165 applications that may provide advanced functionality based on whether the
166 underlying user object can do certain things. In most cases you will want to
167 pass this directly to the underlying user class' C<supports> method. Note that 
168 this is used as a B<class> method against the user class and therefore must 
169 be able to function without an instantiated user object.
170
171 =back
172
173 =head2 USER OBJECT
174
175 The user object is an important piece of your store module. It will be the
176 part of the system that the application developer will interact with most. As
177 such, the API for the user object is very rigid. All user objects B<MUST>
178 inherit from
179 L<Catalyst::Plugin::Authentication::User|Catalyst::Plugin::Authentication::User>.
180
181 =head3 USER METHODS
182
183 The routines required by the
184 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> plugin
185 are below. Note that of these, only get_object is strictly required, as the
186 L<Catalyst::Plugin::Authentication::User|Catalyst::Plugin::Authentication::User>
187 base class contains reasonable implementations of the rest. If you do choose
188 to implement only the C<get_object()> routine, please read the base class
189 documentation so that you fully understand how the other routines will be
190 implemented for you.
191
192 Also, your user object can implement whatever additional methods you require
193 to provide the functionality you need. So long as the below are implemented,
194 and you don't overlap the base class' methods with incompatible routines, you
195 should experience no problems.
196
197 =over 4
198
199 =item id( )
200
201 The C<id()> method should return a unique id (scalar) that can be used to 
202 retreive this user from the store.  Often this will be provided to the store's
203 C<find_user()> routine as C<id =E<gt> $user-E<gt>id> so you should ensure that your 
204 store's C<find_user()> can cope with that. 
205
206 =item supports_features( )
207
208 This method should return a hashref of 'extra' features supported. This is for
209 more flexible integration with some Credentials / applications. It is not
210 required that you support anything, and returning C<undef> is perfectly
211 acceptable and in most cases what you will do.
212
213 =item get( $fieldname )
214
215 This method should return the value of the field matching fieldname provided,
216 or undef if there is no field matching that fieldname. In most cases this will
217 access the underlying storage mechanism for the user data and return the
218 information. This is used as a standard method of accessing an authenticated
219 user's data, and MUST be implemented by all user objects.  
220
221     Note: There is no equivalent 'set' method. Each user class is likely
222     to vary greatly in how data must be saved and it is therefore impractical to 
223     try to provide a standard way of accomplishing it. When an application 
224     developer needs to save data, they should obtain the underlying object / data
225     by calling get_object, and work with it directly.
226     
227
228 =item get_object( )
229
230 This method returns the underlying user object. If your user object is backed
231 by another object class, this method should return that underlying object.
232 This allows the application developer to obtain an editable object. Generally
233 speaking this will only be done by developers who know what they are doing and
234 require advanced functionality which is either unforeseen or inconsistent
235 across user classes. If your object is not backed by another class, or you
236 need to provide additional intermediate functionality, it is perfectly
237 reasonable to return C<$self>.
238
239 =back 
240
241
242 ... Documentation fairy fell asleep here.  
243
244
245 =head1 MULTIPLE BACKENDS
246
247 A key issue to understand about authentication stores is that there are
248 potentially many of them. Each one is registered into the application, and has
249 a name.
250
251 For most applications, there is only one, and in this framework it is called
252 'default'.
253
254 When you use a plugin, like
255
256     use Catalyst qw/
257         Authentication
258         Authentication::Store::Foo
259     /;
260
261 the Store plugins typically only act at setup time. They rarely do more than
262 check out the configuration, and register e.g. Store::Foo::Backend, and set it
263 as the default store.
264
265     __PACKAGE__->default_auth_store( $store );
266
267     # the same as
268
269     __PACKAGE__->register_auth_stores( default => $store );
270
271 =head1 WORKING WITH USERS
272
273 All credential verifiers should accept either a user object, or a user ID.
274
275 If a user ID is provided, then they will fetch the user object from the default
276 store, and check against it.
277
278 This should be pretty much DWIM all the time.
279
280 When you need multiple authentication backends per application then you must
281 fetch things yourself. For example:
282
283     my $user = $c->get_auth_store("other_store")->get_user($id);
284
285     $c->login( $user, $supplied_password );
286
287 Instead of just:
288
289     $c->login( $id, $supplied_password );
290
291 which will go to the default store.
292
293 =head1 WRITING A BACKEND
294
295 Writing an authentication storage backend is a very simple matter.
296
297 The only method you really need to support is C<get_user>.
298
299 This method should accept an arbitrary list of parameters (determined by you or
300 the credential verifyer), and return an object inheriting
301 L<Catalyst::Plugin::Authentication::User>.
302
303 For introspection purposes you can also define the C<user_supports> method. See
304 below for optional features. This is not necessary, but might be in the future.
305
306 =head2 Integrating with Catalyst::Plugin::Session
307
308 If your users support sessions, your store should also define the
309 C<from_session> method. When the user object is saved in the session the
310 C<for_session> method is called, and that is used as the value in the session
311 (typically a user id). The store is also saved in the hash. If
312 C<<$user->store>> returns something registered, that store's name is used. If
313 not, the user's class is used as if it were a store (and must also support
314 C<from_session>).
315
316 =head2 Optional Features
317
318 Each user has the C<supports> method. For example:
319
320     $user->supports(qw/password clear/);
321
322 should return a true value if this specific user has a clear text password.
323
324 This is on a per user (not necessarily a per store) basis. To make assumptions
325 about the store as a whole,
326
327     $store->user_supports(qw/password clear/);
328
329 is supposed to be the lowest common denominator.
330
331 The standardization of these values is to be goverened by the community,
332 typically defined by the credential verification plugins.
333
334 =head2 Stores implying certain credentials
335
336 Sometimes a store is agnostic to the credentials (DB storage, for example), but
337 sometimes it isn't (like an Htpasswd file).
338
339 If you are writing a backend that wraps around a module, like
340 L<Catalyst::Plugin::Authentication::Store::Htpasswd> wraps around
341 L<Authen::Htpasswd>, it makes sense to delegate the credential checks.
342
343 This particular example caused the following "feature" to be added:
344
345     $user->supports(qw/password self_check/);
346
347 =head2 Writing a plugin to go with the backend
348
349 Typically the backend will do the heavy lifting, by registering a store.
350
351 These plugins should look something like this:
352
353     sub setup {
354         my $c = shift;
355
356         $c->default_auth_store(
357             # a store can be an object or a class
358             Catalyst::Plugin::Authentication::Store::Foo::Backend->new(
359                 ...
360             )
361         );
362
363         $c->NEXT::setup(@_);
364     }