The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

APACHE 2.4 PORTING NOTES

VERY IMPORTANT!!!

Apache 2.4 has a VERY different authentication API from previous versions. You will not be able to simply ugrade apache and upgrade AuthCookie in order to migrate to Apache 2.4. You will also need to port your AuthCookie subclass over to the Apache 2.4 API, and update your Apache configuration for Apache 2.4.

This document attempts to help you understand the changes required and how to port your module over to Apache 2.4. If your subclass stopped working when you migrated to Apache 2.4, please make sure you have read and understand everything in this document before filing a bug report.

Changes Required to Run Under Apache 2.4

Mod Perl

You need at least mod_perl version 2.0.9, which is the first official release to support Apache 2.4.

Apache::Test

You need Apache::Test version 1.39 or later. Previous versions do not define the constant APACHE2_4 which is needed for the test suite.

Your AuthCookie Subclass
  • Your module must inherit from Apache2_4::AuthCookie instead of Apache2::AuthCookie

  • You must change every method that was called as a PerlAuthzHandler under previous versions to return one of the following values:

    Apache2::Const::AUTHZ_DENIED_NO_USER

    return this constant if $r->user is empty/undefined and you do not wish to allow anonymous access.

    Apache2::Const::AUTHZ_DENIED

    return this constant if $r->user is not authorized for the current request.

    Apache2::Const::AUTHZ_GRANTED

    return this constant if $r->user is authorized for the current request

    Apache2::Const::AUTHZ_GENERAL_ERROR

    return this constant to indicate an error processing authz requirements.

    Apache2::Const::AUTHZ_NEUTRAL

    return this constant to indicate a neutral response. It is assumed that another authz provider will be checked in a parent/sibling scope that will return granted or denied.

httpd.conf
  • Remove all PerlAuthzHandler entries. PerlAuthzHandler does not exist in Apache 2.4.

  • Depending on what your Require directives say, you may need to add one or more top level PerlAddAuthzProvider entires and implement a handler for each one.

    If your Require directives are simply valid-user or user ... then you do not need to do this. Apache already provides an authz provider that handles user and valid-user requirements for you in mod_authz_user.

    AuthCookie does provide a authz_handler for these requirements for backwards compatibility with previous versions, but the one provided by Apache is preferred.

  • If you are Require'ing anything other than valid-user or user ... then you will need to write your own Authz Provider method and register it with Apache.

    Authz Providers are the Apache 2.4 equivalent of a PerlAuthzHandler method. Each one implements a specific requirement. E.g.:

     PerlAddAuthzProvider species My::AuthCookieHandler->authz_species

    Will be called to handle a

     Require species klingon

    Directive.

    It is important to know that Authz Providers are called twice for a request. First, the authz provider is called before authentication has been processed to check for anonymous access. In this method call, $r->user is not set. You are expected to return one of:

    AUTHZ_GRANTED

    Access is granted and no further authn/authz processing will occur for this request.

    AUTHZ_DENIED
    AUTHZ_NEUTRAL

    The response is HTTP_FORBIDDEN (unless neutral is overridden by another provider)

    AUTHZ_DENIED_NO_USER

    Authentication is processed, $r->user will be set with the current username and your authz provider will be called again.

    The second time the authz provider is called, $r->user is set and you are expected to return one of:

    AUTHZ_GRANTED

    The request is allowed

    AUTHZ_DENIED

    The request is forbidden

    AUTHZ_NEUTRAL

    The request is forbidden, unless another authz provider returns AUTHZ_GRANTED. Consult the apache documentation about authorization merging for more info.

    You could also return AUTHZ_GENERAL_ERROR from any of these to indicate an error processing authz directives and halt processing immediately.

    One way to think about these response codes what kind of Require satisfies is in effect:

    RequireAll/RequireNone

    In this case the priority of responses is:

    AUTHZ_GENERAL_ERROR

    Processing stops immediately

    AUTHZ_DENIED

    Processing stops immediately, no siblings are processed. Request is denied.

    AUTHZ_DENIED_NO_USER

    Process Authentication and try again

    AUTHZ_GRANTED

    Continue processing siblings.

    AUTZ_NEUTRAL

    Continue processing siblings.

    RequireAny

    In this case the priority of responses is:

    AUTHZ_GENERAL_ERROR

    Processing stops immediately

    AUTHZ_GRANTED

    Processing stops immediately, no siblings are processed. Request is allowed.

    AUTHZ_DENIED_NO_USER

    Process Authentication and try again

    AUTHZ_DENIED

    Continue processing siblings.

    AUTZ_NEUTRAL

    Continue processing siblings.

Important Internal API Changes for Apache 2.4

authorize() has been removed

You need to use a PerlAddAuthzProvider and write an appropriate handler as described above instead. Note that you do not need a PerlAddAuthzProvider for user or valid-user requirements. Apache already handles those internally.

${auth_name}Satisfy

Satisfy support is removed as it is no longer needed with Apache 2.4.

You are expected to use RequireAll or RequireAny instead.

e.g.:

    PerlAddAuthzProvider species Your::AuthCookieHandler->authz_species_handler

    <RequireAll>
      Require valid-user
      Require species klingon
    </RequireAll>

see: https://httpd.apache.org/docs/2.4/howto/auth.html#reqaccessctrl

Unauthorized User HTTP Response Code

In Apache 2.4, in mod_authz_core, if no authz handlers return AUTHZ_GRANTED, then HTTP_UNAUTHORIZED is returned. In previous versions of Apache, HTTP_FORBIDDEN was returned. You can get the old behaviour if you want it with:

    AuthzSendForbiddenOnFailure On

FREQUENTLY ASKED QUESTIONS

  • Why is my authz method called twice per request?

    This is normal behaviour under Apache 2.4. This is to accomodate for authorization of anonymous access. You are expected to return Apache2::Const::AUTHZ_DENIED_NO_USER IF $r->user has not yet been set if you want authentication to proceed. Your authz handler will be called a second time after the user has been authenticated.

  • My log shows an entry like:

     authorization result of Require ...: denied (no + # authenticated user yet)

    These are normal. This happens because the authz provider returned AUTHZ_DENIED_NO_USER and the authz provider will be called again after authentication happens.