Skip to main content

Technical Details

This page lists the specifications UniCore implements and describes how it is built. It is aimed at architects and developers who want to evaluate UniCore or integrate it with other systems, for example to check whether a wallet is compatible.

Specifications​

OpenID for Verifiable Credentials​

SpecificationVersionRole in UniCore
OpenID for Verifiable Credential Issuance (OpenID4VCI)1.0Issuer and holder
OpenID for Verifiable Presentations (OpenID4VP)1.0Verifier
Self-Issued OpenID Provider v2 (SIOPv2)Draft 13Verifier

A wallet that wants to receive credentials from UniCore or present them to it needs to support OpenID4VCI 1.0 and OpenID4VP 1.0. The UniMe wallet is built on the same OpenID4VC library as UniCore.

Issuance (OpenID4VCI)

  • Pre-authorized code flow (optionally protected with a transaction code) and authorization code flow
  • Credential offers by reference
  • Nonce Endpoint and Notification Endpoint
  • Proof type jwt for key binding
  • Not supported: batch issuance, deferred issuance, encrypted credential responses

Verification (OpenID4VP and SIOPv2)

  • Credential requests are expressed as Digital Credentials Query Language (DCQL) queries. DIF Presentation Exchange is no longer used.
  • Request objects are passed by reference (request_uri) and signed by UniCore, using the decentralized_identifier client identifier prefix.
  • Responses are received with response mode direct_post.
  • If an authorization request contains no DCQL query, UniCore sends a SIOPv2 request and receives an ID Token instead.

OAuth 2.0​

UniCore includes an OAuth 2.0 authorization server for the OpenID4VCI flows.

SpecificationNotes
RFC 8414: Authorization Server MetadataServed at /.well-known/oauth-authorization-server
RFC 9126: Pushed Authorization Requests (PAR)Also used for interactive authorization
RFC 7636: Proof Key for Code Exchange (PKCE)Required, only with the S256 method

DPoP is not supported.

Credential Formats and Data Models​

Format identifierDescription
jwt_vc_jsonW3C Verifiable Credential secured as a JWT
vc+sd-jwtW3C Verifiable Credential secured with SD-JWT
dc+sd-jwtSD-JWT VC, including Type Metadata

Credentials can follow these data models:

Which format is used for which data model is described in Issuance. The formats ldp_vc and mso_mdoc are not supported.

Credential Status​

Revocation and suspension use the IETF OAuth Token Status List (draft 10). Status lists are served as application/statuslist+jwt.

Cryptography​

  • Signing algorithms: EdDSA (Ed25519, preferred by default) and ES256. SD-JWT credentials and Key Binding JWTs are signed with ES256.
  • Keys are generated and stored in an IOTA Stronghold vault.

Decentralized Identifiers​

SpecificationNotes
DID methods did:key, did:jwk, did:web, did:iotaSee DID Methods
DIF Well Known DID ConfigurationSee Domain Linkage
DIF Linked Verifiable PresentationsPublished as a service in the DID Document

API and Integration​

SpecificationNotes
OpenAPI 3.1See the API references
RFC 9457: Problem Details for HTTP APIsError responses, see Problem Details
CloudEvents 1.0Format of events streamed with Server-Sent Events at GET /v0/events
OpenTelemetry (OTLP)Traces, logs and metrics, see Monitoring

Protocol Endpoints​

Besides the management API under /v0, UniCore serves the following endpoints, which wallets and other agents call. They are documented in the API reference including protocol endpoints.

EndpointPurpose
/.well-known/openid-credential-issuerOpenID4VCI Credential Issuer Metadata
/.well-known/oauth-authorization-serverOAuth 2.0 Authorization Server Metadata
/.well-known/did.json, /.well-known/did-configuration.jsondid:web DID Document and Domain Linkage
/openid4vci/credential-offer/{offer_id}Credential offer by reference
/openid4vci/credential, /openid4vci/nonce, /openid4vci/notificationOpenID4VCI Credential, Nonce and Notification Endpoints
/auth/par, /auth/authorize, /auth/consent, /auth/tokenOAuth 2.0 authorization server
/request/{request_id}, /redirectOpenID4VP request objects and responses
/ietf-oauth-token-status-list/{path}Token Status Lists
/vct/{credential_configuration_id}/{version}SD-JWT VC Type Metadata
/linked-verifiable-presentations/{presentation_id}Linked Verifiable Presentations
/healthz, /livez, /readyzHealth probes

Architecture​

UniCore is built with Domain-Driven Design (DDD) and Command Query Responsibility Segregation with Event Sourcing (CQRS-ES).

Bounded Contexts​

Each bounded context is a separate crate that owns its domain model: aggregates, commands, events and views.

Bounded contextResponsibilityAggregates
agent_issuanceIssuing credentials with OpenID4VCIserver_config, offer, credential, nonce, status_list, public_offer
agent_authorizationOAuth 2.0 authorization serveroauth2_authorization_request, authorization_code, access_token, client
agent_verificationRequesting and verifying presentations with OpenID4VP and SIOPv2authorization_request
agent_holderReceiving credentials and creating presentations as a holderreceived_offer, holder_credential, presentation
agent_identityDIDs, DID Document services, profile and connectionsdocument, service, profile, connection
agent_libraryCredential templates and catalogstemplate, catalog

The shared terminology of these contexts is defined in the Ubiquitous Language.

CQRS and Event Sourcing​

  1. A request to the API is translated into a command for an aggregate.
  2. The aggregate validates the command against its current state and either rejects it or emits one or more events, for example CredentialOfferCreated.
  3. The events are appended to the event store. They are never changed or deleted, and the state of an aggregate is rebuilt by replaying its events.
  4. Queries update read-optimized views from the events, which the API uses to answer read requests.
  5. The events are also passed to an event bus, which streams them to clients with Server-Sent Events and to the configured event publishers (see React to Events).

This gives UniCore a complete audit trail of every state change and lets external systems react to it without polling.

The CQRS-ES implementation is based on the cqrs-es crate. These event stores are supported:

Event storeNotes
PostgreSQLPersistent
MongoDBPersistent, requires a replica set because its change streams feed the event bus
In-memoryFor development and testing, all data is lost on restart

Crates​

CrateResponsibility
agent_applicationExecutable: loads the configuration and wires all components together
agent_api_httpHTTP API, OpenAPI specification and Problem Details
agent_issuance, agent_authorization, agent_verification, agent_holder, agent_identity, agent_libraryBounded contexts (see above)
agent_secret_managerKey management and signing with Stronghold, DID resolution
agent_storeEvent store and view repositories for PostgreSQL, MongoDB and in-memory
agent_event_publisher_http, agent_event_publisher_natsPublishing events to external systems via HTTP or NATS
agent_sharedConfiguration, profiles and shared utilities
shared-kernelBuilding blocks for application services, command handlers and the event bus

Design decisions are recorded as Architecture Decision Records.

Technology Stack​