chiark / gitweb /
docs: more work
[cgi-auth-flexible.git] / caf.pod
diff --git a/caf.pod b/caf.pod
index 8e2d1932959df9ba521718339a4a86aa05fd16c5..5dd2f07fb56ebe9ddecf6dc4955489022f74190e 100644 (file)
--- a/caf.pod
+++ b/caf.pod
@@ -1,3 +1,5 @@
+# -*- fundamental -*-
+
 =head1 NAME
 
 CGI::Auth::Flexible - web authentication optionally using cookies
@@ -41,6 +43,63 @@ 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 CHECKLIST
+
+As a minimum you need to do all of the things on this checklist, where
+applicable.  The items marked SECURITY are the ones that you might
+forget: without them your application may appear to work, but will be
+insecure.
+
+=over
+
+=item *
+
+Call C<new_verifier> (once at application startup)
+
+=item *
+
+Call C<new_request> (once per request)
+
+=item *
+
+B<SECURITY>: Call C<check_ok> or C<check_divert> on every request, and
+honour the return value.
+
+=item *
+
+If you're using C<check_ok>, implement either the
+C<username_password_error> or C<login_ok> hook.
+
+=item *
+
+Call C<get_username> when you need to know who's logged in.
+
+=item *
+
+B<SECURITY>: Call C<check_mutate> or C<mutate_ok>, if you specified
+C<promise_check_mutate>.
+
+=item *
+
+B<SECURITY>: Call C<check_nonpage> for every request which is not a page load
+(if your application has any of those).
+
+=item *
+
+When generating URLs and forms (including AJAX requests), include the
+hidden form parameter using C<secret_hidden_val> or
+C<secret_hidden_html> when appropriate (see below).
+
+=item *
+
+B<SECURITY>: If you do not override the source provision facility (see
+L</SOURCE CODE DOWNLOAD>), check that the assumptions it makes aren't
+going to leak security-critical data.
+
+=back
+
+These points will now be covered in more detail.
+
 =head2 INITIALISATION
 
 Your application should, on startup (eg, when it is loaded by
@@ -52,7 +111,7 @@ 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
+=head2 RESPONSES - 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
@@ -60,45 +119,43 @@ 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<check_ok> you can use C<< $request->get_username >>
-to find out which user the request came from.
+Various hooks are provided to customise the responses generated by
+C<check_ok>.
 
-=head2 SOPHISTICATED APPLICATIONS
+After C<check_ok> returns true you should go ahead and process the
+request; you can use C<< $request->get_username >> to find out which
+user the request came from.
 
-If you want to handle the flow control and to generate login forms,
+=head2 RESPONSES - SOPHISTICATED APPLICATIONS
+
+If you want to handle the control flow 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<divert spec> if some kind of login
 page or diversion should be generated.
 
-=head2 GENERATING (MUTATING) FORMS AND AJAX QUERIES
-
-When you generate a C<POST> 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<check_ok>/C<check_divert> and should be ignored by your application.
-
-By default the hidden parameter is called C<caf_assochash>.  After
-calling C<check_ok> or C<check_divert> the value to put in your form
-can be obtained from C<secret_hidden_val>; C<secret_hidden_html> will
-generate the whole HTML C<< <input...> >> element.
-
-Do not put the secret value in URLs for C<GET> requests.
-
-=head2 MUTATING OPERATIONS AND EXTERNAL LINKS INTO YOUR SITE
+=head2 MUTATING OPERATIONS AND EXTERNAL LINKS - MUTATION-IGNORANT APPLICATIONS
 
 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<POST>.  This restriction arises from complicated deficiencies
-in the web's security architecture.  
+in the web's security architecture.
+
+Such applications are also not able to provide user-specific CSS
+stylesheets, javascript, favicons, etc.
+
+=head2 MUTATING OPERATIONS AND EXTERNAL LINKS - MUTATION-AWARE APPLICATIONS
 
 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.
+just retrieve and/or display information.  We term such requests
+"mutating" requests.
+
+Then non-mutating pages can be linked to from other, untrustworthy,
+websites.
 
 To support external links, and C<GET> requests, pass
 C<< promise_check_mutate => 1 >> in I<settings>, and then call
@@ -106,8 +163,64 @@ C<< $authreq->check_mutate() >> before taking any actions.  If the
 incoming request is not suitable then C<< $authreq->check_mutate() >>
 will call C<die>.
 
-You must make sure that you have no mutating C<GET> requests in your
-application - but you shouldn't have any of those anyway.
+There have to be no mutating C<GET> requests in your application (but
+you shouldn't have any of those anyway); if there are, they won't
+work.  (CGI::Auth::Flexible will spot them and cause them to fail,
+rather than allow them to be insecure.)
+
+=head2 GENERATING URLS, FORMS AND AJAX QUERIES
+
+When you generate a URL, C<POST> form or AJAX request you may need to
+include a secret hidden form parameter for the benefit of
+CGI::Auth::Generic.  This form parameter will be checked by
+C<check_ok>/C<check_divert> and should be ignored by your application.
+
+By default the hidden parameter is called C<caf_assochash>.
+
+After calling C<check_ok> or C<check_divert> the value to put in your
+form can be obtained from C<secret_hidden_val>; C<secret_hidden_html>
+will generate the whole HTML C<< <input...> >> element.
+
+=head3 Mutation-ignorant applications
+
+For mutation-ignorant applications (see above), all forms etc. should
+include the hidden parameter (and as discussed, they must all use
+POST rather than GET).
+
+=head3 Mutation-aware applications
+
+For mutation-aware applications, whether to include the secret
+parameter depends on the kind of request.  CGI::Auth::Flexible knows
+when it is necessary.  You should find out by calling
+C<need_add_hidden>.
+
+If it is inconvenient to call C<need_add_hidden> at runtime, you can
+rely instead on the following promises:  All POST requests (which
+includes all mutating requests) need the parameter.  The return value
+of need_add_hidden depends only on the $method and $reqtype
+parameters, so you can query it once and remember the answer.
+HTML page load GETs do not need the parameter.  It is better to
+err on the side of including the parameter.
+
+If you really must, you can call C<need_add_hidden> "on the bench"
+during development and bake the answer into your application code
+structure.  However, if you do that and a new vulnerability was
+discovered which is fixed by changing the answer, updating
+CGI::Auth::Flexible wouldn't be sufficient to fix it.
+
+=head3 Mutation-aware applications - non-page requests
+
+If your mutation-aware application supports non-page resources (AJAX
+and JSON requests, stylesheets, favicons, etc.) it must inform
+CGI::Auth::Flexible when it is handling such a request, by calling
+C<check_nonpage>.
+
+Normally C<check_nonpage> will simply return (and you can ignore the
+return value).  However, if there is an attack (or, perhaps, a bug) it
+will die, stopping the attack.
+
+(You do not need to call C<check_nonpage> for POST requests, but it is
+harmless to do so.)
 
 =head2 DATA STORAGE
 
@@ -143,19 +256,19 @@ 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.)
+library exception.)
 
 =item *
 
 You have not installed any modified versions of system
-libraries (including system-supplied) Perl modules in C</usr> outside
+libraries (including system-supplied Perl modules) in C</usr> outside
 C</usr/local>.  See C<srcdump_system_dir>.
 
 =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
+contain secrets are in the dvcs's I<.ignore> file.  See
 C<srcdump_vcsscript_git> et al.
 
 =item *
@@ -174,7 +287,7 @@ You don't regard pathnames on your server as secret.
 
 =item *
 
-You don't intentionally load Perl code by virtule of C<.>
+You don't intentionally load Perl code by virtue of C<.>
 being in C<@INC> by default.  (See C<srcdump_filter_cwd>.)
 
 =back
@@ -191,13 +304,13 @@ See L</SETTINGS> below.
 
 =item C<< $verifier->new_request($cgi_query) >>
 
-Prepares to process a request.  C<$cgi_query> should normally
+Prepares to process a request.  I<$cgi_query> should normally
 be the query object from L<CGI(3perl)>.  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>)
+The return value is the authentication request object (I<$authreq>)
 which is used to check the incoming request and will contain
 information about its credentials.
 
@@ -224,3 +337,47 @@ the application should not process the request further.
 Discards the resources (open files, etc.) in the verifier object.
 
 =back
+
+=head REQUEST-HANDLING FUNCTIONS AND METHODS
+
+All of these are only valid after C<check_divert> or C<check_ok> has
+been called.  (In the case of C<check_ok> it won't normally be sensible
+to call these functions unless C<check_ok> returned true.)
+
+=item C<< $authreq->get_divert() >>
+
+Returns the value previously returned by C<check_divert>.
+
+=item C<< $authreq->get_username() >>
+
+Returns the name of the logged-in user.  If the user was not logged
+in (or their session had timed out, or something), returns undef.
+
+=head RESPONSE-RELATED FUNCTIONS AND METHODS
+
+=item C<< $authreq->url_with_query_params($params, [$nonpagetype]) >>
+
+Convenience function which returns a url for a GET request to this
+application.
+
+I<$params> is a hashref specifying the parameters and the PATH_INFO.
+The keys are the parameter names, and the values are array refs with
+the parameter value(s) (as strings, as yet unquoted).  (They are array
+refs because it is possible to pass multiple values for the same
+parameter in a single request; normally each arrayref would be a
+singleton.)
+
+The request path will be the path to the application.  If a parameter
+with name C<< '' >> is supplied, it is taken as the PATH_INFO to
+supply - its value will be appended to the application path.  (It
+should normally start with C<< / >>, and only one value should be
+supplied.)
+
+=item C<< $authreq->chain_params() >>
+
+Returns a hash of the "relevant" parameters to this request, in a form
+used by XXX.  This is all of the query parameters which are not
+related to CGI::Auth::Flexible.  The PATH_INFO from the request is
+returned as the parameter C<< '' >>.
+
+=back