1Catalyst::Plugin::AutheUnsteircaCtoinotnr:iC:baIutntateledyrsnPtae:lr:slP(l3Du)ogciunm:e:nAtuatthieonntication::Internals(3)
2
3
4

NAME

6       Catalyst::Plugin::Authentication::Internals - All about authentication
7       Stores and Credentials
8

INTRODUCTION

10       Catalyst::Plugin::Authentication provides a standard authentication
11       interface to application developers using the Catalyst framework. It is
12       designed to allow application developers to use various methods of user
13       storage and credential verification. It is also designed to provide for
14       minimal change to the application when switching between different
15       storage and credential verification methods.
16
17       While Catalyst::Plugin::Authentication provides the interface to the
18       application developer, the actual work of verifying the credentials and
19       retrieving users is delegated to separate modules. These modules are
20       called Credentials and storage backends, or Stores, respectively. For
21       authentication to function there must be at least one credential and
22       one store. A pairing of a store and a credential is referred to as a
23       Realm. There may be any number of realms defined for an application,
24       though most applications will not require more than one or two.
25
26       The details of using this module can be found in the
27       Catalyst::Plugin::Authentication documentation.
28
29       What follows is an explanation of how the module functions internally
30       and what is required to implement a credential or a store.
31

OVERVIEW

33       There are two main entry points you need to be aware of when writing a
34       store or credential module. The first is initialization and the second
35       is during the actual call to the Catalyst application's authenticate
36       method.
37
38       A simplified description of the authentication process follows:
39
40       Initialization
41
42           Realm Setup - for each realm:
43
44               1) The Realm is instantiated using new() method
45
46               2) The Store is instantiated using new() method
47
48               3) The Credential Instantiated using new() method
49
50               4) Credential and Store objects tied to realm for use during
51               requests
52
53       Authentication
54
55           "$c->authenticate( $userinfo, $realm )" called
56
57               1) Credential object retrieved for realm provided
58
59               2) Credential's authenticate() method called with authinfo and
60               realm object for current realm
61
62                   The realm object and the authinfo hash are provided to the
63                   credential object's authenticate call. In most cases the
64                   credential object will attempt to retrieve a user using the
65                   realm's find_user() method, which by default relays the
66                   call directly to the Store's find_user() method. It will
67                   then usually compare the retrieved user's information with
68                   the information provided in the $authinfo hash. This is how
69                   the default 'Password' credential functions. If the
70                   credentials match, the authenticate() method should return
71                   a user object.
72
73               3) User object stored in session
74
75                   If the user object supports session storage, the
76                   successfully authenticated user will be placed in session
77                   storage. This is done by calling the realm object's
78                   persist_user() method. The persist_user() routine by
79                   default calls the Store's for_session() method, which
80                   should return serialized data (IE a scalar). This
81                   serialized data is passed back to the store via the
82                   from_session() method, so the data should contain enough
83                   information for the store to recreate / reload the user.
84
85       Sessions - Per-Request operations
86
87           When any user-related activity occurs, and $c->authenticate has not
88           yet been called, the Catalyst::Plugin::Authentication module will
89           attempt to restore the persisted user (normally from the session if
90           one is available).  There is only one step in this process:
91
92               1) Store object's from_session() is called
93
94           The serialized data previously returned by the store's
95           for_session() method is provided to the from_session() method. The
96           from_session() method should return a valid user object.
97
98           Note that the for_session() is only called during the original
99           $c->authenticate() call, so if changes are made to the user that
100           need to be reflected in your session data, you will want to call
101           the $c->persist_user() method - which will perform the session
102           storage process again (complete with call to for_session()).
103
104       More detailed information about these processes is below.
105
106   INITIALIZATION
107       When the authentication module is loaded, it reads it's configuration
108       to determine the realms to set up for the application and which realm
109       is to be the default. For each realm defined in the application's
110       config, Catalyst::Plugin::Authentication instantiates both a new
111       credential object and a new store object. See below for the details of
112       how credentials and stores are instantiated.
113
114       NOTE: The instances created will remain active throughout the entire
115       lifetime of the application, and so should be relatively lightweight.
116       Care should be taken to ensure that they do not grow, or retain
117       information per request, because they will be involved in each
118       authentication request and could therefore substantially hurt memory
119       consumption over time.
120
121   AUTHENTICATION
122       When "$c->authenticate()" is called from within an application, the
123       objects created in the initialization process come into play.
124       "$c->authenticate()" takes two arguments. The first is a hash reference
125       containing all the information available about the user. This will be
126       used to locate the user in the store and verify the user's credentials.
127       The second argument is the realm to authenticate against. If the second
128       argument is omitted, the default realm is assumed.
129
130       The main authentication module then locates the credential and store
131       objects for the realm specified and calls the credential object's
132       "authenticate()" method. It provides three arguments, first the
133       application object, or $c, then a reference to the store object, and
134       finally the hashref provided in the "$c->authenticate" call. The main
135       authentication module expects the return value to be a reference to a
136       user object upon successful authentication. If it receives anything
137       aside from a reference, it is considered to be an authentication
138       failure. Upon success, the returned user is marked as authenticated and
139       the application can act accordingly, using "$c->user" to access the
140       authenticated user, etc.
141
142       Astute readers will note that the main Catalyst::Plugin::Authentication
143       module does not interact with the store in any way, save for passing a
144       reference to it to the credential. This is correct. The credential
145       object is responsible for obtaining the user from the provided store
146       using information from the userinfo hashref and/or data obtained during
147       the credential verification process.
148

WRITING A STORE

150       There are two parts to an authentication store, the store object and
151       the user object.
152
153   STORAGE BACKEND
154       Writing a store is actually quite simple.  There are only five methods
155       that must be implemented. They are:
156
157           new()           - instantiates the store object
158           find_user()     - locates a user using data contained in the hashref
159           for_session()   - prepares a user to be stored in the session
160           from_session()  - does any restoration required when obtaining a user from the session
161           user_supports() - provides information about what the user object supports
162
163       STORE METHODS
164
165       new( $config, $app, $realm )
166           The "new()" method is called only once, during the setup process of
167           Catalyst::Plugin::Authentication. The first argument, $config, is a
168           hash reference containing the configuration information for the
169           store module. The second argument is a reference to the Catalyst
170           application.
171
172           Note that when new() is called, Catalyst has not yet loaded the
173           various controller and model classes, nor is it definite that other
174           plugins have been loaded, so your new() method must not rely on any
175           of those being present.  If any of this is required for your store
176           to function, you should defer that part of initialization until the
177           first method call.
178
179           The "new()" method should return a blessed reference to your store
180           object.
181
182       find_user( $authinfo, $c )
183           This is the workhorse of any authentication store. It's job is to
184           take the information provided to it via the $authinfo hashref and
185           locate the user that matches it. It should return a reference to a
186           user object. A return value of anything else is considered to mean
187           no user was found that matched the information provided.
188
189           How "find_user()" accomplishes it's job is entirely up to you, the
190           author, as is what $authinfo is required to contain.  Many stores
191           will simply use a username element in $authinfo to locate the user,
192           but more advanced functionality is possible and you may bend the
193           $authinfo to your needs.  Be aware, however, that both Credentials
194           and Stores usually work with the same $authinfo hash, so take care
195           to avoid overlapping element names.
196
197           Please note that this routine may be called numerous times in
198           various circumstances, and that a successful match for a user here
199           does NOT necessarily constitute successful authentication. Your
200           store class should never assume this and in most cases $c should
201           not be modified by your store object.
202
203       for_session( $c, $user )
204           This method is responsible for preparing a user object for storage
205           in the session.  It should return information that can be placed in
206           the session and later used to restore a user object (using the
207           "from_session()" method).  It should therefore ensure that whatever
208           information provided can be used by the "from_session()" method to
209           locate the unique user being saved.  Note that there is no
210           guarantee that the same Catalyst instance will receive both the
211           "for_session()" and "from_session()" calls.  You should take care
212           to provide information that can be used to restore a user,
213           regardless of the current state of the application.  A good rule of
214           thumb is that if "from_session()" can revive the user with the
215           given information even if the Catalyst application has just started
216           up, you are in good shape.
217
218       from_session( $c, $frozenuser )
219           This method is called whenever a user is being restored from the
220           session.  $frozenuser contains the information that was stored in
221           the session for the user.  This will under normal circumstances be
222           the exact data your store returned from the previous call to
223           "for_session()".  "from_session()" should return a valid user
224           object.
225
226       user_supports( $feature, ...  )
227           This method allows credentials and other objects to inquire as to
228           what the underlying user object is capable of. This is pretty-well
229           free-form and the main purpose is to allow graceful integration
230           with credentials and applications that may provide advanced
231           functionality based on whether the underlying user object can do
232           certain things. In most cases you will want to pass this directly
233           to the underlying user class' "supports" method. Note that this is
234           used as a class method against the user class and therefore must be
235           able to function without an instantiated user object.
236
237   USER OBJECT
238       The user object is an important piece of your store module. It will be
239       the part of the system that the application developer will interact
240       with most. As such, the API for the user object is very rigid. All user
241       objects MUST inherit from Catalyst::Authentication::User.
242
243       USER METHODS
244
245       The routines required by the Catalyst::Plugin::Authentication plugin
246       are below. Note that of these, only get_object is strictly required, as
247       the Catalyst::Authentication::User base class contains reasonable
248       implementations of the rest. If you do choose to implement only the
249       "get_object()" routine, please read the base class code and
250       documentation so that you fully understand how the other routines will
251       be implemented for you.
252
253       Also, your user object can implement whatever additional methods you
254       require to provide the functionality you need. So long as the below are
255       implemented, and you don't overlap the base class' methods with
256       incompatible routines, you should experience no problems.
257
258       id( )
259           The "id()" method should return a unique id (scalar) that can be
260           used to retreive this user from the store.  Often this will be
261           provided to the store's "find_user()" routine as "id => $user->id"
262           so you should ensure that your store's "find_user()" can cope with
263           that.
264
265       supports( $feature, $subfeature ... )
266           This method checks to see if the user class supports a particular
267           feature.  It is implemented such that each argument provides a
268           subfeature of the previous argument. In other words, passing 'foo',
269           'bar'  would return true if the user supported the 'foo' feature,
270           and the 'bar' feature of 'foo'.   This is implemented in
271           Catalyst::Authentication::User, so if your class inherits from
272           that, you do not need to implement this and can instead implement
273           supported_features().
274
275           Note: If you want the authentication module to be able to save your
276           user in the session you must return true when presented with the
277           feature 'session'.
278
279       supported_features( )
280           This method should return a hashref of features supported by the
281           user class.  This is for more flexible integration with some
282           Credentials / applications. It is not required that you support
283           anything, and returning "undef" is perfectly acceptable and in most
284           cases what you will do.
285
286       get( $fieldname )
287           This method should return the value of the field matching fieldname
288           provided, or undef if there is no field matching that fieldname. In
289           most cases this will access the underlying storage mechanism for
290           the user data and return the information. This is used as a
291           standard method of accessing an authenticated user's data, and MUST
292           be implemented by all user objects.
293
294           Note: There is no equivalent 'set' method. Each user class is
295           likely to vary greatly in how data must be saved and it is
296           therefore impractical to try to provide a standard way of
297           accomplishing it. When an application developer needs to save data,
298           they should obtain the underlying object / data by calling
299           get_object, and work with it directly.
300
301       get_object( )
302           This method returns the underlying user object. If your user object
303           is backed by another object class, this method should return that
304           underlying object.  This allows the application developer to obtain
305           an editable object. Generally speaking this will only be done by
306           developers who know what they are doing and require advanced
307           functionality which is either unforeseen or inconsistent across
308           user classes. If your object is not backed by another class, or you
309           need to provide additional intermediate functionality, it is
310           perfectly reasonable to return $self.
311

WRITING A CREDENTIAL

313       Compared to writing a store, writing a credential is very simple.
314       There is only one class to implement, and it consists of only two
315       required routines. They are:
316
317           new()           - instantiates the credential object
318           authenticate()  - performs the authentication and returns a user object
319
320   CREDENTIAL METHODS
321       new( $config, $app, $realm )
322           Like the Store method of the same name, the "new()" method is
323           called only once, during the setup process of
324           Catalyst::Plugin::Authentication. The first argument, $config, is a
325           hash reference containing the configuration information for the
326           credential module. The second argument is a reference to the
327           Catalyst application.  $realm is the instantiated Realm object,
328           which you may use to access realm routines - such as find_user.
329
330           Again, when the credential's new() method is called, Catalyst has
331           not yet loaded the various controller and model classes.
332
333           The new method should perform any necessary setup required and
334           instantiate your credential object.  It should return your
335           instantiated credential.
336
337       authenticate( $c, $realm, $authinfo )
338           This is the workhorse of your credential.  When $c->authenticate()
339           is called the Catalyst::Plugin::Authentication module retrieves the
340           realm object and passes it, along with the $authinfo hash to your
341           credential's authenticate method.  Your module should use the
342           $authinfo hash to obtain the user from the realm passed, and then
343           perform any credential verification steps necessary to authenticate
344           the user.  This method should return the user object returned by
345           the authentication store if credential verification succeeded.  It
346           should return undef on failure.
347
348           How your credential module performs the credential verification is
349           entirely up to you.  In most cases, the credential will retrieve a
350           user from the store first (using the stores find_user() method),
351           and then validate the user's information.  However, this does not
352           have to be the case.
353
354           It is perfectly acceptable for your credential to perform other
355           tasks prior to attempting to retrieve the user from the store. It
356           may also make sense for your credential to perform activities which
357           help to locate the user in question, for example, finding a user id
358           based on an encrypted token.  In these scenarios, the $authinfo
359           hash passed to find_user() can be different than that which is
360           passed in to $c->authenticate(). Once again this is perfectly
361           acceptable if it makes sense for your credential, though you are
362           strongly advised to note this behavior clearly in your credential's
363           documentation - as application authors are almost certainly
364           expecting the user to be found using the information provided to
365           $c->authenticate().
366
367           Look at the Catalyst::Authentication::Credential::Password module
368           source to see this in action.  In order to avoid possible
369           mismatches between the encrypted and unencrypted passwords, the
370           password credential actually removes the provided password from the
371           authinfo array.  It does this because, in many cases, the store's
372           password field will be encrypted in some way, and the password
373           passed to $c->authenticate is almost certainly in plaintext.
374
375           NOTE: You should always assume that a store is going to use all the
376           information passed to it to locate the user in question.  If there
377           are fields in the $authinfo hash that you are sure are specific to
378           your credential, you may want to consider removing them before user
379           retrieval.  A better solution is to place those arguments that are
380           specific to your credential within their own subhash named after
381           your module.
382
383           The Catalyst::Authentication::Store::DBIx::Class module does this
384           in order to encapsulate arguments intended specifically for that
385           module. See the Catalyst::Authentication::Store::DBIx::Class::User
386           source for details.
387

AUTHORS

389       Jay Kuri, "jayk@cpan.org"
390
392       Copyright (c) 2005 the aforementioned authors. All rights reserved.
393       This program is free software; you can redistribute it and/or modify it
394       under the same terms as Perl itself.
395
396
397
398perl v5.12.0                    Ca2t0a0l9y-s1t0:-:1P7lugin::Authentication::Internals(3)
Impressum