fix _auth_realms check to actually work now that we create the classdata in
[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 =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 store object and the user object.
85
86 =head2 STORAGE BACKEND
87
88 Writing a store 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 
110     the various controller and model classes, nor is it definite
111     that other plugins have been loaded, so your new() method 
112     must not rely on any of those being present.  If any of 
113     this is required for your store to function, you should
114     defer that part of initialization until the first method call. 
115
116 The C<new()> method should return a blessed reference to your store object.
117
118 =item find_user( $authinfo, $c ) 
119
120 This is the workhorse of any authentication store. It's job is to take the
121 information provided to it via the C<$authinfo> hashref and locate the user
122 that matches it. It should return a reference to a user object. A return value
123 of anything else is considered to mean no user was found that matched the
124 information provided.
125
126 How C<find_user()> accomplishes it's job is entirely up to you, the author, as
127 is what $authinfo is required to contain.  Many stores will simply use a 
128 username element in $authinfo to locate the user, but more advanced functionality
129 is possible and you may bend the $authinfo to your needs.  Be aware, however, that
130 both Credentials and Stores usually work with the same $authinfo hash, so take 
131 care to avoid overlapping element names.
132
133 Please note that this routine may be called numerous times in various
134 circumstances, and that a successful match for a user here does B<NOT>
135 necessarily constitute successful authentication. Your store class should
136 never assume this and in most cases C<$c> B<should not be modified> by your
137 store object.
138
139 =item for_session( $c, $user )
140
141 This method is responsible for preparing a user object for storage in the session.
142 It should return information that can be placed in the session and later used to 
143 restore a user object (using the C<from_session()> method).  It should therefore
144 ensure that whatever information provided can be used by the C<from_session()>
145 method to locate the unique user being saved.  Note that there is no guarantee
146 that the same Catalyst instance will receive both the C<for_session()> and 
147 C<from_session()> calls.  You should take care to provide information that can
148 be used to restore a user, regardless of the current state of the application. 
149 A good rule of thumb is that if C<from_session()> can revive the user with the
150 given information even if the Catalyst application has just started up, you are 
151 in good shape.
152
153 =item from_session( $c, $frozenuser )
154
155 This method is called whenever a user is being restored from the session.  
156 C<$frozenuser> contains the information that was stored in the session for the user.
157 This will under normal circumstances be the exact data your store returned from 
158 the previous call to C<for_session()>.  C<from_session()> should return a valid
159 user object.
160
161 =item user_supports( $feature, ...  )
162
163 This method allows credentials and other objects to inquire as to what the
164 underlying user object is capable of. This is pretty-well free-form and the
165 main purpose is to allow graceful integration with credentials and
166 applications that may provide advanced functionality based on whether the
167 underlying user object can do certain things. In most cases you will want to
168 pass this directly to the underlying user class' C<supports> method. Note that 
169 this is used as a B<class> method against the user class and therefore must 
170 be able to function without an instantiated user object.
171
172 =back
173
174 =head2 USER OBJECT
175
176 The user object is an important piece of your store module. It will be the
177 part of the system that the application developer will interact with most. As
178 such, the API for the user object is very rigid. All user objects B<MUST>
179 inherit from
180 L<Catalyst::Plugin::Authentication::User|Catalyst::Plugin::Authentication::User>.
181
182 =head3 USER METHODS
183
184 The routines required by the
185 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> plugin
186 are below. Note that of these, only get_object is strictly required, as the
187 L<Catalyst::Plugin::Authentication::User|Catalyst::Plugin::Authentication::User>
188 base class contains reasonable implementations of the rest. If you do choose
189 to implement only the C<get_object()> routine, please read the base class code
190 and documentation so that you fully understand how the other routines will be
191 implemented for you.
192
193 Also, your user object can implement whatever additional methods you require
194 to provide the functionality you need. So long as the below are implemented,
195 and you don't overlap the base class' methods with incompatible routines, you
196 should experience no problems.
197
198 =over 4
199
200 =item id( )
201
202 The C<id()> method should return a unique id (scalar) that can be used to 
203 retreive this user from the store.  Often this will be provided to the store's
204 C<find_user()> routine as C<id =E<gt> $user-E<gt>id> so you should ensure that your 
205 store's C<find_user()> can cope with that. 
206
207 =item supports_features( )
208
209 This method should return a hashref of 'extra' features supported. This is for
210 more flexible integration with some Credentials / applications. It is not
211 required that you support anything, and returning C<undef> is perfectly
212 acceptable and in most cases what you will do.
213
214 =item get( $fieldname )
215
216 This method should return the value of the field matching fieldname provided,
217 or undef if there is no field matching that fieldname. In most cases this will
218 access the underlying storage mechanism for the user data and return the
219 information. This is used as a standard method of accessing an authenticated
220 user's data, and MUST be implemented by all user objects.  
221
222     Note: There is no equivalent 'set' method. Each user class is 
223     likely to vary greatly in how data must be saved and it is 
224     therefore impractical to try to provide a standard way of 
225     accomplishing it. When an application developer needs to save 
226     data, they should obtain the underlying object / data by 
227     calling get_object, and work with it directly.
228     
229
230 =item get_object( )
231
232 This method returns the underlying user object. If your user object is backed
233 by another object class, this method should return that underlying object.
234 This allows the application developer to obtain an editable object. Generally
235 speaking this will only be done by developers who know what they are doing and
236 require advanced functionality which is either unforeseen or inconsistent
237 across user classes. If your object is not backed by another class, or you
238 need to provide additional intermediate functionality, it is perfectly
239 reasonable to return C<$self>.
240
241 =back 
242
243
244 =head1 WRITING A CREDENTIAL
245
246 Compared to writing a store, writing a credential is very simple.  There is only
247 one class to implement, and it consists of only two required routines. They are:
248
249     new()           - instantiates the credential object
250     authenticate()  - performs the authentication and returns a user object
251     
252 =head2 CREDENTIAL METHODS
253
254 =over 4
255
256 =item new( $config, $app )
257
258 Like the Store method of the same name, the C<new()> method is called only 
259 once, during the setup process of 
260 L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication>. The
261 first argument, C<$config>, is a hash reference containing the configuration
262 information for the credential module. The second argument is a reference 
263 to the Catalyst application.
264
265     Again, when the credential's new() method is called, Catalyst 
266     has not yet loaded the various controller and model classes. 
267
268 The new method should perform any necessary setup required and instantiate 
269 your credential object.  It should return your instantiated credential.
270
271 =item authenticate( $c, $authstore, $authinfo )
272
273 This is the workhorse of your credential.  When $c->authenticate() is called
274 the L<Catalyst::Plugin::Authentication|Catalyst::Plugin::Authentication> module retrieves the
275 store object from the realm and passes it, along with the $authinfo hash
276 to your credential's authenticate method.  Your module should use the 
277 $authinfo hash to obtain the user from the store passed, and then perform 
278 any credential verification steps necessary to authenticate the user.  This
279 method should return the user object returned by the authentication store if
280 credential verification succeeded.  It should return undef on failure.  
281
282 How your credential module performs the credential verification is entirely
283 up to you.  In most cases, the credential will retrieve a user from the store
284 first (using the stores find_user() method), and then validate the user's 
285 information.  However, this does not have to be the case.  
286
287 It is perfectly acceptable for your credential to perform other tasks prior to
288 attempting to retrieve the user from the store. It may also make sense for
289 your credential to perform activities which help to locate the user in
290 question, for example, finding a user id based on an encrypted token.
291 In these scenarios, the $authinfo hash passed to the store's find_user()
292 can be different than that which is passed in to $c->authenticate(). Once
293 again this is perfectly acceptable if it makes sense for your credential,
294 though you are strongly advised to note this behavior clearly in your 
295 credential's documentation - as application authors are almost 
296 certainly expecting the user to be found using the information provided 
297 to $c->authenticate().
298
299 Look at the L<Catalyst::Plugin::Authentication::Credential::Password|Catalyst::Plugin::Authentication::Credential::Password>
300 module source to see this in action.  In order to avoid possible 
301 mismatches between the encrypted and unencrypted passwords, the password 
302 credential actually removes the provided password from the authinfo 
303 array.  It does this because, in many cases, the store's password 
304 field will be encrypted in some way, and the password passed to 
305 $c->authenticate is almost certainly in plaintext. 
306
307 NOTE: You should always assume that a store is going to use all
308 the information passed to it to locate the user in question. 
309 If there are fields in the $authinfo hash that you are sure
310 are specific to your credential, you may want to consider 
311 removing them before user retrieval.  A better solution is to
312 place those arguments that are specific to your credential 
313 within their own subhash named after your module.
314  
315 The L<Catalyst::Plugin::Authentication::Store::DBIx::Class|Catalyst::Plugin::Authentication::Store::DBIx::Class> module does this
316 in order to encapsulate arguments intended specifically for 
317 that module. See the L<Catalyst::Plugin::Authentication::Store::DBIx::Class::User|Catalyst::Plugin::Authentication::Store::DBIx::Class::User>
318 source for details.
319
320 =back
321
322 =head1 AUTHORS
323
324 Jay Kuri, C<jayk@cpan.org>
325
326 =head1 COPYRIGHT & LICENSE
327
328 Copyright (c) 2005 the aforementioned authors. All rights
329 reserved. This program is free software; you can redistribute
330 it and/or modify it under the same terms as Perl itself.
331
332 =cut
333
334