AgentMarqueVerifier
The AgentMarqueVerifier validates SD-JWT presentations from agent credentials. It resolves issuer DIDs, checks signatures and holder binding, enforces trust policies, and optionally verifies revocation status.
from agentmarque import AgentMarqueVerifier
Constructor
Create a verifier instance with a set of trusted issuer DIDs. Only credentials signed by these issuers will pass the issuer_trusted check.
Required attributes
- Name
trusted_issuers- Type
- list[str]
- Description
List of issuer DIDs to trust (e.g.,
["did:key:z6Mk...", "did:web:registry.agentmarque.com"]). Presentations from issuers not in this list will fail theissuer_trustedcheck.
Optional attributes
- Name
cache_ttl- Type
- int
- Description
Time-to-live in seconds for cached DID documents and status list responses. Defaults to
300.
Example
verifier = AgentMarqueVerifier(
trusted_issuers=[
"did:key:z6MkRegistry...",
"did:web:registry.agentmarque.com",
],
cache_ttl=600,
)
verify
Verify an SD-JWT presentation synchronously. Runs all checks (signature, holder binding, dates, issuer trust, nonce, audience, revocation, policy) and returns a VerificationResult.
Returns a VerificationResult. Check result.valid for the overall outcome, result.checks for individual check results, and result.errors for failure details.
Required attributes
- Name
presentation- Type
- str
- Description
Compact SD-JWT+KB-JWT presentation string from
AgentCredential.present().
- Name
expected_nonce- Type
- str
- Description
The nonce your service sent to the holder. Checked against the key-binding JWT's
nonceclaim.
- Name
expected_audience- Type
- str
- Description
Your service's identifier (DID or URL). Checked against the key-binding JWT's
audclaim.
Optional attributes
- Name
min_tier- Type
- int
- Description
Minimum required verification tier. Defaults to
0.
- Name
min_reputation- Type
- float
- Description
Minimum required reputation score (0.0 to 1.0). Defaults to
0.0.
- Name
required_capabilities- Type
- list[str] | None
- Description
Capabilities the agent must possess. If provided, all listed capabilities must be present in the disclosed claims. Defaults to
None.
- Name
check_revocation- Type
- bool
- Description
Whether to check the credential status list for revocation. Defaults to
True.
Policy checks (min_tier, min_reputation, required_capabilities) depend on those claims being disclosed in the presentation. If the presenter used selective disclosure to hide a claim, the corresponding policy check will fail.
Example
result = verifier.verify(
presentation=jwt_string,
expected_nonce="abc123",
expected_audience="did:web:api.example.com",
min_tier=1,
min_reputation=0.5,
required_capabilities=["data-query"],
)
if result.valid:
print(result.claims["agentName"])
print(result.claims["capabilities"])
else:
for err in result.errors:
print(f"Failed: {err}")
Check individual results
result = verifier.verify(
jwt_string, "nonce", "did:web:my-service.com",
)
print(result.checks.signature) # True
print(result.checks.cnf_match) # True
print(result.checks.holder_bound) # True
print(result.checks.dates) # True
print(result.checks.issuer_trusted) # True
print(result.checks.status) # True
print(result.checks.nonce) # True
print(result.checks.audience) # True
print(result.checks.policy) # True
verify_vc
Verify a raw VC dictionary (issuer signature only). This checks the Data Integrity proof, dates, revocation, and policy — but does not prove the presenter is the credential subject.
Use verify() with a holder-bound SD-JWT presentation for full verification. Use verify_vc() only for inspecting credential authenticity without a presentation context.
Returns a VerificationResult. The holder_bound, cnf_match, nonce, and audience fields will be None.
- Name
credential- Type
- dict
- Description
The full W3C VC as a dictionary (with
prooffield).
- Name
min_tier- Type
- int
- Description
Minimum verification tier. Defaults to
0.
- Name
min_reputation- Type
- float
- Description
Minimum reputation score. Defaults to
0.0.
- Name
required_capabilities- Type
- list[str] | None
- Description
Required capabilities. Defaults to
None.
- Name
check_revocation- Type
- bool
- Description
Whether to check revocation. Defaults to
True.
verify_vc() does not prove presenter identity. A valid result means the credential is authentic and unexpired, not that the person showing it to you is the subject.
Example
result = verifier.verify_vc(
credential=cred.vc,
check_revocation=False,
)
if result.valid:
print("Credential is authentic")
print(result.checks.holder_bound) # None
Verification Order
The verifier runs checks in a fixed order. Each step must pass before the next is attempted. If a step fails, subsequent steps are skipped and the result reflects the failure.
- Issuer signature -- Verify the SD-JWT issuer signature using the resolved public key.
- Holder binding -- Verify the key-binding JWT signature, confirming the presenter holds the private key.
cnfmatch -- Confirm the key-binding JWT's signing key matches the credential'scnfclaim.- Nonce -- If
expected_nonceis provided, check the key-binding JWT'snonceclaim. - Audience -- If
expected_audienceis provided, check the key-binding JWT'saudclaim. - Dates -- Validate
iat,exp, andnbfclaims against the current time. - Revocation -- If
check_revocationis enabled and the credential includes a status list, fetch and check revocation status. Fails closed: if the status list cannot be fetched (network error, timeout), the check fails rather than passing by default. - Policy -- Evaluate
min_tier,min_reputation, andrequired_capabilitiesagainst disclosed claims.
The issuer_trusted check runs independently and does not block other checks.
Revocation checks fail closed. If the status list endpoint is unreachable, the status check will fail. Design your infrastructure to ensure status list availability.
VerificationCheck fields
# All fields on VerificationCheck
result.checks.signature # bool — issuer signature valid
result.checks.cnf_match # bool | None — cnf claim present and parseable
result.checks.holder_bound # bool | None — KB-JWT signature matches cnf key
result.checks.status # bool | None — not revoked
result.checks.dates # bool — within nbf/exp window
result.checks.issuer_trusted # bool — issuer DID in trusted list
result.checks.nonce # bool | None — KB-JWT nonce matches
result.checks.audience # bool | None — KB-JWT audience matches
result.checks.policy # bool — min tier/rep/capabilities
DID Resolution
The verifier resolves issuer DIDs to retrieve public keys for signature verification. Two DID methods are supported:
did:key-- Resolved locally. The public key is decoded directly from the DID string using z-base58 multibase encoding. No network request required.did:web-- Resolved via HTTP. The verifier fetches the DID document fromhttps://<domain>/.well-known/did.json(or the appropriate path for DIDs with additional path components). Responses are cached according tocache_ttl.
Resolution failures (network errors, malformed documents) cause the signature check to fail with a descriptive error in result.errors.
Trusted issuer examples
verifier = AgentMarqueVerifier(
trusted_issuers=[
# Local resolution (no network)
"did:key:z6MkRegistry...",
# HTTP resolution (cached)
"did:web:registry.agentmarque.com",
],
)
Policy Enforcement
Policy enforcement runs after signature, holder binding, and date validation. The policy field on VerificationCheck is True only when all policy constraints are satisfied:
min_tier-- The disclosedverificationTierclaim must be greater than or equal to the specified minimum.min_reputation-- The disclosedreputationScoreclaim must be greater than or equal to the specified minimum.required_capabilities-- Every capability in the list must appear in the disclosedcapabilitiesclaim.
If a required claim is not disclosed (due to selective disclosure), the policy check fails and an error message indicates which claim was missing.
Example
# Strict policy: tier 2+, high reputation,
# specific capabilities
result = verifier.verify(
presentation=jwt_string,
expected_audience="did:web:api.example.com",
min_tier=2,
min_reputation=0.8,
required_capabilities=[
"invoice-processing",
"payments",
],
)
if not result.checks.policy:
print("Policy check failed:")
for err in result.errors:
print(f" - {err}")