1EdTech / openbadges-validator-core

Open Badges validation in python
Apache License 2.0
51 stars 30 forks source link

Open Badges 3.0 Validator and jsonld.SyntaxError\\nCode: invalid container mapping #251

Open ddxtanx opened 1 year ago

ddxtanx commented 1 year ago

Will this validator be updated to the 3.0 spec recently published? According to the current version, this validator ought to be able to verify 3.0 badges (https://1edtech.github.io/openbadges-specification/ob_v3p0.html#verificaton-and-validation) but it seems that the current version is unable to deal with multiple @context's. In my current case, I'm attempting to validate the following badge:

{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://purl.imsglobal.org/spec/ob/v3p0/context.json",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "..."
  "type": [ "VerifiableCredential", "OpenBadgeCredential" ],
  "issuer": { "id": "...", "type": [ "Profile" ] },
  "issuanceDate": "2023-06-12T17:33:55Z",
  "credentialSubject": {
    "type": [ "AchievementSubject" ],
    "identifier": {
      "type": "IdentityObject",
      "hashed": true,
      "salt": "example",
      "identityHash": "sha256$248ecce3dbbb5c494d9e4f1edd9520efa99d404aedbfaaaf3aef249ec5421984",
      "identityType": "emailAddress"
    }
  },
  "name": "...",
  "description": "...",
  "image": "...",
  "proof": {
    "type": "Ed25519Signature2020",
    "created": "2023-06-12T23:18:42Z",
    "verificationMethod": "...#z6MkgJk3GS6ykaMDkRkPtz98oMpjbDjUmrhKd7nxFrn5GvoP",
    "proofPurpose": "assertionMethod",
    "proofValue": "zC1o4oF7geGvwf3iTtSQgR4jn3PDamVv2tFCLwtJMMiyatcZG7jLK9kzMseR5qC4UR1F5WSK7nXYRoMh8ZWkNXvy"
  }
}

and the current version of the validator returns the following error

{
    "graph": [],
    "input": {
        "value": "...",
        "input_type": "url"
    },
    "report": {
        "validationSubject": "...",
        "errorCount": 1,
        "warningCount": 0,
        "messages": [
            {
                "messageLevel": "ERROR",
                "node_id": "...",
                "result": "<class 'pyld.jsonld.JsonLdError'> ['pyld.jsonld.JsonLdError: (\\'Could not expand input before compaction.\\',)\\nType: jsonld.CompactError\\nCause: (\\'Invalid JSON-LD syntax; @context @container value must be one of the following: @list, @set, @index, or @language.\\',)\\nType: jsonld.SyntaxError\\nCode: invalid container mapping\\nDetails: {\\'context\\': {\\'VerifiablePresentation\\': {\\'@context\\': {\\'holder\\': {\\'@id\\': \\'cred:holder\\', \\'@type\\': \\'@id\\'}, \\'verifiableCredential\\': {\\'@id\\': \\'cred:verifiableCredential\\', \\'@container\\': \\'@graph\\', \\'@type\\': \\'@id\\'}, \\'proof\\': {\\'@id\\': \\'sec:proof\\', \\'@container\\': \\'@graph\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'cred\\': \\'https://www.w3.org/2018/credentials#\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'https://www.w3.org/2018/credentials#VerifiablePresentation\\'}, \\'Ed25519Signature2018\\': {\\'@context\\': {\\'proofPurpose\\': {\\'@context\\': {\\'assertionMethod\\': {\\'@id\\': \\'sec:assertionMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'authentication\\': {\\'@id\\': \\'sec:authenticationMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'sec:proofPurpose\\', \\'@type\\': \\'@vocab\\'}, \\'verificationMethod\\': {\\'@id\\': \\'sec:verificationMethod\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'proofValue\\': \\'sec:proofValue\\', \\'created\\': {\\'@id\\': \\'http://purl.org/dc/terms/created\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'xsd\\': \\'http://www.w3.org/2001/XMLSchema#\\', \\'domain\\': \\'sec:domain\\', \\'nonce\\': \\'sec:nonce\\', \\'jws\\': \\'sec:jws\\', \\'challenge\\': \\'sec:challenge\\', \\'expires\\': {\\'@id\\': \\'sec:expiration\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'https://w3id.org/security#Ed25519Signature2018\\'}, \\'EcdsaSecp256k1Signature2019\\': {\\'@context\\': {\\'proofPurpose\\': {\\'@context\\': {\\'assertionMethod\\': {\\'@id\\': \\'sec:assertionMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'authentication\\': {\\'@id\\': \\'sec:authenticationMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'sec:proofPurpose\\', \\'@type\\': \\'@vocab\\'}, \\'verificationMethod\\': {\\'@id\\': \\'sec:verificationMethod\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'proofValue\\': \\'sec:proofValue\\', \\'created\\': {\\'@id\\': \\'http://purl.org/dc/terms/created\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'xsd\\': \\'http://www.w3.org/2001/XMLSchema#\\', \\'domain\\': \\'sec:domain\\', \\'nonce\\': \\'sec:nonce\\', \\'jws\\': \\'sec:jws\\', \\'challenge\\': \\'sec:challenge\\', \\'expires\\': {\\'@id\\': \\'sec:expiration\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'https://w3id.org/security#EcdsaSecp256k1Signature2019\\'}, \\'EcdsaSecp256r1Signature2019\\': {\\'@context\\': {\\'proofPurpose\\': {\\'@context\\': {\\'assertionMethod\\': {\\'@id\\': \\'sec:assertionMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'authentication\\': {\\'@id\\': \\'sec:authenticationMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'sec:proofPurpose\\', \\'@type\\': \\'@vocab\\'}, \\'verificationMethod\\': {\\'@id\\': \\'sec:verificationMethod\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'proofValue\\': \\'sec:proofValue\\', \\'created\\': {\\'@id\\': \\'http://purl.org/dc/terms/created\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'xsd\\': \\'http://www.w3.org/2001/XMLSchema#\\', \\'domain\\': \\'sec:domain\\', \\'nonce\\': \\'sec:nonce\\', \\'jws\\': \\'sec:jws\\', \\'challenge\\': \\'sec:challenge\\', \\'expires\\': {\\'@id\\': \\'sec:expiration\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'https://w3id.org/security#EcdsaSecp256r1Signature2019\\'}, \\'proof\\': {\\'@id\\': \\'https://w3id.org/security#proof\\', \\'@container\\': \\'@graph\\', \\'@type\\': \\'@id\\'}, \\'VerifiableCredential\\': {\\'@context\\': {\\'credentialStatus\\': {\\'@id\\': \\'cred:credentialStatus\\', \\'@type\\': \\'@id\\'}, \\'issuanceDate\\': {\\'@id\\': \\'cred:issuanceDate\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'credentialSchema\\': {\\'@context\\': {\\'JsonSchemaValidator2018\\': \\'cred:JsonSchemaValidator2018\\', \\'@protected\\': True, \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'cred\\': \\'https://www.w3.org/2018/credentials#\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'cred:credentialSchema\\', \\'@type\\': \\'@id\\'}, \\'credentialSubject\\': {\\'@id\\': \\'cred:credentialSubject\\', \\'@type\\': \\'@id\\'}, \\'@version\\': 1.1, \\'termsOfUse\\': {\\'@id\\': \\'cred:termsOfUse\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'issued\\': {\\'@id\\': \\'cred:issued\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'xsd\\': \\'http://www.w3.org/2001/XMLSchema#\\', \\'sec\\': \\'https://w3id.org/security#\\', \\'refreshService\\': {\\'@context\\': {\\'@protected\\': True, \\'ManualRefreshService2018\\': \\'cred:ManualRefreshService2018\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'cred\\': \\'https://www.w3.org/2018/credentials#\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'cred:refreshService\\', \\'@type\\': \\'@id\\'}, \\'validUntil\\': {\\'@id\\': \\'cred:validUntil\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'proof\\': {\\'@id\\': \\'sec:proof\\', \\'@container\\': \\'@graph\\', \\'@type\\': \\'@id\\'}, \\'issuer\\': {\\'@id\\': \\'cred:issuer\\', \\'@type\\': \\'@id\\'}, \\'expirationDate\\': {\\'@id\\': \\'cred:expirationDate\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'validFrom\\': {\\'@id\\': \\'cred:validFrom\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'id\\': \\'@id\\', \\'cred\\': \\'https://www.w3.org/2018/credentials#\\', \\'evidence\\': {\\'@id\\': \\'cred:evidence\\', \\'@type\\': \\'@id\\'}, \\'type\\': \\'@type\\', \\'holder\\': {\\'@id\\': \\'cred:holder\\', \\'@type\\': \\'@id\\'}}, \\'@id\\': \\'https://www.w3.org/2018/credentials#VerifiableCredential\\'}, \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'RsaSignature2018\\': {\\'@context\\': {\\'domain\\': \\'sec:domain\\', \\'verificationMethod\\': {\\'@id\\': \\'sec:verificationMethod\\', \\'@type\\': \\'@id\\'}, \\'proofPurpose\\': {\\'@context\\': {\\'assertionMethod\\': {\\'@id\\': \\'sec:assertionMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'authentication\\': {\\'@id\\': \\'sec:authenticationMethod\\', \\'@container\\': \\'@set\\', \\'@type\\': \\'@id\\'}, \\'@protected\\': True, \\'sec\\': \\'https://w3id.org/security#\\', \\'@version\\': 1.1, \\'id\\': \\'@id\\', \\'type\\': \\'@type\\'}, \\'@id\\': \\'sec:proofPurpose\\', \\'@type\\': \\'@vocab\\'}, \\'jws\\': \\'sec:jws\\', \\'expires\\': {\\'@id\\': \\'sec:expiration\\', \\'@type\\': \\'xsd:dateTime\\'}, \\'challenge\\': \\'sec:challenge\\', \\'nonce\\': \\'sec:nonce\\', \\'@version\\': 1.1, \\'proofValue\\': \\'sec:proofValue\\', \\'@protected\\': True, \\'created\\': {\\'@id\\': \\'http://purl.org/dc/terms/created\\', \\'@type\\': \\'xsd:dateTime\\'}}, \\'@id\\': \\'https://w3id.org/security#RsaSignature2018\\'}, \\'type\\': \\'@type\\', \\'@protected\\': True}}  File \"/usr/local/lib/python3.5/dist-packages/pyld/jsonld.py\", line 678, in compact\\n    expanded = self.expand(input_, options)\\n  File \"/usr/local/lib/python3.5/dist-packages/pyld/jsonld.py\", line 833, in expand\\n    expanded = self._expand(active_ctx, None, document, options, False)\\n  File \"/usr/local/lib/python3.5/dist-packages/pyld/jsonld.py\", line 1961, in _expand\\n    active_ctx, element[\\'@context\\'], options)\\n  File \"/usr/local/lib/python3.5/dist-packages/pyld/jsonld.py\", line 2563, in _process_context\\n    self._create_term_definition(rval, ctx, k, defined)\\n  File \"/usr/local/lib/python3.5/dist-packages/pyld/jsonld.py\", line 3875, in _create_term_definition\\n    {\\'context\\': local_ctx}, code=\\'invalid container mapping\\')\\n\\n']",
                "success": false,
                "name": "JSONLD_COMPACT_DATA"
            }
        ],
        "valid": false,
        "openBadgesVersion": "2.0"
    }
}

which seems to be due to the fact that the @context field is an array and not a single string.

ottonomy commented 1 year ago

No, this package can't do OB 3.0. 1EdTech is working on a new 3.0 validator, but it's a new project and won't be an update to this python codebase. The roadmap for the various public tools related to Open Badges would be a great topic for conversation @xaviaracil