File Coverage

blib/lib/Apache2/AuthAny.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Apache2::AuthAny;
2              
3 1     1   30247 use strict;
  1         3  
  1         47  
4 1     1   2394391 use Data::Dumper qw(Dumper);
  1         12640  
  1         87  
5 1     1   471 use Apache2::Module ();
  0            
  0            
6             use Apache2::ServerUtil ();
7             use Apache2::Const -compile => qw(OR_AUTHCFG TAKE1 TAKE2 OR_ALL FLAG ITERATE :log);
8              
9              
10             =head1 NAME
11              
12             Apache2::AuthAny - Authentication with any provider or mechanism
13              
14             =head1 VERSION
15              
16             Version 0.201
17              
18             =cut
19              
20             our $VERSION = '0.201';
21              
22             =head1 SYNOPSIS
23              
24             Apache configuration ...
25              
26             PerlSetEnv AUTH_ANY_ROOT /usr/share/authany
27             PerlSetEnv AUTH_ANY_CONFIG_ROOT /etc/authany
28             PerlSetEnv AUTH_ANY_DB mysql
29             PerlSetEnv AUTH_ANY_DB_PW_FILE /etc/authany/db-passwd
30             PerlSetEnv AUTH_ANY_DB_USER authany
31             PerlSetEnv AUTH_ANY_DB_NAME auth_any
32             #PerlSetEnv AUTH_ANY_DB_HOST remote_host_if_needed
33            
34             PerlRequire /usr/share/authany/startup.pl
35             PerlLoadModule Apache2::AuthAny
36              
37            
38             DocumentRoot /var/www/htdocs
39             ...
40              
41             # for Apache2::AuthAny
42            
43             AuthType Basic
44             AuthName AABasic
45             AuthUserFile /etc/authany/config/htpasswd
46             Require valid-user
47            
48              
49            
50             AuthType shibboleth
51             ShibRequireSessionWith UW
52             ShibRequestSetting forceAuthn 1
53             Require valid-user
54            
55             # ...
56            
57              
58             Contents of /var/www/htdocs/private/.htaccess
59              
60             AuthType auth-any
61             AuthAnyGateURL /our-gate/gate.php
62             Require role our_project_administrators
63             Require user john_the_ceo
64              
65             Contents of /var/www/htdocs/our-gate/gate.php
66              
67             ...
68            

Select the method you would like to use to log in:

69            
70            
71            
72             UW Shibboleth Login
73            
74            
75             ...
76              
77             =head1 DESCRIPTION
78              
79             Apache2::AuthAny is extensible authentication layer providing support for any authentication mechanism or provider.
80              
81             AuthAny registers handlers for the Apache headerParser,
82             authentication, fixup, and response phases. The Authentication phase
83             handler checks for existance of an "AA_PID" cookie. If this cookie is
84             not found or not associated with a logged in user, the handler returns
85             a redirect to a gateway ("GATE") page. The gate page offers a link for
86             each identity provider. Each of these URLs (beginning with
87             "/aa_auth/") is protected by a different authentication module
88             configured with standard Apache "" directives and
89             appropriate "Require" directives. If authentication succeeds, the
90             "AA_PID" cookie is set in the browser and in the AuthAny
91             database. Apache redirects to the originally requested URL. Since the
92             cookie now exists, access is permitted.
93              
94             =head2 Environment Variables
95              
96             AuthAny passes environment variables to applications running in
97             the response phase.
98              
99             =head3 REMOTE_USER
100              
101             If the user has successfully authenticated with one of the
102             providers, the "REMOTE_USER" variable gets set. If the
103             userId/provider has an entry in the userIdent table, "REMOTE_USER"
104             will be set to the username value in the user table. Otherwise, it
105             will be set to |
106              
107             "REMOTE_USER" is a standard variable set by all Apache
108             authentication modules. Without the identity resolution provided
109             by AuthAny, the protected application would need to perform this
110             function. (assuming we wish to consider someone logging in with
111             multiple providers as the same person)
112              
113             =head3 AA_USER
114              
115             Set to the identity supplied by the provider.
116              
117             =head3 AA_PROVIDER
118              
119             Set to the provider or authentication mechanisim name.
120              
121             =head3 AA_SESSION
122              
123             Set to 1 if the user has logged in the current browser
124             session.
125              
126             =head3 AA_TIMEOUT
127              
128             This variable is set if the user's session has not yet timed
129             out. The value is the number of seconds that can elapse before the
130             user gets timed out.
131              
132             =head3 AA_STATE
133              
134             This value can be one of "logged_out", "recognized", or
135             "authenticated". A user who has never logged in, has removed their
136             "AA_PID" cookie, or has logged out will be in the "logged_out"
137             state. After signing in, AA_STATE will be "authenticated", however
138             if 'AA_TIMEOUT' seconds have elapsed since the last time a URL was
139             accessed, the user is timed out, and AA_STATE will change to
140             "recognized".
141              
142              
143             =head3 AA_IDENTITIES
144              
145             An identified user might have more than authId|provider
146             combination that they can log in with. This variable is set to a
147             list of all the user's identities
148              
149             =head3 AA_ROLES
150              
151             This variable will be set only if the user is identified, and
152             there are roles associated with that user in the userRole table.
153              
154             Environment variables beginning with "AA_IDENT_" take their values
155             from the "user" table, and are only set if the user is identified.
156              
157             =head3 AA_IDENT_UID
158              
159             Set to the primary key in the user table.
160              
161             =head3 AA_IDENT_username
162              
163             Same as REMOTE_USER for identified users.
164              
165             =head3 AA_IDENT_active
166              
167             Users whose "active" value is not "1" are denied access to
168             directories protected with any "Require" directive (eg. "Require
169             valid-user")
170              
171             In addition to the above, the value of any field in the "user" table
172             will be passed as AA_IDENT_. The demo database includes "firstName",
173             "lastName", and "created".
174              
175             =head2 Logout
176              
177             AuthAny provides a logout feature that allows the user to log out
178             without closing her browser. The feature has two functions. It sets
179             the state in the database to "logged_out". It also logs the user out
180             of Basic auth and Shibboleth. Without the second function, a user
181             would simply be able to click again on the GATE's provider link and
182             get right back into the protected application. Google authentication
183             is not included in this second logout function, however Google's login
184             state is set to expire after about a minute, after which the user must
185             log in again.
186              
187             =cut
188              
189             my %level = (error => Apache2::Const::LOG_ERR,
190             warn => Apache2::Const::LOG_WARNING,
191             notice => Apache2::Const::LOG_NOTICE,
192             info => Apache2::Const::LOG_INFO,
193             debug => Apache2::Const::LOG_DEBUG,
194             );
195              
196             __PACKAGE__->init;
197              
198             sub init {
199             my $self = shift;
200              
201             my @directives = (
202             {
203             name => 'AuthAnyGateURL',
204             args_how => Apache2::Const::TAKE1,
205             errmsg => 'Custom GATE page',
206             },
207              
208             {
209             name => 'AuthAnySkipAuthentication',
210             args_how => Apache2::Const::ITERATE,
211             errmsg => 'Usage: AuthAnySkipAuthentication uri-pattern1 [uri-pattern2 ...]',
212             },
213              
214             {
215             name => 'AuthAnyBasicAuthUserFile',
216             req_override => Apache2::Const::OR_ALL,
217             args_how => Apache2::Const::TAKE1,
218             errmsg => 'Basic auth .htpasswd file',
219             },
220              
221             {
222             name => 'AuthAnyTimeout',
223             args_how => Apache2::Const::TAKE1,
224             errmsg => 'seconds',
225             },
226              
227              
228             );
229              
230             eval {
231             Apache2::Module::add($self, \@directives);
232             my $s = Apache2::ServerUtil->server;
233             $s->push_handlers( PerlMapToStorageHandler =>
234             'Apache2::AuthAny::MapToStorageHandler' );
235             $s->push_handlers( PerlHeaderParserHandler =>
236             'Apache2::AuthAny::RequestConfig' );
237             };
238             warn $@ if $@;
239              
240             }
241              
242             =head1 DIRECTIVES
243              
244             =head2 AuthAnyGateURL (required)
245              
246             If a user needs to log in, she is redirected to a GATE page which
247             contains a list of provider links. This directive defines
248             the URL to the gate page.
249              
250             =cut
251              
252             sub AuthAnyGateURL {
253             my ($self, $params, $arg) = @_;
254             $self->{AuthAnyGateURL} = $arg;
255             }
256              
257             =head2 AuthAnySkipAuthentication
258              
259             This directive accepts a list of URL patterns for which
260             the autentication and authorization phases will be skipped.
261              
262             =cut
263              
264             sub AuthAnySkipAuthentication {
265             my ($self, $params, $arg) = @_;
266             push @{$self->{AuthAnySkipAuthentication}}, $arg;
267             }
268              
269             =head2 AuthAnyBasicAuthUserFile
270              
271             The basic authentication user file for interactive login is defined
272             in the Apache configuration. This directive allows a basic auth
273             user file to be checked with each request to a protected resource.
274             In this way, the request can include an HTTP "Authorization" header
275             to allow scripting. No AA_AUTH cookie is required.
276              
277             =cut
278              
279             sub AuthAnyBasicAuthUserFile {
280             my ($self, $params, $arg) = @_;
281             $self->{AuthAnyBasicAuthUserFile} = $arg;
282             }
283              
284             =head2 AuthAnyTimeout
285              
286             This directive allows a default timeout to be set, after which
287             an "authenticated" user will become only "recognized". The value
288             set by AuthAnyTimeout can be overridden for any identified user
289             by specifying a "timeout" value in the "auth_user" db table.
290              
291             =cut
292              
293             sub AuthAnyTimeout {
294             my ($self, $params, $arg) = @_;
295             $self->{AuthAnyTimeout} = $arg;
296             }
297              
298             =head2 AuthType auth-any (required)
299              
300             This directive turns AuthAny on and causes AuthAny's environment
301             variables to be passed to code running in the response phase.
302              
303             =head2 Require
304              
305             =head3 Require valid-user
306              
307             The user must sign in with any mechanism/provider however
308             the user need not be in the userIdent db table.
309              
310             =head3 Require identified-user
311              
312             The user must have an entry in the userIdent and user table, and
313             not be in a deactivated state.
314              
315             =head3 Require user
316              
317             The specified users are allowed. Note, users who do not have an entry
318             in the userIdent table are seen by the system as "id|provider". For
319             example if you want to grant access to the user "john" when logging in
320             using "basic" authentication, and john does not have an entry in the
321             userIdent table, you would use the following directive:
322              
323             Require user john|basic
324              
325             =head3 Require role
326              
327             Users holding the specified roles are allowed access
328              
329             =head3 Require authenticated
330              
331             Users are not permitted if they they have timed out and thus are no
332             longer authenticated.
333              
334             =head3 Require session
335              
336             Users are not permitted if they they haven't logged in the current
337             browser session. This allows the administrator to force logout when
338             the user exits her browser.
339              
340             =head1 ISSUES
341              
342             =head2 mod_dir ignores AuthType
343              
344             If a request is made to a directory, mod_dir will try to use one
345             of the index file names specified by "DirectoryIndex". It appears
346             that mod_dir is ignoring the "AuthName auth-any" directive and is
347             trying to use basic authentication resulting in errors such as,
348              
349             "configuration error: couldn't check user. No user file?: /gossamer/index.php"
350              
351             A workaround is to use mod_rewrite on directories:
352              
353             RewriteEngine On
354             RewriteRule ^gossamer/$ /gossamer/index.php
355             RewriteRule ^$ /gossamer/index.php
356              
357             =head1 TODO
358              
359             =head2 Google authentication
360              
361             Google authentication is directly included in Apache2::AuthAny,
362             rather than being set up through Apache configuration. This
363             was done because at the time when AuthAny was written, Attribute
364             Exchange was not available through mod_auth_openID. Once an
365             acceptable OpenID library is found and tested that will run
366             in the authentication phase, the Google authentication
367             should be removed from the codebase.
368              
369             =head2 GATE API
370              
371             A variety of error messages are made available to the GATE page.
372             (timeout, unknown user, no role, etc). A PHP file is provided
373             that makes it easy to implement a GATE page. The administrator
374             might prefer not to use PHP for the GATE page, so the GATE error
375             API should be clarified, and documented.
376              
377             =head2 Server errors
378              
379             There are some system errors, such as an unavailable database
380             that will send the user to the GATE page with a "Technical
381             Difficulties" error message. Errors such as this should
382             probably produce a server error (500) and be handled by
383             a seperately defined custom ErrorDocument.
384              
385             =head1 AUTHOR
386              
387             Kim Goldov, C<< >>
388              
389             =head1 ACKNOWLEDGEMENTS
390              
391             AuthAny was developed at the Clinical Informatics Research Group of
392             the University of Washington. Supporting staff included,
393              
394             Eric Webster
395             Justin McReynolds
396             Bill Lober
397             Debra Revere
398             Paul Bugni
399             Svend Sorensen
400             Blaine Reeder
401              
402             =head1 COPYRIGHT & LICENSE
403              
404             Copyright (c) 2010-2011, University of Washington
405              
406             This program is free software; you can redistribute it and/or modify it
407             under the same terms as Perl itself.
408              
409             =cut
410              
411             1; # End of Apache2::AuthAny