Python SPNEGO Authentication Library
pyspnego is a Python library designed to handle SPNEGO (Negotiate, NTLM, Kerberos) and CredSSP authentication, offering a unified interface across different operating systems. It leverages SSPI on Windows and GSSAPI on Linux, and also includes a utility for parsing raw NTLM/SPNEGO/Kerberos tokens. The library is actively maintained, with version 0.12.1 released on March 2, 2026, and follows a regular release cadence.
Warnings
- breaking Support for Python 3.7 was dropped in version 0.12.0. The minimum required Python version is now 3.9+.
- deprecated Direct imports from `spnego.gss`, `spnego.negotiate`, `spnego.ntlm`, and `spnego.sspi` are deprecated. These exports are now private.
- deprecated The `username` and `password` properties on authentication context objects are deprecated and will return `None` in future releases.
- breaking In CredSSP contexts, the `client_credential` property has been removed.
- gotcha When using GSSAPI on Linux, particularly with MIT krb5 versions <=1.18.2, channel bindings might fail with pure SPNEGO. This can lead to authentication failures if channel bindings are required by the acceptor.
- gotcha When using explicit Kerberos credentials with MIT krb5 versions less than 1.14, the credentials might be stored in the system credential cache, making them accessible to other processes for that user.
Install
-
pip install pyspnego -
pip install pyspnego[kerberos]
Imports
- client
import spnego.client
- server
import spnego.server
Quickstart
import spnego
import os
# Example for a client initiating a Negotiate (SPNEGO) context
# Replace with actual credentials or environment variables
username = os.environ.get('SPNEGO_USERNAME', 'testuser')
password = os.environ.get('SPNEGO_PASSWORD', 'testpassword')
service_principal_name = os.environ.get('SPNEGO_SPN', 'HTTP@myservice.example.com')
try:
# Create a client context. 'negotiate' is the default protocol.
# For NTLM: protocol='ntlm'
# For Kerberos: protocol='kerberos' (requires system GSSAPI/Kerberos libs on Linux)
client_context = spnego.client.Context(
username=username,
password=password,
hostname=service_principal_name.split('@')[1] if '@' in service_principal_name else None,
service=service_principal_name.split('@')[0] if '@' in service_principal_name else None,
protocol='negotiate'
)
# The client typically sends an initial token
initial_token = client_context.step()
print(f"Initial SPNEGO token (base64 encoded): {initial_token.decode('utf-8')}")
# In a real scenario, this token would be sent to the server,
# which would then return a response token. The client would then
# call client_context.step(server_response_token) until complete.
except spnego.exceptions.NegotiateError as e:
print(f"Authentication error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")