Skip to main content

caselaw-auth-server

Server-side OIDC for Python products, interchangeable with the caselaw-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 caselaw-auth-server

Why

caselaw-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 caselaw_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.

Related

Download files

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

Source Distribution

caselaw_auth_server-0.3.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

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

caselaw_auth_server-0.3.0-py3-none-any.whl (10.6 kB view details)

Uploaded Python 3

File details

Details for the file caselaw_auth_server-0.3.0.tar.gz.

File metadata

  • Download URL: caselaw_auth_server-0.3.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for caselaw_auth_server-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f1ef2e812452c1e746b4c75157e199c4a4680b53cb29cef739ccde0cc697452b
MD5 6673883eb848d4bff18418abc5ca81d5
BLAKE2b-256 c59fd0b273320428ea5d3df393b3bae78055d61e9498c2f3652efc6b42c517c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for caselaw_auth_server-0.3.0.tar.gz:

Publisher: publish-python.yml on MaastrichtU-BISS/caselaw-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caselaw_auth_server-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for caselaw_auth_server-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d796e36faf1ddb797e8800002208ba6a9c18839afc7b84a52d2770109cf3e487
MD5 d28dffce15f36df3df373feffb16f996
BLAKE2b-256 6abb224b809ec8b661ac520ae04a042c042a027123b1de033465442667c66da1

See more details on using hashes here.

Provenance

The following attestation bundles were made for caselaw_auth_server-0.3.0-py3-none-any.whl:

Publisher: publish-python.yml on MaastrichtU-BISS/caselaw-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

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