Skip to main content

hypershub-sso

Typed synchronous and asynchronous OAuth 2.0 / OpenID Connect client for HypersHub SSO. It implements Authorization Code + PKCE for Python backends and BFFs, verifies ID Tokens, and manages refreshable server-side sessions.

Use this package only in a trusted Python server. Never expose the OAuth client secret, PKCE verifier, authorization code, access token, or refresh token to browser code.

Requirements

  • Python 3.11 or newer
  • An SSO client registration with an exact HTTPS redirect URI
  • A server-side session store such as Redis, Valkey, or a database
  • A high-entropy opaque browser session identifier in a host-only HttpOnly; Secure; SameSite=Lax cookie

Install

python -m pip install hypershub-sso

Synchronous client

Use SsoClient with Flask, Django, or another synchronous application:

import os

from hypershub_sso import (
    KeyValueStore,
    SsoClient,
    create_encrypted_session_store,
)


class RedisStore(KeyValueStore):
    def get(self, key: str) -> str | None:
        value = redis.get(key)
        return value.decode() if value is not None else None

    def set(self, key: str, value: str, ttl_seconds: int) -> None:
        redis.set(key, value, ex=ttl_seconds)

    def delete(self, key: str) -> None:
        redis.delete(key)


session_store = create_encrypted_session_store(
    RedisStore(),
    os.environ["SSO_SESSION_ENCRYPTION_KEY"],
)

sso = SsoClient(
    issuer="https://main.example.com/sso",
    client_id=os.environ["SSO_CLIENT_ID"],
    client_secret=os.environ["SSO_CLIENT_SECRET"],
    redirect_uri="https://project.example.com/auth/callback",
    store=session_store,
)

Asynchronous client

Use AsyncSsoClient with FastAPI, Starlette, Quart, or another asyncio application. The raw store methods must also be async:

from hypershub_sso import (
    AsyncSsoClient,
    create_async_encrypted_session_store,
)

session_store = create_async_encrypted_session_store(
    async_redis_store,
    os.environ["SSO_SESSION_ENCRYPTION_KEY"],
)

sso = AsyncSsoClient(
    issuer="https://main.example.com/sso",
    client_id=os.environ["SSO_CLIENT_ID"],
    client_secret=os.environ["SSO_CLIENT_SECRET"],
    redirect_uri="https://project.example.com/auth/callback",
    store=session_store,
)

Close a client during application shutdown with sso.close() or await sso.aclose(). A caller-supplied httpx.Client or httpx.AsyncClient remains owned by the caller and is not closed by the SDK.

Route integration

The SDK does not own framework cookies or responses. Your application supplies the opaque browser session ID as key:

# GET /auth/login
return redirect(sso.begin_login(session_id, "/dashboard"))

# GET /auth/callback?code=...&state=...
result = sso.handle_callback(session_id, request.args)
return redirect(result.return_to)

# Before a protected handler
session = sso.require_session(session_id)
user_subject = session.principal.sub

# POST /auth/logout; protect this route with normal CSRF controls
sso.logout(session_id)
clear_session_cookie()

For AsyncSsoClient, await each method. Only the opaque session ID belongs in the cookie; token-bearing SsoSession objects remain in server-side storage.

Encryption key

Generate a 256-bit key once, then store it in your secret manager:

python -c "from hypershub_sso import generate_session_encryption_key as g; print(g())"

The encrypted adapters use AES-256-GCM and authenticate the storage key to prevent ciphertext swapping. Rotating the key requires a key-ring migration or invalidating existing local sessions. Never commit it to source control.

For multi-process deployments, the raw store may implement with_lock using a Redis SET NX lock and owner-token checked Lua release. The encrypted adapter automatically exposes it to the client as a distributed refresh lock.

Errors

Expected failures are SsoClientError instances with stable codes:

from hypershub_sso import SsoClientError

try:
    session = sso.require_session(session_id)
except SsoClientError as error:
    if error.code == "AUTH_REAUTH_REQUIRED":
        return redirect("/auth/login")
    if error.retriable:
        return service_unavailable()
    raise
  • AUTH_REAUTH_REQUIRED: the local or refresh session is invalid; begin login.
  • SSO_TEMPORARILY_UNAVAILABLE: network, timeout, rate-limit, JWKS, or SSO 5xx failure. Return 503 or retry later; do not log the user out.
  • SSO_STATE_MISMATCH, SSO_NONCE_MISMATCH, SSO_ID_TOKEN_INVALID: reject the callback and do not create an application session.
  • SSO_TOKEN_ERROR: the token endpoint rejected a non-retryable request.

Messages do not include credentials or tokens. Optional SDK logs contain only fixed text and non-sensitive error metadata.

Defaults

Option Default Purpose
refresh_ahead_seconds 300 Refresh before access-token expiry
session_idle_seconds 43200 Sliding local-session idle lifetime
session_absolute_seconds 2592000 Maximum local-session lifetime
refresh_max_attempts 3 Attempts for transient refresh failures
refresh_retry_base_delay 0.2 Initial exponential delay in seconds
request_timeout 10 Token, revocation, and JWKS timeout
clock_tolerance_seconds 60 ID Token clock-skew tolerance
validate_return_to relative paths only Prevent open redirects

Remote JWKS honor bounded Cache-Control: max-age caching. An unknown kid causes one immediate refresh. Plain HTTP is rejected except for loopback development hosts unless allow_insecure_http=True is explicitly set.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hypershub_sso-0.1.0.tar.gz (67.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hypershub_sso-0.1.0-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

File details

Details for the file hypershub_sso-0.1.0.tar.gz.

File metadata

  • Download URL: hypershub_sso-0.1.0.tar.gz
  • Upload date:
  • Size: 67.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hypershub_sso-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1a1b8c36f34bb21f98eb51f79cec64642105687199aceecd5928e0aabde068dd
MD5 219312b01bfb4b7b2c366d038738d014
BLAKE2b-256 5fb690f9f4f77adfe11e64b1fda25ba5183e839044ca1046a6a5005a8781efc6

See more details on using hashes here.

File details

Details for the file hypershub_sso-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hypershub_sso-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 17.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for hypershub_sso-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4a2cf342a4675f9ca043a4b471361905d4791412e38b80e186602198335ab584
MD5 cbacff9135e21541f2d8de1b7be234e1
BLAKE2b-256 364a757cbb2577229159a6ca93fd04897f205b07980a656275f0b6bf0c738b6b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page