Requests and Kerberos
Requests and Kerberos#
The basic flow of a typical Kerberos authentication is as follows:
Client sends an unauthenticated request to the server
Server sends back a 401 response with a
WWW-Authenticate: Negotiate
header with no authentication detailsClient sends a new request with an
Authorization: Negotiate
headerServer checks the
Authorization
header against the Kerberos infrastructure and either allows or denies access accordingly. If access is allowed, it should include aWWW-Authenticate: Negotiate
header with authentication details in the reply.Client checks the authentication details in the reply to ensure that the request came from the server
A sample Python code using Requests
and Kerberos, requests_kerberos.py
:
import requests
import kerberos
import dns.resolver
from requests.compat import urlparse
def myrequests_request(method, url, client_principal=None, **kwargs):
req = requests.request(method, url, **kwargs)
if "Negotiate" in req.headers.get("www-authenticate", ""):
hostname = urlparse(req.url).hostname
canonical_name = dns.resolver.Resolver().query(hostname).canonical_name
ret_code, context = kerberos.authGSSClientInit(f"HTTP@{canonical_name}", principal=client_principal)
kerberos.authGSSClientStep(context, "")
kwargs["headers"] = {**kwargs.get("headers", {}),
**{"Authorization": f"Negotiate {kerberos.authGSSClientResponse(context)}"}}
req = requests.request(method, req.url, **kwargs)
return req
myrequests_get = lambda url, **kwargs: myrequests_request('GET', url, **kwargs)
myrequests_post = lambda url, **kwargs: myrequests_request('POST', url, **kwargs)
req = myrequests_get("http://your.server.com/")
Before running above script, you need to obtain and cache Kerberos ticket-granting tickets (using kinit)
How to create keytab file and run kinit with it
kutil -v -k your.keytab.kt add -p User@your.domain -V 0 -e arcfour-hmac-md5
kinit -kt your.keytab.kt User@your.domain
References: