From c3ab3dccb8b74b609eb012ca9d3e8ace38789800 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 18 Dec 2025 12:55:35 +0100 Subject: [PATCH 01/11] Fix VP JWT type marshalling being a []string --- vcr/holder/presenter.go | 10 ++++++---- vcr/holder/presenter_test.go | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index 182f434d41..f00f77db1f 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -23,6 +23,9 @@ import ( "encoding/json" "errors" "fmt" + "strings" + "time" + "github.com/google/uuid" "github.com/lestrrat-go/jwx/v2/jws" "github.com/lestrrat-go/jwx/v2/jwt" @@ -37,8 +40,6 @@ import ( "github.com/nuts-foundation/nuts-node/vcr/signature/proof" "github.com/nuts-foundation/nuts-node/vdr/resolver" "github.com/piprate/json-gold/ld" - "strings" - "time" ) type presenter struct { @@ -128,15 +129,16 @@ func (p presenter) buildJWTPresentation(ctx context.Context, subjectDID did.DID, } id := did.DIDURL{DID: subjectDID} id.Fragment = strings.ToLower(uuid.NewString()) + type VPAlias vc.VerifiablePresentation claims := map[string]interface{}{ jwt.SubjectKey: subjectDID.String(), jwt.JwtIDKey: id.String(), - "vp": vc.VerifiablePresentation{ + "vp": VPAlias(vc.VerifiablePresentation{ Context: append([]ssi.URI{VerifiableCredentialLDContextV1}, options.AdditionalContexts...), Type: append([]ssi.URI{VerifiablePresentationLDType}, options.AdditionalTypes...), Holder: options.Holder, VerifiableCredential: credentials, - }, + }), } if options.ProofOptions.Nonce != nil { claims["nonce"] = *options.ProofOptions.Nonce diff --git a/vcr/holder/presenter_test.go b/vcr/holder/presenter_test.go index efc47e70b8..454b63c361 100644 --- a/vcr/holder/presenter_test.go +++ b/vcr/holder/presenter_test.go @@ -20,6 +20,9 @@ package holder import ( "context" + "testing" + "time" + ssi "github.com/nuts-foundation/go-did" "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" @@ -39,8 +42,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" - "testing" - "time" ) func TestPresenter_buildPresentation(t *testing.T) { @@ -162,7 +163,33 @@ func TestPresenter_buildPresentation(t *testing.T) { assert.NotNil(t, result.JWT()) nonce, _ := result.JWT().Get("nonce") assert.Empty(t, nonce) + + t.Run("#3957: Verifiable Presentation type is marshalled incorrectly in JWT format", func(t *testing.T) { + t.Run("make sure the fix is backwards compatible", func(t *testing.T) { + vp := vc.VerifiablePresentation{ + Type: []ssi.URI{ssi.MustParseURI("VerifiablePresentation")}, + } + t.Run("sanity check: regular JSON marshalling yields type: string", func(t *testing.T) { + data, err := vp.MarshalJSON() + require.NoError(t, err) + assert.Contains(t, string(data), `"type":"VerifiablePresentation"`) + }) + }) + vpAsMap := result.JWT().PrivateClaims()["vp"].(map[string]any) + t.Run("make sure type now marshalls as array", func(t *testing.T) { + typeProp := vpAsMap["type"].([]any) + assert.Equal(t, []any{"VerifiablePresentation"}, typeProp) + }) + t.Run("make sure the VP can be unmarshalled", func(t *testing.T) { + presentation, err := vc.ParseVerifiablePresentation(result.Raw()) + require.NoError(t, err) + assert.Equal(t, result.ID.String(), presentation.ID.String()) + assert.Len(t, presentation.Type, 1) + assert.Equal(t, "VerifiablePresentation", presentation.Type[0].String()) + }) + }) }) + t.Run("ok - multiple VCs", func(t *testing.T) { ctrl := gomock.NewController(t) From 7a27d5b6b159827ed5bda7624fec443b66922659 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 18 Dec 2025 14:29:00 +0100 Subject: [PATCH 02/11] Claude AI tried to fix the e2e test --- vcr/holder/presenter.go | 54 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index f00f77db1f..7a39b5abcc 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -48,6 +48,55 @@ type presenter struct { keyResolver resolver.KeyResolver } +// vpJWT is a wrapper around vc.VerifiablePresentation to ensure proper JSON marshaling for JWT VPs. +// When marshaling a VP into JWT format, the 'type' field must always be an array according to the W3C spec, +// even when it contains a single value. The go-did library's default marshaling optimizes single values to strings. +type vpJWT struct { + vc.VerifiablePresentation +} + +// MarshalJSON marshals the VP ensuring the 'type' and '@context' fields are always arrays in JWT format +func (v vpJWT) MarshalJSON() ([]byte, error) { + // Marshal the underlying VP to a map + vpBytes, err := v.VerifiablePresentation.MarshalJSON() + if err != nil { + return nil, err + } + + var vpMap map[string]interface{} + if err := json.Unmarshal(vpBytes, &vpMap); err != nil { + return nil, err + } + + // Ensure 'type' is always an array + if typeVal, ok := vpMap["type"]; ok { + switch t := typeVal.(type) { + case string: + // Convert single string to array + vpMap["type"] = []string{t} + case []interface{}: + // Already an array, keep as is + case []string: + // Already a string array, keep as is + } + } + + // Ensure '@context' is always an array + if ctxVal, ok := vpMap["@context"]; ok { + switch c := ctxVal.(type) { + case string: + // Convert single string to array + vpMap["@context"] = []string{c} + case []interface{}: + // Already an array, keep as is + case []string: + // Already a string array, keep as is + } + } + + return json.Marshal(vpMap) +} + func (p presenter) buildSubmission(ctx context.Context, credentials map[did.DID][]vc.VerifiableCredential, presentationDefinition pe.PresentationDefinition, params BuildParams) (*vc.VerifiablePresentation, *pe.PresentationSubmission, error) { // match against the wallet's credentials @@ -129,16 +178,15 @@ func (p presenter) buildJWTPresentation(ctx context.Context, subjectDID did.DID, } id := did.DIDURL{DID: subjectDID} id.Fragment = strings.ToLower(uuid.NewString()) - type VPAlias vc.VerifiablePresentation claims := map[string]interface{}{ jwt.SubjectKey: subjectDID.String(), jwt.JwtIDKey: id.String(), - "vp": VPAlias(vc.VerifiablePresentation{ + "vp": vpJWT{vc.VerifiablePresentation{ Context: append([]ssi.URI{VerifiableCredentialLDContextV1}, options.AdditionalContexts...), Type: append([]ssi.URI{VerifiablePresentationLDType}, options.AdditionalTypes...), Holder: options.Holder, VerifiableCredential: credentials, - }), + }}, } if options.ProofOptions.Nonce != nil { claims["nonce"] = *options.ProofOptions.Nonce From a05b17576ce84d15007d235c3200964e462f0447 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 18 Dec 2025 14:56:46 +0100 Subject: [PATCH 03/11] Claude AI tried to fix the e2e test --- vcr/holder/presenter.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index 7a39b5abcc..c4fd2448ed 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -55,7 +55,9 @@ type vpJWT struct { vc.VerifiablePresentation } -// MarshalJSON marshals the VP ensuring the 'type' and '@context' fields are always arrays in JWT format +// MarshalJSON marshals the VP ensuring certain fields are always arrays in JWT format. +// According to W3C VC spec, when a VP is in JWT format, the following fields must always be arrays: +// - 'type', '@context', 'verifiableCredential', and 'proof' (even when containing a single value) func (v vpJWT) MarshalJSON() ([]byte, error) { // Marshal the underlying VP to a map vpBytes, err := v.VerifiablePresentation.MarshalJSON() @@ -94,6 +96,31 @@ func (v vpJWT) MarshalJSON() ([]byte, error) { } } + // Ensure 'verifiableCredential' is always an array + if vcVal, ok := vpMap["verifiableCredential"]; ok { + switch vc := vcVal.(type) { + case string: + // Convert single string to array + vpMap["verifiableCredential"] = []string{vc} + case map[string]interface{}: + // Convert single object to array + vpMap["verifiableCredential"] = []interface{}{vc} + case []interface{}: + // Already an array, keep as is + } + } + + // Ensure 'proof' is always an array + if proofVal, ok := vpMap["proof"]; ok { + switch p := proofVal.(type) { + case map[string]interface{}: + // Convert single object to array + vpMap["proof"] = []interface{}{p} + case []interface{}: + // Already an array, keep as is + } + } + return json.Marshal(vpMap) } From 6cdd44d7ddd1181fceeccbb00ca506f35c78ceea Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 18 Dec 2025 15:13:36 +0100 Subject: [PATCH 04/11] Claude AI tried to fix the e2e test (revert 1) --- vcr/holder/presenter.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index c4fd2448ed..bd1be58382 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -97,18 +97,18 @@ func (v vpJWT) MarshalJSON() ([]byte, error) { } // Ensure 'verifiableCredential' is always an array - if vcVal, ok := vpMap["verifiableCredential"]; ok { - switch vc := vcVal.(type) { - case string: - // Convert single string to array - vpMap["verifiableCredential"] = []string{vc} - case map[string]interface{}: - // Convert single object to array - vpMap["verifiableCredential"] = []interface{}{vc} - case []interface{}: - // Already an array, keep as is - } - } + //if vcVal, ok := vpMap["verifiableCredential"]; ok { + // switch vc := vcVal.(type) { + // case string: + // // Convert single string to array + // vpMap["verifiableCredential"] = []string{vc} + // case map[string]interface{}: + // // Convert single object to array + // vpMap["verifiableCredential"] = []interface{}{vc} + // case []interface{}: + // // Already an array, keep as is + // } + //} // Ensure 'proof' is always an array if proofVal, ok := vpMap["proof"]; ok { From 7aa3568149702a70062bbde7e3d3578e6c0e7575 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Thu, 18 Dec 2025 16:08:15 +0100 Subject: [PATCH 05/11] fix test? --- vcr/pe/presentation_submission.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/vcr/pe/presentation_submission.go b/vcr/pe/presentation_submission.go index 1d78ed137f..501501220f 100644 --- a/vcr/pe/presentation_submission.go +++ b/vcr/pe/presentation_submission.go @@ -22,13 +22,14 @@ import ( "encoding/json" "errors" "fmt" + "strings" + "github.com/PaesslerAG/jsonpath" "github.com/google/uuid" "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" "github.com/nuts-foundation/nuts-node/vcr/credential" v2 "github.com/nuts-foundation/nuts-node/vcr/pe/schema/v2" - "strings" ) // ParsePresentationSubmission validates the given JSON and parses it into a PresentationSubmission. @@ -136,8 +137,8 @@ func (b *PresentationSubmissionBuilder) Build(format string) (PresentationSubmis // go-did always marshals a single VC as a single VC for JSON-LD VPs. So we might need to fix the mapping paths. // todo the check below actually depends on the format of the credential and not the format of the VP - if len(signInstruction.Mappings) == 1 { - signInstruction.Mappings[0].Path = "$.verifiableCredential" + if format == vc.JWTPresentationProofFormat && len(signInstruction.Mappings) == 1 { + signInstruction.Mappings[0].Path = "$.verifiableCredential[0]" } // Just 1 VP, no nesting needed From 3647757763da50f1d1c141311143ec026483949c Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Fri, 19 Dec 2025 14:39:50 +0100 Subject: [PATCH 06/11] debug level for e2e test --- e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml | 2 +- e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml b/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml index 32ed855184..40f6ad5d7a 100644 --- a/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml +++ b/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml @@ -1,5 +1,5 @@ url: https://nodeA -verbosity: debug +verbosity: trace strictmode: false internalratelimiter: false http: diff --git a/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml b/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml index fb78e0ee5f..3ba913f1fa 100644 --- a/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml +++ b/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml @@ -1,5 +1,5 @@ url: https://nodeB -verbosity: debug +verbosity: trace strictmode: false internalratelimiter: false http: From 7ec04b07b91b8fed618e439643a0d091d539bff6 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Fri, 19 Dec 2025 14:47:43 +0100 Subject: [PATCH 07/11] info level logging --- auth/client/iam/openid4vp.go | 11 ++++++----- vcr/holder/presenter.go | 23 ++++++----------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/auth/client/iam/openid4vp.go b/auth/client/iam/openid4vp.go index 0f9e370601..7fc952eae2 100644 --- a/auth/client/iam/openid4vp.go +++ b/auth/client/iam/openid4vp.go @@ -24,16 +24,17 @@ import ( "encoding/json" "errors" "fmt" - "github.com/nuts-foundation/nuts-node/http/client" - "github.com/nuts-foundation/nuts-node/vcr/credential" - "github.com/nuts-foundation/nuts-node/vdr/didsubject" - "github.com/piprate/json-gold/ld" "maps" "net/http" "net/url" "slices" "time" + "github.com/nuts-foundation/nuts-node/http/client" + "github.com/nuts-foundation/nuts-node/vcr/credential" + "github.com/nuts-foundation/nuts-node/vdr/didsubject" + "github.com/piprate/json-gold/ld" + "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" "github.com/nuts-foundation/nuts-node/auth/log" @@ -328,7 +329,7 @@ func (c *OpenID4VPClient) RequestRFC021AccessToken(ctx context.Context, clientID } } - log.Logger().Tracef("Requesting access token from '%s' for scope '%s'\n VP: %s\n Submission: %s", metadata.TokenEndpoint, scopes, assertion, string(presentationSubmission)) + log.Logger().Infof("Requesting access token from '%s' for scope '%s'\n VP: %s\n Submission: %s", metadata.TokenEndpoint, scopes, assertion, string(presentationSubmission)) token, err := iamClient.AccessToken(ctx, metadata.TokenEndpoint, data, dpopHeader) if err != nil { // the error could be a http error, we just relay it here to make use of any 400 status codes. diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index bd1be58382..2582baddda 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -97,25 +97,14 @@ func (v vpJWT) MarshalJSON() ([]byte, error) { } // Ensure 'verifiableCredential' is always an array - //if vcVal, ok := vpMap["verifiableCredential"]; ok { - // switch vc := vcVal.(type) { - // case string: - // // Convert single string to array - // vpMap["verifiableCredential"] = []string{vc} - // case map[string]interface{}: - // // Convert single object to array - // vpMap["verifiableCredential"] = []interface{}{vc} - // case []interface{}: - // // Already an array, keep as is - // } - //} - - // Ensure 'proof' is always an array - if proofVal, ok := vpMap["proof"]; ok { - switch p := proofVal.(type) { + if vcVal, ok := vpMap["verifiableCredential"]; ok { + switch vc := vcVal.(type) { + case string: + // Convert single string to array + vpMap["verifiableCredential"] = []string{vc} case map[string]interface{}: // Convert single object to array - vpMap["proof"] = []interface{}{p} + vpMap["verifiableCredential"] = []interface{}{vc} case []interface{}: // Already an array, keep as is } From 021ad6c024faeac54b87e02160b8927cf8ec5e4f Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Fri, 19 Dec 2025 15:23:11 +0100 Subject: [PATCH 08/11] Attempt --- auth/client/iam/openid4vp.go | 4 ++++ vcr/holder/presenter.go | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/auth/client/iam/openid4vp.go b/auth/client/iam/openid4vp.go index 7fc952eae2..ccc58abe3e 100644 --- a/auth/client/iam/openid4vp.go +++ b/auth/client/iam/openid4vp.go @@ -329,6 +329,10 @@ func (c *OpenID4VPClient) RequestRFC021AccessToken(ctx context.Context, clientID } } + println("===== VP =====") + println(vp.Raw()) + println("===== Submission =====") + println(string(presentationSubmission)) log.Logger().Infof("Requesting access token from '%s' for scope '%s'\n VP: %s\n Submission: %s", metadata.TokenEndpoint, scopes, assertion, string(presentationSubmission)) token, err := iamClient.AccessToken(ctx, metadata.TokenEndpoint, data, dpopHeader) if err != nil { diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index 2582baddda..5799a268aa 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -194,15 +194,16 @@ func (p presenter) buildJWTPresentation(ctx context.Context, subjectDID did.DID, } id := did.DIDURL{DID: subjectDID} id.Fragment = strings.ToLower(uuid.NewString()) + type VPAlias vc.VerifiablePresentation claims := map[string]interface{}{ jwt.SubjectKey: subjectDID.String(), jwt.JwtIDKey: id.String(), - "vp": vpJWT{vc.VerifiablePresentation{ + "vp": VPAlias(vc.VerifiablePresentation{ Context: append([]ssi.URI{VerifiableCredentialLDContextV1}, options.AdditionalContexts...), Type: append([]ssi.URI{VerifiablePresentationLDType}, options.AdditionalTypes...), Holder: options.Holder, VerifiableCredential: credentials, - }}, + }), } if options.ProofOptions.Nonce != nil { claims["nonce"] = *options.ProofOptions.Nonce From 630345d479d09959b0e1cf57b8ef54ae26587d3f Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Fri, 19 Dec 2025 15:55:23 +0100 Subject: [PATCH 09/11] fixzz --- auth/api/iam/session.go | 19 +++++- e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml | 2 +- e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml | 2 +- vcr/holder/presenter.go | 67 +------------------- vcr/pe/presentation_submission.go | 14 ++-- 5 files changed, 29 insertions(+), 75 deletions(-) diff --git a/auth/api/iam/session.go b/auth/api/iam/session.go index 6eb16376e8..d36787fde7 100644 --- a/auth/api/iam/session.go +++ b/auth/api/iam/session.go @@ -19,11 +19,13 @@ package iam import ( + "encoding/json" "errors" "fmt" - "github.com/nuts-foundation/nuts-node/auth/oauth" "net/url" + "github.com/nuts-foundation/nuts-node/auth/oauth" + "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" "github.com/nuts-foundation/nuts-node/http" @@ -121,7 +123,20 @@ func (v *PEXConsumer) fulfill(submission pe.PresentationSubmission, envelope pe. return errors.New("presentation definition is already fulfilled") } - _, err := submission.Validate(envelope, *definition) + // Marshal and println VP (envelope) and submission + jsonData, err := envelope.MarshalJSON() + if err != nil { + return fmt.Errorf("could not marshal presentation exchange envelope: %w", err) + } + fmt.Printf("Received PEX Envelope: %s\n", string(jsonData)) + + jsonData, err = json.Marshal(submission) + if err != nil { + return fmt.Errorf("could not marshal presentation submission: %w", err) + } + fmt.Printf("Received Presentation Submission: %s\n", string(jsonData)) + + _, err = submission.Validate(envelope, *definition) if err != nil { return fmt.Errorf("presentation submission does not conform to presentation definition (id=%s)", definition.Id) } diff --git a/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml b/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml index 40f6ad5d7a..32ed855184 100644 --- a/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml +++ b/e2e-tests/oauth-flow/rfc021/node-A/nuts.yaml @@ -1,5 +1,5 @@ url: https://nodeA -verbosity: trace +verbosity: debug strictmode: false internalratelimiter: false http: diff --git a/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml b/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml index 3ba913f1fa..fb78e0ee5f 100644 --- a/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml +++ b/e2e-tests/oauth-flow/rfc021/node-B/nuts.yaml @@ -1,5 +1,5 @@ url: https://nodeB -verbosity: trace +verbosity: debug strictmode: false internalratelimiter: false http: diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index 5799a268aa..64066e2dfc 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -48,71 +48,6 @@ type presenter struct { keyResolver resolver.KeyResolver } -// vpJWT is a wrapper around vc.VerifiablePresentation to ensure proper JSON marshaling for JWT VPs. -// When marshaling a VP into JWT format, the 'type' field must always be an array according to the W3C spec, -// even when it contains a single value. The go-did library's default marshaling optimizes single values to strings. -type vpJWT struct { - vc.VerifiablePresentation -} - -// MarshalJSON marshals the VP ensuring certain fields are always arrays in JWT format. -// According to W3C VC spec, when a VP is in JWT format, the following fields must always be arrays: -// - 'type', '@context', 'verifiableCredential', and 'proof' (even when containing a single value) -func (v vpJWT) MarshalJSON() ([]byte, error) { - // Marshal the underlying VP to a map - vpBytes, err := v.VerifiablePresentation.MarshalJSON() - if err != nil { - return nil, err - } - - var vpMap map[string]interface{} - if err := json.Unmarshal(vpBytes, &vpMap); err != nil { - return nil, err - } - - // Ensure 'type' is always an array - if typeVal, ok := vpMap["type"]; ok { - switch t := typeVal.(type) { - case string: - // Convert single string to array - vpMap["type"] = []string{t} - case []interface{}: - // Already an array, keep as is - case []string: - // Already a string array, keep as is - } - } - - // Ensure '@context' is always an array - if ctxVal, ok := vpMap["@context"]; ok { - switch c := ctxVal.(type) { - case string: - // Convert single string to array - vpMap["@context"] = []string{c} - case []interface{}: - // Already an array, keep as is - case []string: - // Already a string array, keep as is - } - } - - // Ensure 'verifiableCredential' is always an array - if vcVal, ok := vpMap["verifiableCredential"]; ok { - switch vc := vcVal.(type) { - case string: - // Convert single string to array - vpMap["verifiableCredential"] = []string{vc} - case map[string]interface{}: - // Convert single object to array - vpMap["verifiableCredential"] = []interface{}{vc} - case []interface{}: - // Already an array, keep as is - } - } - - return json.Marshal(vpMap) -} - func (p presenter) buildSubmission(ctx context.Context, credentials map[did.DID][]vc.VerifiableCredential, presentationDefinition pe.PresentationDefinition, params BuildParams) (*vc.VerifiablePresentation, *pe.PresentationSubmission, error) { // match against the wallet's credentials @@ -194,7 +129,7 @@ func (p presenter) buildJWTPresentation(ctx context.Context, subjectDID did.DID, } id := did.DIDURL{DID: subjectDID} id.Fragment = strings.ToLower(uuid.NewString()) - type VPAlias vc.VerifiablePresentation + type VPAlias = vc.VerifiablePresentation claims := map[string]interface{}{ jwt.SubjectKey: subjectDID.String(), jwt.JwtIDKey: id.String(), diff --git a/vcr/pe/presentation_submission.go b/vcr/pe/presentation_submission.go index 501501220f..2adb9391c9 100644 --- a/vcr/pe/presentation_submission.go +++ b/vcr/pe/presentation_submission.go @@ -134,11 +134,15 @@ func (b *PresentationSubmissionBuilder) Build(format string) (PresentationSubmis } // the verifiableCredential property in Verifiable Presentations can be a single VC or an array of VCs when represented in JSON. - // go-did always marshals a single VC as a single VC for JSON-LD VPs. So we might need to fix the mapping paths. - - // todo the check below actually depends on the format of the credential and not the format of the VP - if format == vc.JWTPresentationProofFormat && len(signInstruction.Mappings) == 1 { - signInstruction.Mappings[0].Path = "$.verifiableCredential[0]" + // go-did always marshals a single VC as a single VC for JSON-LD VPs. So we need to fix the mapping paths. + if len(signInstruction.Mappings) == 1 { + if format == vc.JWTPresentationProofFormat { + // JWT VP always has an array of VCs + signInstruction.Mappings[0].Path = "$.verifiableCredential[0]" + } else { + // JSON-LD VP with single VC has single VC in verifiableCredential + signInstruction.Mappings[0].Path = "$.verifiableCredential" + } } // Just 1 VP, no nesting needed From f37f7c89600ddf39a5c34380e1a77012ab7d8c43 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Sat, 20 Dec 2025 10:13:42 +0100 Subject: [PATCH 10/11] fixzz --- vcr/holder/presenter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcr/holder/presenter.go b/vcr/holder/presenter.go index 64066e2dfc..f00f77db1f 100644 --- a/vcr/holder/presenter.go +++ b/vcr/holder/presenter.go @@ -129,7 +129,7 @@ func (p presenter) buildJWTPresentation(ctx context.Context, subjectDID did.DID, } id := did.DIDURL{DID: subjectDID} id.Fragment = strings.ToLower(uuid.NewString()) - type VPAlias = vc.VerifiablePresentation + type VPAlias vc.VerifiablePresentation claims := map[string]interface{}{ jwt.SubjectKey: subjectDID.String(), jwt.JwtIDKey: id.String(), From ba228ea990cf10761064150595ed5400cbef1ba9 Mon Sep 17 00:00:00 2001 From: Rein Krul Date: Wed, 24 Dec 2025 14:15:28 +0100 Subject: [PATCH 11/11] reverts --- auth/api/iam/session.go | 19 +----- auth/client/iam/openid4vp.go | 6 +- test/pki/certificate-and-key.pem | 86 +++++++++++++------------- test/pki/truststore.pem | 34 +++++----- vcr/pe/presentation_submission_test.go | 7 ++- 5 files changed, 67 insertions(+), 85 deletions(-) diff --git a/auth/api/iam/session.go b/auth/api/iam/session.go index d36787fde7..6eb16376e8 100644 --- a/auth/api/iam/session.go +++ b/auth/api/iam/session.go @@ -19,12 +19,10 @@ package iam import ( - "encoding/json" "errors" "fmt" - "net/url" - "github.com/nuts-foundation/nuts-node/auth/oauth" + "net/url" "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" @@ -123,20 +121,7 @@ func (v *PEXConsumer) fulfill(submission pe.PresentationSubmission, envelope pe. return errors.New("presentation definition is already fulfilled") } - // Marshal and println VP (envelope) and submission - jsonData, err := envelope.MarshalJSON() - if err != nil { - return fmt.Errorf("could not marshal presentation exchange envelope: %w", err) - } - fmt.Printf("Received PEX Envelope: %s\n", string(jsonData)) - - jsonData, err = json.Marshal(submission) - if err != nil { - return fmt.Errorf("could not marshal presentation submission: %w", err) - } - fmt.Printf("Received Presentation Submission: %s\n", string(jsonData)) - - _, err = submission.Validate(envelope, *definition) + _, err := submission.Validate(envelope, *definition) if err != nil { return fmt.Errorf("presentation submission does not conform to presentation definition (id=%s)", definition.Id) } diff --git a/auth/client/iam/openid4vp.go b/auth/client/iam/openid4vp.go index ccc58abe3e..3f9ef0dc79 100644 --- a/auth/client/iam/openid4vp.go +++ b/auth/client/iam/openid4vp.go @@ -329,11 +329,7 @@ func (c *OpenID4VPClient) RequestRFC021AccessToken(ctx context.Context, clientID } } - println("===== VP =====") - println(vp.Raw()) - println("===== Submission =====") - println(string(presentationSubmission)) - log.Logger().Infof("Requesting access token from '%s' for scope '%s'\n VP: %s\n Submission: %s", metadata.TokenEndpoint, scopes, assertion, string(presentationSubmission)) + log.Logger().Tracef("Requesting access token from '%s' for scope '%s'\n VP: %s\n Submission: %s", metadata.TokenEndpoint, scopes, assertion, string(presentationSubmission)) token, err := iamClient.AccessToken(ctx, metadata.TokenEndpoint, data, dpopHeader) if err != nil { // the error could be a http error, we just relay it here to make use of any 400 status codes. diff --git a/test/pki/certificate-and-key.pem b/test/pki/certificate-and-key.pem index c9c757e231..6f7a2fb485 100644 --- a/test/pki/certificate-and-key.pem +++ b/test/pki/certificate-and-key.pem @@ -1,48 +1,48 @@ -----BEGIN CERTIFICATE----- -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 -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxt+FgwH4gJZGR -7xHf9+kNQdqXqPPV6BVdTNWGMosy6pa2IY3eQJWwTirzqhEasZ5o6LRbXT79gry0 -jbzI2J1tWb64KVEZBXH8ZYw/qNfjTyhlnlvBEseNw8OwfM5PbFGOyl1120MKYMb4 -OVBzD6nVlxo7ejRBm051QPsM1y+DrnD6xhmiEGIHob+wbJWyu0sfrhICYgqQiJzv -fFyjpjj/HBvV4YWHsmt7BaNa8Sy42WGdsl5Ojisc1nyA3ZDFTE1/kSbLIe2DPIR4 -flV3nT1nk/aprN/qBONp8yit3EzwQmc+kLHmkwUeHovCFFec2W52pgBMhjwu5Xtq -V42H/AWFAgMBAAECggEAEDFAGnvncf/iS9DjyMuSgyf3Jf7ZmqmO+sWDpfrIdo7r -xPP5NGEfkmUI4lMiRFOfKpFbT4DHOrt0/KF2bDlaXKqC504yaqx1lojdFrbIVthx -RpL/aq/OmVLXK2cvuApXQwKaseCUsuce8eJs+1LXx1OBax5nEPw40ZOmXCTmGiH9 -gE/wNv2qknJLkqy5SF4pbpC5ZWADwwqodDerQbxwasVavIST4cPolsgebpGJs/7w -L15BDzTOMLktABUFg9A4pymox4+GZOg66Zeyo03vzup3aoj8MjHoLUK4dmyKK7rV -o1KQnq7DmSFBf90k+2Xo24H6dNZ77CmMjptC9/upiQKBgQDnHkLjL3yGn3RYx3PI -DrfYFWP4BOa8iodL6mUu+EF2qt8+KFqh83X2JPXXSa4ve7L5nGBTg5w94KOcHvsl -tUjKwQVw/eQ3oXQLmSYgpbdMu+BbDqA68vc/QnmFEjfnA/kxjrjXoPBBnHyJK3Gg -vq9TA7q7vkQ5ducSmMwlL+pvbQKBgQDE2eOkPvxw2q8GYoMkhF2TOja5mUWff9ye -P6NJFxyvPfF/GMTKNJu0d8hMe5X03dxZAhsCGiVz4mtqSnQzW3rbe9sD6nz7HNLH -qFL/il+mL8+Wzc2wAfL4NV6/rBrfAPB7Gc23QZ8bhv+E8lU1S7qQg8OaF+l39PhH -sXOsturneQKBgFtlpzPqqocedcdKEOpzj5Z/VwpU/d5ftgN6jUsW1+SSzDfrg3P6 -MJMHqMTbmWujsnJtudYs/NOni2wJAG64EzJDROCbNu4dBiQ0C1Tr0+IfhijcTtch -EE/O/Pl36+2Kr7g+ZbC4L2ry9HjWWlgkMHdWyTjHlHlZISZEkK7AFSi9AoGBAJ7v -lb7dJBEyX7J2A5COVscyb1D3EaGwKL6Ufw/aW0yaZMvLgcgJJdZWCCDIf9DO+MPc -0VWnKqogG74cEyoMKGvh2nmU8AgHw590pl6wqH2TiLYnwHTlffktjiyPlrqLFZ8u -vEvD7eTZ4KDE0EtRs3ZPDLTzrYsu/O9VtSG0JoFxAoGBALcjE36unr7dnEnP8Zu2 -5Jm07qcXKoJxfF0PDwKoK/c3sqJ6DvaR9szkwxTQFLBldG/Zn9r4us0HWevZz5Wc -HbUChCc7qS0Lfc2ywLnXvOl/cs+/oTXccxpcrWBg+3FbcZSu6uq846uNTb6zmZuG -XvBXyerr5QY+KwEkepVQa36B +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDjE7enXS0Aid/7 +OBv+gF8WZVTV55k9Zn+3OVppUbeGbRQ11latyTSG7WJnHj2qJKuKwX4KQTypLHYb +uZSQkwIsKOJsyBJdMCBoYqM7vx9kHzHI3yCViqbeMpGDHzZrK2ytT3tsu0k1urow +LAN7stZV8/okAIIYrpK8ZGVT8PDj1UMzHUzwX1HIAaFIMkErpJ048cvZzNnL3mgO +flzU1v81el/p2KFcPIwD22YhC2MRsUVkKCq30NXfV7BfH+KUTzoOOVCJ1KQLWlbO +dA9X2elr/WHtbl2jtLoYTszIegS0lx+Auhr2mqThqKnrfYkBPRcrOemW+22kXFwg +d5Wj5KvbAgMBAAECggEAG2WOm+e2/UClQGcVoZAVaNtS7/fgWjMap52I1fog/Vv9 +uz0f+hmzd6/+Vliksfl4pOYRceVLD1Io8dFjJkpGUdOg9eTxqkKbNlzoOtYlUGwf +EpAxGzm+RkKtobdLVoTHuOVFC+pQu+XKfvNgfDUofPhRrrRM/fNaCtbGDumb9rDT +GofVyO1C/N9UDpav32IA738KljmUNfcW0V37MbPXwzKIgXR98baBRM12kVJ8BoU+ +N+wNvRw6mLEzYG9F+YToM1eAohfH/J+kQDfEMYRjT+suZmCvi1EhTRA8e81nJOhh +2y87PI7UDLCkE1/EmEkxjb2ZMgnNAwWBj951l3ZJGQKBgQD0V710aGFcd3rBSfB7 +ahnv8yDhBEy4MtwjSTyZ2IV6tz085gDRbYjrz6HthMfeZPHFc5T38k3vLWh8xU5P +lFMhym67jldViz/OQFz/0QYJ9JmhIWjSLwZZ7Qe0vxkcGZncttAQ4qb2ME4HHmBo +W72neHbzexvNjKQ3tRJbYTFV7QKBgQDt6Rqda28+92q1tlt24omIiq5vDOxqhif2 +Ne7kcM6zslKk8RjgNgtuXebNYPLTOD/IjfrpLLpvplFdUD0M76N1FG8vK/nS14gp +9LC0oxLJJix58HmE+v0o5XT0GPzVwJf2fdv5cXwxo3E1uYf4dzTYqiT/xNBG/6Wa +pVkzdsxP5wKBgQCFEjPP7fj4Tum/0vDxhbtSfurtIVZXCvvxC7XBY7ZuOtVTEUBo +zmq/Ynkhziq75+X0TxpWXtQq6mP5b8tSc8lCoejkpITTxd6eCVecys2rJld09akM +ryeaWgjUWy7lqtus5LM0PvwHIA+euOBwdWY4itbdi7J8o5fb7vVsZuZjkQKBgQDD +IuE7oTUb1l/mL26R8nmQTv+IAnefX+5DGjWZlZVU+ryioUYgEPQLUGXQquZArPBU +FXBp9M/uZ+JwwTFx/NR7YYlYjZ9ZeoMqtpKBdwgfiHoOglmJ4zvmYV4uIJiw0klS +WiUlUhnltQNUZ5rJBy2HUPcL+mhC88jnMRwbBCPMnQKBgQDRl4AklAWRE0i6yfK7 +/NSGBoVhhflxMfsn3fj6Sv8GO3W6ybcfm7mjTpJ+WfW33wDBitInyX7MXw0dbLQq +yo37+fNAy2jMflACe52UDwVr9mHqNJ9oUA9rPowK7jmF0RXwrYZ7LLTGARYtjwvP +spGbZw75UY2AdIHmZYw10+ksyQ== -----END PRIVATE KEY----- diff --git a/test/pki/truststore.pem b/test/pki/truststore.pem index e54fd3eef8..699f63e5d2 100644 --- a/test/pki/truststore.pem +++ b/test/pki/truststore.pem @@ -1,19 +1,19 @@ -----BEGIN CERTIFICATE----- -MIIDBTCCAe2gAwIBAgIUZXkXcHCJWCMCAWJxkO3kaOEtCkUwDQYJKoZIhvcNAQEL -BQAwEjEQMA4GA1UEAwwHUm9vdCBDQTAeFw0yMzA5MTgwNzQzMzFaFw0yODA5MTYw -NzQzMzFaMBIxEDAOBgNVBAMMB1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB -DwAwggEKAoIBAQDXQK6vCjlszOkg0WdjAAbv6xNq6x6VgDWI7MzG3hOOl8PQWWA9 -l1NC32pRXAxxDZ2eyXqTWb9UIURNqTizvgTWv1JaAOC4q42e7dcZcLtldqwsOP5z -m0+85hfpBO2HdTbyk5WSppEi2C91zGDu1dH5D3jyyxqafasG4j+U4GwDiRNvJuSy -rtyfHgb0/i2ZokitvQi9t2wNqgJ1DMCYuEsLSyZopDI8BnTjf3ymmRE0SGt8Vafy -bJ3Y6MH9FoxqfkydxMlzzH0I6cssPW1zklSxt3WAWWVFcnYgZ4ZLA/y2RzMX6dz2 -MQbV8LshjbWcQz/9z4vRGe2CYpK3R+dJTz8fAgMBAAGjUzBRMB0GA1UdDgQWBBQx -A2u4Flfb6Fh213p0A5pc58/d5jAfBgNVHSMEGDAWgBQxA2u4Flfb6Fh213p0A5pc -58/d5jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBjQM3Azjxz -FysIOP4ENxgGyCIw8Re0oo1A3ksPSSAbZgm/7jJ/WjqtZuufF1w4/FJbAB8hVnqu -JiXGmQszZ/QUHF2cPNUTCYoxlOtxt78h04TYQZXzZuX1dg1hTuob93hqMIbWdaLN -B4R8Lt5t+fv9oieT2iGL5IBrVOrKpgP9K5TwB36+G5+DtgCS0KcQoIPs5UVEXrIf -ipvbGrjsdQeUFqle2BRkbpu2hwWmeOCXlRrOgv2fefgJ3ikeUd3nIzPN3akOGDrD -/FIrtJYGMdfv/HkEVeTojyH7oHdbZher3/3VvIaDS+AEETsxMKsyJc2xrLys3y/O -cMPaRZyq2sH2 +MIIDBTCCAe2gAwIBAgIUCZwA9MWIVcamq8xfFCD4aqM6V5QwDQYJKoZIhvcNAQEL +BQAwEjEQMA4GA1UEAwwHUm9vdCBDQTAeFw0yNTEyMjQxMzA5MDJaFw0zMDEyMjMx +MzA5MDJaMBIxEDAOBgNVBAMMB1Jvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQD5yzpZAYwGMpH7EzTCGgpmRGMngM9yPzrlKnlWArulDjgQicPT +1HZcSWLMeMmFwxzrqIlSxam+RYv+84bu2lPXYuFRPUvq5PPkE7SAHzzFtN00Xe5k +mXaNUvDYNXCtGgqBPFo8GFPx0md6/gS+X3SDceeOAth/5NzABFZHtVEiYaCwHsm8 +i/WGHXs0d2eP9qpX938AROpaHsoGhCUQ5O8XAO7XbRQn3i2YzKduZR0/ZB+cm4Ta +O7yN89p6VmLNdsBYQyBG9O4VSUrCAzegc3uWvT6efx5RKsOUmJkUMisxbP7TyCPG +rWFVLn6pQd29KSe6P+KDdTMfPrBvyWelm3C1AgMBAAGjUzBRMB0GA1UdDgQWBBR5 +s+88oQmwtCwpXo/TEbGok7P7rDAfBgNVHSMEGDAWgBR5s+88oQmwtCwpXo/TEbGo +k7P7rDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCQ1IAlf9hu +bOcar4SfPnQaUROwj1kwWxtfoji4SRuNJctyouLinOF/kTDvSjHPuAt6hUV0nW4W +wQ/wHArBPmWXgMsF+Ajg4j2/fQKE+Qj5HPvGhycDQprBJOmqd5OyT2K7WreKZWEd +HxZUvkD7chckFFvoTz0tXECEDefmoY8Hds/hS9SSpJNKZug2UkKkZ0ct8Tw6VRG5 +CBqMDVBJ71dcs50SZQwiEfr5i7FeJoP8PxK++ckNhEvwAS0z/AINiek6Lw9vhSQU +AFiNGLCli+Za1Sx7DIrubStPOY1bLz68FAJXs3Zxot3aen0I7SxlnyY2MvGI8gEB +XNkk7Xed254U -----END CERTIFICATE----- diff --git a/vcr/pe/presentation_submission_test.go b/vcr/pe/presentation_submission_test.go index 5388e234ef..b85e60afb9 100644 --- a/vcr/pe/presentation_submission_test.go +++ b/vcr/pe/presentation_submission_test.go @@ -20,6 +20,9 @@ package pe import ( "encoding/json" + "testing" + "time" + ssi "github.com/nuts-foundation/go-did" "github.com/nuts-foundation/go-did/did" "github.com/nuts-foundation/go-did/vc" @@ -27,8 +30,6 @@ import ( "github.com/nuts-foundation/nuts-node/vcr/signature/proof" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "testing" - "time" ) func TestParsePresentationSubmission(t *testing.T) { @@ -189,7 +190,7 @@ func TestPresentationSubmissionBuilder_Build(t *testing.T) { assert.Len(t, signInstruction.VerifiableCredentials, 1) assert.Equal(t, holder1, signInstruction.Holder) require.Len(t, submission.DescriptorMap, 1) - assert.Equal(t, "$.verifiableCredential", submission.DescriptorMap[0].Path) + assert.Equal(t, "$.verifiableCredential[0]", submission.DescriptorMap[0].Path) }) }) }