Overriding Raven authentication for parts of a site

From RavenWiki
Revision as of 13:27, 21 June 2006 by jml4 (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

[NB Primarily relevant to Apache servers using mod_ucam_webauth, though also relevant to other authentication mechanisms on Apache.]

One problem with Apache authentication (Basic Auth, Raven via mod_ucam_webauth, etc.) is that the configuration settings (AuthType etc.) are "inherited". In consequence, if you enable Raven authentication in a <Location /> block, it will apply e.g. to /error-pages, which may be a problem if you have custom error pages that should be shown for login failures (user cancelled logins, cookies not working, etc.).

Apache does not provide a built-in way to override inherited AuthType etc. - there's no "AuthType None" - so the only solution (that I've found) is to add a pair of "null" authentication and authorisation handlers and specify those.

If the Apache server has been built with mod_perl support, there is an easy Perl-based way to add such "null" handlers.

Just add (in perl.conf or equivalent if the Perl configuration is in a separate file, otherwise httpd.conf or wherever seems best)

<perl>
{
    package Ucam::Apache::AuthNull;
    use strict;
    use Apache::Constants qw(:common);
    use Apache::Log;

    sub handler
    {
        my $r = shift;
        return DECLINED if lc($r->auth_type) ne 'ucam-authnull';
        my $uri = $r->uri;
        $r->log->debug("AuthNull for $uri");
        return OK;
    }


    package Ucam::Apache::AuthzNull;
    use strict;
    use Apache::Constants qw(:common);
    use Apache::Log;

    sub handler
    {
        my $r = shift;
        return DECLINED if lc($r->auth_type) ne 'ucam-authnull';
        my $uri = $r->uri;
        $r->log->debug("AuthZNull for $uri");
        my $requires = $r->requires;
        foreach my $req (@$requires)
        {
            my $value = lc($req->{'requirement'});
            if ($value eq 'any-user') { $r->user('AuthNull'); return OK; }
            else
            {
                $r->server->log->warn("AuthzNull: bad 'require' type $value");
                return DECLINED;        # maybe another module will say OK
            }
        }
        return OK;                       
    }

}
</perl>

PerlAuthenHandler Ucam::Apache::AuthNull
PerlAuthzHandler Ucam::Apache::AuthzNull

and then in whichever file (e.g. http.conf) contains the access control details include

<Location /error-pages>
 Order deny,allow
 Allow from all
# In order for Ucam-AuthNull to take precedence over Ucam-WebAuth (Raven),
# we appear to need Satisfy all (not any).
 Satisfy all
 Require any-user
 AuthType Ucam-AuthNull
</Location>

and the AuthType etc., should override any inherited Raven or Basic Auth configuration for URLs with the specified prefix (and similarly for directory-based access controls).

Caveats, cautions and other comments

  • I've only tried the above with the Apache 1.3.29 server that's included in SUSE's SLES9 Linux distribution, and in particular it would need adjustments for the Apache 2 version of mod_perl due to incompatible mod_perl changes.
  • For reasons which I've not investigated, simply specifying "Satisfy any" does not have the expected effect of allowing access according to the address-based controls and involving the authentication module only if address-based access is denied. It only works with "Satisfy all".
  • It's not clear whether the auth handler is required to set a username, or the potential consequences if it doesn't, so it returns dummy user "AuthNull".
  • Rather than "Require valid-user", you must specify "Require any-user", chosen to make clear that it's not applying any restrictions. Any/all users (that meet address-based restrictions) will be allowed access.
  • The main purpose of the debug-level logging calls is to provide a way of confirming that the handlers really are being invoked, if they don't seem to be working.

jml4 14:27, 21 June 2006 (BST)