Duo Client
Official Python SDK for the Duo Security Auth, Admin, and Accounts REST APIs.
Repository Health
Technical Analysis
duo_client is the official Python client library published by Duo Security (Cisco) for integrating with Duo’s Auth, Admin, and Accounts REST APIs. It handles the low-level mechanics of talking to Duo’s platform — HMAC request signing, TLS certificate validation against a bundled CA bundle, and JSON response parsing — so integrators can call domain-specific methods like enroll, get_users_by_email, or create_account instead of hand-rolling signed HTTP requests.
The library ships three primary clients: Auth for two-factor authentication flows (enrollment, push/passcode verification), Admin for provisioning and reporting on users, phones, groups, and policies, and Accounts for multi-tenant MSP-style account management. It’s maintained directly by Duo/Cisco, tested across Python 3.7-3.12 in CI, and distributed on PyPI as duo-client for teams building custom MFA integrations, admin tooling, or SSO provisioning workflows around Duo Security.
What You Get
- Auth client covering ping/check health endpoints plus full 2FA enrollment and verification flows
- Admin client with 150+ methods spanning users, phones, groups, policies, telephony credits, and trust monitor events
- Accounts client for creating, listing, and deleting child accounts in MSP/reseller deployments
- Built-in request signing (HMAC-SHA1/SHA512) and bundled CA certificate validation, no manual crypto required
Common Use Cases
- Building a custom MFA enrollment flow into an internal identity portal
- Automating bulk user and phone provisioning via the Admin API instead of the Duo dashboard
- Pulling authentication logs and trust monitor events into a SIEM using the bundled Splunk example script
- Managing multiple child accounts programmatically for MSPs reselling Duo
Under The Hood
Architecture client.py defines a low-level Client class handling request signing (canon_params, HMAC-SHA1/SHA512 depending on signature version) and TLS connection handling via https_wrapper.CertValidatingHTTPSConnection, which verifies hosts against the bundled ca_certs.pem. duo_client/init.py exposes Auth, Admin, and Accounts as subclasses of client.Client, each implementing API endpoint methods that delegate to self.json_api_call() or self.api_call(). Admin (admin.py, ~140KB, 150+ methods) is the largest surface, covering users, phones, groups, policies, telephony credits, and trust monitor events; accounts.py wraps the Accounts API for MSP-style child-account management, and its AccountAdmin subclass extends Admin for cross-account operations. auth_v1.py is retained alongside the current auth.py for legacy signature-version support. This is a flat, single-responsibility-per-file layered design: transport/signing (client.py, https_wrapper.py) sits beneath thin per-API-domain subclasses (auth.py, admin.py, accounts.py). There is no dependency-injection framework — instances are constructed directly with an integration key, secret key, and host — so every subclass depends directly on the shared signing/canon_params logic in client.py.
Tech Stack Pure Python 3.7+ built entirely on the standard library (http.client, ssl, hashlib, hmac, base64, urllib.parse), deliberately avoiding third-party HTTP dependencies to keep the footprint minimal; pytz is an optional dependency only needed for timezone-aware request signing. Packaging uses plain setuptools (setup.py, requirements.txt lists only “setuptools”). The package bundles its own ca_certs.pem for TLS certificate validation against Duo’s API hosts. Testing runs on nose2 with dev dependencies (nose2, flake8, dlint, freezegun) and GitHub Actions CI (python-ci.yml) exercising the full test suite across Python 3.7 through 3.12, plus a separate publish.yml release workflow that includes an SBOM-generation step. The library is distributed to PyPI as duo-client.
Code Quality The repo has an extensive test suite under tests/ (admin/, accountAdmin/, resources/, test_client.py, test_https_wrapper.py) with dozens of per-endpoint test modules covering policies, groups, phones, u2f, passport, identity verification, trust monitor events, and more, built on nose2 with shared base.py fixtures per subpackage. flake8 plus the security-focused dlint linter are enforced via .flake8 and CI. Error handling is explicit: client.py raises exceptions with parsed JSON error bodies from failed API calls rather than silently swallowing failures. There are no type hints or static type checking (mypy), and documentation relies on inline docstrings rather than a separate docs site — but the CI matrix testing across six Python versions offsets the lack of static typing with strong runtime coverage.
API Design Each domain client (Auth, Admin, Accounts) maps close to 1:1 with Duo’s REST endpoints, giving a discoverable method-per-endpoint API — Admin alone exposes 150+ documented methods, each with an inline docstring describing its exact return shape, reducing the need to cross-reference external API docs for routine calls. Getting started only requires an integration key, secret key, and API host — no configuration files. The bundled CA certificate bundle removes a common TLS setup footgun, and the examples/ directory (Accounts, Admin, Auth, splunk) provides copy-pasteable starting points for common reporting, provisioning, and log-forwarding tasks. The thin REST-wrapper pattern itself isn’t novel, but it’s executed consistently and tailored precisely to Duo’s API surface, keeping boilerplate low for integrators.