Provided by: libcatalyst-plugin-authentication-perl_0.10024-1_all bug

NAME

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

INTRODUCTION

       Catalyst::Plugin::Authentication provides a standard authentication interface to application developers
       using the Catalyst framework. It is designed to allow application developers to use various methods of
       user storage and credential verification. It is also designed to provide for minimal change to the
       application when switching between different storage and credential verification methods.

       While Catalyst::Plugin::Authentication provides the interface to the application developer, the actual
       work of verifying the credentials and retrieving users is delegated to separate modules. These modules
       are called Credentials and storage backends, or Stores, respectively. For authentication to function
       there must be at least one credential and one store. A pairing of a store and a credential is referred to
       as a Realm. There may be any number of realms defined for an application, though most applications will
       not require more than one or two.

       The details of using this module can be found in the Catalyst::Plugin::Authentication documentation.

       What follows is an explanation of how the module functions internally and what is required to implement a
       credential or a store.

OVERVIEW

       There are two main entry points you need to be aware of when writing a store or credential module. The
       first is initialization and the second is during the actual call to the Catalyst application's
       authenticate method.

       A simplified description of the authentication process follows:

       Initialization

           Realm Setup - for each realm:

               1) The Realm is instantiated using new() method

               2) The Store is instantiated using new() method

               3) The Credential Instantiated using new() method

               4) Credential and Store objects tied to realm for use during requests

       Authentication

           "$c->authenticate( $userinfo, $realm )" called

               1) Credential object retrieved for realm provided

               2) Credential's authenticate() method called with authinfo and realm object for current realm

                   The realm object and the authinfo hash are provided to the credential object's authenticate
                   call. In most cases the credential object will attempt to retrieve a user using the realm's
                   find_user() method, which by default relays the call directly to the Store's find_user()
                   method. It will then usually compare the retrieved user's information with the information
                   provided in the $authinfo hash. This is how the default 'Password' credential functions. If
                   the credentials match, the authenticate() method should return a user object.

               3) User object stored in session

                   If the user object supports session storage, the successfully authenticated user will be
                   placed in session storage. This is done by calling the realm object's persist_user() method.
                   The persist_user() routine by default calls the Store's for_session() method, which should
                   return serialized data (IE a scalar). This serialized data is passed back to the store via
                   the from_session() method, so the data should contain enough information for the store to
                   recreate / reload the user.

       Sessions - Per-Request operations

           When any user-related activity occurs, and $c->authenticate has not yet been called, the
           Catalyst::Plugin::Authentication module will attempt to restore the persisted user (normally from the
           session if one is available).  There is only one step in this process:

               1) Store object's from_session() is called

           The serialized data previously returned by the store's for_session() method is provided to the
           from_session() method. The from_session() method should return a valid user object.

           Note that the for_session() is only called during the original $c->authenticate() call, so if changes
           are made to the user that need to be reflected in your session data, you will want to call the
           $c->persist_user() method - which will perform the session storage process again (complete with call
           to for_session()).

       More detailed information about these processes is below.

   INITIALIZATION
       When the authentication module is loaded, it reads it's configuration to determine the realms to set up
       for the application and which realm is to be the default. For each realm defined in the application's
       config, Catalyst::Plugin::Authentication instantiates both a new credential object and a new store
       object. See below for the details of how credentials and stores are instantiated.

       NOTE: The instances created will remain active throughout the entire lifetime of the application, and so
       should be relatively lightweight.  Care should be taken to ensure that they do not grow, or retain
       information per request, because they will be involved in each authentication request and could therefore
       substantially hurt memory consumption over time.

   AUTHENTICATION
       When "$c->authenticate()" is called from within an application, the objects created in the initialization
       process come into play.  "$c->authenticate()" takes two arguments. The first is a hash reference
       containing all the information available about the user. This will be used to locate the user in the
       store and verify the user's credentials. The second argument is the realm to authenticate against. If the
       second argument is omitted, the default realm is assumed.

       The main authentication module then locates the credential and store objects for the realm specified and
       calls the credential object's authenticate() method. It provides three arguments, first the application
       object, or $c, then a reference to the store object, and finally the hashref provided in the
       "$c->authenticate" call. The main authentication module expects the return value to be a reference to a
       user object upon successful authentication. If it receives anything aside from a reference, it is
       considered to be an authentication failure. Upon success, the returned user is marked as authenticated
       and the application can act accordingly, using "$c->user" to access the authenticated user, etc.

       Astute readers will note that the main Catalyst::Plugin::Authentication module does not interact with the
       store in any way, save for passing a reference to it to the credential. This is correct. The credential
       object is responsible for obtaining the user from the provided store using information from the userinfo
       hashref and/or data obtained during the credential verification process.

WRITING A STORE

       There are two parts to an authentication store, the store object and the user object.

   STORAGE BACKEND
       Writing a store is actually quite simple.  There are only five methods that must be implemented. They
       are:

           new()           - instantiates the store object
           find_user()     - locates a user using data contained in the hashref
           for_session()   - prepares a user to be stored in the session
           from_session()  - does any restoration required when obtaining a user from the session
           user_supports() - provides information about what the user object supports

       STORE METHODS

       new( $config, $app, $realm )
           The  new()  method is called only once, during the setup process of Catalyst::Plugin::Authentication.
           The first argument, $config, is a hash reference containing the  configuration  information  for  the
           store module. The second argument is a reference to the Catalyst application.

           Note that when new() is called, Catalyst has not yet loaded the various controller and model classes,
           nor  is it definite that other plugins have been loaded, so your new() method must not rely on any of
           those being present.  If any of this is required for your store to function, you  should  defer  that
           part of initialization until the first method call.

           The new() method should return a blessed reference to your store object.

       find_user( $authinfo, $c )
           This is the workhorse of any authentication store. It's job is to take the information provided to it
           via the $authinfo hashref and locate the user that matches it. It should return a reference to a user
           object.  A  return  value  of  anything else is considered to mean no user was found that matched the
           information provided.

           How find_user() accomplishes it's job is entirely up to you, the author,  as  is  what  $authinfo  is
           required to contain.  Many stores will simply use a username element in $authinfo to locate the user,
           but  more advanced functionality is possible and you may bend the $authinfo to your needs.  Be aware,
           however, that both Credentials and Stores usually work with the same $authinfo hash, so take care  to
           avoid overlapping element names.

           Please  note  that  this  routine  may  be called numerous times in various circumstances, and that a
           successful match for a user here does NOT  necessarily  constitute  successful  authentication.  Your
           store  class  should  never  assume  this  and  in most cases $c should not be modified by your store
           object.

       for_session( $c, $user )
           This method is responsible for preparing a user object for storage in the session.  It should  return
           information  that  can  be  placed  in the session and later used to restore a user object (using the
           from_session() method).  It should therefore ensure that whatever information provided can be used by
           the from_session() method to locate the unique user being saved.  Note that  there  is  no  guarantee
           that  the  same  Catalyst instance will receive both the for_session() and from_session() calls.  You
           should take care to provide information that can be used to restore a user, regardless of the current
           state of the application.  A good rule of thumb is that if from_session() can revive  the  user  with
           the given information even if the Catalyst application has just started up, you are in good shape.

       from_session( $c, $frozenuser )
           This  method  is called whenever a user is being restored from the session.  $frozenuser contains the
           information that was stored in the session for the user.  This will under normal circumstances be the
           exact data your store returned from the previous call to for_session().  from_session() should return
           a valid user object.

       user_supports( $feature, ...  )
           This method allows credentials and other objects to inquire as to what the underlying user object  is
           capable  of. This is pretty-well free-form and the main purpose is to allow graceful integration with
           credentials and applications that may provide advanced functionality based on whether the  underlying
           user  object  can  do  certain  things.  In  most  cases  you  will want to pass this directly to the
           underlying user class' "supports" method. Note that this is used as a class method against  the  user
           class and therefore must be able to function without an instantiated user object.

       OPTIONAL STORE METHODS

       If you want your store to be able to auto- create users, then you can implement these methods:

       auto_update_user( $authinfo, $c, $res )

       This method is called if the realm's auto_update_user setting is true.

       auto_create_user( $authinfo, $c )

       This method is called if the realm's auto_create_user setting is true.

   USER OBJECT
       The  user  object  is an important piece of your store module. It will be the part of the system that the
       application developer will interact with most. As such, the API for the user object is  very  rigid.  All
       user objects MUST inherit from Catalyst::Authentication::User.

       USER METHODS

       The  routines required by the Catalyst::Plugin::Authentication plugin are below. Note that of these, only
       get_object is strictly required, as the Catalyst::Authentication::User  base  class  contains  reasonable
       implementations of the rest. If you do choose to implement only the get_object() routine, please read the
       base class code and documentation so that you fully understand how the other routines will be implemented
       for you.

       Also, your user object can implement whatever additional methods you require to provide the functionality
       you  need.  So  long  as  the  below  are implemented, and you don't overlap the base class' methods with
       incompatible routines, you should experience no problems.

       id( )
           The id() method should return a unique id (scalar) that can be used to retrieve this  user  from  the
           store.   Often  this  will be provided to the store's find_user() routine as "id => $user->id" so you
           should ensure that your store's find_user() can cope with that.

       supports( $feature, $subfeature ... )
           This method checks to see if the user class supports a particular feature.  It  is  implemented  such
           that  each  argument  provides  a subfeature of the previous argument. In other words, passing 'foo',
           'bar'  would return true if the user supported the 'foo' feature, and the  'bar'  feature  of  'foo'.
           This  is  implemented  in Catalyst::Authentication::User, so if your class inherits from that, you do
           not need to implement this and can instead implement supported_features().

           Note: If you want the authentication module to be able to save your user  in  the  session  you  must
           return true when presented with the feature 'session'.

       supported_features( )
           This  method  should  return  a  hashref  of  features supported by the user class.  This is for more
           flexible integration with some Credentials / applications.  It  is  not  required  that  you  support
           anything, and returning "undef" is perfectly acceptable and in most cases what you will do.

       get( $fieldname )
           This method should return the value of the field matching fieldname provided, or undef if there is no
           field  matching  that  fieldname. In most cases this will access the underlying storage mechanism for
           the user data and return the information.  This  is  used  as  a  standard  method  of  accessing  an
           authenticated user's data, and MUST be implemented by all user objects.

           Note: There is no equivalent 'set' method. Each user class is likely to vary greatly in how data must
           be  saved  and it is therefore impractical to try to provide a standard way of accomplishing it. When
           an application developer needs to save data, they should obtain  the  underlying  object  /  data  by
           calling get_object, and work with it directly.

       get_object( )
           This  method  returns  the  underlying  user  object. If your user object is backed by another object
           class, this method should return that underlying object.  This allows the  application  developer  to
           obtain an editable object. Generally speaking this will only be done by developers who know what they
           are  doing  and require advanced functionality which is either unforeseen or inconsistent across user
           classes. If your object  is  not  backed  by  another  class,  or  you  need  to  provide  additional
           intermediate functionality, it is perfectly reasonable to return $self.

WRITING A CREDENTIAL

       Compared  to writing a store, writing a credential is very simple.  There is only one class to implement,
       and it consists of only two required routines. They are:

           new()           - instantiates the credential object
           authenticate()  - performs the authentication and returns a user object

   CREDENTIAL METHODS
       new( $config, $app, $realm )
           Like the Store method of the same name, the new() method  is  called  only  once,  during  the  setup
           process  of  Catalyst::Plugin::Authentication.  The  first  argument,  $config,  is  a hash reference
           containing the configuration information  for  the  credential  module.  The  second  argument  is  a
           reference to the Catalyst application.  $realm is the instantiated Realm object, which you may use to
           access realm routines - such as find_user.

           Again,  when  the  credential's  new()  method  is  called,  Catalyst  has not yet loaded the various
           controller and model classes.

           The new method should perform any necessary setup required and instantiate  your  credential  object.
           It should return your instantiated credential.

       authenticate( $c, $realm, $authinfo )
           This   is   the   workhorse   of   your   credential.    When   $c->authenticate()   is   called  the
           Catalyst::Plugin::Authentication module retrieves the realm object and  passes  it,  along  with  the
           $authinfo  hash  to your credential's authenticate method.  Your module should use the $authinfo hash
           to obtain the user from the  realm  passed,  and  then  perform  any  credential  verification  steps
           necessary  to  authenticate  the  user.   This  method  should return the user object returned by the
           authentication store if credential verification succeeded.  It should return undef on failure.

           How your credential module performs the credential verification is  entirely  up  to  you.   In  most
           cases,  the  credential  will  retrieve  a  user  from  the store first (using the stores find_user()
           method), and then validate the user's information.  However, this does not have to be the case.

           It is perfectly acceptable for your credential to perform other tasks prior to attempting to retrieve
           the user from the store. It may also make sense for your credential to perform activities which  help
           to locate the user in question, for example, finding a user id based on an encrypted token.  In these
           scenarios,  the $authinfo hash passed to find_user() can be different than that which is passed in to
           $c->authenticate(). Once again this is perfectly acceptable if it makes sense  for  your  credential,
           though you are strongly advised to note this behavior clearly in your credential's documentation - as
           application  authors  are  almost  certainly  expecting  the  user  to be found using the information
           provided to $c->authenticate().

           Look at the Catalyst::Authentication::Credential::Password module source to see this in  action.   In
           order  to  avoid  possible  mismatches  between the encrypted and unencrypted passwords, the password
           credential actually removes the provided password from the authinfo array.  It does this because,  in
           many  cases,  the  store's  password  field will be encrypted in some way, and the password passed to
           $c->authenticate is almost certainly in plaintext.

           NOTE: You should always assume that a store is going to use all  the  information  passed  to  it  to
           locate  the  user  in  question.   If  there  are  fields in the $authinfo hash that you are sure are
           specific to your credential, you may want to consider removing them before user retrieval.  A  better
           solution  is  to  place those arguments that are specific to your credential within their own subhash
           named after your module.

           The Catalyst::Authentication::Store::DBIx::Class module does this in order to  encapsulate  arguments
           intended  specifically  for  that  module. See the Catalyst::Authentication::Store::DBIx::Class::User
           source for details.

AUTHORS

       Jay Kuri, "jayk@cpan.org"

COPYRIGHT & LICENSE

       Copyright (c) 2005 the aforementioned authors. All rights reserved. This program is  free  software;  you
       can redistribute it and/or modify it under the same terms as Perl itself.

perl v5.40.0                                       2024-10-28              Catalyst::Plug...tion::Internals(3pm)