-
Notifications
You must be signed in to change notification settings - Fork 1
Python API OB2
Programmatic guide to the strict Open Badges 2.0 API exposed by openbadgeslib.ob2. This layer produces conformant JSON-LD Badge Objects (every object carries @context and type, the assertion uses an IRI id, a verification object, a boolean hashed, and ISO 8601 dates) and signs the assertion as a JWS baked into an SVG/PNG image. For the legacy pre-2.0 format see Python API OB1; for the JWT-VC path see Python API OB3; for how the generations differ see OB2 vs OB3.
The full, always-up-to-date class/function reference is generated from the docstrings: API Reference.
All public OB2 names are re-exported from openbadgeslib.ob2:
from openbadgeslib.ob2 import (
OB2Signer, OB2Verifier, OB2VerificationError,
Assertion, IdentityObject, Verification,
BadgeClass, Profile, CryptographicKey, RevocationList,
hash_identity, OB2_CONTEXT,
)Each Badge Object is a @dataclass with a to_dict() that emits conformant JSON-LD; the ones read back from untrusted input also provide a validating from_dict().
-
IdentityObject— the recipient.IdentityObject.create(email, salt)builds the hashed form (identity="sha256$<hex>",hashed=True).from_dictrejects the legacy string"true". -
Verification—Verification(type="SignedBadge", creator=<CryptographicKey IRI>)orVerification(type="HostedBadge").from_dictcanonicalises thesigned/hostedaliases. -
Assertion— the signed/hosted claim.idauto-generates asurn:uuid:…when omitted (pass the hosting URL explicitly for a HostedBadge);issued_ondefaults to now (UTC). -
BadgeClass,Profile,CryptographicKey,RevocationList— the hosted metadata objects emitted byopenbadges-publish -V 2.
from datetime import datetime, timezone
from openbadgeslib.ob2 import Assertion, IdentityObject, Verification
assertion = Assertion(
recipient=IdentityObject.create('recipient@example.com', salt='s4lt3d'),
badge='https://example.com/badge_1/badge.json',
verification=Verification(type='SignedBadge',
creator='https://example.com/badge_1/key.json'),
issued_on=datetime(2026, 1, 1, tzinfo=timezone.utc),
image='https://example.com/badge_1/badge.svg',
)OB2Signer(privkey_pem, algorithm='RS256')Signs an Assertion as a JWS whose payload is the full Assertion JSON-LD document. algorithm is bound to the key type (RS256 for RSA, ES256 for ECC P-256, EdDSA for Ed25519).
-
sign(assertion)→ the compact JWS string (header.payload.signature). -
sign_into_svg(assertion, svg_bytes)/sign_into_png(assertion, png_bytes)→ the baked image bytes (OB 2.0 carrier:<openbadges:assertion>/ theopenbadgesiTXt keyword).
OB2Verifier(pubkey_pem=None)-
pubkey_pem— an optional trusted public key. When supplied it verifies SignedBadge assertions directly (trusted). When omitted, a SignedBadge is verified against the key resolved fromverification.creator, whose CryptographicKeyowner/publicKeyback-link to the issuer is checked — internally consistent, but not proof of issuer identity.
verify(token, expected_recipient=None, check_revocation=False) returns the decoded Assertion or raises OB2VerificationError. It:
- verifies the signature (SignedBadge) or fetches the assertion from its
idand enforces the issuer scope (HostedBadge); - validates
@context/typeand rejects legacy shapes (stringhashed, Unix dates,uid-only); - checks expiry, and (with
check_revocation=True, network) the issuer'sRevocationList; - with
expected_recipient, re-hashes the email + salt and binds it to the recipient.
Token extraction: OB2Verifier.extract_token_from_svg(bytes) / extract_token_from_png(bytes).
from datetime import datetime, timezone
from openbadgeslib.ob2 import (
OB2Signer, OB2Verifier, Assertion, IdentityObject, Verification,
)
priv = open('test_sign_rsa.pem', 'rb').read()
pub = open('test_verify_rsa.pem', 'rb').read()
svg = open('sample1.svg', 'rb').read()
assertion = Assertion(
recipient=IdentityObject.create('recipient@example.com', salt='s4lt3d'),
badge='https://example.com/badge_1/badge.json',
verification=Verification(type='SignedBadge',
creator='https://example.com/badge_1/key.json'),
issued_on=datetime(2026, 1, 1, tzinfo=timezone.utc),
)
baked = OB2Signer(privkey_pem=priv, algorithm='RS256').sign_into_svg(assertion, svg)
token = OB2Verifier.extract_token_from_svg(baked)
result = OB2Verifier(pubkey_pem=pub).verify(token, expected_recipient='recipient@example.com')
print('verified:', result.id)check_revocation=True (and HostedBadge verification) additionally fetch the issuer's hosted JSON over the network — see Security Model for the trust model.
For a HostedBadge, pass the hosting URL as the assertion id, sign with Verification(type='HostedBadge'), and publish assertion.to_dict() at that URL. On verification the (scope-checked) HTTPS retrieval of the id is the trust anchor. From the CLI this is openbadges-signer -V 2 -H (see CLI Reference), which also writes the .assertion.json to publish.
- Signing and Verification — the end-to-end concepts.
-
Keys and Errors —
KeyType, key generation, and exception types. - Security Model — trusted keys, hosted trust, and scope enforcement.
- Python API OB1 / Python API OB3 — the other two generations.
-
CLI Reference — the same operations from the command line (
-V 2).
openbadgeslib · LGPLv3 (library) / BSD (CLI) · Issues
Getting Started
Concepts
Reference
Guides
Project