Verification Federation API (v2)
The Verification Federation API allows a tenant who runs an upstream identity provider (a bank’s online banking session, a government eID, a telecom’s pre-enrolled authenticator) to mint a federation token that the platform validates and treats as a verified factor, bypassing the platform’s own KBV flow.
The API is the strict-conformance path for NIST SP 800-63B §5.1.3 (pre-enrolled out-of-band authenticators). Tenants without a federation provider use the platform’s email magic-link possession factor by default; that path is aligned with §5.1.3’s principles but does not meet the literal “pre-enrolled” requirement.
Status
Section titled “Status”The contract below is fixed. The implementation lands in v1.1 of the identity rework. v1 ships everything except the federation acceptance path; this page lets enterprise prospects evaluate whether the conformance route exists.
High-level flow
Section titled “High-level flow”- Tenant registers a trust anchor in their workspace settings: an asymmetric public key (RSA-PSS or Ed25519), an issuer string, and a list of
factor_typevalues the issuer is permitted to assert. - Tenant’s identity provider issues a federation assertion to the data subject (a user-of-tenant). The assertion is a signed JWT-shaped token whose claims describe the principal, the factor type minted, and the issuer.
- Tenant’s customer-facing application redirects the data subject’s session into the oHallo platform (chat-widget bootstrap, voice callback, or inbound email subscription URL) with the federation assertion attached.
- The platform validates the assertion against the workspace’s trust anchor and mints the corresponding
Factorrecord. The caller is nowidentified(one factor) orhigh-assurance(combined with another factor of a different category) without running KBV.
Trust anchor
Section titled “Trust anchor”A trust anchor declares which issuer the platform is willing to accept assertions from and what factors that issuer can vouch for.
PUT /api/workspaces/{workspace_id}/verification-trust-anchors/{anchor_id}Authorization: Bearer sf_live_v1_...Content-Type: application/json
{ "issuer": "https://identity.acme-bank.example/", "algorithm": "EdDSA", "public_key_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----", "permitted_factor_types": ["upstream_attested", "webauthn", "push_app"], "max_assertion_age_seconds": 300, "audience": "https://platform.ohallo.eu/"}Returns 201 on creation, 200 on update. The trust anchor is durable and applies to all subsequent verification flows for the workspace.
Federation assertion shape
Section titled “Federation assertion shape”The assertion is a signed JWT with these required claims:
{ "iss": "https://identity.acme-bank.example/", "sub": "contact-uuid-as-known-to-platform", "aud": "https://platform.ohallo.eu/", "iat": 1715520000, "exp": 1715520300, "factor_type": "upstream_attested", "factor_category": "possession", "level_of_assurance": "ial2"}subMUST match acontact_idknown to the workspace. The tenant is responsible for mapping their internal user id to the platform’s contact id (typically at contact create time via theexternal_idfield).factor_typeandfactor_categoryMUST be inpermitted_factor_typeson the trust anchor.exp - iatMUST NOT exceedmax_assertion_age_seconds.audMUST match the platform audience configured on the anchor.
Signature is verified using the trust anchor’s algorithm + public_key_pem. Any failure path (bad signature, expired, unknown issuer, audience mismatch, factor not permitted, contact not found) returns a typed deny without minting a factor.
Presenting the assertion
Section titled “Presenting the assertion”The assertion travels via one of three channels:
Chat-widget bootstrap
Section titled “Chat-widget bootstrap”The tenant’s bootstrap call to the chat-widget script includes the assertion in the oHallo.start({ ..., federationAssertion: '<jwt>' }) call. The widget forwards it to the platform on the first message.
Voice callback redirection
Section titled “Voice callback redirection”For voice callers, the tenant’s customer-facing application embeds the assertion in a one-time callback URL that triggers an outbound call from the platform. The tenant calls:
POST /api/conversations/voice/dispatchAuthorization: Bearer sf_live_v1_...Content-Type: application/json
{ "callee_phone": "+15551234567", "workspace_id": "...", "federation_assertion": "<jwt>"}The platform dials the callee, and the assertion is associated with the resulting conversation. The verification specialist sees the caller as already identified on session start.
Inbound email subscription URL
Section titled “Inbound email subscription URL”For email, the tenant includes the assertion as a query parameter on the platform-issued conversation subscription URL. The first inbound email on that URL is associated with the asserted contact.
Limits
Section titled “Limits”- One assertion per conversation. Re-presenting different assertions inside the same conversation is rejected.
- No revocation channel in v2. The assertion lifetime is governed solely by
exp. If the tenant needs to revoke an assertion mid-conversation, they trigger a fresh verification flow on the platform side via the v1 DSR / scope-management surface. - Audit logging. Every accepted assertion writes a
factor_addedidentity_event withevidence_ref: federation:{anchor_id}:{jti}. Thejticlaim, if present in the assertion, is captured for non-replay analysis.
Why we cite NIST §5.1.3
Section titled “Why we cite NIST §5.1.3”§5.1.3 defines out-of-band authenticators as devices the user has separately enrolled with a trusted issuer. The platform’s email magic-link is a close substitute — the user has demonstrably enrolled their email address as a recovery channel — but it is not a pre-enrolled authenticator in the §5.1.3 sense. Federation closes that gap: the tenant’s identity provider IS the pre-enrolling party.
This matters for tenants whose regulators (FFIEC, EBA, MAS) require literal §5.1.3 conformance rather than the principle-aligned signal the magic-link gives. Federation gets you there.