Skip to main content

biss-auth-server

This package owns the standalone implementation. It has no dependency on the legacy package. The legacy name forwards to BISS Auth starting with npm 0.6.6 and Python 0.3.1. Public symbols and session formats remain compatible.

Server-side OIDC for Python products, interchangeable with the biss-auth npm package's /server entry point.

A session cookie sealed by either implementation unseals in the other, byte for byte. Both are written against packages/contract/contract.json, and both load packages/contract/conformance/cases.json at test time — which is what keeps them from drifting.

pip install biss-auth-server

Why

biss-auth/server is TypeScript, and half this estate is not: caselaw-access is FastAPI and citations-api is a Python HTTP server. Without a Python implementation, those two would have stayed on browser-side sessions purely because of the language their backend happens to be written in — with the refresh token in localStorage, where page script can read it.

Usage

from biss_auth_server import create_server_auth, create_pkce_pair, random_token

auth = create_server_auth(
    issuer=os.environ["AUTH_ISSUER"],              # .../realms/caselaw
    client_id=os.environ["AUTH_CLIENT_ID"],
    redirect_uri=os.environ["AUTH_REDIRECT_URI"],
    session_secret=os.environ["AUTH_SESSION_SECRET"],
    client_secret=os.environ.get("AUTH_CLIENT_SECRET"),   # confidential clients
)

Start a sign-in:

verifier, challenge = create_pkce_pair()
state = random_token()
# state and verifier must survive the round trip and stay unreadable by page
# script — a short httpOnly cookie, not anything the browser can see.
url = auth.authorization_url(state=state, code_challenge=challenge)

Complete it:

tokens = auth.exchange_code(code=code, code_verifier=verifier)
claims = auth.verify_token(tokens["access_token"])
session = auth.session_from_claims(claims, id_token=tokens.get("id_token"))
cookie = auth.seal_session(session)

Read it on any request — an HMAC check, no network call:

session = auth.unseal_session(request.cookies.get("caselaw_session"))
if not session or "admin" not in session["roles"]:
    raise Forbidden()

End it. id_token_hint is what makes this a real single sign-out:

auth.end_session_url(id_token=session.get("idToken"), return_to=site)

Mapping to the TypeScript package

Method names are idiomatic per language. Session keys are camelCase in both, because they are wire format rather than API surface: renaming them per language would break the property the whole contract exists to guarantee.

TypeScript Python
createServerAuth(config) create_server_auth(...)
authorizationUrl(options) authorization_url(...)
exchangeCode(options) exchange_code(...)
verifyToken(token, options) verify_token(token, ...)
rolesFromClaims(claims) roles_from_claims(claims)
sessionFromClaims(claims, options) session_from_claims(claims, ...)
sealSession(session, name) seal_session(session, name)
unsealSession(value) unseal_session(value)
cookieOptions(maxAge, options) cookie_options(max_age, ...)
endSessionUrl(options) end_session_url(...)
createPkcePair() create_pkce_pair()

Errors are typed here rather than string-matched: InvalidToken, AuthBackendUnavailable and SessionTooLarge, all under AuthError. The split between the first two is deliberate — collapsing them sends users to re-authenticate during an outage, which cannot help and doubles the load on the thing already failing.

Behaviour worth knowing

  • session_from_claims does not keep the access token. Where one is genuinely needed, put it in a cookie of its own; a token in a cookie leaks with the cookie.
  • The session carries its own TTL, not the token's few minutes.
  • seal_session raises above 4096 bytes rather than returning a cookie the browser will silently discard.
  • verify_token does not check aud by default. Keycloak puts account there for a public client's access token and names the client in azp.
  • JWKS is cached and retried once; a token that is itself invalid is never retried.

Tests

pip install -e ".[dev]"
pytest

The suite loads the shared conformance cases by relative path. Running it from a checkout of this repository is therefore required — the cases are not vendored into the package.

Metadata

Release files for biss-auth-server 0.3.1

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

Source distribution (sdist)

Source distribution for biss-auth-server 0.3.1
File Size Uploaded Provenance Actions
biss_auth_server-0.3.1.tar.gz 11.6 kB With provenance Details for biss_auth_server-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for biss-auth-server 0.3.1
File Interpreter ABI Platform Actions
biss_auth_server-0.3.1-py3-none-any.whl Python 3 none any Details for biss_auth_server-0.3.1-py3-none-any.whl

Total release size: 22.2 kB

Release files / biss_auth_server-0.3.1.tar.gz

Download URL biss_auth_server-0.3.1.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
ae09e63f816eecef0d90eb16dc1b9a0ae357c0342fdbe8be5123a0860c9aa8cc
BLAKE2b-256 checksum
How to use checksums
4fe3c91576de1fab1b6afdd83056711478095ea8ed1e734b58ee0488760b0dc3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 12, 2026.

Transparency log

Release files / biss_auth_server-0.3.1-py3-none-any.whl

Download URL biss_auth_server-0.3.1-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
521b5f1575dfdfaf2ecd54097e7781afbf9ce7f8c2cfcaf28d84ea03a53328ca
BLAKE2b-256 checksum
How to use checksums
a70f50235ffe80ee88408baed66cca99f4b1e24f9853fb214376f099281f7af6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 12, 2026.

Transparency log

Security for biss-auth-server 0.3.1

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.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for biss_auth_server-0.3.1.tar.gz

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 Nov 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.1 This release

2 release files Full provenance

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