=head1 NAME CGI::Auth::Flexible - web authentication optionally using cookies =head1 SYNOPSYS my $verifier = CGI::Auth::Flexible->new_verifier(setting => value,...); my $authreq = $verifier->new_request($cgi_query_object); # simple applications $authreq->check_ok() or return; # sophisticated applications my $divert_kind = $authreq->check_divert(); if ($divert_kind) { ... print diversion page and quit ... } # while handling the request $user = $authreq->get_username(); $authreq->check_mutate(); =head1 DESCRIPTION CGI::Auth::Flexible is a library which you can use to add a forms/cookie-based login facility to a Perl web application. CGI::Auth::Flexible doesn't interfere with your application's URL path namespace and just needs a few (configurable) form parameter and cookie name(s) for its own use. It tries to avoid making assumptions about the implementation structure of your application. Because CGI::Auth::Flexible is licenced under the AGPLv3, you will probably need to provide a facility to allow users (even ones not logged in) to download the source code for your web app. Conveniently by default CGI::Auth::Flexible provides (for pure Perl webapps) a mechanism for users to get the source. CGI::Auth::Flexible is designed to try to stop you accidentally granting access by misunderstanding the API. (Also it, of course, guards against cross-site scripting.) You do need to make sure to call CGI::Auth::Flexible before answering AJAX requests as well as before generating HTML pages, of course, and to call it in every entrypoint to your system. =head2 INITIALISATION Your application should, on startup (eg, when it is loaded by mod_perl) do C<< $verifier = CGI::Auth::Flexible->new_verifier(settings...) >>. This call can be expensive and is best amortised. The resulting verifier object can be used to process individual requests, in each case with C<< $authreq = CGI::Auth::Flexible->new_request($cgi_query) >>. =head2 SIMPLE APPLICATIONS The simplist usage is to call C<< $request->check_ok() >> which will check the user's authentication. If the user is not logged in it will generate a login form (or redirection or other appropriate page) and return false; your application should not then processing that request any further. If the user is logged in it will return true. After calling C you can use C<< $request->get_username >> to find out which user the request came from. =head2 SOPHISTICATED APPLICATIONS If you want to handle the flow control and to generate login forms, redirections, etc., yourself, you can say C<< $divert = $request->check_divert >>. This returns undef if the user is logged in, or I if some kind of login page or diversion should be generated. =head2 GENERATING (MUTATING) FORMS AND AJAX QUERIES When you generate a C form or AJAX request you need to include a special secret hidden form parameter for the benefit of CGI::Auth::Generic. This form parameter will be checked by C/C and should be ignored by your application. By default the hidden parameter is called C. After calling C or C the value to put in your form can be obtained from C; C will generate the whole HTML C<< >> element. Do not put the secret value in URLs for C requests. =head2 NON-PAGE RESOURCES Some, but not all, non-page resources (fetched with GET) need to have the secret hidden parameter in the query parameters in the form url. So if your application supports anything except HTML pages you need to take special measures. (Wholly invariant resources which don't depend on which user is logged in are an exception.) When you generate a url to such a resource you must call resource_get_needs_secret_hidden to find out whether to include the hidden form parameter xxx fixme You can only when logged in call C when you are processing one of these. You need to supply a parameter specifying exactly what kind of resource this is: before you generate any output (other than =head2 MUTATING OPERATIONS AND EXTERNAL LINKS INTO YOUR SITE By default CGI::Auth::Flexible does not permit external links into your site. All GET requests give a "click to continue" page which submits a form which loads your app's main page. In this configuration all your application's forms and AJAX requests should use C. This restriction arises from complicated deficiencies in the web's security architecture. The alternative is for your application to always make a special check when the incoming request is going to do some kind of action (such as modifying the user's setup, purchasing goods, or whatever) rather than just display HTML pages. Then non-mutating pages can be linked to from other, untrustworthy, websites. To support external links, and C requests, pass C<< promise_check_mutate => 1 >> in I, and then call C<< $authreq->check_mutate() >> before taking any actions. If the incoming request is not suitable then C<< $authreq->check_mutate() >> will call C. You must make sure that you have no mutating C requests in your application - but you shouldn't have any of those anyway. =head2 DATA STORAGE CGI::Auth::Flexible needs to store various information in plain files; it does this in the directory specified by the C parameter. =head1 SOURCE CODE DOWNLOAD By default, CGI::Auth::Flexible provides a facility for users to download the source code for the running version of your web application. This facility makes a number of important assumptions which you need to check. Note that if the provided facility is not sufficient because your application is more sophisticated than it copes with (or if you disable the builtin facility), you may need to implement a functioning alternative to avoid violating the AGPLv3 licence. Here are the most important (default) assumptions: =over =item * Your app's source code is available by looking at @INC, $0 and S<$ENV{'SCRIPT_FILENAME'}> (the B). See C. Where these point to files or directories under revision control, the source item is the whole containing vcs tree. =item * Specifically, there are no compiled or autogenerated Perl files, Javascript resources, etc., which are not contained in one of the source item directories. (Files which came with your operating system install don't need to be shipped as they fall under the system library exceptio.) =item * You have not installed any modified versions of system libraries (including system-supplied) Perl modules in C outside C. See C. =item * For each source item in a dvcs, the entire dvcs history does not contain anything confidential (or libellous). Also, all files which contain secrets are in the dvcs's C<.ignore> file. See C et al. =item * For each source item NOT in a dvcs, there are no confidential files with the world-readable bit set (being in a world-inaccessible directory is not sufficient). See C. =item * You have none of your app's source code in C. =item * You don't regard pathnames on your server as secret. =item * You don't intentionally load Perl code by virtule of C<.> being in C<@INC> by default. (See C.) =back =head1 MAIN FUNCTIONS AND METHODS =over =item C<< CGI::Auth::Flexible->new_verifier(setting => value, ...) >> Initialises an instance and returns a verifier object. The arguments are setting pairs like a hash initialiser. See L below. =item C<< $verifier->new_request($cgi_query) >> Prepares to process a request. C<$cgi_query> should normally be the query object from L. Most of the default hook methods assume that it is; however if you replace enough of the hook methods then you can pass any value you like and it will be passed to your hooks. The return value is the authentication request object (C<$authreq>) which is used to check the incoming request and will contain information about its credentials. =item C<< $authreq->check_divert() >> Checks whether the user is logged in. Returns undef if the user is logged in and we should service the request. Otherwise returns a divert spec (see L) saying what should happen instead. This method may die if it doesn't like the request, in which case the request needs to be rejected. =item C<< $authreq->check_ok() >> Checks whether the user is logged in. Returns true if the user is logged in and we should service the request. Otherwise it handles the request itself, generating any appropriate redirect, login form, or continuation page. It then returns false and the application should not process the request further. =item C<< $verifier->disconnect() >> Discards the resources (open files, etc.) in the verifier object. =back