Skip to main content

ZanShield SDK for Python

Add ZanShield multi-factor authentication to your system's login. ZanShield is the authentication service run by eGAZ (eGovernment Authority Zanzibar).

Your system checks the user's password as usual, then hands them to ZanShield for the second factor. ZanShield decides everything from there: whether the user sets up their first method or verifies an existing one, and which methods (authenticator app, security key, email, SMS) your system allows. It then sends the user back to you with a signed acknowledgement. This library builds the ticket you send and checks the acknowledgement you get back.

Install

pip install zanshield-sdk

Requires Python 3.9+. Installs cryptography automatically.

Before you start

Your institution admin registers your system in the ZanShield administration console. You get:

  • your system code (e.g. PAYROLL01) and institution code
  • your system's private key (shown once; keep it on your server only, never in a browser or mobile app)
  • ZanShield's engine public key (the admin console's "Download ZanShield public key" button)
  • the portal address, e.g. https://portal.zanshield.devtech.co.tz

The redirect URI you register is where ZanShield sends users back to.

Usage

from zanshield_sdk import AcknowledgementRejected, ZanShieldClient, load_private_key, load_public_key

client = ZanShieldClient(
    system_code="PAYROLL01",
    institution_code="EGAZ",
    my_private_key=load_private_key(open("/secure/zanshield-private.pem").read()),
    engine_public_key=load_public_key(open("/secure/zanshield-engine-public.pem").read()),
)

# 1. After the user's password is correct:
ticket = client.create_ticket(
    user.id,
    user.email,
    full_name=user.full_name,  # optional: the portal greets the user by name
    mobile=user.phone,         # optional: without it the user can't choose SMS codes
)
return redirect(ZanShieldClient.portal_url("https://portal.zanshield.devtech.co.tz", ticket))

# 2. At your redirect URI, ZanShield sends the user back with ?ticket=...
try:
    ack = client.accept_acknowledgement(request.args["ticket"])
except AcknowledgementRejected as e:
    # Genuine, but must not sign in: e.reason is "NOT_AUTHENTICATED", "EXPIRED" or "REPLAYED".
    return show_error(e.acknowledgement.message or str(e))
start_session_for(ack.user_id)

accept_acknowledgement does every check your callback needs before it starts a session. If any check fails it raises an exception and returns nothing:

  1. The ticket decrypts with your key and is signed by ZanShield. If not, it raises ZanShieldError, and you must never trust such a ticket.
  2. response_code is 9000 and is_authenticated is true.
  3. It's fresh: issued less than 3 minutes ago, configurable with max_acknowledgement_age=.
  4. Its txn_id hasn't been used before, so a leaked callback URL can't be replayed into a second session.

More than one server

By default, used txn_ids are remembered in memory, which protects a single process. If your application runs on several servers or workers, pass a store backed by something they share. Any object with a mark_used(txn_id, keep_until) -> bool method works:

class RedisTxnIdStore:
    def __init__(self, redis):
        self.redis = redis

    def mark_used(self, txn_id, keep_until):
        ttl = max(1, int((keep_until - datetime.now(timezone.utc)).total_seconds()))
        return bool(self.redis.set(f"zanshield:txn:{txn_id}", 1, nx=True, ex=ttl))

client = ZanShieldClient(..., txn_id_store=RedisTxnIdStore(redis))

Response codes

ResponseCodes has every code ZanShield uses. On an acknowledgement, only ResponseCodes.SUCCESS (9000) means the user verified.

License

Apache-2.0

Metadata

Release files for zanshield-sdk 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zanshield-sdk 1.0.0
File Size Uploaded
zanshield_sdk-1.0.0.tar.gz 15.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zanshield-sdk 1.0.0
File Interpreter ABI Platform
zanshield_sdk-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.2 kB

Release files / zanshield_sdk-1.0.0.tar.gz

Download URL zanshield_sdk-1.0.0.tar.gz
Size 15.3 kB
Tags Source
SHA-256 checksum
How to use checksums
a5b7fb22e819d784cc8823f37d55a17be8758685883ecb53969bbb163d8a40b0
BLAKE2b-256 checksum
How to use checksums
45a5ee9aee57c006c6fdb0c0e55f4ca2d8812e89a4ae9d89bb86b20d319d32de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / zanshield_sdk-1.0.0-py3-none-any.whl

Download URL zanshield_sdk-1.0.0-py3-none-any.whl
Size 12.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
09b46df006c6a0ce766ef8f9e053f841017f11b893ce4a8a31952ec24cfa2b84
BLAKE2b-256 checksum
How to use checksums
84b48bf14f279b1171c3231cdd7672e4603db774f9f0dc11d1eaf10f5a1c1975
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page