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_claimsdoes 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_sessionraises above 4096 bytes rather than returning a cookie the browser will silently discard.verify_tokendoes not checkaudby default. Keycloak putsaccountthere for a public client's access token and names the client inazp.- 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
- caselaw-auth — the realm, themes, and both implementations
- docs/SERVER_SIDE_AUTH.md — the full walkthrough
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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.