This document defines a normative UCP-specific integration profile for using I2H2A SD-JWT+KB credentials in Universal Commerce Protocol (UCP) flows. It is an adaptation layer on top of the MCVI-aligned I2H2A core specification.
I2H2A and UCP address different trust layers:
I2H2A is complementary to UCP, not a replacement for UCP authentication or payment rails.
In the UCP actor model:
This profile applies across UCP transports (REST, MCP, A2A, Embedded).
Implementations using this profile MUST require an I2H2A SD-JWT VC that conforms to I2H2A v0.2, including:
vct = https://i2h2a.org/credentials/I2H2Atyp = dc+sd-jwt for UCP profile conformance. During migration, verifiers SHOULD accept both dc+sd-jwt and legacy vc+sd-jwt.iss, sub, iat, nbf (if present), expcnf.jwk with kty=EC, crv=P-256, x, y_sd_alg = sha-256credentialStatus (type=BitstringStatusListEntry, required statusPurpose, statusListIndex, statusListCredential)statusListIndex MUST be a base-10 string per W3C Bitstring Status List. For compatibility, integer inputs MAY be accepted if normalized to equivalent base-10 string before validation.aud, nonce, sd_hash, signed by key corresponding to cnf.jwkVerifiers MUST enforce:
cnf.jwkaud, nonce, sd_hash)credentialStatus is present_sddelegationDepth, parentCredential, required scope disclosure)Core I2H2A v0.2 fields are scope.mcpServers and scope.taskType in the MCVI-aligned profile.
For UCP usage:
scope.taskType SHOULD represent the operation class (for example: checkout, discovery, order).scope.mcpServers into scope.services as verifier/service identifiers, including UCP merchant verifier identifiers where used.scope.services as authoritative when present, and MAY derive equivalent semantics from scope.mcpServers for compatibility with the core profile.Because UCP capability identifiers are namespaced (for example dev.ucp.shopping.checkout), implementers SHOULD define a shared mapping policy from UCP operation/capability to scope.taskType values.
The authorization disclosure is opaque to generic verifiers and MAY carry UCP-specific policy constraints.
When used in UCP, authorization SHOULD contain only constraints already agreed by participating parties (for example amount limits, merchant binding, narrow expiry windows, operation limitations), while preserving backward compatibility with generic I2H2A verification.
Generic I2H2A verifiers MUST NOT require authorization semantics beyond structural presence unless platform policy explicitly requires it.
I2H2A v0.2 requires temporal checks (nbf, exp).
For checkout-grade risk posture, issuers SHOULD use short validity windows appropriate for session-bound delegation and SHOULD minimize credential reuse windows.
Implementations MUST NOT overload OAuth Authorization: Bearer with I2H2A presentation data.
OAuth and I2H2A MUST be carried as separate artifacts.
Authorization: Bearer <oauth-token>.X-I2H2A-Presentation: <sd-jwt+kb>.meta.i2h2a.presentation.Verifiers MUST issue nonce values that are:
Per transport:
KB-JWT aud MUST match the verifier audience configured by the receiving merchant/verifier integration.
Audience SHOULD be a stable verifier identifier (for example merchant verifier endpoint identifier, service identifier, or equivalent verifier audience value configured in deployment).
Verifiers MUST reject presentations when:
sd_hash mismatchVerifiers SHOULD enforce narrow nonce lifetimes and replay cache windows.
A UCP merchant integration SHOULD execute verification in this order:
verifyI2H2APresentation) with:
did:keyCurrent middleware response shape:
{
"valid": true,
"error": "optional string when invalid",
"claims": {
"agentDid": "did:key:...",
"delegatedBy": "did:...",
"scope": {
"services": ["..."],
"taskType": "..."
},
"authorization": {}
}
}
UCP response code mapping is transport-specific. Implementations SHOULD map I2H2A verification failures to UCP authentication/authorization error handling conventions without changing UCP protocol semantics.
Recommended baseline:
For UCP checkout latency sensitivity, deployments SHOULD:
POST /checkout-sessions/abc/complete HTTP/1.1
Authorization: Bearer eyJhbGciOi...
UCP-Agent: profile="https://i2h2a.org/.well-known/ucp-profile.json"
X-I2H2A-Presentation: <issuer-jwt>~<disclosure>~...~<kb-jwt>
Content-Type: application/json
{
"payment": {
"instruments": [
{
"handler_id": "processor_tokenizer",
"credential": { "token": "tok_123" }
}
]
}
}
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "complete_checkout",
"arguments": {
"meta": {
"ucp-agent": {
"profile": "https://i2h2a.org/.well-known/ucp-profile.json"
},
"i2h2a": {
"presentation": "<issuer-jwt>~<disclosure>~...~<kb-jwt>"
}
},
"checkout": {
"id": "checkout_123"
}
}
},
"id": 1
}
REST example:
{
"code": "authorization_failed",
"content": "I2H2A verification failed: KB-JWT nonce mismatch"
}
MCP example:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000,
"message": "Unauthorized",
"data": {
"reason": "I2H2A verification failed: Issuer JWT signature invalid"
}
}
}
This profile does not:
I2H2A in this profile is strictly the human delegation proof layer used alongside existing UCP mechanisms.
An implementation claiming conformance to this profile: