Authentication
The Zscaler SDK uses OAuth 2.0 to authenticate with credentials issued by Authentication Service. A single Session authenticates against all supported products, such as Authentication Service, Client Connector, Cloud & Branch Connector ZDX, ZIA, and ZPA.
Client Credentials
You can create and manage API clients in the Zscaler Admin Console. The Getting Started guide provides a walkthrough of the full onboarding flow. To learn more about API client configuration, see About API Clients Adding an API Client.
From an API client, you obtain:
- Client ID: The public identifier for the API client
- Client Secret: A confidential shared secret (alternatively, a certificate or private key for JWT bearer authentication)
- Vanity domain: Your organization's subdomain assigned when your Authentication Service tenant was provisioned (for example, if your login URL is
https://acme.zslogin.net, your subdomain isacme). It is not a full hostname.
Explicit Authentication
Pass the credentials directly to Session(). No cloud parameter is required in the production environment.
import os
from zssdk import Session
session = Session(
vanity_domain="acme",
client_id=os.environ["ZSCALER_CLIENT_ID"],
client_secret=os.environ["ZSCALER_CLIENT_SECRET"],
)
# Every product is accessible from the same session
for user in session.zia.admin_users.all():
print(user.name)
Implicit Authentication
The SDK can automatically discover credentials from ZSCALER_* environment variables, so you can keep them out of code.
export ZSCALER_VANITY_DOMAIN="acme"
export ZSCALER_CLIENT_ID="your_client_id"
export ZSCALER_CLIENT_SECRET="your_client_secret"
from zssdk import Session
session = Session() # picks up credentials from env vars
Use ZSCALER_* variables for credentials and ZSSDK_* variables for SDK behavior. For a complete list of variables, see the Configuration guide.
Configuration File
You can store credentials in ~/.zscaler/config (INI format) and select a profile when creating the session:
# ~/.zscaler/config
[default]
vanity_domain = acme
client_id = your_client_id
client_secret = your_client_secret
from zssdk import Session
session = Session(profile_name="default")
For a complete precedence chain (constructor arguments → instance variables → environment variables → config file → defaults), see the Configuration guide.
Beta Environment
The only valid explicit value for the cloud parameter is beta, which points the SDK to the Authentication Service beta environment (zsloginbeta.net). Omit cloud entirely in the production environment.
Legacy cloud names (e.g., zscalerone.net, zscalertwo.net) are not supported by the SDK.
from zssdk import Session
# Authentication Service beta environment (non-production testing only)
session = Session(
cloud="beta",
vanity_domain="acme",
client_id=os.environ["ZSCALER_CLIENT_ID"],
client_secret=os.environ["ZSCALER_CLIENT_SECRET"],
)
JWT Bearer Authentication
For stronger security, authenticate with a private key instead of a shared secret.
Using a Private Key File
import os
from zssdk import Session
session = Session(
vanity_domain="acme",
client_id=os.environ["ZSCALER_CLIENT_ID"],
cert_file_path="/path/to/private_key.pem",
)
Using a Private Key String
import os
from zssdk import Session
session = Session(
vanity_domain="acme",
client_id=os.environ["ZSCALER_CLIENT_ID"],
private_key="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----",
)
Custom Token Provider
If you already obtain tokens from an external identity system (for example, a secrets-management service or another OAuth provider), you can plug in a custom token provider:
from zssdk import Session
class MyTokenProvider:
"""Implements the TokenProvider protocol."""
def get_token(self) -> str:
# Fetch token from your own identity provider
return "your-jwt-token"
def get_expiration_time(self) -> int:
# Unix timestamp when the token expires
return 1700000000
session = Session(
vanity_domain="acme",
token_provider=MyTokenProvider(),
)
Token Lifecycle
The SDK manages tokens automatically after the session is created. The token is:
- Issued on first request (lazy), and no upfront token fetch takes place.
- Cached between requests for the token's lifetime (up to 24 hours per Authentication Service).
- Refreshed transparently when the token is within a 5‑minute expiry buffer.
- Thread-safe using double-checked locking.
The Authentication Service token lifetime (up to 24 hours) is independent of each backend product's session concept. For example, ZIA maintains a separate backend session with its own (short) timeout; the SDK does not own or expose that. To learn more about the distinction, see Session Management.
Multiple Sessions
A single session authenticates against all supported products, but you can create multiple sessions to target different tenants or environments simultaneously.
from zssdk import Session
# Two independent tenants — each with its own Authentication Service credentials
tenant_a = Session(profile_name="tenant-a")
tenant_b = Session(profile_name="tenant-b")
for role in tenant_a.zia.admin_roles.all():
print("tenant A:", role.name)
for role in tenant_b.zia.admin_roles.all():
print("tenant B:", role.name)
Advanced Configuration
Proxy settings, timeouts, Federal Information Processing Standards (FIPS) endpoints, and logging—all attach to the session through a Config object.
Proxy
from zssdk import Session
from zssdk.zscore.config import Config, Proxy
config = Config(
proxy=Proxy(
host="proxy.company.com",
port=8080,
username="proxy-user", # optional
password="proxy-password", # optional
)
)
session = Session(
vanity_domain="acme",
client_id="your-client-id",
client_secret="your-client-secret",
config=config,
)
Timeouts and Connection Pool
from zssdk import Session
from zssdk.zscore.config import Config, HttpConnection
config = Config(
http_connection=HttpConnection(
connect_timeout=30.0,
read_timeout=60.0,
write_timeout=30.0,
pool_timeout=10.0,
max_connections=200,
max_keepalive_connections=50,
keepalive_expiry=30.0,
)
)
session = Session(
vanity_domain="acme",
client_id="your-client-id",
client_secret="your-client-secret",
config=config,
)
FIPS Endpoints
For FIPS-compliant production deployments, enable the FIPS flag in Config. This selects the FIPS variant of each service's endpoint where available.
from zssdk import Session
from zssdk.zscore.config import Config
config = Config(use_fips_endpoint=True)
session = Session(
vanity_domain="acme",
client_id="your-client-id",
client_secret="your-client-secret",
config=config,
)
Security Best Practices
For the best results:
- Do not hard code credentials in source control; use environment variables or a secrets manager instead.
- Rotate the
client_secret(or the private key) on a schedule appropriate for your environment. - Use least-privilege scopes when creating API clients in Authentication Service.
- Prefer JWT bearer authentication (
cert_file_pathorprivate_key) over static secrets for production. - Store private keys with
0600permissions. - Enable logging with
logging_format="json"in the production environment. Credentials andAuthorizationheaders are redacted automatically.
Troubleshooting
If authentication fails, enable verbose logging to examine the request and response. Credentials and bearer tokens are redacted automatically.
from zssdk import Session
from zssdk.zscore.config import Config, LoggerConfig
logger_config = LoggerConfig(
enabled=True,
verbose=True,
log_to_file=True,
log_file_path="auth_debug.log",
)
config = Config(logger_config=logger_config)
try:
session = Session(
vanity_domain="acme",
client_id="your-client-id",
client_secret="your-client-secret",
config=config,
)
# Any API call triggers token acquisition
list(session.zid.api_clients.all())
except Exception as e:
print(f"Authentication failed: {e}")
print("Check:")
print(" - Client ID and Client Secret are correct and active in Authentication Service")
print(" - `vanity_domain` matches your Authentication Service tenant (subdomain only)")
print(" - If targeting the beta environment, `cloud=\"beta\"` is set")
print(" - The API client has scopes for the product you're accessing")
print(" - Network connectivity to `{vanity_domain}.zslogin.net`")
Related
- Getting Started: End-to-end onboarding, including creating an API client in the Zscaler Admin Console.
- Configuration: Configuration file format, environment variables, and precedence chain.
- Session Management: Session lifecycle and its distinction from backend product sessions.
- Logging: Log formats and automatic credential redaction.