Skip to main content

Stackure Python SDK

Check build PyPI version Python versions PyPI - Downloads Trusted publisher License: MIT

Passwordless magic-link authentication SDK for Python — drop-in ASGI and WSGI middleware, zero dependencies.

Protect an app with one line, or verify sessions and send magic links directly against the Stackure auth API.

Install

pip install stackure

Requires Python 3.14+.

Protect an app

import stackure

app_id = "7f3c1a2e-9b4d-4e6f-8a1b-2c3d4e5f6071"  # your app's UUID in Stackure

# ASGI — FastAPI, Starlette, Quart
app = stackure.auth(app_id, "can_approve_invoice")(app)

# WSGI — Flask, Django
flask_app.wsgi_app = stackure.auth(app_id, "can_approve_invoice")(flask_app.wsgi_app)

The same wrapper handles both; it detects the protocol it was called under.

Access the authenticated user in your view:

user = stackure.user_from_request(request)
print(user.user_email, user.user_permissions)
  • API requests get JSON errors
  • Browser requests get redirected to sign-in
  • The sign-in handoff is automatic: Stackure hands the browser back with a session_token, the middleware stores it as a cookie on your domain and strips it from the URL

Requirements

Stackure binds sessions to the browser's user agent and IP. The SDK validates from your server, so it forwards the original User-Agent and X-Forwarded-For. Your app must see the real client IP — if it runs behind a proxy or CDN, make sure that layer sets X-Forwarded-For.

Every request with a session token is validated against Stackure, so revocation is immediate. Requests without a well-formed token get the sign-in URL without a Stackure call.

Verify manually

result = stackure.verify(app_id, request)

if not result.authenticated:
    # result.error.code, result.error.message, result.error.sign_in_url
    ...

# result.user

verify never raises — transport and API failures come back as a 500 result. It accepts a WSGI environ, an ASGI scope, or a framework request object (Starlette, FastAPI, Flask, Django).

resp = stackure.send_magic_link("user@example.com", app_id)
# resp.message

Log out

r = stackure.logout(request)

Returns the status and headers that clear the app's cookie and redirect to Stackure's sign-out. Your framework builds the response:

# Flask
return "", r.status, r.headers

# Starlette / FastAPI
return Response(status_code=r.status, headers=dict(r.headers))

Configuration

Set STACKURE_BASE_URL to point at a non-production environment:

STACKURE_BASE_URL=https://stage.stackure.com python app.py

Retry-on-5xx (one retry after 500ms) and the 2-second request timeout are hard-coded. Timeouts are never retried.

Errors

Everything except verify raises StackureError. Switch on .code:

from stackure import StackureError

try:
    stackure.send_magic_link(email)
except StackureError as err:
    match err.code:
        case "validation": ...  # bad input
        case "auth": ...        # 401 from the API
        case "forbidden": ...   # 403 from the API
        case "timeout": ...     # request exceeded the 2s timeout
        case "network": ...     # everything else

Contributing

Open a PR. Tag a release when ready: git tag vX.Y.Z && git push --tags — the release workflow builds, signs, and publishes.

Security

Report vulnerabilities via GitHub Security Advisories. Releases publish to PyPI via OIDC trusted publishing with GitHub build-provenance attestations.

License

MIT

Release files for stackure 1.20260925.8

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

Source distribution (sdist)

Source distribution for stackure 1.20260925.8
File Size Uploaded
stackure-1.20260925.8.tar.gz 13.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for stackure 1.20260925.8
File Interpreter ABI Platform
stackure-1.20260925.8-py3-none-any.whl Python 3 none any Details

Total release size: 28.5 kB

Release files / stackure-1.20260925.8.tar.gz

Download URL stackure-1.20260925.8.tar.gz
Size 13.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a25f7df5bd68c4a38ea54f630b848a9472467b186cb1b9ed5feed38cd5bae8fa
BLAKE2b-256 checksum
How to use checksums
259082723fc1c749b05f55bdf40d6dd86ac0e4e0d7a04b6f94c438aac70a8577
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 Sep 25, 2026.

Transparency log

Release files / stackure-1.20260925.8-py3-none-any.whl

Download URL stackure-1.20260925.8-py3-none-any.whl
Size 15.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c6c0346f86c45c604a2307dced03a893d47dad152e5347813e6948f36938a6b9
BLAKE2b-256 checksum
How to use checksums
7b124c09f24275d84c8c158dda0061e2f5b1fd9489c5ac2a6d2b68faa72f9f73
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 Sep 25, 2026.

Transparency log
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