Generated from sirosfoundation/go-wallet-backend's
RELEASE_NOTES.md, fetched at build time. Corrections belong in that file, not here.
Wallet Backend Release Notes
[v0.19.0] - 2026-09-07
Fixed
- OID4VP request encryption now respects the
algheader specified in the verifier's JWK instead of always inferring it from the key material, preventing validation failures when the verifier checks the returnedvp_token(#315)
[v0.18.4] - 2026-09-07
This is the first usable release of the 0.18 line. v0.18.1 does not build, v0.18.2 rejects every WebAuthn sign-up and login, and v0.18.3 was tagged on the wrong commit. Deployments on v0.17.0 should move straight here.
Fixed
- WebAuthn registration and login now accept PRF (Pseudo-Random Function) extension outputs from clients. After the go-webauthn 0.18 upgrade, both flows were rejecting credentials when clients returned PRF outputs that the backend hadn't explicitly requested, breaking sign-up and authentication for wallets that use client-side PRF salts (#312)
[v0.18.3] - 2026-09-06
Broken release - use v0.18.4. This tag was created on the wrong commit and contains the same code as v0.18.2, including the WebAuthn sign-up and login failure fixed in v0.18.4. No container image was published for it.
Changed
- Updated release notes documentation for v0.18.2 (#311)
[v0.18.2] - 2026-09-06
Do not deploy - use v0.18.4. WebAuthn sign-up and login fail on this release with
Client returned the "prf" extension output which was not requested; v0.18.4 fixes it and delivers everything listed here.
Use this instead of v0.18.1. v0.18.1 does not compile and produced no container image; everything it lists is delivered here.
Fixed
- Restored compilation against go-webauthn 0.18 by updating the
VerifyAttestationcall site to pass the two new policy arguments required by the library's API change. The signature policy explicitly selects BER encoding tolerance to maintain support for YubiKey firmware 5.8's non-minimally-encoded ECDSA signatures, which would otherwise be rejected by 0.18's stricter DER-only default (#310)
[v0.18.1] - 2026-09-06
Broken release - use v0.18.2. The go-webauthn 0.18.0 bump below changed an API whose call site was not updated, so this tag does not build and no image was published for it.
Fixed
- Increased signing timeout from 30 seconds to 3 minutes to accommodate zero-knowledge proof operations on slower devices (#300)
-mode allnow starts every role. It expanded to a hardcoded list of five, silently omittingstorageandwallet-provider, so a deployment that asked for every role was not running those two; it now expands toValidRoles. The-modehelp text also lists every role rather than three (#290)
Changed
- Updated dependencies: go-webauthn/webauthn to v0.18.0 (adds Post-Quantum Cryptography support), golang.org/x/crypto, and getkin/kin-openapi (#308)
[v0.18.0] - 2026-09-06
Added
- Issuer entitlement verification implementing ARF v3.0.0 §6.6.2.3 and CIR (EU) 2025/848 requirements. The
/v1/resolveendpoint now evaluates an issuer's access certificate (WRPAC) and registration certificate (WRPRC) to determine whether the issuer is entitled to issue what it offers, returning anissuer_entitlementdecision alongside metadata. Controlled byISSUER_ENTITLEMENT_MODEenvironment variable (warnby default,fail, oroff). The defaultwarnmode logs violations without blocking issuance, reflecting the 24-month grace period before ARF registration obligations take effect. (#306)
[v0.17.0] - 2026-09-04
Added
The engine now asks the client for its Wallet Instance Attestation at the point where it can actually be built (#304). The per-flow OAuth-Client-Attestation-PoP has to name the issuer's authorization server as its aud, and that server is only known after the credential offer and issuer metadata have been resolved. A browser wallet cannot resolve a cross-origin credential_offer_uri itself, so it could never compute the audience before starting the flow; the native SDKs only managed it by duplicating the backend's discovery on the device.
The OID4VCI engine therefore sends a new sign_request action, request_attestation, right after metadata resolution whenever FlowStart did not already carry client_attestation and client_attestation_pop. Its params are audience (the authorization server URL, for the PoP aud) and issuer (the effective client_id, for the PoP iss); the client answers with client_attestation and client_attestation_pop in its sign_response, or with neither to proceed without attestation. Attestation supplied up front on FlowStart is still honoured and takes precedence. The instance key never leaves the client.
Client compatibility. A client that predates this action does not answer the request. The engine waits at most 10 seconds for it (not the general 30 second signing timeout) and then continues without attestation, so older wallet-frontend and SDK builds keep working with a one-off delay per issuance until they are updated. The companion changes are wallet-frontend#196, siros-sdk-kotlin#154 and siros-sdk-swift#122; the follow-ups that drop the SDKs' own discovery (siros-sdk-kotlin#155, siros-sdk-swift#123) must not ship before this release is deployed.
[v0.16.0] - 2026-09-02
Fixed
Wallet Unit Attestations now carry the status claims CS-04 requires (#302). The WIA was missing client_status and the Key Attestation was missing key_storage_status, both mandated by WE BUILD CS-04 §7.1.2/§7.1.3 (TS-03 clauses 2.3.1/2.3.2). A conformant PID or Attestation Provider rejects a WUA without them, which is exactly what the WE BUILD ITB testbed did: invalid_proof: WUA signature verification failed: Key Attestation missing required key_storage_status. Take this release before any interop run against a CS-04-conformant issuer.
The claims were removed in v0.13.0 (#261) on the grounds that this wallet provider implements no revocation-chaining. That reasoning still holds — short attestation lifetimes, not a revocation list, are what bound exposure here — but it conflated not revoking through a status list with being allowed to omit the claims that reference one. Both now reference the wallet provider's own Token Status List, which is served all-VALID and never has a bit set; the config comments and docs/wallet-instance-attestation.md say so plainly rather than implying a revocation capability that isn't there. KA indices follow CS-04 §7.2.3 Option 1 (type-shared, one per keystore tier), and a mixed batch is indexed by its weakest tier so an issuer is never told the batch is better protected than it is.
A deployment that would rather advertise no revocation mechanism than an inert one can set wallet_provider.attestation.status_list.enabled: false and go back to omitting the claims, at the cost of CS-04 conformance. The reference URI defaults to <server.base_url>/wallet-provider/status-list, and the maintenance exp defaults to 45 days — deliberately not the 31-day floor, since CS-04 §7.2.2 requires those 31 days to still be remaining at presentation, not at issuance.
- The Key Attestation also emitted no
key_storage,user_authenticationorcertificationat all when the client omittedsecurity_properties, and could still dropuser_authenticationfor a trusted client that reported"none". All three are required on every KA, so each now falls back to the weakest value in the ISO 18045 vocabulary rather than being left absent — a floor never overstates what the client claimed. (#302, with fixes from @Didr)
[v0.15.2] - 2026-08-31
Fixed
- OID4VP presentation requests using
client_id_scheme=x509_hashare now accepted. Previously the wallet rejected all such requests with "Invalid message format" because the scheme was missing from the allowlist, breaking interoperability with verifiers like NIST's OpenID4VP reference implementation. (#298)
[v0.15.1] - 2026-08-30
Fixed
- Fixed OID4VP presentation flows incorrectly reporting "Could not parse credential offer" (an issuance error) when the actual failure was fetching or parsing the presentation request from a verifier's
request_uri. Now returns a distinct "Could not parse the presentation request" error code. Also logs the response body (capped, at Debug level) when arequest_urifetch fails, making it possible to distinguish expired verifier sessions from network errors without reproducing the failure separately (#294) - Fixed mdoc issuance flows being blocked with 403 errors during issuer-trust evaluation. The authorization proxy's allowlist included
mdoc-reader-auth(for presentation) but was missing the issuer-side mirrormdoc-issuer-auth, causing all VICAL issuer-trust queries to be denied before reaching the policy decision point regardless of issuer identity (#296) - Fixed
--mode registrypanicking on startup when CORS origins list is empty. Now handles empty configuration gracefully and warns when wildcard CORS is combined withAllowCredentials(#292)
Changed
- Updated to go-trust v0.16.0, which adds support for loading additional trusted roots via YAML configuration (#288)
- Updated Go runtime to 1.27 stable (#287)
- Updated dependency group including testify, cbor, and kin-openapi (#288)
[v0.15.0] - 2026-08-24
Fixed
Key Attestation JWTs now carry the spec-registered typ (#289). The JOSE header said keyattestation+jwt, the pre-1.0 draft spelling; OpenID4VCI 1.0 registers the media type as application/key-attestation+jwt (Appendix G.6.2), and the JOSE typ carries the short form key-attestation+jwt, hyphenated. Issuers pin this exactly and reject the whole credential request rather than falling back to the jwt proof type. Because a wallet picks its proof type per issuer rather than per credential, this failed every credential type at once against any issuer advertising the attestation proof type. The error was invisible from the client, which only ever saw the sanitized "Credential issuance failed". This release is worth taking before bumping any issuer image past 2026-08-19, the point at which SUNET/vc began advertising attestation alongside jwt for every scope. Deployments pinned to an older issuer were unaffected only because their issuer never offered the attestation path.
Changed
GET /issuer/:id/metadata embeds the issuer's own images as data: URIs (#284). A logo or SVG template hosted somewhere that sends no Access-Control-Allow-Origin is unusable by a browser wallet, which fetches the SVG to substitute claim values into it and renders a broken image. The endpoint now runs the issuer's own credential_configurations_supported through the existing image embedder, which removes the cross-origin fetch. Only asset delivery changes — nothing is substituted from the VCTM registry, so the response remains the issuer's own content. Failure is soft by construction: an image too large (>1 MB), too slow (>10 s) or unreachable leaves the issuer's original URL in place, exactly as before. Note that only https:// image URLs are embedded, so an all-HTTP local development stack sees no change.
[v0.14.1] - 2026-08-21
Fixed
-
HTTP issuer resolution now works when
allow_httpis enabled (#282). Previously, resolving a plain-HTTP credential issuer (subject_type: "url") failed even withallow_httpconfigured — the scheme validation inResolve()hardcoded HTTPS regardless of the flag, and the authorization rules lacked an HTTP variant forcredential_issuerqueries. Both layers now honor theallow_httpsetting. HTTPS-only remains the default. -
PAR failures are now surfaced immediately when the Authorization Server requires PAR (#280). Previously, any Pushed Authorization Request failure triggered a silent fallback to a standard
/authorizerequest with inline parameters. For an AS that mandates PAR (require_pushed_authorization_requests: true), this fallback is guaranteed to fail with a confusing downstream error instead of showing the real PAR failure reason. The client now checks the AS metadata and surfaces the actual PAR error immediately when PAR is required, while preserving the fallback for ASs that support PAR optionally.
Changed
- TS11 schema fetching delegated to
go-ts11client(#281). TheprocessTS11Responselogic for fetching and paginating/api/v1/schemas.jsonnow uses the sharedgithub.com/sirosfoundation/go-ts11clientlibrary instead of maintaining duplicate implementations. Legacy registry formats, the multi-source overlay model, and per-item skip logging remain unchanged.
[v0.14.0] - 2026-08-20
Added
- New
mdoc-reader-authaction is now permitted in the default SPOCP authorization policy, enabling SDK reader-trust checks (subject typekey, resource typex5c) to pass through/v1/evaluatewithout requiring a custom rules file (#279)
Fixed
- Resolved
crypto/ecdsadeprecation warnings (Go 1.26+) by migrating from direct field access (PublicKey.X/Y,PrivateKey.D) to the newECDH()API in OID4VCI, JWKS, and JWT utility code (#279)
Changed
- Configuration documentation (
docs/CONFIGURATION.md) is now enforced to stay in sync with code via CI — builds fail if the generated doc drifts from the config structs, preventing silent staleness (#278)
[v0.13.0] - 2026-08-18
Added
- Forward verifier session ID to
sign_presentationto enable correct ZKverifier_contextderivation for pairwise-pseudonym presentations (#277)
Fixed
- Raise wallet→backend WebSocket message read limit to accommodate ZK proofs, which were previously larger than the connection's default cap and could not be sent (#277)
- Pre-authentication read-limit bypass: unauthenticated clients could previously force repeated multi-MB allocations by exploiting the larger message cap applied before handshake/auth checks; now capped at 64KB until token validation completes (#277)
- JWT/JSON request-body misclassification that could incorrectly identify a JSON body containing a URL-like field as a JWT (#277)
Changed
- Dependency updates: Go toolchain and Docker builder base images (#275, #276)
[v0.12.0] - 2026-08-14
Added
- OID4VCI credential renewal support: the backend now relays
refresh_tokenfrom issuers to clients and implements a renewal-request engine action that reuses the wallet's persistent credential-holder-binding key to satisfy EUDI ARF ISSU_65 continuity requirements (#273, #274)
Fixed
- Deduplicated OID4VCI token-exchange grant handling and clarified cross-repository issue references (#274)
Security
- Upgraded Go toolchain to 1.26.6, resolving 5 standard library CVEs that were blocking the vulnerability-check gate (#274)
[v0.11.1] - 2026-08-14
Changed
- Default JWE content-encryption algorithm for
direct_post.jwtresponses changed fromA128CBC-HS256toA128GCMwhen verifiers don't declareauthorization_encrypted_response_encin their client metadata. Improves interoperability with verifiers that only implement the GCM cipher family (e.g., multipaz), while remaining spec-compliant. (#272)
[v0.11.0] - 2026-08-11
Added
- Per-route TAC (Token Access Control) enforcement across all HTTP and WebSocket routes. Previously, any authenticated token could access all routes regardless of its
tacclaim. Routes now require specific TAC values:r(read),w(write/mutate),l(list),i(create), ord(delete). WebSocket flows enforcerfor OID4VP presentation andifor OID4VCI issuance. Legacy HMAC authentication (which has no TAC concept) continues to work unchanged. (#264) - FIDO2/CTAP2 hardware attestation is now recognized as key attestation trust evidence for WIA flows, verified against the go-trust root store rather than pinned CAs. Attestation evidence is stored per-key (not instance-level), and attestation level-of-assurance is surfaced in type-metadata responses. (#266, #267)
Fixed
haip-vp://scheme (HAIP 1.0 final) is now recognized in OID4VP request-URI parsing. Previously onlyopenid4vp://and the drafthaip://were accepted, causing real verifier requests to fail with "invalid message format" instead of dereferencing the request. (#270)
Security
- Upgraded
go-tokenauthto v0.4.0, which fixes two vulnerabilities reachable through JWKS fetch: a crypto/tls ECH privacy leak (GO-2026-5856) and a quic-go HTTP/3 QPACK memory-exhaustion bug (GO-2026-5676). (#268) - Dependency updates:
go-redis/v99.21.0 → 9.22.0 andkin-openapipatch bump. (#271)
[v0.10.1] - 2026-08-06
Fixed
- Key Attestation nonce compatibility: The
attestationproof type now sends bothc_nonceandnonceclaims to the credential endpoint, fixing issuance failures with providers (like geneva2026.mdoc.online) that expectnoncerather than the TS03-specifiedc_nonce. An unrecognized extra claim is harmless to conformant verifiers. (#265)
Changed
- SPOCP delegation policy documentation: Replaced misleading read-only rules in
delegation.ruleswith documentation clarifying that delegation intentionally supports downscoping to any subset of the parent token's capabilities (including write/delete/re-delegation), not just read operations. The actual security boundary—delegated capabilities must be a subset of the delegating token's capabilities—remains enforced in code as before. No behavior change. (#263)
[v0.10.0] - 2026-08-06
Added
- Wallet-attestation-based OAuth client authentication: Clients can now authenticate to the Authorization Server using a self-attested Wallet Instance Attestation (WIA) instead of pre-registered credentials, per draft-ietf-oauth-attestation-based-client-auth. The AS auto-enables for
--mode=authdeployments, reusing the wallet provider's signing key and bundled SPOCP policy unless explicitly configured otherwise. (#259) - IETF/ETSI mode split for WIA/Key Attestation: New
wallet_provider.wia.modesetting (etsi/ietf) controls whether WIA uses x5c-based trust (ETSI TS 119 472-3, EC TS03 v1.5.2) or JWKS-based trust (IETF draft). ETSI mode requires a certificate; IETF mode works with a signing key alone. A bare-root/.well-known/jwks.jsonroute now serves the wallet provider's public key for JWKS-based trust resolution. (#261) - Audience-based token scoping: Anonymous tokens (issued for trust-evaluation workflows) are now restricted to
wallet-registry/wallet-backendaudiences and rejected on identity-bearing routes. AuthZEN proxy and engine transport routes require one of those audiences; general user-facing routes requirewallet-backend. (#262)
Fixed
- Authorization Server metadata unreachable via AuthZEN proxy: The
/v1/resolveendpoint's allowlist rejectedresource_type=oauth-authorization-serverqueries before reaching the handler that explicitly supported them, breaking PAR-endpoint discovery for wallets. The allowlist now includesoauth-authorization-server. (#260) - SPOCP wildcard rules never matched: Rules loaded from
.rulesfiles used canonical netstring format, which parsed wildcards as ordinary empty lists instead of actual wildcards—causing every wildcard rule to silently deny all queries. Rules now load in advanced form ((tac (*))syntax) and are duplicated per query shape (with-acr, without-acr, anonymous) to align with go-spocp's positional field matching. (#258) - Nil-pointer panic on
--mode=auth: Running the server with--mode=authalone would panic at startup because the AS'sEnableForRole()call expected a config that was only loaded for other roles.RoleAuthis now included in the config-load condition. (#259) - Missing JWKS route in standalone wallet-provider mode: Deployments running
--mode=wallet-provideras a separate microservice had no way to serve their JWKS. The JWKS route is now wired into both co-hosted and standalone modes. (#259)
Changed
- WIA/Key Attestation aligned with EC TS03 v1.5.2 and ETSI TS 119 472-3: Removed
client_status/key_storage_statusclaims (no revocation-chaining support); WIA lifetime now defaults to 5 minutes. Fixed the Key Attestation's nonce claim (c_nonce) and removed its strayissclaim. Corrected theattestation_sourceclaim's citation to reference the SIROS extension mirroring the open Annex C PR to WP4 CS-04. (#261) - Config validation tightened:
wallet_provider.wia.omit_x5c: true(now superseded bymode: ietf) is rejected if nowia.issueris set, preventing silent misuse ofwallet_provider_urias a JWKS-discovery URL. (#259)
[v0.9.1] - 2026-08-04
Security
- Key Attestation requests no longer accept self-asserted security properties. The
key_storage,certification, anduser_authenticationclaims inkeyattestation+jwtare now clamped to software-level defaults (iso_18045_basic/"none") unless the request'swallet_instance_idresolves to a wallet instance whose WIA was backed by verified native platform attestation (iOS App Attest or Android Play Integrity). Previously, any caller could claim hardware-level security (e.g.,key_storage: ["iso_18045_high"]) and have it signed without verification, undermining relying parties' Level of Assurance decisions. (#256)
Fixed
- Key Attestation now normalizes internal WSCD vocabulary (
software/hardware/trusted_execution/remote_hsm) to the registered ISO 18045 enum (iso_18045_basic/iso_18045_moderate/iso_18045_high) before signing. Previously, raw internal values were likely being emitted in production attestations, producing non-compliant claim values. (#256)
[v0.9.0] - 2026-08-04
Added
- Wallet Instance Attestation (WIA) issuance per CS-04 §7.1.2 and §7.1.4: new
/wallet-provider/wia/challengeand/wallet-provider/wia/generateendpoints issue single-use, PoP-bound WIA JWTs signed with the wallet-provider key and including x5c chains,cnfbinding to the instance DPoP key, and Tier 3 baseline attestation claims. (#221)
Fixed
- OpenID4VP engine now correctly handles
haip://-scheme requests (High Assurance Interoperability Profile) and fetches bare reference-URL requests (e.g.,.../haip-vplinks with no query string) instead of treating them as empty by-value requests. (#255) - WIA issuance now rejects suspended or revoked wallet instances; previously
Upsertunconditionally reset status toActive, allowing revoked instances to re-attest and obtain fresh credentials. (#221) - MongoDB WIA challenge store is now correctly selected for horizontally-scalable deployments; the
Database()method was never forwarded, causing all MongoDB backends to silently fall back to the single-instance in-memory store. (#221) WalletInstance.UserIDis now populated during WIA issuance, fixing the previously-empty results fromGET /admin/tenants/:id/users/:user_id/instances. (#221)- WebSocket and session connection limits now count every upgraded connection from open to close and reserve slots atomically, preventing both unauthenticated-connection bypass and check-then-increment races under concurrent load. (#221)
- Isolated wallet-provider mode now accepts AS-issued tokens instead of rejecting them with hardcoded legacy HMAC auth. (#221)
- PKCS#11 key-loading failures now correctly fall back to configured file-based keys instead of stopping at the first failure. (#221)
- Pre-authorized code token exchange now sends client-attestation headers, matching the PAR and authorization_code flows; wallets using attestation-based auth previously had no client authentication on this (most common) flow. (#221)
- Play Integrity decryption/verification keys now support
*_pathfile-based loading, consistent with other secrets in the configuration. (#221)
[v0.8.0] - 2026-07-28
Added
- Registry support for
mso_mdoccredentials alongside sd-jwt VCTM: local overrides, dynamic fetch, and TS11/registry polling now recognizedoctype-identified MDDL documents in addition tovct-identified VCTM ones. When a TS11 schema offers both formats, both are now cached and served instead of silently dropping the mdoc variant. (#254) - Verifier
client_id_schemesupport: verifiers can now identify themselves via DID, OpenID Federation entity statements, or X.509 attestation, enabling trust evaluation of the verifier before credential presentation. (#237) - Server-side issuer trust evaluation: when a go-trust PDP URL is configured, the wallet backend now evaluates issuer trust directly without requiring frontend mediation. Falls back to the existing frontend-mediated flow when no PDP is configured, ensuring backward compatibility. (#239)
Security
- Workflow tokens now use least-privilege permissions (
contents: readby default, with explicit job-level write grants only where needed), addressing OpenSSF Scorecard token-permissions requirements. (#245)
Changed
- Replaced sunset Go Report Card badge with OpenSSF Scorecard badge, which reports on security best practices including branch protection, CI configuration, and dependency management. (#244)
- CI workflows can now be triggered manually via the Actions UI (
workflow_dispatch), enabling ad-hoc builds from any ref. (#242) - CodeQL configuration now excludes MongoDB BSON query construction from SQL injection analysis (parameterized NoSQL queries are not vulnerable to the same injection patterns as string-concatenated SQL). (#247)
[v0.7.1] - 2026-07-08
Fixed
-
JARM encryption algorithm inference for
direct_post.jwtresponse mode (#235) — Whenresponse_mode=direct_post.jwtis used butauthorization_encrypted_response_algis absent fromclient_metadata, the wallet now infers the encryption algorithm from the verifier's public key material (EC key → ECDH-ES, RSA key → RSA-OAEP) instead of failing with "An error occurred during credential verification". This fixes interoperability with x509_san_dns verifiers using ETSI TS 119 411-8 access certificates, such as Sikt and SUNET deployments. -
OID4VCI/VP conformance test failures (#232) — Fixed RFC 8414 OAuth AS metadata URL construction (trailing slash handling), added support for the
authorization_serversarray field (OID4VCI 1.0 Final), and corrected negative-test behavior to silently reject invalid authorization requests rather than POST error responses. VCI conformance improved from 0/4 to 4/4 passed; VP negative tests now correctly reject invalid requests.
Changed
- Sensitive route cache headers (#187) — Auth, session, and credential storage endpoints now emit
Cache-Control: no-store, no-cache, must-revalidateheaders to prevent browser or intermediary caching of sensitive wallet state and encrypted private data.
Security
- Go 1.26.5 upgrade — Fixes GO-2026-5856, an Encrypted Client Hello privacy leak in
crypto/tls.
[v0.7.0] - 2026-07-03
Added
- Key Attestation security properties: Key Attestation JWTs now include
key_storage,user_authentication, andcertificationclaims describing WSCD security characteristics. Callers can optionally provide these properties when generating attestations, enabling verifiers to assess key protection levels. (#219) - Transaction data relay for payment SCA: OID4VP authorization requests now parse and relay the verifier's
transaction_dataarray through to the frontend sign request. This allows the SDK to bind transaction details into the key binding proof, satisfying EUDI TS12 payment strong customer authentication requirements. (#220) - Authorization Server with session-based tokens: Complete Authorization Server implementation (
internal/as/) replacing legacy HMAC tokens with short-lived JWT sessions (default 2 min TTL). Includes JWKS endpoint, SPOCP policy-based authorization with per-audience TAC (token access control) permissions, delegation token issuance with subset enforcement, OIDC authentication, WebAuthn passkey scaffolding, and session management with secure cookies. Legacy token mode remains available during migration with configurable sunset schedule. (#229)
Security
- OIDC host header injection fixed: Authorization Server OIDC flows now use configured
ExternalURLinstead of theHostheader for redirect URIs, preventing attacker-controlled redirects. (#229) - OIDC nonce validation: OIDC state parameter now includes a SHA-256 nonce challenge verified on callback to prevent replay attacks. (#229)
Changed
- Dependency updates: go-redis/v9 9.20.0→9.20.1 (fixes RESP3 pub/sub message loss), golang.org/x/crypto, golang.org/x/net. (#217)
- CI updates: actions/checkout v4→v7, ossf/scorecard-action, SonarSource/sonarqube-scan-action. (#216)
- Base container image: Alpine 3.23→3.24. (#215)
[v0.6.1] - 2026-06-14
Fixed
- Preserve trailing slashes in issuer identifier paths when constructing well-known URLs, fixing metadata discovery failures with external issuers (like the OIDF Conformance Suite) that include trailing slashes in their
credential_issueridentifier per RFC 8615 (#214)
[v0.6.0] - 2026-06-10
Added
- Resource-type routing for
/v1/resolveendpoint:oauth-authorization-servernow resolves AS metadata via RFC 8414 well-known discovery, andcredential_offer_urifetches and validates OID4VCI credential offers server-side (#170, #153) - Forward optional
credential_typesarray through/v1/resolveto upstream PDP asaction.parameters.credential_typesfor credential-type-specific trust evaluation (#198) - Configuration reference generator (
make gen-config-docs) that producesdocs/CONFIGURATION.mdfrom Go config structs, covering 166 fields across backend and registry server (#172) - WebSocket engine stress tests covering 13 scenarios: expired tokens, concurrent flow limits, session replacement, rapid reconnect, malformed messages, and slow sign responses (#170)
- Debug logging for WebAuthn credential assertion responses with increased preview limit to capture relevant parts (#181)
- Forensic fingerprints (SHA-256 hashes of auth data, client data, signature, and x5c leaf) in WebAuthn registration and login error paths to help diagnose intermittent attestation verification failures (#188, #197)
- OpenAPI spec route coverage test to ensure all admin API endpoints are documented (#201)
- SonarCloud and OpenSSF Scorecard CI workflows for continuous code quality and supply-chain security analysis (#204)
- Registry server support for TS11 paginated API format with
modeconfig field (ts11orregistry) to select between legacy and new formats (#174) - Support for
did:webcredential issuers:subject_type=keywithresource_type=credential_issuernow converts DID to URL and resolves issuer metadata (#206, #208)
Fixed
- DPoP JTI reuse on token endpoint
use_dpop_nonceretry: each retry now generates a freshclient_assertionJWT with unique JTI (#170) - Issuer metadata resolver cache misses caused by trailing slash inconsistency: URLs are now normalized before cache lookup (#170)
- Conformance workflow security: replaced inline shell logic with centralized composite action, fixing GITHUB_OUTPUT injection vulnerability and adding variant-filter support (#185)
- OpenAPI admin spec alignment: added missing
require_invite,trust_config,oidc_gate, verifierclient_id/client_id_scheme, and trust status fields; documented OIDC gate modes and verifier client ID schemes; bumped spec to v1.1.0 (#159) - Scorecard workflow permissions: replaced
read-allwith explicit minimal permissions (contents: read,actions: read) to address SonarCloud security hotspot (#205) - CVE-2026-40898: bumped quic-go to v0.59.1 to fix connection migration DoS vulnerability (#207)
Changed
- Registry integration tests now gated behind
integrationbuild tag sogo test ./...runs only fast unit tests (#174) - Upgraded OpenAPI spec from 3.0.0 to 3.1.0 for
if/thenschema support (#201) - MongoDB tests now gated behind environment variable to avoid requiring MongoDB for default test runs (#201)
- Dependency updates: go-webauthn 0.17.3→0.17.4, go-trust 0.4.1→0.6.0, go-redis 9.19.0→9.20.0, codecov-action 6→7 (#184, #189, #203, #209)
[v0.5.2] - 2026-05-18
Fixed
-
Registry server now reads JWT secrets from files. The registry's
JWTConfigonly supported inlinejwt.secret, causingJWT secret is emptyerrors when deployments usedjwt.secret_path(common in Docker/Kubernetes with mounted secrets). Now matches the main backend's behavior by reading the file during validation. (#175) -
JWT validation no longer rejects tokens due to clock skew. Added 5-second leeway to
nbf(not-before) andexp(expiration) checks in both engine and legacy WebSocket handlers. Previously, tokens could fail validation within the same second they were issued due to strict timing or minor clock differences between containers. (#176) -
WebSocket connections no longer fail after 15 seconds. Cleared the stale write deadline inherited from net/http's
WriteTimeoutimmediately after WebSocket upgrade. Without this fix, all writes to upgraded connections would fail once the deadline elapsed. Affects both engine and legacy handlers. (#178) -
X-Served-Byheader restored to all responses. The middleware was lost during server refactoring and has been re-wired into the unified router. This header identifies which instance served each request, critical for debugging multi-replica deployments. (#179) -
X-Served-Byheader now appears on WebSocket upgrade responses. Gin middleware cannot inject headers aftergorilla/websockethijacks the connection, so the header is now explicitly passed to the upgrader in both WebSocket handlers. (#180)
Changed
- Go runtime updated from 1.26.2 to 1.26.3 in
go.modand Dockerfiles for reproducible builds. (#180)
[v0.5.1] - 2026-05-15
Fixed
- Fixed
private_key_jwtclient authentication to include thekidheader in JWT assertions and use the correctaudclaim value, ensuring proper token endpoint authentication (#590b3d44) - Preserved trailing slashes in well-known URIs to maintain strict RFC compliance when resolving OAuth/OIDC metadata endpoints (#dac5ecb8, #0b4df038)
- Removed redundant
formatandvctparameters from credential requests that were causing validation failures with some issuers (#0b4df038)
[v0.5.0] - 2026-05-15
Added
- Prometheus metrics — HTTP request counters and latency histograms exposed on
/metrics, with/healthzendpoint for Kubernetes probes (#89) - Local VCTM overrides — Load credential type metadata from local JSON files that take precedence over remote registry entries (#120)
- Issuer metadata endpoint —
GET /issuer/:id/metadatafetches OpenID4VCI metadata server-side for authenticated users, avoiding WebSocket proxy limitations (#123) - DCQL query support — OID4VP flows now accept DCQL queries for credential selection; Presentation Definition support removed in favor of DCQL-only (#128)
- Multiple WebAuthn RP origins —
rp_originsconfig field enables native app wrappers (Android/iOS) to register alongside web frontends (#144) - URL-based issuer resolution —
/v1/resolveendpoint accepts HTTPS issuer URLs alongside DID-based subjects, with local metadata resolution and registered issuer enrichment (#131, #151) - TS11 schemas API support — Registry client migrated from legacy
.well-known/vctm-registry.jsonto/api/v1/schemas.jsonwith full pagination and multi-registry merging (#141) - JWKS retry and circuit breaker — Token validation now retries transient IdP failures with exponential backoff and falls back to stale cache when circuit opens (#160)
- WebSocket keepalive — Server-side ping/pong prevents mobile network idle disconnects after 15 minutes (#165)
- OID4VCI Nonce Endpoint — Support for dedicated nonce endpoint per OID4VCI 1.0 final spec, with backward compatibility for token-response nonces (#166)
private_key_jwtclient authentication — OID4VCI flows can now authenticate to token endpoints using signed JWTs instead of client secrets (#166)
Fixed
- Admin token security — Production deployments now refuse to start without an explicit admin token; auto-generation and DEBUG logging restricted to development mode only (#118)
- Right-to-erasure cascade —
DeleteUsernow deletes credentials, presentations, tenant memberships, WebAuthn challenges, invite references, and WebSocket sessions across all stores (#89) - VCI flow resumption — Auth code and code verifier now propagate correctly through flow state; credential issuer and selected configuration ID included in completion messages (#122)
- VP response body decoding — JSON string responses from verifiers are now properly decoded (#126)
- Proof JWT issuer claim — OID4VCI proof JWTs now include
issclaim set to redirect URI (#133) - Trust cache isolation — Verifier trust evaluations use a dedicated in-memory TTL cache instead of polluting the persistent store (#130)
- go-trust URL subject support — Bumped to v0.4.0 to enable
subject_type="url"in AuthZEN resolver (#149) - SSRF vs TLS decoupling —
AllowPrivateIPsandAllowHTTPnow independent ofInsecureSkipVerify, fixing metadata resolution in private networks with valid TLS (#152) - PDP client restrictions — Operator-configured PDP endpoints now use an unrestricted HTTP client, allowing internal/localhost addresses without disabling SSRF protection globally (#158)
- RFC 8615 well-known URIs — Issuer metadata URLs now correctly constructed per RFC 8615 for issuers with path components (#164)
- VP verifier encryption key extraction — Added x5c certificate chain fallback for mdoc thumbprint calculation when
kidis absent (#161) - Encryption JWK algorithm —
algfield now set on encryption JWK forcredential_response_encryption(#122)
Changed
- VP credential selection flow — Consolidated two-step matching + consent into single
credential_selectionround-trip; client performs local matching and presents consent UI in one pass (#136) - GDPR log cleanup — Removed admin token, user IDs, holder DIDs, and subject IDs from INFO-level logs across all components (#89)
- Default registry URL — Updated from
.well-known/vctm-registry.jsonto/api/v1/schemas.jsonin default config (#141) - Issuer metadata resolution — Engine OID4VCI flow now uses shared
issuermetadata.Resolverwith SSRF protection and TTL caching (#134)
Security
- Admin token enforcement — Production mode now fails fast if no admin token is configured, preventing accidental deployments with auto-generated credentials (#118)
- PII minimization — User identifiers removed from production logs to comply with GDPR Article 5(1)(c) data minimization (#89)
- Signed metadata verification — Issuer metadata with
signed_metadataJWT that fails verification now hard-fails instead of silently falling back to unsigned metadata (#151) - SSRF protection for issuer-controlled URIs —
jwks_uriand logo fetching now block private/loopback/link-local IPs and cloud metadata endpoints whenAllowPrivateIPs=false(#151)
[v0.4.1] - 2026-04-20
Fixed
- Fixed proof validation logic to correctly handle attestation proofs that can cover multiple credentials, unlike JWT proofs which require one proof per credential instance. The validator now only enforces proof count requirements for JWT proofs and ensures all received proofs are of the same type (#117)
[v0.4.0] - 2026-04-20
Added
- OIDC gate for identity binding (#47): Require users to authenticate with an external IdP before registration or login. Includes
OIDCGateMiddlewarefor JWKS-based token validation,GET /api/v1/tenants/:id/configfor frontend tenant configuration,configure-oidc-gateCLI command with--bind-identityflag, andIdentityBindingdomain model for linking OIDC subjects to wallet accounts. - OID4VCI authorization code flow enhancements (#103): Comprehensive security improvements including PAR (RFC 9126) with automatic fallback, PKCE (RFC 7636) with conditional enablement, DPoP (RFC 9449) with nonce handling and retry logic, credential response encryption (OID4VCI §7.3) with algorithm negotiation, OAuth state parameter for CSRF protection, and structured OAuth error parsing. Scope handling now uses issuer metadata without hardcoded fallbacks.
- Match request/response protocol (#78): Dedicated message types (
match_request/match_response) for privacy-preserving client-side credential matching in OID4VP flows, following thesign_request/sign_responsepattern with explicit message ID correlation, 30-second configurable timeout, and error reporting. - Trust integration tests (#83): Wire go-trust testserver into integration tests covering issuer/verifier trust evaluation, per-flow PDP configuration, AuthZEN wire protocol, session overrides, policy-based decisions, discovery, and health recovery scenarios.
- TLS configuration for admin server (#96): Separate
AdminTLSconfiguration option allows the admin HTTP server to use dedicated certificates independently of the main TLS config, addressing security needs when admin traffic flows over untrusted network segments. Backward compatible with fallback to shared TLS settings. - AuthZEN proxy endpoint (#72): Frontend trust evaluation via
/v1/evaluateand/v1/resolveendpoints with per-tenant PDP configuration, configurable tenant lookup failure behavior, and SPOCP-based authorization rules. Includes unified mode support (#112). - Security startup warnings (#79): Log warnings at startup for potentially dangerous configurations (disabled trust evaluation, CORS wildcard) with elevated severity in production environments (detected via
ENVIRONMENT,GO_ENV, orAPP_ENV). - Client ID support for verifiers (#46): Verifiers can now specify
client_idwith validation forclient_id_scheme, and configured client IDs are used as VP audience when set. - Support for different proof types in OID4VCI (#116): Engine now handles multiple proof type formats from issuers, properly formatting proofs before sending and validating only one type is present per request.
Fixed
- AuthZEN proxy routes missing in unified mode (#112): Routes
/v1/evaluateand/v1/resolvenow register correctly when running with-mode=backend,engine. Also fixed store resource leak in error path. - Query string privacy leak in registry logger (#114): Removed
RawQueryfrom structured logs to prevent exposure of sensitive parameters like?vct=,?tenant=, and issuer URLs. - JWT compatibility (#77): Accept
uuidclaim in addition tosubfor wallet-backend-server compatibility. - Admin token log exposure (#80): Reduced logging of sensitive admin token data.
- Data races in requestProofs tests (#116): Resolved race conditions using channels for proper synchronization.
- WebAuthn attestation configuration (#76): Made attestation format configurable with
noneas default, addressing BER signature failures with direct attestation.
Changed
- Go version (#90, #94): Upgraded to Go 1.26 with CI now reading version from
go.modinstead of hardcoded values. - Certificate parsing (#46): Integrated
go-cryptoutilfor extensible certificate parsing, promoted to direct dependency. - WebSocket authentication format (#72): Support new auth format with
tenantIdfield. - Deprecated field removal (#72): Removed deprecated
TrustEndpointfield in favor of per-tenant PDP configuration. - Authorization rules loading (#72): Use go-spocp's native file loading for multi-line rules.
- Logo validation (#76): Allow HTTP URLs in dev/test environments for easier local development.
- Dependency updates: gin v1.11.0→v1.12.0, gin-contrib/cors v1.7.6→v1.7.7, go-webauthn/webauthn v0.16.3→v0.16.5, go-cryptoutil v0.2.0→v0.5.0, go-trust v0.0.0-20260223112607→v0.3.0, mongo-driver v1.17.6→v1.17.9, golang.org/x/crypto v0.49.0→v0.50.0, golang.org/x/time v0.14.0→v0.15.0 (#91, #111).
Security
- Error sanitization and WebSocket limits (#72): Hardened error handling to prevent information leakage and added WebSocket connection limits with thread safety improvements.
- Security toolchain (#90): Integrated Trivy vulnerability scanning, gosec, and govulncheck into CI pipeline.
- Production fail-closed guard (#112): AuthZEN proxy initialization now fails closed in production when rules file is invalid.
[v0.3.0] - 2026-03-26
Added
- Attestation conveyance is now configurable, allowing operators to control whether authenticator attestation statements are requested during registration (#49)
Fixed
- Default attestation conveyance changed to "none" to avoid unnecessary privacy exposure and compatibility issues with authenticators that don't support attestation
- BER-encoded ECDSA signatures from certain authenticators are now correctly parsed by switching to a patched webauthn library fork
- Docker badge now correctly references the container registry workflow
Changed
- Documentation updated to reflect production-ready status
- Dependency management simplified by using remote module replace directives instead of local paths
[v0.2.1] - 2026-03-25
Fixed
- Upgraded go-webauthn to v0.16.1 to fix authentication failures with YubiKey 5.8 devices that produce BER-encoded ECDSA signatures instead of the expected IEEE P1363 format (#48)
[v0.2.0] - 2026-03-19
Added
- Container images for wallet-admin are now built and published (#44)
X-Served-Byresponse header identifies which server instance handled each request (#40)require_inviteconfiguration option for tenant sync to control invitation requirements (#39)- mTLS support for MongoDB connections, allowing mutual certificate authentication (#42)
- TLS configuration for all HTTP listeners, enabling encrypted server communications (#41)
- Centralized HTTP client for proxy and egress traffic with configurable TLS settings (#43)
Fixed
- Race condition in readiness test by switching to atomic.Int64 for thread-safe counter access
[v0.1.1-RC1] - 2026-04-30
Added
- Build workflow automation for continuous integration
Changed
- Enhanced credential debugging by logging fully decoded credential data instead of partial information
[v0.1.1-RC0] - 2026-04-30
Changed
- Allow multiple relying party origins to be configured, enabling a single verifier instance to serve multiple frontend applications or domains (#144)
[v0.1.0] - 2026-03-17
Added
/readyzendpoint with mode-specific readiness checks for better deployment health monitoring (#7a9ffcf4, #2bc09d31)wallet-admin synccommand for YAML-based tenant configuration management (#32612791)- JWK support for issuer and verifier trust evaluation, enabling cryptographic verification of trust relationships (#6bba0a3d)
- Invite code system with admin mode controls, allowing tenant-level gating of new user registration (#242b6b78, #e34e1a95)
- Support for specifying invite codes in POST requests and exposing
require_inviteflag in admin tenant API (#e3cfefbd, #2c6a033b) client_id_schemesupport in OID4VP with JWT signature verification for enhanced verifier authentication (#4e235846)- Verifier trust caching with domain model and storage layer for improved performance (#91eb9774)
- Trust fields in verifier info responses to enable frontend trust indicators (#46889e6a)
Changed
- Extracted
TrustServicetopkg/trustwith per-flow configuration for better modularity (#e54325d9) - Harmonized trust configuration with vc project for consistency across components (#8447d4ad)
Fixed
- High and medium severity trust evaluation gaps that could allow untrusted issuers or verifiers (#1f61ae57)
- Invite system architectural hardening to prevent bypass and improve error handling (#6a4d51db, #e3cfefbd)
- Provider lifecycle management by calling
Starton providers implementingStartableProvider(#6d219a7b) - Registry configuration issues including envconfig tag cleanup (#5f04c86c, #ba0e1ce7)
Removed
- Deprecated tenant-scoped registration and login methods that were no longer in use (#34)
- Unused tenant auto-retry login mechanism and tenant-mismatch error handling (#36)
[v0.1.0RC0] - 2026-03-03
Added
- Multi-tenancy support with tenant discovery from passkey credentials, enabling a single deployment to serve multiple organizations (#27)
- Header-based tenant routing via
X-Tenant-IDinstead of path-based routing, with tenant claims in JWT tokens for improved security (ADR-011) - Hybrid binary architecture with
--modeflag supporting comma-separated roles (auth, storage, registry) to eliminate proxy requirements (#28) - WebSocket v2 engine protocol for real-time credential exchange with session store abstraction and Direct transport for frontend integration
- Native SDK interfaces for CLI integration with key material extraction for trust evaluation
- VCTM registry server with
/issuer-metadataendpoint and image embedding to convert URLs to data URIs for offline use (#22) - Trust evaluation service with JIT discover-and-trust endpoint, mandating remote evaluation via AuthZEN PDP with per-tenant caching
- TLS/mTLS configuration for HTTPS listeners and MongoDB connections, plus HTTP proxy support for egress requests
- Secret loading from files for improved security in containerized deployments
- Storage health check to
/statusendpoint with unified mode field across all operational modes - Admin API bearer token authentication with refresh-tokens capability in role-based access control
Fixed
- Tenant isolation vulnerabilities: userHandle validation in login, tenant-scoped user queries, and correct TenantID storage in credentials during registration (#17)
- MongoDB and GORM index definitions to use correct fields (Verifier.URL) and ensure tenant_id presence in collections (#32, #33)
- Race condition in 304 handler and deadlock when ConcurrentFetches=0 in registry fetcher
- Passkey UUID generation, account deletion, and tenant-scoped route handling (#12, #13, #14)
- HTTP proxy method handling to force uppercase and trim whitespace (#10)
- Docker container
/app/datadirectory ownership for nonroot user compatibility - Default tenant display name now returned in login-finish response and defaults to tenant name when not provided (#28)
- SQLite storage selection now shows clear error message instead of generic failure
- Verifier existence check returns appropriate error instead of 500 server error
- Admin API routes now properly registered in provider architecture with session management
Changed
- Simplified trust architecture to use go-trust exclusively, removing redundant trust store layer
- Unified HTTP server architecture with RouteProvider pattern across auth, storage, and registry modes
- Registration and login APIs now use single global endpoints that complete operations for any tenant
- Access logs no longer include
/statusand/healthendpoints to reduce noise - Trust refresh interval moved from per-issuer to global server setting
- Upgraded golangci-lint to v2.10.0 for configuration compatibility
Security
- Enforced tenant isolation through userHandle validation preventing cross-tenant credential access
- Added JWT-based tenant security with tenant_id claims for authorization
- Minimized user tracking and fingerprinting in authentication flows
- Mandated remote trust evaluation via AuthZEN PDP instead of local trust decisions