cms-hte-ial2-reader
Reads IAL2 token, verifies digital signature and returns FHIR Patient resource
Accepts a signed JWT (ID Token) from a Credential Service Provider (CSP), verifies the signature via JWKS, extracts demographics, and returns a FHIR R4 Patient resource. Transparently accepts three token shapes, with no caller-facing difference in usage:
- CMS-Aligned Networks CSP Payload Specification V7.1 -- flat claims.
- TEFCA IAS SOP v3.0 -- flat claims with a different field-name
vocabulary (e.g.
regionalityinstead ofregion); a token missing theidentity_assurance_levelclaim is treated as implicit IAL2 if it looks TEFCA-shaped, since the SOP guarantees IAL2 proofing as a precondition of the CSP issuing the token at all. - Unified Identity Token Payload (OIDC4IDA-style) -- the CMS-Aligned
Networks / TEFCA working group's in-progress target format, nesting
verified attributes in a
verified_claims.{verification,claims}envelope. This is a discussion draft, not a finalized spec.
Usage
from cmshteial2reader import IAL2Extractor, TokenVerifier
verifier = TokenVerifier(
jwks_uri="https://idp.example.com/.well-known/jwks.json",
audience="my-client-id",
)
extractor = IAL2Extractor(verifier=verifier)
patient = await extractor.extract(token_string)
# patient is a FHIR R4 Patient resource dict
To accept tokens from any issuer on an explicit allow list (rather than a
single pinned issuer), use MultiIssuerTokenVerifier in place of
TokenVerifier:
from cmshteial2reader import IAL2Extractor, MultiIssuerTokenVerifier
verifier = MultiIssuerTokenVerifier.from_env(audience="my-client-id")
extractor = IAL2Extractor(verifier=verifier)
patient = await extractor.extract(token_string)
MultiIssuerTokenVerifier.from_env reads its whitelist of trusted JWKS URLs
from the IAL2_ALLOWED_JWKS_URLS environment variable (comma-separated).
Assurance-level enforcement
IAL2Extractor requires the token's identity_assurance_level claim to be
at least IAL2 (accepting values like "ial2", "IAL2", or "2") -- a
token missing the claim, or asserting a lower level (e.g. "ial1"), raises
InsufficientAssuranceLevelError (a subclass of TokenVerificationError,
so existing callers that only catch the latter still catch this). This
applies to both extract() and extract_claims(). To require a higher
level, pass minimum_assurance_level to the constructor:
extractor = IAL2Extractor(verifier=verifier, minimum_assurance_level=3)
A TEFCA-dialect token (one with no identity_assurance_level claim but
recognizable TEFCA-only fields such as regionality/historical_address/
ssn_last_four_digits) is only treated as implicit IAL2 -- never a higher
level, since that's all the SOP guarantees -- and only after the token has
already passed signature verification (and, for MultiIssuerTokenVerifier,
issuer whitelisting). Raising minimum_assurance_level above 2 will reject
TEFCA-dialect tokens, since they can't assert anything higher.
CMS Blue Button cms_smart extension
CMS Aligned Networks convey a patient's IAL2-verified identity by nesting a
CSP-issued ID token inside the outer auth token's claims, under
extensions.cms_smart.id_token (see
https://bluebutton.cms.gov/cms-aligned-networks-documentation/). Callers
that receive an already-verified outer JWT (e.g. from their own auth
middleware) can pull out the nested token with extract_cms_smart_id_token
and pass it to IAL2Extractor.extract:
from cmshteial2reader import IAL2Extractor, MultiIssuerTokenVerifier, extract_cms_smart_id_token
id_token = extract_cms_smart_id_token(outer_jwt_claims)
if id_token is not None:
verifier = MultiIssuerTokenVerifier.from_env(audience="my-client-id")
extractor = IAL2Extractor(verifier=verifier)
patient = await extractor.extract(id_token)
extract_cms_smart_id_token only reads the id_token claim -- it does not
verify anything, and it does not inspect or enforce purpose_of_use or
version. The outer JWT must already be signature-verified by the caller,
the nested id_token still needs its own verification via
IAL2Extractor/TokenVerifier, and a caller that needs to gate on
purpose-of-use must check claims["extensions"]["cms_smart"] itself.
Quickstart
make initto set up the local dev environment.make upto start the Docker dev stack.make teststo run tests in the dev container.
Common Tasks
make shellto open a shell in the dev container.make run-pre-committo run linting and formatting hooks.make buildto build the package artifacts.
Publishing
- Set a token:
export TWINE_PASSWORD=pypi-xxx make packageto publish to PyPI ormake testpackagefor TestPyPI.
Project Metadata
- Repo: https://github.com/icanbwell/cms-hte-ial2-reader
- Author: Imran Qureshi imran.qureshi@bwell.com
Metadata
Release files for cms-hte-ial2-reader 0.0.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cms_hte_ial2_reader-0.0.4.tar.gz | 33.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cms_hte_ial2_reader-0.0.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 58.6 kB
Release files / cms_hte_ial2_reader-0.0.4.tar.gz
| Download URL | cms_hte_ial2_reader-0.0.4.tar.gz |
|---|---|
| Size | 33.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c8283650dc4d684b687d5f5f4d5610fae862845326330fa239a1cf995c4f8802
|
|
BLAKE2b-256 checksum How to use checksums |
f89900857e74fc24114f98a957f2924d7cabf129743fdfaa7bfc817185a1daa6
|
| 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 18, 2026.
Transparency logRelease files / cms_hte_ial2_reader-0.0.4-py3-none-any.whl
| Download URL | cms_hte_ial2_reader-0.0.4-py3-none-any.whl |
|---|---|
| Size | 25.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dace0f1b468afff5b9ccb023820d64c83ab3d14b614735855929967f178dcf36
|
|
BLAKE2b-256 checksum How to use checksums |
4460c0be942502223faaa8272f222ed2b2d54b0531dbd151ec055159e9ba9cd4
|
| 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 18, 2026.
Transparency log