Search code examples
apacheflaskkerberos

Request to Kerberos authenticated API considered unauthorized despite having kerberos ticket in authorization header


I am trying to call a Flask API endpoint (http://monarch.example.com:8080/) hosted in Apache web server in a Linux machine. This endpoint is protected by Kerberos authentication. I use kinit user to initialize Kerberos. Then I am using python kerberos library to get the ticket and requests library for the api call. I am providing the ticket in the Authorization header of the request. Relevant code snippet for that:

`__, krb_context = kerberos.authGSSClientInit("HTTP@monarch.example.com")
kerberos.authGSSClientStep(krb_context, "")
auth_header = ("Negotiate " + kerberos.authGSSClientResponse(krb_context))
headers = {"Authorization": auth_header}`

I have checked that the Authorization header is populated with a value. However I get 401-unauthorized as response.

The Kerberos configuration from /etc/apache2/sites-available/monarch.conf for the Service containing the endpoint is:

<Directory /var/www/monarch>
       AuthType Kerberos
       AuthName "Acme Corporation"
       KrbAuthRealms EXAMPLE.COM
       KrbMethodNegotiate Off
       KrbSaveCredentials Off
       KrbVerifyKDC Off
       KrbMethodK5Passwd On
       # Krb5Keytab /etc/apache2/http.keytab
       Krb5keytab /etc/krb5.keytab
       Require user user@EXAMPLE.COM
</Directory>

Lastly, the list of principals is:

host/monarch.example.com@EXAMPLE.COM
HTTP/monarch.example.com@EXAMPLE.COM
K/M@EXAMPLE.COM
kadmin/admin@EXAMPLE.COM
kadmin/changepw@EXAMPLE.COM
krbtgt/EXAMPLE.COM@EXAMPLE.COM
user@EXAMPLE.COM
root/admin@EXAMPLE.COM

And the list of keys from /etc/krb5.keytab is:

slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    2     host/monarch.example.com@EXAMPLE.COM
   2    2     host/monarch.example.com@EXAMPLE.COM
   3    2     HTTP/monarch.example.com@EXAMPLE.COM
   4    2     HTTP/monarch.example.com@EXAMPLE.COM

I have been stuck with this problem for a few days now. It would be great if anyone can help me in this regard.


Solution

  • You're trying to send a 'Negotiate' auth token but you've disabled the actual method – that's what KrbMethodNegotiate Off did.

    The only thing you've left enabled is "kpasswd", i.e. HTTP Basic auth where the server merely validates the password against a Kerberos KDC. (And on top of that, you even disabled KrbVerifyKDC, the lack of which makes the password-check subject to trivial KDC spoofing attacks.)

    Do not add unnecessary options; all you need is Krb5Keytab.

    Although in 2023 you probably should not use mod_auth_kerb in general. You should be using mod_auth_gssapi.


    Similarly, use pyspnego or python-gssapi instead of python-kerberos; they still use the same libgssapi underneath, but they have a more pleasant Python API. (And maybe do not use those directly, either – use requests-kerberos or requests-gssapi or urllib-gssapi or httpx-gssapi.)