oid4vp

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: MIT Imports: 21 Imported by: 0

README

go-oid4vp

OpenID for Verifiable Presentations 1.0 — the verifier (Relying Party) protocol engine in Go: signed Request Objects (JAR/RFC 9101) with WRPAC x5c, request_uri lifecycle, encrypted direct_post.jwt response processing with per-session ephemeral keys, Digital Credentials API (DCAPI) request and response shapes, same-device response_code return, transaction_data, and OID4VP error-response mapping.

  • Storage-free: bring your own SessionStore (in-memory reference included; contract test suite exported in package storetest).
  • HTTP-free: services own transport; this library builds and consumes protocol payloads.
  • All cryptography via github.com/gmb-eudi/go-eudi-crypto (ECCG-pinned policy; algorithms are configured and policy-validated, never chosen by tokens).
  • client_id prefix v1: x509_san_dns only; verifier_attestation is an extension point (constructor rejects it until implemented).
  • Response encryption keys are per-session ephemeral; static operator decryption keys are not supported.

Implemented specs: OpenID4VP 1.0 (final) §5/§6/§8/§12.1, Annex A, Annex B; RFC 9101; HAIP 1.0 (final); ARF 2.9 RPRC_19a; CIR 2024/2982 Art. 3.

Status: pre-v1. API frozen no earlier than OIDF conformance pass.

Documentation

Overview

Package oid4vp implements the verifier (Relying Party) side of OpenID for Verifiable Presentations 1.0: signed Request Objects (RFC 9101 JAR) carrying the operator WRPAC, request_uri lifecycle, encrypted direct_post.jwt response processing with per-session ephemeral keys, Digital Credentials API shapes (Annex A), same-device response_code return (§8.2/§8.3), and OID4VP error responses.

The package is storage-free (SessionStore interface; in-memory reference implementation; contract suite in storetest) and HTTP-free (services own transport). All cryptography is delegated to github.com/gmb-eudi/go-eudi-crypto; algorithms come from configuration validated against the ECCG policy, never from tokens.

Error mapping guidance for services (docs/conventions.md taxonomy) is on each sentinel in errors.go; wallet-boundary serialization is (*Engine).ErrorResponse — OID4VP error shapes, not problem+json.

Index

Constants

View Source
const (
	// DefaultSessionTTL bounds request_uri fetch + wallet interaction.
	DefaultSessionTTL = 5 * time.Minute
	// DefaultMaxResponseBody caps wallet-posted bodies (T-08.6 oversized
	// body defense).
	DefaultMaxResponseBody = 1 << 20
)
View Source
const ClientIDPrefixX509SANDNS = "x509_san_dns"

ClientIDPrefixX509SANDNS is the only client_id prefix supported in v1 (OID4VP §5 client identifier prefixes; WP-08 decision — verifier_attestation is an extension point, rejected by New until implemented).

Variables

View Source
var (
	// Session / store lifecycle.
	ErrSessionInvalid     = errors.New("oid4vp: invalid session")              // programming error; 500 at boundary
	ErrSessionNotFound    = errors.New("oid4vp: session not found or expired") // err:session:not-found
	ErrSessionExpired     = errors.New("oid4vp: session expired")              // err:session:not-found
	ErrSessionConsumed    = errors.New("oid4vp: session already consumed")     // err:session:consumed
	ErrSessionNotConsumed = errors.New("oid4vp: session must be obtained via SessionStore.ConsumeOnce")

	// Engine configuration / request spec.
	ErrConfig                    = errors.New("oid4vp: invalid engine config")
	ErrSANMismatch               = errors.New("oid4vp: client DNS name does not match a SAN dNSName in the WRPAC leaf") // OID4VP §5 x509_san_dns
	ErrUnsupportedClientIDPrefix = errors.New("oid4vp: unsupported client_id prefix")                                   // WP-08 decision: x509_san_dns only in v1
	ErrSpec                      = errors.New("oid4vp: invalid request spec")
	ErrNoRegistration            = errors.New("oid4vp: registration reference required in every request (ARF RPRC_19a)")
	ErrFlowMismatch              = errors.New("oid4vp: operation not valid for this session flow")

	// request_uri lifecycle (T-08.4).
	ErrRequestURIConsumed    = errors.New("oid4vp: request object already served (single-use request_uri)") // OID4VP §5 request_uri
	ErrWalletMetadataInvalid = errors.New("oid4vp: wallet metadata rejected")

	// Response processing (T-08.5/6/7). All map to
	// err:presentation:invalid-response unless noted.
	ErrBodyTooLarge        = errors.New("oid4vp: response body exceeds configured cap")
	ErrMalformedResponse   = errors.New("oid4vp: malformed response")
	ErrDecrypt             = errors.New("oid4vp: response decryption failed")               // stale/foreign key, bad JWE
	ErrStateMismatch       = errors.New("oid4vp: state does not match session")             // err:presentation:nonce-mismatch
	ErrAPVMismatch         = errors.New("oid4vp: JWE apv does not match the session nonce") // err:presentation:nonce-mismatch
	ErrUnknownCredentialID = errors.New("oid4vp: vp_token key does not identify a credential query")

	// Same-device return (T-08.8), OID4VP §8.2/§8.3/§12.1.
	ErrNoResponseCode       = errors.New("oid4vp: no response_code minted for this session")
	ErrResponseCodeMismatch = errors.New("oid4vp: response_code is not bound to this session") // err:presentation:nonce-mismatch
	ErrResponseCodeConsumed = errors.New("oid4vp: response_code already used")                 // err:session:consumed

	// DCAPI (T-08.9), OID4VP Annex A.
	ErrOriginNotExpected = errors.New("oid4vp: response origin not in expected_origins")

	// transaction_data (T-08.10, phase-2 flag).
	ErrTransactionDataDisabled   = errors.New("oid4vp: transaction_data requested but the phase-2 flag is off")
	ErrTransactionDataInvalid    = errors.New("oid4vp: invalid transaction_data entry")
	ErrTransactionDataMissing    = errors.New("oid4vp: transaction_data_hashes missing from presentation")
	ErrTransactionDataUnexpected = errors.New("oid4vp: transaction_data_hashes present but none were requested")
	ErrTransactionDataMismatch   = errors.New("oid4vp: transaction_data_hashes do not match the request")

	// SessionTranscript delegation (T-08.7).
	ErrTranscriptParams = errors.New("oid4vp: presentation lacks the parameters for a SessionTranscript")
)

Sentinel errors. Libraries return typed errors; services map them to err:domain:reason problem codes (docs/conventions.md). The mapping each sentinel is expected to receive is noted inline. None of these messages ever carries attribute values, request bodies, or token contents (hard rule 3).

Functions

func SessionTranscriptFor

func SessionTranscriptFor(p Presentation) (mdoc.SessionTranscript, error)

SessionTranscriptFor builds the ISO 18013-5 SessionTranscript for one verified-to-be mso_mdoc Presentation by delegating to the go-mdoc constructors (OID4VP Annex B.2; ISO/IEC TS 18013-7 Annex B; Annex A for DCAPI):

  • request_uri flows: OID4VPHandover(clientID, nonce, jwkThumbprint, responseURI).
  • DCAPI flows (Origin set): OID4VPDCAPIHandover(origin, nonce, jwkThumbprint) — no client_id or response_uri in this variant.

jwkThumbprint (Presentation.JWKThumbprint) is the RFC 7638 thumbprint of the RP's OWN ephemeral response-encryption public key — computed by ProcessResponse from Session.EphemeralKeyPKCS8, never from anything wallet-supplied. The JWE apu value is NOT an input to either constructor here and is not read anywhere in the pipeline (T-08.7 correction 2026-07-06: this task's original brief assumed apu/mdocGeneratedNonce filled this slot; the go-mdoc constructors' actual, EU-reference-verified shape takes jwkThumbprint instead — see WP-08 README Decisions "T-08.7/T-08.9 correction" for the full rationale).

FLAG (carried from go-mdoc's OID4VPHandover/OID4VPDCAPIHandover doc comments and docs/mdoc-eu-gap-report.md): this handover shape is corroborated against a production EU reference verifier, not yet byte-for-byte confirmed against the OpenID4VP 1.0 Annex B.2 primary spec text (not vendored under references/ at the time of writing) — re-verify once that text is available.

verifier-core passes the result to mdoc.Verifier.Verify as VerifyInput.SessionTranscript (WP-03). Fail closed: incomplete parameters are an error, never a zero transcript. Pure delegation — no CBOR/SessionTranscript construction of its own.

func TransactionDataHashes

func TransactionDataHashes(td [][]byte, alg string, policy crypto.Policy) ([]string, error)

TransactionDataHashes computes the expected transaction_data_hashes for a set of request entries: base64url( H( base64url(entry) ) ), where H is the digest bound to alg by the ECCG policy (OID4VP §5 transaction_data; HAIP baseline ES256 ⇒ SHA-256). No hash literal here — the algorithm comes from the policy (hard rule 4).

Types

type Config

type Config struct {
	Keys           crypto.KeyProvider // operator signing key (WRPAC key)
	SigningKeyID   string
	WRPACChain     []*x509.Certificate // leaf first; goes into x5c (CIR 2024/2982 Art. 3)
	ClientDNSName  string              // must match a SAN dNSName of the leaf
	ClientIDPrefix string              // "" = x509_san_dns; anything else is rejected in v1

	Policy crypto.Policy    // nil = crypto.ECCG()
	Clock  func() time.Time // nil = time.Now
	Rand   io.Reader        // nil = crypto/rand.Reader

	RequestURIBase string // e.g. https://verifier.example.com/request — session id is appended (default request_uri builder; ignored when RequestURIFunc is set)
	// RequestURIFunc, when set, fully controls the request_uri embedded in
	// the wallet invocation (OID4VP §5: the spec only requires client_id +
	// request_uri + request_uri_method by reference, not any particular URL
	// shape) — the consumer owns its own routing and builds the exact URL
	// its bound route expects. When nil, RequestURIBase+"/"+id is used
	// (backward-compatible default). RequestURIBase may be empty when this
	// is set.
	RequestURIFunc    func(sessionID string) string
	UniversalLinkBase string // wallet universal-link endpoint, e.g. https://wallet.example.org/authorize

	SessionTTL      time.Duration // 0 = DefaultSessionTTL
	MaxResponseBody int           // 0 = DefaultMaxResponseBody

	ResponseEncryption ResponseEncryption
	VPFormats          VPFormats

	EnableTransactionData bool // phase-2 flag (T-08.10)
}

Config assembles an Engine. Everything is explicit and validated in New; zero values that have safe defaults are documented per field.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine is the OpenID4VP verifier protocol engine (WP-08 README). It is stateless between calls: all per-verification state lives in Session.

func New

func New(ctx context.Context, cfg Config) (*Engine, error)

New validates cfg and derives the client identifier from the WRPAC leaf. Fail closed: any unknown algorithm/curve, prefix, or malformed base URL is a construction error (hard rule 7).

func (*Engine) AbsorbWalletMetadata

func (e *Engine) AbsorbWalletMetadata(s *Session, raw []byte) error

AbsorbWalletMetadata is the T-08.4 wallet-metadata absorption hook (OID4VP §5 request_uri_method). v1 pins request_uri_method=get, so no metadata arrives on the request_uri fetch yet; services call this when the future post method (or a DCAPI capability hint) delivers one. The document is validated as a JSON object, size-capped, and stored verbatim on the session for policy use — never parsed further here, never logged (hard rule 3: treat as untrusted).

func (*Engine) ClientID

func (e *Engine) ClientID() string

ClientID returns the full prefixed client identifier, e.g. "x509_san_dns:verifier.example.com" (OID4VP §5).

func (*Engine) ConsumeResponseCode

func (e *Engine) ConsumeResponseCode(s *Session, code ResponseCode) error

ConsumeResponseCode redeems a response_code: constant-time comparison against the code minted FOR THIS SESSION, single-use. This is the §12.1 session-fixation defense — an attacker who fixated their own session id on a victim cannot fetch the victim's result: their code is bound to their session. The caller persists s (SessionStore.Save) so the used-marker sticks.

func (*Engine) DCAPIRequest

func (e *Engine) DCAPIRequest(ctx context.Context, s *Session) ([]byte, error)

DCAPIRequest renders the SIGNED dc_api.jwt request member for navigator.credentials.get (OID4VP Annex A): a JAR-typed JWT with the WRPAC x5c, expected_origins (REQUIRED for signed requests), and no response_uri/state — the browser returns the response and the origin is validated instead.

func (*Engine) DCAPIUnsignedRequest

func (e *Engine) DCAPIUnsignedRequest(s *Session) ([]byte, error)

DCAPIUnsignedRequest renders the UNSIGNED dc_api variant (Annex A): the request parameters as a plain JSON object — no client_id (the calling origin is the identity). WP-08 decision: the unsigned variant still uses response_mode dc_api.jwt because HAIP makes response encryption mandatory.

func (*Engine) ErrorResponse

func (e *Engine) ErrorResponse(err error) (int, []byte)

ErrorResponse serializes an engine error for the WALLET boundary in the OpenID4VP Error Response format ({"error":..,"error_description":..}), NOT problem+json — the protocol wins on the wallet boundary (docs/conventions.md). status is a plain int so this library imports no HTTP package (ADR-0004). Services map the SAME sentinels to err:domain:reason problem codes for their own logging/metrics.

Unknown or internal errors collapse to 500 server_error: fail closed, leak nothing.

func (*Engine) NewSession

func (e *Engine) NewSession(ctx context.Context, spec RequestSpec) (*Session, WalletInvocation, error)

NewSession validates spec, generates the session secrets (id, nonce, state — ≥128-bit from the injected rand; OID4VP §5, §12.1) and the per-session ephemeral response-encryption key (WP-08 decision), and returns the wallet invocation. The caller persists the session (SessionStore.Save).

func (*Engine) ProcessDCAPIResponse

func (e *Engine) ProcessDCAPIResponse(ctx context.Context, s *Session, origin string, data []byte) ([]Presentation, error)

ProcessDCAPIResponse handles the browser-returned dc_api.jwt response (OID4VP Annex A): validate the calling origin against expected_origins, then decrypt and parse like direct_post.jwt — but with no state member (the browser context provides correlation; binding is nonce-based plus origin validation, WP-08 decision) and the DCAPI handover. Fail closed: an origin absent from expected_origins is rejected with ErrOriginNotExpected before any decryption — the DCAPI analog of the §8.2 state binding. Precondition: s obtained via SessionStore.ConsumeOnce.

func (*Engine) ProcessResponse

func (e *Engine) ProcessResponse(ctx context.Context, s *Session, r RawResponse) ([]Presentation, ResponseCode, error)

ProcessResponse handles the §8.2 direct_post.jwt response for request_uri flows: form parse → JWE decrypt with the per-session ephemeral key → apv handling (Annex B.2) → vp_token object parse (§8.1) → state binding → response_code mint (§8.2, same-device).

Precondition: s was obtained from SessionStore.ConsumeOnce (atomic one-time consumption; replays die at the store). The caller persists s afterwards (Save) to store the minted response_code.

func (*Engine) RedirectURI

func (e *Engine) RedirectURI(s *Session) (string, error)

RedirectURI renders the §8.3 same-device return: the response endpoint answers the wallet's POST with 200 {"redirect_uri": <this value>}, and the wallet navigates the user's browser there. The response_code in the query fences the result fetch to the browser session that actually completed the presentation (OID4VP §8.2, §12.1).

func (*Engine) RequestObjectJWT

func (e *Engine) RequestObjectJWT(ctx context.Context, s *Session) ([]byte, error)

RequestObjectJWT builds and signs the Request Object for GET request_uri (RFC 9101 JAR; OID4VP §5; HAIP §5). Single-use: the session is marked served and the caller MUST persist it (SessionStore.Save); a second call fails with ErrRequestURIConsumed (T-08.4).

func (*Engine) ValidateTransactionDataEcho

func (e *Engine) ValidateTransactionDataEcho(s *Session, echoedHashes []string, hashAlgName string) error

ValidateTransactionDataEcho compares the transaction_data_hashes echoed by the wallet (in a KB-JWT for dc+sd-jwt, or the device-signed payload for mso_mdoc — extracted by go-sdjwt/go-mdoc, WP-09) against the hashes of the session's request entries (OID4VP §5). Set semantics: the wallet may reorder. present/absent/mismatch matrix (T-08.10):

  • flag off but session carries entries → ErrTransactionDataDisabled
  • entries requested, none echoed → ErrTransactionDataMissing
  • none requested, some echoed → ErrTransactionDataUnexpected
  • counts differ or any hash unmatched → ErrTransactionDataMismatch

type Flow

type Flow string

Flow selects the presentation flow of a session (WP-08 README).

const (
	SameDevice  Flow = "same-device"  // OID4VP §8.2/§8.3: redirect_uri + response_code return
	CrossDevice Flow = "cross-device" // QR / polling; response endpoint returns no redirect
	DCAPI       Flow = "dcapi"        // OID4VP Annex A: browser Digital Credentials API
)

Flow values (WP-08 README naming).

type MemStore

type MemStore struct {
	// contains filtered or unexported fields
}

MemStore is the in-memory reference SessionStore: single-process, for tests and development. Sessions are stored as JSON snapshots, which (a) gives Load copy semantics identical to a networked store and (b) proves every Session is serializable exactly as the WP-09 Valkey store needs.

func NewMemStore

func NewMemStore(clock func() time.Time) *MemStore

NewMemStore returns an empty MemStore. clock nil defaults to time.Now.

func (*MemStore) ConsumeOnce

func (m *MemStore) ConsumeOnce(_ context.Context, id string) (*Session, error)

ConsumeOnce atomically hands the session to exactly one caller (OID4VP §8.2 one-time response consumption; §12.1 replay defense). The Consumed marker is sticky: it survives later Save calls, so a replayed wallet POST fails even after the service persisted post-processing state (WP-08 decision, recorded in the README).

func (*MemStore) Load

func (m *MemStore) Load(_ context.Context, id string) (*Session, error)

Load returns an independent copy of the stored session. Expired sessions are evicted and reported as not found (store contract; the Engine also checks ExpiresAt itself — fail closed).

func (*MemStore) Save

func (m *MemStore) Save(_ context.Context, s *Session) error

Save stores a JSON snapshot of s.

type Presentation

type Presentation struct {
	QueryCredID string // DCQL credential query id (vp_token key, §8.1)
	Format      string // dcql.FormatSDJWT | dcql.FormatMdoc (from the session's query)
	Payload     []byte // dc+sd-jwt: presentation string verbatim; mso_mdoc: base64url-decoded DeviceResponse

	Nonce, ClientID, ResponseURI string
	Origin                       string // DCAPI only (Annex A)

	// JWKThumbprint is the RFC 7638 thumbprint of the RP's OWN ephemeral
	// response-encryption public key (the same key advertised in
	// client_metadata, T-08.3) — computed by ProcessResponse from
	// Session.EphemeralKeyPKCS8 via crypto.JWKThumbprint, never from
	// anything wallet-supplied. The JWE apu header is not read at all (see
	// WP-08 README Decisions "T-08.7/T-08.9 correction"): JWKThumbprint is
	// the mdoc SessionTranscript handover's sole key-binding input, set
	// only for mso_mdoc presentations.
	JWKThumbprint string
}

Presentation is one entry of the vp_token object (OID4VP §8.1), paired with the binding parameters downstream verification needs: nonce and client_id for KB-JWT (go-sdjwt), and the OID4VPHandover / OID4VPDCAPIHandover inputs for mdoc (go-mdoc, Annex B.2 / Annex A).

type RawResponse

type RawResponse struct {
	Body []byte
}

RawResponse is the wallet's POST body to the response endpoint (OID4VP §8.2 direct_post.jwt: application/x-www-form-urlencoded with response=<JWE>). The service passes it verbatim, size-unchecked — the engine owns the cap.

type RequestSpec

type RequestSpec struct {
	Query           dcql.Query
	Flow            Flow // SameDevice | CrossDevice | DCAPI
	ResponseURI     string
	ReturnURI       string                 // same-device only (§8.3)
	Registration    rpcert.RegistrationRef // always (ARF RPRC_19a)
	WRPRC           []byte                 // optional (ADR-0003)
	TransactionData [][]byte               // phase 2 (T-08.10)
	ExpectedOrigins []string               // DCAPI signed requests (Annex A)
}

RequestSpec describes one verification request (WP-08 README target interface). ReturnURI is the same-device §8.3 redirect target — a README addition required by T-08.8, flagged in the plan's README corrections.

type ResponseCode

type ResponseCode string

ResponseCode is the single-use §8.2 response_code minted for same-device sessions and redeemed via ConsumeResponseCode (§8.3/§12.1).

type ResponseEncryption

type ResponseEncryption struct {
	Curve     string   // ephemeral key curve, e.g. the HAIP baseline P-256
	Alg       string   // JWE key agreement advertised on the ephemeral JWK
	EncValues []string // encrypted_response_enc_values_supported (§8.2)
}

ResponseEncryption configures the per-session ephemeral response encryption advertised in client_metadata (OID4VP §8.2 direct_post.jwt; HAIP §5: encryption mandatory). Values are supplied by the service's configuration and validated against crypto.Policy — this library hardcodes no algorithm strings (hard rule 4).

type Session

type Session struct {
	ID       string `json:"id"`
	Flow     Flow   `json:"flow"`
	ClientID string `json:"client_id"` // full prefixed form, e.g. "x509_san_dns:verifier.example.com"

	Nonce string `json:"nonce"` // OID4VP §5: ≥128-bit, crypto/rand, base64url
	State string `json:"state"` // response binding (§8.2)

	ResponseURI string `json:"response_uri"`         // §8.2 direct_post.jwt endpoint
	ReturnURI   string `json:"return_uri,omitempty"` // same-device §8.3 redirect target (see README corrections)

	Query           dcql.Query             `json:"query"`                      // OID4VP §6
	Registration    rpcert.RegistrationRef `json:"registration"`               // ARF RPRC_19a — always present
	WRPRC           []byte                 `json:"wrprc,omitempty"`            // optional registration certificate (ADR-0003)
	TransactionData [][]byte               `json:"transaction_data,omitempty"` // phase 2 (T-08.10)
	ExpectedOrigins []string               `json:"expected_origins,omitempty"` // DCAPI (Annex A)

	EphemeralKeyPKCS8 []byte `json:"ephemeral_key_pkcs8"` // per-session response-encryption private key, PKCS#8 DER

	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`

	RequestObjectServed bool   `json:"request_object_served"`     // single-use request_uri (T-08.4)
	WalletMetadata      []byte `json:"wallet_metadata,omitempty"` // absorbed hook payload (T-08.4)
	Consumed            bool   `json:"consumed"`                  // sticky one-time marker (ConsumeOnce)
	ResponseCode        string `json:"response_code,omitempty"`   // minted §8.2 (T-08.5), redeemed §8.3 (T-08.8)
	ResponseCodeUsed    bool   `json:"response_code_used,omitempty"`
}

Session is the per-verification protocol state. It is a plain JSON-serializable record so SessionStore implementations (Valkey in WP-09) can persist it verbatim. Fields are exported for storage, not for mutation: services treat a Session as opaque between Engine calls.

The response-encryption key is per-session ephemeral (WP-08 decision; HAIP-aligned): it lives only inside the session record and dies with it.

type SessionStore

type SessionStore interface {
	Save(ctx context.Context, s *Session) error
	Load(ctx context.Context, id string) (*Session, error)
	ConsumeOnce(ctx context.Context, id string) (*Session, error) // atomic: response endpoint
}

SessionStore persists sessions. The Valkey implementation lives in services (WP-09); it MUST pass storetest.Run unchanged.

Contract (verified by storetest.Run):

  • Save then Load returns an equal, independent copy (mutating a loaded session does not affect the stored one).
  • Load/ConsumeOnce of an unknown OR expired id returns ErrSessionNotFound (expiry may be storage eviction, e.g. Valkey TTL; the Engine additionally enforces ExpiresAt itself, fail closed).
  • ConsumeOnce is atomic: for one id, exactly one caller ever receives the session (returned with Consumed=true); every other and every later call gets ErrSessionConsumed — even after subsequent Save calls of the same session (the consumed marker is sticky; WP-08 decision). This is the §12.1 replay defense for the response endpoint (OID4VP §8.2).

type VPFormats

type VPFormats struct {
	SDJWTAlgValues          []string // dc+sd-jwt sd-jwt_alg_values
	KBJWTAlgValues          []string // dc+sd-jwt kb-jwt_alg_values
	MdocIssuerAuthAlgValues []int64  // mso_mdoc issuerauth_alg_values (COSE labels)
	MdocDeviceAuthAlgValues []int64  // mso_mdoc deviceauth_alg_values (COSE labels)
}

VPFormats configures client_metadata vp_formats_supported (OID4VP §5; Annex B.2/B.3). Same rule: values from config, validated by policy.

type WalletError

type WalletError struct {
	Code        string
	Description string
}

WalletError is an OID4VP error response sent BY the wallet (e.g. the user declined: error=access_denied). It is not an engine failure; the service records the outcome and acknowledges the wallet. Code and Description are wallet-supplied, length-capped, and must be treated as untrusted text (never logged raw next to attribute data, hard rule 3).

func (*WalletError) Error

func (e *WalletError) Error() string

type WalletInvocation

type WalletInvocation struct {
	SchemeURI     string // openid4vp://?client_id=...&request_uri=...&request_uri_method=get
	UniversalLink string // UniversalLinkBase + same query
	QRPayload     string // string to encode into the cross-device QR
	DCAPI         []byte // Annex A request member JSON (populated for Flow == DCAPI, T-08.9)
}

WalletInvocation carries the flow-specific way to put the request in front of a wallet: custom-scheme URI, https universal link and QR payload for request_uri flows, or the DCAPI request member (T-08.9).

Directories

Path Synopsis
Package storetest exports the SessionStore contract suite (WP-08 T-08.1).
Package storetest exports the SessionStore contract suite (WP-08 T-08.1).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL