piprate/json-gold

Framing of fields with the same IDs

kdimak opened this issue · 3 comments

If the input JSON-LD document contains two sibling fields with the same id, then it's possible that framing is applied on the wrong element.

Example test code (note that issuer and credentialSubject have the same id did:example:b34ca6cd37bbf23:

func TestJSONLDFramingWithSameSiblingIDs(t *testing.T) {
	vcJSON := `
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://raw.githubusercontent.com/w3c-ccg/ldp-bbs2020/master/contexts/v0.1.jsonld"
  ],
  "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
  "type": [
    "VerifiableCredential",
    "PermanentResidentCard"
  ],
  "issuer": "did:example:b34ca6cd37bbf23",
  "identifier": "83627465",
  "name": "Permanent Resident Card",
  "description": "Government of Example Permanent Resident Card.",
  "issuanceDate": "2019-12-03T12:19:52Z",
  "expirationDate": "2029-12-03T12:19:52Z",
  "credentialSubject": {
    "id": "did:example:b34ca6cd37bbf23",
    "type": [
      "PermanentResident",
      "Person"
    ],
    "givenName": "JOHN",
    "familyName": "SMITH",
    "gender": "Male",
    "image": "data:image/png;base64,iVBORw0KGgokJggg==",
    "residentSince": "2015-01-01",
    "lprCategory": "C09",
    "lprNumber": "999-999-999",
    "commuterClassification": "C1",
    "birthCountry": "Bahamas",
    "birthDate": "1958-07-17"
  }
}
`

	frameJSON := `
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/citizenship/v1",
    "https://raw.githubusercontent.com/w3c-ccg/ldp-bbs2020/master/contexts/v0.1.jsonld"
  ],
  "type": ["VerifiableCredential", "PermanentResidentCard"],
  "credentialSubject": {
    "@explicit": true,
    "type": ["PermanentResident", "Person"],
    "givenName": {},
    "familyName": {},
    "gender": {}
  }
}
`

	options := ld.NewJsonLdOptions("")
	options.ProcessingMode = ld.JsonLd_1_1
	options.Format = "application/n-quads"
	options.ProduceGeneralizedRdf = true
	options.FrameDefault = true
	options.OmitGraph = true

	var vcDoc map[string]interface{}
	err := json.Unmarshal([]byte(vcJSON), &vcDoc)
	require.NoError(t, err)

	var frameDoc map[string]interface{}
	err = json.Unmarshal([]byte(frameJSON), &frameDoc)
	require.NoError(t, err)

	proc := ld.NewJsonLdProcessor()
	frame, err := proc.Frame(vcDoc, frameDoc, options)
	require.NoError(t, err)

	frame["@context"] = frameDoc["@context"]

	filteredVCDoc, _ := json.MarshalIndent(frame, "", " ")
	println(string(filteredVCDoc))

	expectedVCDoc := `{
 "@context": [
  "https://www.w3.org/2018/credentials/v1",
  "https://w3id.org/citizenship/v1",
  "https://raw.githubusercontent.com/w3c-ccg/ldp-bbs2020/master/contexts/v0.1.jsonld"
 ],
 "credentialSubject": {
  "familyName": "SMITH",
  "gender": "Male",
  "givenName": "JOHN",
  "id": "did:example:b34ca6cd37bbf23",
  "type": [
   "PermanentResident",
   "Person"
  ]
 },
 "description": "Government of Example Permanent Resident Card.",
 "expirationDate": "2029-12-03T12:19:52Z",
 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
 "identifier": "83627465",
 "issuanceDate": "2019-12-03T12:19:52Z",
 "issuer": "did:example:b34ca6cd37bbf23",
 "name": "Permanent Resident Card",
 "type": [
  "VerifiableCredential",
  "PermanentResidentCard"
 ]
}`
	require.Equal(t, expectedVCDoc, string(filteredVCDoc))
}

The output JSON-LD is wrong and looks like the following:

{
 "@context": [
  "https://www.w3.org/2018/credentials/v1",
  "https://w3id.org/citizenship/v1",
  "https://raw.githubusercontent.com/w3c-ccg/ldp-bbs2020/master/contexts/v0.1.jsonld"
 ],
 "credentialSubject": "did:example:b34ca6cd37bbf23",
 "description": "Government of Example Permanent Resident Card.",
 "expirationDate": "2029-12-03T12:19:52Z",
 "id": "https://issuer.oidp.uscis.gov/credentials/83627465",
 "identifier": "83627465",
 "issuanceDate": "2019-12-03T12:19:52Z",
 "issuer": {
  "birthCountry": "Bahamas",
  "birthDate": "1958-07-17",
  "commuterClassification": "C1",
  "familyName": "SMITH",
  "gender": "Male",
  "givenName": "JOHN",
  "id": "did:example:b34ca6cd37bbf23",
  "image": "data:image/png;base64,iVBORw0KGgokJggg==",
  "lprCategory": "C09",
  "lprNumber": "999-999-999",
  "residentSince": "2015-01-01",
  "type": [
   "PermanentResident",
   "Person"
  ]
 },
 "name": "Permanent Resident Card",
 "type": [
  "VerifiableCredential",
  "PermanentResidentCard"
 ]
}

Here all the fields from credentialSubject got copied to the issuer without proper framing, while issuer is empty.

It works properly at JSON-LD playground though (link).

@kdimak thanks for reporting. The trouble is that in order to bring the library to better compliance with Framing 1.1 spec, the framing implementation requires a full rewrite. It's not a huge job, a couple of days of coding, but it's not done yet. Until then, I wouldn't recommend using the library for any framing beyond the 1.0 logic.

I see you have a workaround. How critical is it for you to get this issue fixed? Are you using framing extensively?

hi @kazarena ! thank you for your input! We are using the framing for the generation of Selective Disclosures for Verifiable Credentials. JSON-LD framing suits perfectly for this purpose. Yes, we already have a very simple workaround - to rename duplicated IDs with some unique random strings, execute the framing and then restore the IDs. We can for sure wait for the proper rewrite from your side, and just thank you very much for your fast feedback and friendly approach!

@kdimak, it sounds like a worthy cause. I'll prioritise the framing update.