5 CGI::Auth::Flexible - web authentication optionally using cookies
9 my $verifier = CGI::Auth::Flexible->new_verifier(setting => value,...);
10 my $authreq = $verifier->new_request($cgi_query_object);
13 $authreq->check_ok() or return;
15 # sophisticated applications
16 my $divert_kind = $authreq->check_divert();
17 if ($divert_kind) { ... print diversion page and quit ... }
19 # while handling the request
20 $user = $authreq->get_username();
21 $authreq->check_mutate();
25 CGI::Auth::Flexible is a library which you can use to add a
26 forms/cookie-based login facility to a Perl web application.
28 CGI::Auth::Flexible doesn't interfere with your application's URL path
29 namespace and just needs a few (configurable) form parameter and
30 cookie name(s) for its own use. It tries to avoid making assumptions
31 about the implementation structure of your application.
33 Because CGI::Auth::Flexible is licenced under the AGPLv3, you will
34 probably need to provide a facility to allow users (even ones not
35 logged in) to download the source code for your web app. Conveniently
36 by default CGI::Auth::Flexible provides (for pure Perl webapps) a
37 mechanism for users to get the source.
39 CGI::Auth::Flexible is designed to try to stop you accidentally
40 granting access by misunderstanding the API. (Also it, of course,
41 guards against cross-site scripting.) You do need to make sure to
42 call CGI::Auth::Flexible before answering AJAX requests as well as
43 before generating HTML pages, of course, and to call it in every
44 entrypoint to your system.
48 As a minimum you need to do all of the things on this checklist, where
49 applicable. The items marked SECURITY are the ones that you might
50 forget: without them your application may appear to work, but will be
57 Call C<new_verifier> (once at application startup)
61 Call C<new_request> (once per request)
65 B<SECURITY>: Call C<check_ok> or C<check_divert> on every request, and
66 honour the return value.
70 If you're using C<check_ok>, implement either the
71 C<username_password_error> or C<login_ok> hook.
75 Call C<get_username> when you need to know who's logged in.
79 B<SECURITY>: Call C<check_mutate> or C<mutate_ok>, if you specified
80 C<promise_check_mutate>.
84 B<SECURITY>: Call C<check_nonpage> for every request which is not a page load
85 (if your application has any of those).
89 When generating URLs and forms (including AJAX requests), include the
90 hidden form parameter using C<secret_hidden_val> or
91 C<secret_hidden_html> when appropriate (see below).
95 B<SECURITY>: If you do not override the source provision facility (see
96 L</SOURCE CODE DOWNLOAD>), check that the assumptions it makes aren't
97 going to leak security-critical data.
101 These points will now be covered in more detail.
103 =head2 INITIALISATION
105 Your application should, on startup (eg, when it is loaded by
107 C<< $verifier = CGI::Auth::Flexible->new_verifier(settings...) >>.
108 This call can be expensive and is best amortised.
110 The resulting verifier object can be used to process individual
111 requests, in each case with
112 C<< $authreq = CGI::Auth::Flexible->new_request($cgi_query) >>.
114 =head2 RESPONSES - SIMPLE APPLICATIONS
116 The simplist usage is to call C<< $request->check_ok() >> which will
117 check the user's authentication. If the user is not logged in it will
118 generate a login form (or redirection or other appropriate page) and
119 return false; your application should not then processing that request
120 any further. If the user is logged in it will return true.
122 Various hooks are provided to customise the responses generated by
125 After C<check_ok> returns true you should go ahead and process the
126 request; you can use C<< $request->get_username >> to find out which
127 user the request came from.
129 =head2 RESPONSES - SOPHISTICATED APPLICATIONS
131 If you want to handle the control flow and to generate login forms,
132 redirections, etc., yourself, you can say
133 C<< $divert = $request->check_divert >>. This returns undef if
134 the user is logged in, or I<divert spec> if some kind of login
135 page or diversion should be generated.
137 =head2 MUTATING OPERATIONS AND EXTERNAL LINKS - MUTATION-IGNORANT APPLICATIONS
139 By default CGI::Auth::Flexible does not permit external links into
140 your site. All GET requests give a "click to continue" page which
141 submits a form which loads your app's main page. In this
142 configuration all your application's forms and AJAX requests should
143 use C<POST>. This restriction arises from complicated deficiencies
144 in the web's security architecture.
146 Such applications are also not able to provide user-specific CSS
147 stylesheets, javascript, favicons, etc.
149 =head2 MUTATING OPERATIONS AND EXTERNAL LINKS - MUTATION-AWARE APPLICATIONS
151 The alternative is for your application to always make a special check
152 when the incoming request is going to do some kind of action (such as
153 modifying the user's setup, purchasing goods, or whatever) rather than
154 just retrieve and/or display information. We term such requests
157 Then non-mutating pages can be linked to from other, untrustworthy,
160 To support external links, and C<GET> requests, pass
161 C<< promise_check_mutate => 1 >> in I<settings>, and then call
162 C<< $authreq->check_mutate() >> before taking any actions. If the
163 incoming request is not suitable then C<< $authreq->check_mutate() >>
166 There have to be no mutating C<GET> requests in your application (but
167 you shouldn't have any of those anyway); if there are, they won't
168 work. (CGI::Auth::Flexible will spot them and cause them to fail,
169 rather than allow them to be insecure.)
171 =head2 GENERATING URLS, FORMS AND AJAX QUERIES
173 When you generate a URL, C<POST> form or AJAX request you may need to
174 include a secret hidden form parameter for the benefit of
175 CGI::Auth::Generic. This form parameter will be checked by
176 C<check_ok>/C<check_divert> and should be ignored by your application.
178 By default the hidden parameter is called C<caf_assochash>.
180 After calling C<check_ok> or C<check_divert> the value to put in your
181 form can be obtained from C<secret_hidden_val>; C<secret_hidden_html>
182 will generate the whole HTML C<< <input...> >> element.
184 =head3 Mutation-ignorant applications
186 For mutation-ignorant applications (see above), all forms etc. should
187 include the hidden parameter (and as discussed, they must all use
188 POST rather than GET).
190 =head3 Mutation-aware applications
192 For mutation-aware applications, whether to include the secret
193 parameter depends on the kind of request. CGI::Auth::Flexible knows
194 when it is necessary. You should find out by calling
197 If it is inconvenient to call C<need_add_hidden> at runtime, you can
198 rely instead on the following promises: All POST requests (which
199 includes all mutating requests) need the parameter. The return value
200 of need_add_hidden depends only on the $method and $reqtype
201 parameters, so you can query it once and remember the answer.
202 HTML page load GETs do not need the parameter. It is better to
203 err on the side of including the parameter.
205 If you really must, you can call C<need_add_hidden> "on the bench"
206 during development and bake the answer into your application code
207 structure. However, if you do that and a new vulnerability was
208 discovered which is fixed by changing the answer, updating
209 CGI::Auth::Flexible wouldn't be sufficient to fix it.
211 =head3 Mutation-aware applications - non-page requests
213 If your mutation-aware application supports non-page resources (AJAX
214 and JSON requests, stylesheets, favicons, etc.) it must inform
215 CGI::Auth::Flexible when it is handling such a request, by calling
218 Normally C<check_nonpage> will simply return (and you can ignore the
219 return value). However, if there is an attack (or, perhaps, a bug) it
220 will die, stopping the attack.
222 (You do not need to call C<check_nonpage> for POST requests, but it is
227 CGI::Auth::Flexible needs to store various information in plain files;
228 it does this in the directory specified by the C<dir> parameter.
230 =head1 SOURCE CODE DOWNLOAD
232 By default, CGI::Auth::Flexible provides a facility for users to
233 download the source code for the running version of your web
236 This facility makes a number of important assumptions which you need
237 to check. Note that if the provided facility is not sufficient
238 because your application is more sophisticated than it copes with (or
239 if you disable the builtin facility), you may need to implement a
240 functioning alternative to avoid violating the AGPLv3 licence.
242 Here are the most important (default) assumptions:
248 Your app's source code is available by looking at @INC, $0 and
249 S<$ENV{'SCRIPT_FILENAME'}> (the B<source items>). See
250 C<srcdump_listitems>. Where these point to files or directories under
251 revision control, the source item is the whole containing vcs tree.
255 Specifically, there are no compiled or autogenerated Perl
256 files, Javascript resources, etc., which are not contained in one of
257 the source item directories. (Files which came with your operating
258 system install don't need to be shipped as they fall under the system
263 You have not installed any modified versions of system
264 libraries (including system-supplied Perl modules) in C</usr> outside
265 C</usr/local>. See C<srcdump_system_dir>.
269 For each source item in a dvcs, the entire dvcs history does
270 not contain anything confidential (or libellous). Also, all files which
271 contain secrets are in the dvcs's C<.ignore> file. See
272 C<srcdump_vcsscript_git> et al.
276 For each source item NOT in a dvcs, there are no confidential
277 files with the world-readable bit set (being in a world-inaccessible
278 directory is not sufficient). See C<srcdump_excludes>.
282 You have none of your app's source code in C</etc>.
286 You don't regard pathnames on your server as secret.
290 You don't intentionally load Perl code by virtue of C<.>
291 being in C<@INC> by default. (See C<srcdump_filter_cwd>.)
295 =head1 MAIN FUNCTIONS AND METHODS
299 =item C<< CGI::Auth::Flexible->new_verifier(setting => value, ...) >>
301 Initialises an instance and returns a verifier object.
302 The arguments are setting pairs like a hash initialiser.
303 See L</SETTINGS> below.
305 =item C<< $verifier->new_request($cgi_query) >>
307 Prepares to process a request. C<$cgi_query> should normally
308 be the query object from L<CGI(3perl)>. Most of the default
309 hook methods assume that it is; however if you replace enough of
310 the hook methods then you can pass any value you like and it
311 will be passed to your hooks.
313 The return value is the authentication request object (C<$authreq>)
314 which is used to check the incoming request and will contain
315 information about its credentials.
317 =item C<< $authreq->check_divert() >>
319 Checks whether the user is logged in. Returns undef if the user is
320 logged in and we should service the request. Otherwise returns a
321 divert spec (see L</DIVERT SPEC>) saying what should happen instead.
323 This method may die if it doesn't like the request, in which case
324 the request needs to be rejected.
326 =item C<< $authreq->check_ok() >>
328 Checks whether the user is logged in. Returns true if the user is
329 logged in and we should service the request.
331 Otherwise it handles the request itself, generating any appropriate
332 redirect, login form, or continuation page. It then returns false and
333 the application should not process the request further.
335 =item C<< $verifier->disconnect() >>
337 Discards the resources (open files, etc.) in the verifier object.