SSPI API Bindings for Python
sspilib is a Python library that provides bindings for the Windows Security Support Provider Interface (SSPI) API. It offers both a high-level and a low-level interface to facilitate SSPI integration in other Python libraries. The library currently supports Python 3.9+ and ships as pre-compiled wheels for various platforms, including experimental support for non-Windows systems via `sspi-rs`, a Rust implementation.
Warnings
- breaking The constructor arguments for `sspilib.ClientSecurityContext` and `sspilib.ServerSecurityContext` changed. The `credential` argument became non-optional and was moved to the first positional argument.
- breaking Python 3.8 support was dropped. The library now requires Python 3.9 or newer.
- gotcha Non-Windows support for sspilib is experimental and relies on the `sspi-rs` Rust library. Compatibility with actual Windows SSPI is not 100%, and its use on non-Windows platforms is at your own risk. It is recommended to use a library that wraps GSSAPI (e.g., `python-gssapi`) for more robust cross-platform authentication.
- gotcha While `sspilib` supports Python Free-Threading (PEP 779), it is not designed to be thread-safe out of the box. Limited testing has been performed in free-threading environments.
Install
-
pip install sspilib
Imports
- sspilib
import sspilib
- sspilib.raw
from sspilib import raw
- UserCredential
from sspilib import UserCredential
- ClientSecurityContext
from sspilib import ClientSecurityContext
- WindowsError
from sspilib import WindowsError
Quickstart
import sspilib
import os
try:
# Get credentials and SPN from environment variables for a runnable example
# In a real application, retrieve these securely.
username = os.environ.get("SSPI_USERNAME", "user@DOMAIN.COM")
password = os.environ.get("SSPI_PASSWORD", "your_secure_password")
spn = os.environ.get("SSPI_SPN", "HOST/targetserver.domain.com")
if not all([username, password, spn]):
print("Please set SSPI_USERNAME, SSPI_PASSWORD, and SSPI_SPN environment variables for a real test.")
print("Proceeding with placeholders, which will likely fail on actual SSPI operations.")
print(f"Attempting to establish client security context for {username} to {spn}")
# Define user credentials
cred = sspilib.UserCredential(username, password)
# Initialize a client-side security context
# The credential argument is now mandatory and the first positional argument since v0.2.0
ctx = sspilib.ClientSecurityContext(cred, spn)
# Generate the first token (Client's initial negotiate message)
client_token = ctx.initialize_security_context()
if client_token:
print(f"Generated initial client token (first leg of handshake): {client_token.hex()}")
print("This token would typically be sent to the server for processing.")
print("A full SSPI handshake involves multiple token exchanges between client and server.")
# In a real scenario, you would send client_token to the server and receive a server_token.
# Then you would call ctx.initialize_security_context(server_token) again.
else:
print("No initial client token generated (context might be complete or error occurred).")
if ctx.complete:
print("Security context reports as complete (may indicate successful single-leg auth or simulated completion).")
else:
print("Security context not yet complete (requires further server interaction).")
except sspilib.WindowsError as e:
print(f"SSPI Error: {e.strerror} (Error Code: {e.errno})")
print("Ensure you are running on Windows or have sspi-rs correctly set up for non-Windows.")
except Exception as e:
print(f"An unexpected error occurred: {e}")