Inspecting Kerberos Tickets and Using Them with Python Requests
Kerberos provides ticket-based authentication for services in an Active Directory or other Kerberos realm. Instead of sending a password to every service, a client first obtains a ticket-granting ticket (TGT). It can then request service tickets and present them to the relevant services.
This post covers three practical tasks:
- Obtaining and inspecting Kerberos tickets with
kinitandklist - Checking Windows device and Azure AD registration with
dsregcmd /status - Sending HTTP requests with Kerberos authentication from Python
Obtain a Ticket with kinit
On Linux, macOS, and other systems with MIT Kerberos tools installed, use kinit to authenticate and create a TGT in the local credential cache:
kinit user@EXAMPLE.COM
Enter the password when prompted. If the command succeeds, it normally produces no output. The ticket is stored in the credential cache, commonly /tmp/krb5cc_<uid> on Linux.
For a keytab-based, non-interactive login, use:
kinit -kt /path/to/service.keytab HTTP/service.example.com@EXAMPLE.COM
Keytabs are sensitive credentials. Restrict their file permissions and do not commit them to source control.
Inspect Tickets with klist
Run klist to display the credentials currently in the cache:
klist
Typical output contains the default principal, the credential cache location, and ticket validity times:
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user@EXAMPLE.COM
Valid starting Expires Service principal
07/17/2026 09:00:00 07/17/2026 19:00:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM
The krbtgt/EXAMPLE.COM@EXAMPLE.COM entry is the TGT. Once an application connects to a Kerberos-protected service, klist may also show a service ticket such as HTTP/api.example.com@EXAMPLE.COM.
If a ticket has expired, obtain a new one with kinit. To remove cached credentials explicitly, run:
kdestroy
On Windows, the built-in klist command can inspect the tickets held by the current logon session:
klist
Check Windows Device Registration
Kerberos authentication in enterprise environments can depend on the device’s identity and its relationship to Active Directory or Microsoft Entra ID. On Windows, use the following command from a Command Prompt or PowerShell session:
dsregcmd /status
Review the Device State and User State sections. Common fields include:
| Field | Meaning |
|---|---|
AzureAdJoined |
The device is joined to Microsoft Entra ID. |
DomainJoined |
The device is joined to an on-premises Active Directory domain. |
WorkplaceJoined |
A work or school account is registered on the device. |
AzureAdPrt |
A Primary Refresh Token is available for the signed-in user. |
For example, a hybrid-joined device often reports both AzureAdJoined : YES and DomainJoined : YES. A device that should use integrated authentication but reports an unexpected join state may need device-registration or policy investigation before debugging the application itself.
dsregcmd /status reports device and user registration state; it does not replace klist when you need to inspect Kerberos tickets directly.
Use Kerberos Authentication with requests
Python’s requests library does not implement Kerberos authentication by itself. The requests-kerberos package supplies an authentication handler that uses the current user’s Kerberos credential cache.
Install the packages:
python -m pip install requests requests-kerberos
After running kinit or signing in to the domain, attach HTTPKerberosAuth to a request:
import requests
from requests_kerberos import HTTPKerberosAuth, OPTIONAL
response = requests.get(
"https://api.example.com/protected-resource",
auth=HTTPKerberosAuth(mutual_authentication=OPTIONAL),
timeout=30,
)
response.raise_for_status()
print(response.json())
The HTTP server must be configured for Negotiate authentication and must have an HTTP service principal name (SPN) that matches the hostname in the URL. For example, a request to https://api.example.com/ typically needs an SPN similar to:
HTTP/api.example.com@EXAMPLE.COM
Prefer the service’s canonical DNS name in the URL. Accessing the same service by IP address, an alias without a registered SPN, or an untrusted hostname can prevent the client from obtaining the correct service ticket.
Troubleshooting Checklist
When an authenticated request fails, check the authentication path in order:
- Run
klistand verify that the TGT exists and has not expired. - Run
kinit user@EXAMPLE.COMto refresh the credential cache when needed. - Retry the request, then use
klistagain to see whether anHTTP/<hostname>service ticket was issued. - On Windows, run
dsregcmd /statusto verify the expected device and user registration state. - Confirm that the URL hostname matches the HTTP SPN configured on the server.
- Check server logs for Negotiate, SPN, or delegation errors.
Takeaway
kinit obtains Kerberos credentials, and klist shows the tickets available to the current user. On Windows, dsregcmd /status provides complementary device-registration information. In Python, requests-kerberos connects requests to the existing Kerberos credential cache, allowing HTTP clients to use Negotiate authentication without handling passwords in application code.