Apache Kerberos Authentication and basic authentication fallback

Many businesses and organizations use Active Directory or other LDAP-based authentication systems, and many web applications (like Drupal) can easily integrate with them for authentication and user account provisioning.

The Kerberos Module for Apache allows users to be automatically logged into your web application, by passing through their credentials behind the scenes. This makes for a seamless user experience—the user never needs to log into your web application if the user is authenticated on his local machine.

A standard configuration for Kerberos authentication inside your Apache configuration file looks like:

<Directory "/path/to/site/root">
    # By default, allow access to anyone.
    Order allow,deny
    Allow from All

    # Enable Kerberos authentication using mod_auth_kerb.
    AuthType Kerberos
    AuthName "Your Web Application"
    KrbAuthRealm example.com
    Krb5KeyTab "/path/to/krb5.keytab"
    KrbMethodNegotiate on
    KrbSaveCredentials on
    KrbVerifyKDC on
    KrbServiceName Any
    Require valid-user
</Directory>

However, if you use this configuration, users who aren't authenticated via Kerberos will be prompted to log in using basic authentication by their browser:

HTTP Basic Authentication Dialog Window Prompt

This browser-based auth dialog is not very user-friendly, and can't contain any branding or other information besides the string you define as the AuthName. Your web application probably has it's own login screen that looks nicer, allows users to manage passwords like they do with other websites, and already integrates with LDAP/AD behind the scenes.

So, to disable/ignore the basic authentication when automatic Kerberos authentication fails, you need to modify your config to be like the following:

<Directory "/path/to/site/root">
    # By default, allow access to anyone.
    Order allow,deny
    Allow from All
    # Require authentication for internal private network users.
    Deny from 10.0.0.0/8

    # Enable Kerberos authentication using mod_auth_kerb.
    AuthType Kerberos
    AuthName "Your Web Application"
    KrbAuthRealm example.com
    Krb5KeyTab "/path/to/krb5.keytab"
    KrbMethodNegotiate on
    KrbSaveCredentials on
    KrbVerifyKDC on
    KrbServiceName Any
    Require valid-user

    Satisfy Any
</Directory>

Removing Require valid-user and adding Satisfy Any tells Apache to still attempt Kerberos authentication, but if that fails, allow access anyways. Then your web application can take care of the authentication using it's own screen/mechanism.

Read more:

Comments

This sounds great. But it's not working for me. If I add Satisfy Any and remove "Require valid-user" the request will be passed anyway but there is no REMOTE_USER visible in php. :(

Thank you, this is very helpful. It has saved me a great deal of time and trouble.

This method did not work for me, it simply skips all Kerberos authentication. I believe the suggested behaviour is not how Apache was intended to work - having both 'Satisfy Any' and 'Allow from All' set means every request is valid without needing to attempt Kerberos authentication. I believe it's been discussed in various threads before but AFAIK there is no 'attempt authentication but don't worry if it fails' setting.

Jeff, can you confirm that using this config the Kerberos auth was actually taking place? Otherwise this post may be misleading to others.

I can confirm that the exact code in this post was working (and well tested) when I posted the article. There are a few major caveats, though—the order of the statements is important, the configuration on the server itself, the location and permissions of the kerberos keytab files, etc.

We had to test 8 different user login scenarios, and all 8 worked with this configuration :)

I can confirm authentication bypass if "Require valid-user" is omitted. Used the same configration as in this post even with the same ordering of the statements. There is no authentication without "Require valid-user". Using mod_auth_kerb 5.4-2.1 and apache2 2.4.7. Is there a way to force the authentication?

I can confirm that it's working if you Deny your local subnet.

Then on your local subnet you will be logged in via Kerberos. If you are outside the defined subnet Kerberos authentification will be ignored.

Regards

The problem with the "deny" Access control is that you fill up your logs with error messages.
In Apache 2.4 you can use if expressions, here is an working example wich i am using:

AuthType Kerberos
Krb5Keytab /etc/krb5.keytab
KrbAuthRealms MY.DOMAIN
Require valid-user

Regards Richi

Thanks for the clear explanation, it helped me with several hurdles. It sort of works for my setup. I have a simple network of a KDC, an Apache server, and a workstation as 3 separate boxes. I can use kerberized SSH to log in to either server just fine. But Apache is not quite right. Shouldn't I see the http service principal on the workstation when I do klist, after I log in ? And should I just be able to log in to apache after doing having done ssh. It feels like all I am getting is a page cache for my efforts. Do you have any pointers to help unravel my blunder ?
Thanks

FYI, apache debug logs show:
AH01626: authorization result of : denied (no authenticated user yet)
kerb_authenticate_user entered with user (NULL) and auth_type Kerberos
Using http/www.example.org@ as server principal for password verification
Trying to get TGT for user [email protected]
Trying to verify authenticity of KDC using principal http/www.example.org@
kerb_authenticate_user_krb5pwd ret=0 user=[email protected] authtype=Basic
authorization result of Require user [email protected] granted
AH01626: authorization result of : granted

Thanks for this. Doesn't exactly match my use case but it helped point me in the right direction. One question, though... you say "Removing Require valid-user and adding Satisfy Any tells Apache to still attempt Kerberos authentication..." but 'valid-user' is still present in your second example. I assume that's an oversight... just pointing it out... thanks!