Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
refactor: disabled JSON-LD checks for VPs with JWT VCs by default
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Biriukov <anton.biriukov@avast.com>
  • Loading branch information
birtony committed Feb 28, 2023
1 parent 27d04b3 commit bb00190
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 12 deletions.
46 changes: 34 additions & 12 deletions pkg/doc/verifiable/presentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,14 @@ import (
"encoding/json"
"errors"
"fmt"

jsonld "github.com/piprate/json-gold/ld"
"github.com/xeipuuv/gojsonschema"

"github.com/hyperledger/aries-framework-go/pkg/doc/jose"
docjsonld "github.com/hyperledger/aries-framework-go/pkg/doc/jsonld"
"github.com/hyperledger/aries-framework-go/pkg/doc/jwt"
"github.com/hyperledger/aries-framework-go/pkg/doc/signature/verifier"
jsonutil "github.com/hyperledger/aries-framework-go/pkg/doc/util/json"
jsonld "github.com/piprate/json-gold/ld"
"github.com/xeipuuv/gojsonschema"
"strings"
)

const basePresentationSchema = `
Expand Down Expand Up @@ -350,12 +349,13 @@ func (rp *rawPresentation) UnmarshalJSON(data []byte) error {

// presentationOpts holds options for the Verifiable Presentation decoding.
type presentationOpts struct {
publicKeyFetcher PublicKeyFetcher
disabledProofCheck bool
ldpSuites []verifier.SignatureSuite
strictValidation bool
requireVC bool
requireProof bool
publicKeyFetcher PublicKeyFetcher
disabledProofCheck bool
ldpSuites []verifier.SignatureSuite
strictValidation bool
requireVC bool
requireProof bool
requireVCJSONLDChecks bool

jsonldCredentialOpts
}
Expand Down Expand Up @@ -402,6 +402,14 @@ func WithPresJSONLDDocumentLoader(documentLoader jsonld.DocumentLoader) Presenta
}
}

// WithPresRequiredVCJSONLDChecks requires performing JSON-LD checks for the VC when parsing a VP.
// By default, JSON-LD checks are disabled for VPs with VCs that use a JWT format.
func WithPresRequiredVCJSONLDChecks() PresentationOpt {
return func(opts *presentationOpts) {
opts.requireVCJSONLDChecks = true
}
}

// ParsePresentation creates an instance of Verifiable Presentation by reading a JSON document from bytes.
// It also applies miscellaneous options like custom decoders or settings of schema validation.
func ParsePresentation(vpData []byte, opts ...PresentationOpt) (*Presentation, error) {
Expand All @@ -412,7 +420,18 @@ func ParsePresentation(vpData []byte, opts ...PresentationOpt) (*Presentation, e
return nil, err
}

err = validateVP(vpDataDecoded, vpOpts)
credentialBytes := []byte(fmt.Sprint(vpRaw.Credential))

var vcStr string
var isVPWithJWTCredential = false
var credential rawCredential
err = credential.UnmarshalJSON(credentialBytes)
if err != nil {
vcStr = strings.Trim(fmt.Sprint(vpRaw.Credential), "[]")
isVPWithJWTCredential = jwt.IsJWS(vcStr)
}

err = validateVP(vpDataDecoded, vpOpts, isVPWithJWTCredential)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -542,12 +561,15 @@ func decodeCredentials(rawCred interface{}, opts *presentationOpts) ([]interface
}
}

func validateVP(data []byte, opts *presentationOpts) error {
func validateVP(data []byte, opts *presentationOpts, isVPWithJWTCredential bool) error {
err := validateVPJSONSchema(data)
if err != nil {
return err
}

if isVPWithJWTCredential && !opts.requireVCJSONLDChecks {
return nil
}
return validateVPJSONLD(data, opts)
}

Expand Down
54 changes: 54 additions & 0 deletions pkg/doc/verifiable/presentation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,38 @@ const validPresentationWithCustomFields = `
}
`

const validPresentationWithJWTVC = `
{
"@context":[
"https://www.w3.org/2018/credentials/v1",
"https://identity.foundation/presentation-exchange/submission/v1"
],
"presentation_submission":{
"id":"0137f0ec-6676-4123-a374-4cc3a4262458",
"definition_id":"32f54163-7166-48f1-93d8-ff217bdb0153",
"descriptor_map":[
{
"id":"VerifiedEmployee",
"format":"jwt_vp",
"path":"$",
"path_nested":{
"id":"VerifiedEmployee",
"format":"jwt_vc",
"path":"$.verifiableCredential[0]"
}
}
]
},
"type":[
"VerifiablePresentation",
"PresentationSubmission"
],
"verifiableCredential":[
"eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6b3JiOnVBQUE6RWlEVHhIVzBuUXljYU04ZmNmNG42YmxSa0VNM2VaYWV0dEtuT2VjSFpVU1BKdyMxNDE0YTZjMy02N2MzLTRlNDItYmY1Ny00OTAwNTUwZDc3YjIifQ.eyJleHAiOjE3MDg4MDgwMTEsImlhdCI6MTY3NzI3MjAxMSwiaXNzIjoiZGlkOm9yYjp1QUFBOkVpRFR4SFcwblF5Y2FNOGZjZjRuNmJsUmtFTTNlWmFldHRLbk9lY0haVVNQSnciLCJqdGkiOiJ1cm46dXVpZDo4MjkxNzY3Ni0yNDJlLTQxZGYtOGQ1My1mZDg5ZTQ2OTU0Y2QiLCJuYmYiOjE2NzcyNzIwMTEsInN1YiI6ImRpZDppb246RWlEQjNjWUVYVXdBY2drUTd2WHlpNE5qb0VzTVJyU1FFaGdUR1Bnb3JHYnBSdzpleUprWld4MFlTSTZleUp3WVhSamFHVnpJanBiZXlKaFkzUnBiMjRpT2lKaFpHUXRjSFZpYkdsakxXdGxlWE1pTENKd2RXSnNhV05MWlhseklqcGJleUpwWkNJNklqSmFOelpqWldFMmJYbHZSM2RzUWtoYVNqaHpkRTlmU1ZJNGRXaGtZbEl3UjA5WVYxTk9lWEl0U1UwaUxDSndkV0pzYVdOTFpYbEtkMnNpT25zaVkzSjJJam9pUldReU5UVXhPU0lzSW10MGVTSTZJazlMVUNJc0luZ2lPaUowVUZGM1pWa3pUSEJrVm5KdE0xQkRUVzR3YTNCa2VFSXhZbkJ3V0Vwc1kyTkJWWFpGTlhkeFpGbEpJbjBzSW5CMWNuQnZjMlZ6SWpwYkltRjFkR2hsYm5ScFkyRjBhVzl1SWl3aVlYTnpaWEowYVc5dVRXVjBhRzlrSWwwc0luUjVjR1VpT2lKS2MyOXVWMlZpUzJWNU1qQXlNQ0o5WFgxZExDSjFjR1JoZEdWRGIyMXRhWFJ0Wlc1MElqb2lSV2xDWVcxTVZHOUpSVE5uVURaNlVrbEpjRzFVT0RKSFVGTXhPR1JHV204elFsUk9kV056VFdoaE5tSjZkeUo5TENKemRXWm1hWGhFWVhSaElqcDdJbVJsYkhSaFNHRnphQ0k2SWtWcFExOXZRMk5mWkZKb1NYTTNlRTFwYmxGTFpYaDBaMUZSY1hKYWFVVmFORkEwY3pGbFVqWnRObVI0ZVZFaUxDSnlaV052ZG1WeWVVTnZiVzFwZEcxbGJuUWlPaUpGYVVGVGJVeDFXa2syU0VkdlprSmFkRWMwTURWRllXTkdNRVpsYXpOSFZtRnBUMHBHZEhWMFkweGlNbUZCSW4wc0luUjVjR1VpT2lKamNtVmhkR1VpZlEiLCJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSIsImh0dHBzOi8vdzNpZC5vcmcvdmMvc3RhdHVzLWxpc3QvMjAyMS92MSIsImh0dHBzOi8vdzNjLWNjZy5naXRodWIuaW8vbGRzLWp3czIwMjAvY29udGV4dHMvbGRzLWp3czIwMjAtdjEuanNvbiJdLCJjcmVkZW50aWFsU3RhdHVzIjp7ImlkIjoidXJuOnV1aWQ6NDY4YTIxNDEtOTc2My00OTg5LWEwNWEtMTQxZjc2MDcyOThmIiwic3RhdHVzTGlzdENyZWRlbnRpYWwiOiJodHRwOi8vbG9jYWxob3N0OjgwNzUvaXNzdWVyL3Byb2ZpbGVzL2JhbmtfaXNzdWVyL2NyZWRlbnRpYWxzL3N0YXR1cy8xIiwic3RhdHVzTGlzdEluZGV4IjoiNSIsInN0YXR1c1B1cnBvc2UiOiJyZXZvY2F0aW9uIiwidHlwZSI6IlN0YXR1c0xpc3QyMDIxRW50cnkifSwiY3JlZGVudGlhbFN1YmplY3QiOnsiZGlzcGxheU5hbWUiOiJKb2huIERvZSIsImdpdmVuTmFtZSI6IkpvaG4iLCJpZCI6ImRpZDppb246RWlEQjNjWUVYVXdBY2drUTd2WHlpNE5qb0VzTVJyU1FFaGdUR1Bnb3JHYnBSdzpleUprWld4MFlTSTZleUp3WVhSamFHVnpJanBiZXlKaFkzUnBiMjRpT2lKaFpHUXRjSFZpYkdsakxXdGxlWE1pTENKd2RXSnNhV05MWlhseklqcGJleUpwWkNJNklqSmFOelpqWldFMmJYbHZSM2RzUWtoYVNqaHpkRTlmU1ZJNGRXaGtZbEl3UjA5WVYxTk9lWEl0U1UwaUxDSndkV0pzYVdOTFpYbEtkMnNpT25zaVkzSjJJam9pUldReU5UVXhPU0lzSW10MGVTSTZJazlMVUNJc0luZ2lPaUowVUZGM1pWa3pUSEJrVm5KdE0xQkRUVzR3YTNCa2VFSXhZbkJ3V0Vwc1kyTkJWWFpGTlhkeFpGbEpJbjBzSW5CMWNuQnZjMlZ6SWpwYkltRjFkR2hsYm5ScFkyRjBhVzl1SWl3aVlYTnpaWEowYVc5dVRXVjBhRzlrSWwwc0luUjVjR1VpT2lKS2MyOXVWMlZpUzJWNU1qQXlNQ0o5WFgxZExDSjFjR1JoZEdWRGIyMXRhWFJ0Wlc1MElqb2lSV2xDWVcxTVZHOUpSVE5uVURaNlVrbEpjRzFVT0RKSFVGTXhPR1JHV204elFsUk9kV056VFdoaE5tSjZkeUo5TENKemRXWm1hWGhFWVhSaElqcDdJbVJsYkhSaFNHRnphQ0k2SWtWcFExOXZRMk5mWkZKb1NYTTNlRTFwYmxGTFpYaDBaMUZSY1hKYWFVVmFORkEwY3pGbFVqWnRObVI0ZVZFaUxDSnlaV052ZG1WeWVVTnZiVzFwZEcxbGJuUWlPaUpGYVVGVGJVeDFXa2syU0VkdlprSmFkRWMwTURWRllXTkdNRVpsYXpOSFZtRnBUMHBHZEhWMFkweGlNbUZCSW4wc0luUjVjR1VpT2lKamNtVmhkR1VpZlEiLCJqb2JUaXRsZSI6IlNvZnR3YXJlIERldmVsb3BlciIsIm1haWwiOiJqb2huLmRvZUBmb28uYmFyIiwicGhvdG8iOiJkYXRhLVVSTC1lbmNvZGVkIGltYWdlIiwicHJlZmVycmVkTGFuZ3VhZ2UiOiJFbmdsaXNoIiwic3VybmFtZSI6IkRvZSJ9LCJleHBpcmF0aW9uRGF0ZSI6IjIwMjQtMDItMjRUMjA6NTM6MzFaIiwiaWQiOiJ1cm46dXVpZDo4MjkxNzY3Ni0yNDJlLTQxZGYtOGQ1My1mZDg5ZTQ2OTU0Y2QiLCJpc3N1YW5jZURhdGUiOiIyMDIzLTAyLTI0VDIwOjUzOjMxWiIsImlzc3VlciI6eyJpZCI6ImRpZDpvcmI6dUFBQTpFaURUeEhXMG5ReWNhTThmY2Y0bjZibFJrRU0zZVphZXR0S25PZWNIWlVTUEp3IiwibmFtZSI6IkJhbmsgSXNzdWVyIn0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJWZXJpZmllZEVtcGxveWVlIl19fQ.ZrxhchIBHyy1_b1J7TTkAmMEj97E4kPFIWJe__P5RipijjPIrMwtBpw1yz3W89f2PBNc4JNmepHyRmqP39Je3g"
]
}
`

//go:embed testdata/context/presentation_submission_v1.jsonld
var presentationSubmissionV1 []byte //nolint:gochecknoglobals

Expand Down Expand Up @@ -293,6 +325,28 @@ func TestParsePresentation(t *testing.T) {
require.EqualError(t, err, "JSON-LD doc has different structure after compaction")
require.Nil(t, vp)
})

t.Run("parsing VP with a JWT VC succeeds", func(t *testing.T) {
loader := createTestDocumentLoader(t, ldcontext.Document{
URL: "https://trustbloc.github.io/context/vc/presentation-exchange-submission-v1.jsonld",
Content: presentationSubmissionV1,
})

vp, err := ParsePresentation([]byte(validPresentationWithJWTVC), WithPresDisabledProofCheck(), WithPresJSONLDDocumentLoader(loader))
require.NoError(t, err)
require.NotNil(t, vp)
})

t.Run("parsing VP with a JWT VC with required JSON-LD checks succeeds", func(t *testing.T) {
loader := createTestDocumentLoader(t, ldcontext.Document{
URL: "https://trustbloc.github.io/context/vc/presentation-exchange-submission-v1.jsonld",
Content: presentationSubmissionV1,
})

vp, err := ParsePresentation([]byte(validPresentationWithJWTVC), WithPresDisabledProofCheck(), WithPresJSONLDDocumentLoader(loader), WithPresRequiredVCJSONLDChecks())
require.NoError(t, err)
require.NotNil(t, vp)
})
}

func TestValidateVP_Context(t *testing.T) {
Expand Down

0 comments on commit bb00190

Please sign in to comment.