├── .gitignore ├── artifacts ├── README.md ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── src │ ├── main │ │ ├── resources │ │ │ ├── issuance │ │ │ │ ├── example │ │ │ │ │ ├── credential-status.json │ │ │ │ │ ├── credential-message-rejected.json │ │ │ │ │ ├── credential-request-message.json │ │ │ │ │ ├── credential-message.json │ │ │ │ │ ├── credential-object.json │ │ │ │ │ ├── credential-offer-message.json │ │ │ │ │ └── issuer-metadata.json │ │ │ │ ├── credential-offer-message-schema.json │ │ │ │ ├── credential-request-message-schema.json │ │ │ │ ├── credential-object-schema.json │ │ │ │ ├── credential-status-schema.json │ │ │ │ ├── issuer-metadata-schema.json │ │ │ │ └── credential-message-schema.json │ │ │ ├── presentation │ │ │ │ ├── example │ │ │ │ │ ├── presentation-query-message.json │ │ │ │ │ ├── presentation-response-message.json │ │ │ │ │ ├── presentation-response-message-w-presentation-submission.json │ │ │ │ │ └── presentation-query-message-w-presentation-definition.json │ │ │ │ ├── presentation-response-message-schema.json │ │ │ │ └── presentation-query-message-schema.json │ │ │ ├── common │ │ │ │ └── context-schema.json │ │ │ └── context │ │ │ │ ├── dcp.jsonld │ │ │ │ └── odrl.jsonld │ │ └── java │ │ │ └── org │ │ │ └── eclipse │ │ │ └── dcp │ │ │ └── schema │ │ │ └── SchemaConstants.java │ └── test │ │ ├── resources │ │ ├── claim-format-registry │ │ │ └── schemas │ │ │ │ ├── presentation-submission-claim-format-designations.json │ │ │ │ └── presentation-definition-claim-format-designations.json │ │ └── presentation-exchange │ │ │ └── schemas │ │ │ ├── presentation-submission.json │ │ │ └── presentation-definition.json │ │ └── java │ │ └── org │ │ └── eclipse │ │ └── dcp │ │ ├── context │ │ ├── presentation │ │ │ └── PresentationContextTest.java │ │ ├── issuance │ │ │ └── IssuanceContextTest.java │ │ └── fixtures │ │ │ └── AbstractJsonLdTest.java │ │ └── schema │ │ ├── fixtures │ │ └── AbstractSchemaTest.java │ │ ├── issuance │ │ ├── CredentialStatusSchemaTest.java │ │ ├── CredentialOfferMessageSchemaTest.java │ │ ├── IssuerMetadataSchemaTest.java │ │ ├── CredentialObjectSchemaTest.java │ │ ├── CredentialRequestMessageSchemaTest.java │ │ └── CredentialMessageSchemaTest.java │ │ └── presentation │ │ ├── PresentationResponseMessageSchemaTest.java │ │ └── PresentationQueryMessageSchemaTest.java ├── settings.gradle.kts ├── .gitignore ├── config │ └── checkstyle │ │ └── suppressions.xml ├── build.gradle.kts ├── gradlew.bat └── gradlew ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── 1-bug.yml │ └── 2-feature-request.yml ├── actions │ └── setup-java │ │ └── action.yaml ├── PULL_REQUEST_TEMPLATE.md ├── scripts │ ├── index.html │ └── checkout-tags.sh └── workflows │ ├── artifacts.yaml │ └── autopublish.yaml ├── CODE_OF_CONDUCT.md ├── docs ├── roadmap │ └── DCP_Roadmap_Plan.pdf └── decision-records │ ├── 2023-09-22-release-process │ └── README.md │ └── 2024-12-12-profiles │ └── README.md ├── SECURITY.md ├── specifications ├── auth.flow.puml ├── issuance.flow.puml ├── dsp.profile.md ├── terminology.md ├── diagram.styles.puml ├── identity-trust-sts-api.yaml ├── dataspace.ecosystem.md ├── dcp.profiles.md ├── issuer-holder-verifier-model.svg ├── base.protocol.md ├── participant-agent-model.svg ├── trust.model.md ├── auth.flow.svg └── issuance.flow.svg ├── README.md ├── NOTICE.md ├── CONTRIBUTING.md ├── WEBSITE.md ├── pr_etiquette.md ├── index.html └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | resources/ -------------------------------------------------------------------------------- /artifacts/README.md: -------------------------------------------------------------------------------- 1 | # DCP Artifacts 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | See the [Eclipse Code Of Conduct](https://www.eclipse.org/org/documents/Community_Code_of_Conduct.php). -------------------------------------------------------------------------------- /docs/roadmap/DCP_Roadmap_Plan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-dataspace-dcp/decentralized-claims-protocol/HEAD/docs/roadmap/DCP_Roadmap_Plan.pdf -------------------------------------------------------------------------------- /artifacts/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eclipse-dataspace-dcp/decentralized-claims-protocol/HEAD/artifacts/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report a found vulnerability here: 6 | [https://www.eclipse.org/security/](https://www.eclipse.org/security/) -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-status.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "CredentialStatus", 6 | "issuerPid": "issuerPid", 7 | "holderPid": "holderPid", 8 | "status": "RECEIVED" 9 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/example/presentation-query-message.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "PresentationQueryMessage", 6 | "scope": [ 7 | "presentation1", 8 | "presentation2" 9 | ] 10 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/example/presentation-response-message.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "PresentationResponseMessage", 6 | "presentation": [ 7 | "presentation1", 8 | "presentation2" 9 | ] 10 | } -------------------------------------------------------------------------------- /.github/actions/setup-java/action.yaml: -------------------------------------------------------------------------------- 1 | name: "Setup JDK 17" 2 | description: "Setup JDK 17" 3 | runs: 4 | using: "composite" 5 | steps: 6 | - name: Setup JDK 17 7 | uses: actions/setup-java@v4.1.0 8 | with: 9 | java-version: '17' 10 | distribution: 'temurin' 11 | cache: 'gradle' 12 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-message-rejected.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "CredentialMessage", 6 | "issuerPid": "issuerPid", 7 | "holderPid": "holderPid", 8 | "status": "REJECTED", 9 | "rejectionReason": "final approval not granted" 10 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-request-message.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "CredentialRequestMessage", 6 | "holderPid": "holderPid", 7 | "credentials": [ 8 | { 9 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1" 10 | }, 11 | { 12 | "id": "c0f81e68-6d35-4f9d-bc04-51e511b2e46c" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## WHAT 2 | 3 | _Briefly describe what your PR changes, which features it adds/modifies._ 4 | 5 | Closes # <-- _insert Issue number if one exists_ 6 | 7 | ## How was the issue fixed? 8 | 9 | _Briefly state why the change was necessary._ 10 | 11 | ## More context 12 | 13 | _List other areas that have changed but are not necessarily linked to the main feature. This could be naming changes, 14 | bugs that were encountered and were fixed inline, etc._ -------------------------------------------------------------------------------- /artifacts/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | rootProject.name = "artifacts" -------------------------------------------------------------------------------- /.github/scripts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 |

11 | This redirects to the latest Release here 12 |

13 | 14 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-message.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "CredentialMessage", 6 | "credentials": [ 7 | { 8 | "credentialType": "MembershipCredential", 9 | "payload": "", 10 | "format": "jwt" 11 | }, 12 | { 13 | "credentialType": "OrganizationCredential", 14 | "payload": "", 15 | "format": "json-ld" 16 | } 17 | ], 18 | "issuerPid": "issuerPid", 19 | "holderPid": "holderPid", 20 | "status": "ISSUED" 21 | } -------------------------------------------------------------------------------- /artifacts/src/test/resources/claim-format-registry/schemas/presentation-submission-claim-format-designations.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "Presentation Submission Claim Format Designations", 4 | "type": "object", 5 | "definitions": { 6 | "format": { 7 | "type": "string", 8 | "enum": [ 9 | "jwt", 10 | "jwt_vc", 11 | "jwt_vp", 12 | "ldp", 13 | "ldp_vc", 14 | "ldp_vp", 15 | "mso_mdoc", 16 | "ac_vc", 17 | "ac_vp", 18 | "sd_jwt" 19 | ] 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/common/context-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "ContextSchema", 4 | "type": "array", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/ContextSchema" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v08/common/context-schema.json", 11 | "definitions": { 12 | "ContextSchema": { 13 | "type": "array", 14 | "items": { 15 | "type": "string", 16 | "items": { 17 | "type": "string" 18 | } 19 | }, 20 | "contains": { 21 | "const": "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /specifications/auth.flow.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !pragma layout smetana 3 | 4 | !include diagram.styles.puml 5 | 6 | autonumber 7 | 8 | box "Client Entity" 9 | participant "Client" as C 10 | participant "Secure Token Service" as STS 11 | participant "DID Service" as DS 12 | participant "Credential Service" as CS 13 | end box 14 | 15 | box "Verifier Entity" 16 | participant "Verifier" as V 17 | end box 18 | 19 | C -> STS: request 20 | STS -> C: response incl. access token 21 | 22 | C -> V: request w/ self-issued id token incl. access token 23 | DS <- V: resolve DID 24 | DS -> V: DID document response 25 | CS <- V: request w/ self-issued id token incl. access token 26 | CS ->V: VP response 27 | C <- V: response 28 | @enduml -------------------------------------------------------------------------------- /artifacts/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2024 Metaform Systems, Inc. 3 | # 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Apache License, Version 2.0 which is available at 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # SPDX-License-Identifier: Apache-2.0 9 | # 10 | # Contributors: 11 | # Metaform Systems, Inc. - initial API and implementation 12 | # 13 | # 14 | 15 | distributionBase=GRADLE_USER_HOME 16 | distributionPath=wrapper/dists 17 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip 18 | networkTimeout=10000 19 | validateDistributionUrl=true 20 | zipStoreBase=GRADLE_USER_HOME 21 | zipStorePath=wrapper/dists 22 | -------------------------------------------------------------------------------- /artifacts/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | .idea 16 | out/ 17 | !**/src/main/**/out/ 18 | !**/src/test/**/out/ 19 | 20 | ### Eclipse ### 21 | .apt_generated 22 | .classpath 23 | .factorypath 24 | .project 25 | .settings 26 | .springBeans 27 | .sts4-cache 28 | bin/ 29 | !**/src/main/**/bin/ 30 | !**/src/test/**/bin/ 31 | 32 | ### NetBeans ### 33 | /nbproject/private/ 34 | /nbbuild/ 35 | /dist/ 36 | /nbdist/ 37 | /.nb-gradle/ 38 | 39 | ### VS Code ### 40 | .vscode/ 41 | 42 | ### Mac OS ### 43 | .DS_Store 44 | 45 | 46 | -------------------------------------------------------------------------------- /artifacts/config/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/example/presentation-response-message-w-presentation-submission.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "PresentationResponseMessage", 6 | "presentation": [ 7 | "jwtPresentation" 8 | ], 9 | "presentationSubmission": { 10 | "id": "Presentation example 2", 11 | "definition_id": "Example with multiple VPs", 12 | "descriptor_map": [ 13 | { 14 | "id": "id_credential", 15 | "format": "jwt_vp", 16 | "path": "$.presentation[0]", 17 | "path_nested": { 18 | "id": "id_nested_credential", 19 | "format": "jwt_vc", 20 | "path": "$.vp.verifiableCredential[0]" 21 | } 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /specifications/issuance.flow.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !pragma layout smetana 3 | 4 | !include diagram.styles.puml 5 | 6 | autonumber 7 | 8 | box "Client Entity" 9 | participant "Client" as C 10 | participant "Secure Token Service" as STS 11 | participant "DID Service" as DS 12 | participant "Credential Service" as CS 13 | end box 14 | 15 | box "Issuer Entity" 16 | participant "Issuer Service" as IS 17 | end box 18 | 19 | C -> STS: request 20 | STS -> C: response incl. access token 21 | C -> IS: request credential(s) w/ self-issued ID token incl. access token 22 | DS <- IS: resolve DID 23 | DS -> IS: DID document response 24 | C <- IS: ack 25 | CS <- IS: (async) write credential(s)\n w/ self-issued ID token access token 26 | CS -> CS: Validate token and\n store credentials 27 | 28 | @enduml 29 | -------------------------------------------------------------------------------- /.github/scripts/checkout-tags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p HEAD 4 | git fetch --all --tags 5 | tags_string=$(git tag) 6 | echo got tag string 7 | echo $tags_string 8 | tags_array=($tags_string) 9 | mv * HEAD 10 | for tag in "${tags_array[@]}" 11 | do 12 | echo starting with tag $tag 13 | mkdir $tag 14 | cd $tag 15 | git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY.git --depth 1 --branch ${tag} --quiet 16 | pwd 17 | mv ./decentralized-claims-protocol/* . 18 | cd .. 19 | done 20 | pwd 21 | for dir in */; do 22 | if [ -f "$dir/index.html" ]; then 23 | echo "index exists." 24 | mkdir -p $dir/resources 25 | cp -r $dir/artifacts/src/main/resources/* $dir/resources 26 | rm -rf $dir/artifacts 27 | else 28 | echo "index does not exist. No copy operations" 29 | fi 30 | done -------------------------------------------------------------------------------- /artifacts/src/main/java/org/eclipse/dcp/schema/SchemaConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema; 16 | 17 | /** 18 | * Defines constants for schema validation. 19 | */ 20 | public interface SchemaConstants { 21 | 22 | String DCP_CONTEXT = "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"; 23 | String DCP_PREFIX = "https://w3id.org/dspace-dcp/v1.0/"; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/artifacts.yaml: -------------------------------------------------------------------------------- 1 | name: Verify Artifacts 2 | 3 | on: 4 | workflow_call: 5 | 6 | workflow_dispatch: 7 | 8 | pull_request: 9 | paths: 10 | - "artifacts/**" 11 | 12 | jobs: 13 | verify-formatting: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - uses: ./.github/actions/setup-java 19 | - name: Run Checkstyle 20 | working-directory: ./artifacts 21 | run: | 22 | ./gradlew checkstyleMain checkstyleTest 23 | 24 | verify-artifacts: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v4 29 | - uses: ./.github/actions/setup-java 30 | - name: Checks artifacts 31 | working-directory: ./artifacts 32 | run: | 33 | ./gradlew test 34 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/example/presentation-query-message-w-presentation-definition.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "PresentationQueryMessage", 6 | "presentationDefinition": { 7 | "id": "presentation1", 8 | "input_descriptors": [ 9 | { 10 | "id": "organization credential", 11 | "format": { 12 | "ldp_vc": { 13 | "proof_type": [ 14 | "Ed25519Signature2018" 15 | ] 16 | } 17 | }, 18 | "constraints": { 19 | "fields": [ 20 | { 21 | "path": [ 22 | "$.type" 23 | ], 24 | "filter": { 25 | "type": "string", 26 | "pattern": "OrganizationCredential" 27 | } 28 | } 29 | ] 30 | } 31 | } 32 | ] 33 | } 34 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-object.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 6 | "type": "CredentialObject", 7 | "credentialType": "CompanyCredential", 8 | "credentialSchema": "https://example.com/credentials/credentialSchema", 9 | "offerReason": "reissue", 10 | "bindingMethods": [ 11 | "did:web" 12 | ], 13 | "profile": "vc20-bssl/jwt", 14 | "issuancePolicy": { 15 | "id": "Scalable trust example", 16 | "input_descriptors": [ 17 | { 18 | "id": "pd-id", 19 | "constraints": { 20 | "fields": [ 21 | { 22 | "path": [ 23 | "$.vc.type" 24 | ], 25 | "filter": { 26 | "type": "string", 27 | "pattern": "^AttestationCredential$" 28 | } 29 | } 30 | ] 31 | } 32 | } 33 | ] 34 | } 35 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/credential-offer-message.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "CredentialOfferMessage", 6 | "issuer": "issuer", 7 | "credentials": [ 8 | { 9 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 10 | "type": "CredentialObject", 11 | "credentialType": "CompanyCredential", 12 | "offerReason": "reissue", 13 | "bindingMethods": [ 14 | "did:web" 15 | ], 16 | "profile": "vc10-sl2021/jwt", 17 | "issuancePolicy": { 18 | "id": "Scalable trust example", 19 | "input_descriptors": [ 20 | { 21 | "id": "pd-id", 22 | "constraints": { 23 | "fields": [ 24 | { 25 | "path": [ 26 | "$.vc.type" 27 | ], 28 | "filter": { 29 | "type": "string", 30 | "pattern": "^AttestationCredential$" 31 | } 32 | } 33 | ] 34 | } 35 | } 36 | ] 37 | } 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /docs/decision-records/2023-09-22-release-process/README.md: -------------------------------------------------------------------------------- 1 | # Defining a simple release process 2 | 3 | ## Decision 4 | 5 | The release process for the specifications should be simple and easy to understand. We will not follow GitFlow, but 6 | employ a simple tag-based approach. 7 | 8 | ## Rationale 9 | 10 | With code artefacts it is oftentimes required to be able to back-port bugfixes or even features, or maintain older 11 | versions. Here, the deliverable is merely a compressed archive with static non-code content, so the release process can 12 | be kept fairly simple and linear. 13 | 14 | ## Approach 15 | 16 | Every release will be tagged on the `main` branch using semantic versioning, starting at `0.1.0`. Then, 17 | using that tag, a GitHub Release is to be created, for example using the `ncipollo/release-action` GitHub action. 18 | Finally, a compressed archive containing the current specification documents will be uploaded as artefact to the 19 | GitHub release. 20 | 21 | ## Further notes 22 | 23 | Even though it is common to create a separate branch containing just the release commit (often named `releases`), there 24 | is no apparent advantage over the tag-only approach. -------------------------------------------------------------------------------- /.github/workflows/autopublish.yaml: -------------------------------------------------------------------------------- 1 | name: Auto-Publish 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | tests-artifacts: 10 | uses: ./.github/workflows/artifacts.yaml 11 | build: 12 | name: Build and Validate 13 | runs-on: ubuntu-22.04 14 | permissions: 15 | contents: write 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 22.x 21 | - name: Create Release folders 22 | run: | 23 | chmod +x .github/scripts/checkout-tags.sh 24 | ./.github/scripts/checkout-tags.sh 25 | - name: Redirect top to head 26 | run: cp .github/scripts/index.html . 27 | - uses: actions/upload-pages-artifact@v3 28 | with: 29 | path: . 30 | deploy: 31 | needs: build 32 | permissions: 33 | pages: write 34 | id-token: write 35 | environment: 36 | name: github-pages 37 | url: ${{ steps.deployment.outputs.page_url }} 38 | runs-on: ubuntu-22.04 39 | steps: 40 | - name: Deploy to GitHub Pages 41 | id: deployment 42 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Decentralized Claims Protocol DCP 2 | 3 | This repository contains normative documents defining protocols and flows of the Eclipse Decentralized Claims Protocol 4 | Specification (DCP). The specification defines an interoperable overlay to 5 | the [Dataspace Protocol Specification (DSP)](https://github.com/eclipse-dataspace-protocol-base/DataspaceProtocol) for 6 | conveying organizational identities and establishing trust in a way that preserves privacy and limits the possibility of 7 | network disruption. 8 | 9 | The scope of the Eclipse DCP specification includes: 10 | 11 | - Specifying a format for self-issued identity tokens 12 | - Defining a protocol for storing and presenting Verifiable Credentials and other identity-related resources 13 | - Defining a protocol for parties to request credentials from a credential issuer 14 | 15 | Eclipse DCP supports multiple trust anchors and allows participants to manage and verify presentations without needing 16 | third-party systems outside their control. 17 | 18 | ## Technology Compatibility Kit 19 | 20 | Eclipse DCP includes a [Technology Compatibility Kit (TCK)](https://github.com/eclipse-dataspacetck/dcp-tck) that can be 21 | used to test implementation compliance to the specification. -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/credential-offer-message-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "CredentialOfferMessageSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/CredentialOfferMessage" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-offer-message-schema.json", 11 | "definitions": { 12 | "CredentialOfferMessage": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "issuer": { 19 | "type": "string" 20 | }, 21 | "credentials": { 22 | "type": "array", 23 | "items": { 24 | "$ref": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-object-schema.json#/definitions/CredentialObject" 25 | } 26 | }, 27 | "type": { 28 | "type": "string", 29 | "const": "CredentialOfferMessage" 30 | } 31 | }, 32 | "required": [ 33 | "@context", 34 | "issuer", 35 | "credentials", 36 | "type" 37 | ] 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/example/issuer-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 4 | ], 5 | "type": "IssuerMetadata", 6 | "issuer": "did:web:issuer-url", 7 | "credentialsSupported": [ 8 | { 9 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 10 | "type": "CredentialObject", 11 | "credentialType": "CompanyCredential", 12 | "offerReason": "reissue", 13 | "credentialSchema": "https://example.com/company-credential-schema.json", 14 | "bindingMethods": [ 15 | "did:web" 16 | ], 17 | "profile": "vc10-sl2021/jwt", 18 | "issuancePolicy": { 19 | "id": "Scalable trust example", 20 | "input_descriptors": [ 21 | { 22 | "id": "pd-id", 23 | "constraints": { 24 | "fields": [ 25 | { 26 | "path": [ 27 | "$.vc.type" 28 | ], 29 | "filter": { 30 | "type": "string", 31 | "pattern": "^AttestationCredential$" 32 | } 33 | } 34 | ] 35 | } 36 | } 37 | ] 38 | } 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /artifacts/build.gradle.kts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | plugins { 16 | `java-library` 17 | checkstyle 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | implementation("com.networknt:json-schema-validator:1.5.2") { 26 | exclude("com.fasterxml.jackson.dataformat", "jackson-dataformat-yaml") 27 | } 28 | 29 | testImplementation("org.assertj:assertj-core:3.26.3") 30 | testImplementation("com.apicatalog:titanium-json-ld:1.4.1") 31 | testImplementation("org.glassfish:jakarta.json:2.0.1") 32 | testImplementation("com.fasterxml.jackson.core:jackson-databind:2.18.0") 33 | testImplementation("com.fasterxml.jackson.datatype:jackson-datatype-jakarta-jsonp:2.18.0") 34 | } 35 | 36 | testing { 37 | suites { 38 | val test by getting(JvmTestSuite::class) { 39 | useJUnitJupiter("5.8.1") 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/credential-request-message-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "CredentialRequestMessageSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/CredentialRequestMessage" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-request-message-schema.json", 11 | "definitions": { 12 | "CredentialRequestMessage": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "type": { 19 | "type": "string" 20 | }, 21 | "holderPid": { 22 | "type": "string" 23 | }, 24 | "credentials": { 25 | "type": "array", 26 | "items": { 27 | "type": "object", 28 | "properties": { 29 | "id": { 30 | "type": "string" 31 | } 32 | }, 33 | "required": [ 34 | "id" 35 | ] 36 | } 37 | } 38 | }, 39 | "required": [ 40 | "@context", 41 | "holderPid", 42 | "credentials", 43 | "type" 44 | ] 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | # Notices for Eclipse Dataspace DCP 2 | 3 | This content is produced and maintained by the Eclipse Decentralized Claims Protocol project. 4 | 5 | ## Trademarks 6 | 7 | Eclipse Decentralized Claims Protocol is a trademark of the Eclipse Foundation. 8 | 9 | ## Copyright 10 | 11 | All content is the property of the respective authors or their employers. For 12 | more information regarding authorship of content, please consult the listed 13 | source code repository logs. 14 | 15 | ## Declared Project Licenses 16 | 17 | This specification project repository uses the following license: 18 | 19 | - XXX 20 | 21 | ## Source Code 22 | 23 | The project maintains the following source code repositories 24 | in the GitHub organization https://github.com/eclipse-dataspace-dcp: 25 | 26 | * https://github.com/eclipse-dataspace-dcp/decentralized-claims-protocol 27 | 28 | ## Third-party Content 29 | 30 | N/A 31 | 32 | ## Cryptography 33 | 34 | Content may contain encryption software. The country in which you are currently 35 | may have restrictions on the import, possession, and use, and/or re-export to 36 | another country, of encryption software. BEFORE using any encryption software, 37 | please check the country's laws, regulations and policies concerning the import, 38 | possession, or use, and re-export of encryption software, to see if this is 39 | permitted. -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/presentation-response-message-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "PresentationResponseMessageSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/PresentationResponseMessage" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/presentation/presentation-response-message-schema.json", 11 | "definitions": { 12 | "PresentationResponseMessage": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "presentation": { 19 | "type": "array", 20 | "items": { 21 | "type": [ 22 | "object", 23 | "string" 24 | ] 25 | } 26 | }, 27 | "presentationSubmission": { 28 | "$ref": "https://identity.foundation/presentation-exchange/schemas/presentation-submission.json#/properties/presentation_submission" 29 | }, 30 | "type": { 31 | "type": "string", 32 | "const": "PresentationResponseMessage" 33 | } 34 | }, 35 | "required": [ 36 | "@context", 37 | "type", 38 | "presentation" 39 | ] 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /artifacts/src/test/resources/claim-format-registry/schemas/presentation-definition-claim-format-designations.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "Presentation Definition Claim Format Designations", 4 | "type": "object", 5 | "additionalProperties": false, 6 | "patternProperties": { 7 | "^jwt$|^jwt_vc$|^jwt_vp$": { 8 | "type": "object", 9 | "additionalProperties": false, 10 | "properties": { 11 | "alg": { 12 | "type": "array", 13 | "minItems": 1, 14 | "items": { 15 | "type": "string" 16 | } 17 | } 18 | } 19 | }, 20 | "^ldp_vc$|^ldp_vp$|^ldp$": { 21 | "type": "object", 22 | "additionalProperties": false, 23 | "properties": { 24 | "proof_type": { 25 | "type": "array", 26 | "minItems": 1, 27 | "items": { 28 | "type": "string" 29 | } 30 | } 31 | } 32 | }, 33 | "^ac_vc$|^ac_vp$": { 34 | "type": "object", 35 | "additionalProperties": false, 36 | "properties": { 37 | "proof_type": { 38 | "type": "array", 39 | "minItems": 1, 40 | "items": { 41 | "type": "string" 42 | } 43 | } 44 | } 45 | }, 46 | "mso_mdoc": { 47 | "type": "object" 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Create a report to improve maturity of the spec! 3 | labels: ["bug", "triage"] 4 | body: 5 | - type: textarea 6 | id: what 7 | attributes: 8 | label: What's wrong? 9 | placeholder: Reasons could be contradictions (internally or to external standards), ambiguities, wrong schema files, writing 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: why 14 | attributes: 15 | label: Why is this a bug? 16 | description: Also tell us, what did you expect to happen? 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: how 21 | attributes: 22 | label: How could it be fixed? 23 | description: Feel free to suggest and weigh several resolution strategies. Omit if obvious. 24 | - type: textarea 25 | id: context 26 | attributes: 27 | label: More context 28 | description: If applicable, add additional info to help explain your problem. 29 | - type: markdown 30 | attributes: 31 | value: | 32 | _Please be sure to take a look at 33 | our [contribution guidelines](https://github.com/eclipse-dataspace-dcp/decentralized-claims-protocol/blob/main/CONTRIBUTING.md) and 34 | our [PR etiquette](https://github.com/eclipse-dataspace-dcp/decentralized-claims-protocol/blob/main/pr_etiquette.md)._ -------------------------------------------------------------------------------- /artifacts/src/main/resources/presentation/presentation-query-message-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "PresentationQueryMessageSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/PresentationQueryMessage" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/presentation/presentation-query-message-schema.json", 11 | "definitions": { 12 | "PresentationQueryMessage": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "type": { 19 | "type": "string", 20 | "const": "PresentationQueryMessage" 21 | }, 22 | "scope": { 23 | "type": "array", 24 | "minItems": 1, 25 | "items": { 26 | "type": "string" 27 | } 28 | }, 29 | "presentationDefinition": { 30 | "type": "object", 31 | "$ref": "https://identity.foundation/presentation-exchange/schemas/presentation-definition.json" 32 | } 33 | }, 34 | "anyOf": [ 35 | { "required": ["scope"] }, 36 | { "required": ["presentationDefinition"] } 37 | ], 38 | "required": [ 39 | "@context", 40 | "type" 41 | ] 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /docs/decision-records/2024-12-12-profiles/README.md: -------------------------------------------------------------------------------- 1 | # Interop Profiles for DCP 2 | 3 | ## Decision 4 | 5 | DCP will define two interop profiles that constrain the VC data model, the revocation system and the proof stack. 6 | 7 | ## Rationale 8 | 9 | In order to provide to implementors a way to establish interoperability without having to define a whole profile, DCP will specify two standard profiles. 10 | These profiles are the "sane defaults" for which DCP will also provide Technology Compatibility Kits. 11 | 12 | ## Approach 13 | 14 | Profiles are defined using an _alias_ that should be indicative of what they contain: 15 | - `vc20+bssl/jwt`: uses VC Data Model 2.0, BitStringStatusList as revocation system and enveloped proofs as JWT 16 | - `vc11+sl2021/jwt`: uses VC Data Model 1.1, StatusList2021 as revocation system and external proofs in the form of JWT 17 | 18 | 19 | In the specification document, the `CredentialObject` will be modified such that the `credentials[].format` and `credentials[].cryptography` properties get collapsed into the `credentials[].profile` property, which should contain the profile alias, e.g. `vc20+bssl/jwt`. 20 | 21 | ## Further notes 22 | 23 | As an added bonus, the specification document should contain a non-normative text passage that outlines, which decisions authors of subsequent profiles need to make, i.e. the minimum set of things a profile descriptions should specify. 24 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/credential-object-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "CredentialObjectSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/CredentialObject" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-object-schema.json", 11 | "definitions": { 12 | "CredentialObject": { 13 | "type": "object", 14 | "properties": { 15 | "id": { 16 | "type": "string", 17 | "format": "uri" 18 | }, 19 | "credentialType": { 20 | "type": "string" 21 | }, 22 | "credentialSchema": { 23 | "type": "string" 24 | }, 25 | "offerReason": { 26 | "type": "string" 27 | }, 28 | "bindingMethods": { 29 | "type": "array", 30 | "items": { 31 | "type": "string" 32 | } 33 | }, 34 | "profile": { 35 | "type": "string" 36 | }, 37 | "issuancePolicy": { 38 | "type": "object", 39 | "$ref": "https://identity.foundation/presentation-exchange/schemas/presentation-definition.json" 40 | }, 41 | "type": { 42 | "type": "string", 43 | "const": "CredentialObject" 44 | } 45 | }, 46 | "required": [ 47 | "id", 48 | "type" 49 | ] 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request Report 2 | description: Tell us about your idea and request a new feature 3 | labels: ["enhancement", "triage"] 4 | body: 5 | - type: textarea 6 | id: what 7 | attributes: 8 | label: What's missing? 9 | placeholder: Describe what the spec should govern but currently doesn't 10 | validations: 11 | required: true 12 | - type: textarea 13 | id: why 14 | attributes: 15 | label: Why should it be in the spec? 16 | description: Explain why this is an issue for DCP specifically. Reasons might be to eliminate ambiguity or take new functionality into scope. 17 | validations: 18 | required: true 19 | - type: textarea 20 | id: where 21 | attributes: 22 | label: Where should this be added? 23 | description: What location in the existing structure could be extended to accommodate the proposed feature? 24 | - type: textarea 25 | id: context 26 | attributes: 27 | label: More context 28 | description: If applicable, add additional info to help explain your problem. 29 | - type: markdown 30 | attributes: 31 | value: | 32 | _Please be sure to take a look at 33 | our [contribution guidelines](https://github.com/eclipse-dataspace-dcp/decentralized-claims-protocol/blob/main/CONTRIBUTING.md) and 34 | our [PR etiquette](https://github.com/eclipse-dataspace-dcp/decentralized-claims-protocol/blob/main/PR_ETIQUETTE.md)._ -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/credential-status-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "CredentialStatusSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/CredentialStatus" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-status-schema.json", 11 | "definitions": { 12 | "CredentialStatusClass": { 13 | "type": "object", 14 | "properties": { 15 | "issuerPid": { 16 | "type": "string" 17 | }, 18 | "holderPid": { 19 | "type": "string" 20 | }, 21 | "status": { 22 | "type": "string", 23 | "enum": [ 24 | "RECEIVED", 25 | "REJECTED", 26 | "ISSUED" 27 | ] 28 | }, 29 | "type": { 30 | "type": "string", 31 | "const": "CredentialStatus" 32 | } 33 | }, 34 | "required": [ 35 | "issuerPid", 36 | "holderPid", 37 | "status", 38 | "type" 39 | ] 40 | }, 41 | "CredentialStatus": { 42 | "type": "object", 43 | "allOf": [ 44 | { 45 | "$ref": "#/definitions/CredentialStatusClass" 46 | }, 47 | { 48 | "properties": { 49 | "@context": { 50 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 51 | } 52 | }, 53 | "required": [ 54 | "@context" 55 | ] 56 | } 57 | ] 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/issuer-metadata-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "IssuerMetadataSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/IssuerMetadata" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/issuance/issuer-metadata-schema.json", 11 | "definitions": { 12 | "IssuerMetadata": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "credentialsSupported": { 19 | "type": "array", 20 | "items": { 21 | "allOf": [ 22 | { 23 | "$ref": "https://w3id.org/dspace-dcp/v1.0/issuance/credential-object-schema.json#/definitions/CredentialObject" 24 | }, 25 | { 26 | "type": "object", 27 | "required": [ 28 | "credentialType", 29 | "credentialSchema", 30 | "offerReason", 31 | "bindingMethods", 32 | "profile" 33 | ] 34 | } 35 | ] 36 | } 37 | }, 38 | "issuer": { 39 | "type": "string" 40 | }, 41 | "type": { 42 | "type": "string", 43 | "const": "IssuerMetadata" 44 | } 45 | }, 46 | "required": [ 47 | "@context", 48 | "issuer", 49 | "credentialsSupported", 50 | "type" 51 | ] 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /artifacts/src/test/resources/presentation-exchange/schemas/presentation-submission.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "Presentation Submission", 4 | "type": "object", 5 | "properties": { 6 | "presentation_submission": { 7 | "type": "object", 8 | "properties": { 9 | "id": { 10 | "type": "string" 11 | }, 12 | "definition_id": { 13 | "type": "string" 14 | }, 15 | "descriptor_map": { 16 | "type": "array", 17 | "items": { 18 | "$ref": "#/definitions/descriptor" 19 | } 20 | } 21 | }, 22 | "required": [ 23 | "id", 24 | "definition_id", 25 | "descriptor_map" 26 | ], 27 | "additionalProperties": false 28 | } 29 | }, 30 | "definitions": { 31 | "descriptor": { 32 | "type": "object", 33 | "properties": { 34 | "id": { 35 | "type": "string" 36 | }, 37 | "path": { 38 | "type": "string" 39 | }, 40 | "path_nested": { 41 | "type": "object", 42 | "$ref": "#/definitions/descriptor" 43 | }, 44 | "format": { 45 | "$ref": "https://identity.foundation/claim-format-registry/schemas/presentation-submission-claim-format-designations.json#/definitions/format" 46 | } 47 | }, 48 | "required": [ 49 | "id", 50 | "path", 51 | "format" 52 | ], 53 | "additionalProperties": false 54 | } 55 | }, 56 | "required": [ 57 | "presentation_submission" 58 | ], 59 | "additionalProperties": false 60 | } -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/context/presentation/PresentationContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.context.presentation; 16 | 17 | import org.eclipse.dcp.context.fixtures.AbstractJsonLdTest; 18 | import org.junit.jupiter.api.Test; 19 | 20 | public class PresentationContextTest extends AbstractJsonLdTest { 21 | 22 | @Test 23 | void verifyPresentationQueryMessage() { 24 | verifyRoundTrip("/presentation/example/presentation-query-message.json", "/presentation/presentation-query-message-schema.json"); 25 | } 26 | 27 | @Test 28 | void verifyPresentationQueryMessage_withPresentationDefinition() { 29 | verifyRoundTrip("/presentation/example/presentation-query-message-w-presentation-definition.json", "/presentation/presentation-query-message-schema.json"); 30 | } 31 | 32 | @Test 33 | void verifyPresentationResponseMessage() { 34 | verifyRoundTrip("/presentation/example/presentation-response-message.json", "/presentation/presentation-response-message-schema.json"); 35 | } 36 | 37 | @Test 38 | void verifyPresentationResponseMessage_withPresentationSubmission() { 39 | verifyRoundTrip("/presentation/example/presentation-response-message-w-presentation-submission.json", "/presentation/presentation-response-message-schema.json"); 40 | } 41 | } -------------------------------------------------------------------------------- /specifications/dsp.profile.md: -------------------------------------------------------------------------------- 1 | # 1. Introduction 2 | 3 | This document defines a profile of 4 | the [Dataspace Protocol Specifications (DSP)](https://github.com/International-Data-Spaces-Association/ids-specification). 5 | 6 | # Catalog Metadata for the __Well-Known__ Endpoint 7 | 8 | Catalogs that support the [Credential Issuance Protocol (CIP)](credential.issuance.protocol.md) MUST return a JSON 9 | object from the `/.well-known/dspace-trust` endpoint with the following properties: 10 | 11 | - `@context`: REQUIRED. Specifies a valid [Json-Ld context](https://www.w3.org/TR/json-ld11/#the-context). 12 | - `credentialsSupported`: REQUIRED. Contains a Json structure corresponding to the schema 13 | specified [below](#the-credentialssupported-object). 14 | 15 | A non-normative example is: 16 | 17 | ```json 18 | { 19 | "@context": [ 20 | ... 21 | ], 22 | "credentialsSupported": [ 23 | { 24 | "types": [ 25 | "VerifiableCredential", 26 | "CompanyCredential" 27 | ], 28 | "bindingMethod": "did:web", 29 | "cryptographicSuite": "JsonWebSignature2020" 30 | } 31 | ] 32 | } 33 | 34 | ``` 35 | 36 | ### The `CredentialsSupported` Object 37 | 38 | The credentials supported contains a single Json Object or an Array of each verifiable credential (VC) supported by the 39 | catalog. The `CredentialsSupported` object contains the following properties: 40 | 41 | - `types`: REQUIRED. An array of verifiable credential type strings the credential corresponds to 42 | - `bindingMethod`: REQUIRED. String that identifies how the credential is bound to the identifier of the 43 | credential holder. 44 | - `profiles` REQUIRED. An array of strings containing the aliases of the [profiles](./dcp.profiles.md), e.g. `"vc20-bssl/jwt"`. 45 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/issuance/credential-message-schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "CredentialMessageSchema", 4 | "type": "object", 5 | "allOf": [ 6 | { 7 | "$ref": "#/definitions/CredentialMessage" 8 | } 9 | ], 10 | "$id": "https://w3id.org/dspace-dcp/v1.0/presentation/credential-message-schema.json", 11 | "definitions": { 12 | "CredentialMessage": { 13 | "type": "object", 14 | "properties": { 15 | "@context": { 16 | "$ref": "https://w3id.org/dspace-dcp/v1.0/common/context-schema.json" 17 | }, 18 | "credentials": { 19 | "type": "array", 20 | "items": { 21 | "$ref": "https://w3id.org/dspace-dcp/v1.0/presentation/credential-message-schema.json#/definitions/CredentialContainer" 22 | } 23 | }, 24 | "issuerPid": { 25 | "type": "string" 26 | }, 27 | "holderPid": { 28 | "type": "string" 29 | }, 30 | "credentialType": { 31 | "type": "string", 32 | "const": "CredentialMessage" 33 | }, 34 | "format": { 35 | "type": "string" 36 | }, 37 | "status": { 38 | "type": "string", 39 | "enum": ["ISSUED", "REJECTED"] 40 | }, 41 | "rejectionReason": { 42 | "type": "string" 43 | } 44 | }, 45 | "required": [ 46 | "@context", 47 | "type", 48 | "issuerPid", 49 | "status" 50 | ] 51 | }, 52 | "CredentialContainer": { 53 | "type": "object", 54 | "properties": { 55 | "payload": { 56 | "type": [ 57 | "string" 58 | ] 59 | }, 60 | "credentialType": { 61 | "type": "string" 62 | }, 63 | "format": { 64 | "type": "string" 65 | } 66 | }, 67 | "required": [ 68 | "payload", 69 | "credentialType", 70 | "format" 71 | ] 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /specifications/terminology.md: -------------------------------------------------------------------------------- 1 | # Terminology 2 | 3 | The following terms are used to describe concepts in this specification. 4 | 5 | - Claim - An assertion made about a [=Subject=]. 6 | - DID - A decentralized identifier as defined by [[[did-core]]]. 7 | - Holder - An entity that possesses a set of identity resources as defined by the [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol). 8 | The holder will typically be the subject of a [=Verifiable Credential=]. 9 | - Issuer - An entity that asserts [=claims=] about one or more subjects by issuing 10 | a [=Verifiable Credential=] to a [=Holder=]. 11 | - Resource - A resource is an entity managed by the Credential Service such as a [=Verifiable Credential=] 12 | or [=Verifiable Presentation=]. 13 | - Subject - The target of a set of claims contained in a [=Verifiable Credential=] as defined 14 | by the [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol). In a dataspace, a subject will be a participant. 15 | - Verifiable Credential A tamper-evident credential 16 | whose authorship can be cryptographically verified as defined by the [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol). 17 | - Verifiable Presentation A tamper-evident 18 | presentation of information whose authorship can be cryptographically verified as defined by [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol). 19 | - Verifiable Data Registry - Maintains identifiers such as [=DIDs=] and [=Verifiable Credential=] schemas in 20 | a dataspace. 21 | - Verifier - An entity that receives a [=Verifiable Credential=], optionally presented inside 22 | a [=Verifiable Presentation=] as defined by the [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol). 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Decentralized Claims Protocol Specification Project 2 | 3 | Thanks for your interest in this project. 4 | 5 | ## Project description 6 | 7 | The Decentralized Claims Protocol is a specification project under the governance of the [Eclipse Dataspace Working 8 | Group](https://www.eclipse.org/org/workinggroups/dataspace-charter.php) (EDWG). 9 | 10 | * https://projects.eclipse.org/projects/technology.dataspace-dcp 11 | 12 | ## Project licenses 13 | 14 | This repository uses the following license: 15 | 16 | * XXX 17 | 18 | ## Terms of Use 19 | 20 | This repository is subject to the Terms of Use of the Eclipse Foundation 21 | 22 | * https://www.eclipse.org/legal/termsofuse.php 23 | 24 | ## Developer resources 25 | 26 | Information regarding source code management, builds, coding standards, and 27 | more. 28 | 29 | * https://projects.eclipse.org/projects/technology.dataspace-dcp/governance 30 | 31 | The project maintains the source code repositories in the following GitHub organization: 32 | 33 | * https://github.com/eclipse-dataspace-dcp 34 | 35 | ## Eclipse Development Process 36 | 37 | This Eclipse Foundation open specification project is governed by the Eclipse Foundation 38 | Development Process and operates under the terms of the Eclipse IP Policy. 39 | 40 | * https://eclipse.org/projects/dev_process 41 | * https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf 42 | 43 | ## Eclipse Contributor Agreement 44 | 45 | In order to be able to contribute to Eclipse Foundation projects you must 46 | electronically sign the Eclipse Contributor Agreement (ECA). 47 | 48 | * http://www.eclipse.org/legal/ECA.php 49 | 50 | The ECA provides the Eclipse Foundation with a permanent record that you agree 51 | that each of your contributions will comply with the commitments documented in 52 | the Developer Certificate of Origin (DCO). Having an ECA on file associated with 53 | the email address matching the "Author" field of your contribution's Git commits 54 | fulfills the DCO's requirement that you sign-off on your contributions. 55 | 56 | For more information, please see the Eclipse Committer Handbook: 57 | https://www.eclipse.org/projects/handbook/#resources-commit 58 | 59 | ## Contact 60 | 61 | Contact the project developers via the project's "dev" list. 62 | 63 | * https://accounts.eclipse.org/mailing-list/dataspace-dcp-dev -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/fixtures/AbstractSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.fixtures; 16 | 17 | import com.networknt.schema.JsonSchema; 18 | import com.networknt.schema.JsonSchemaFactory; 19 | import com.networknt.schema.SchemaLocation; 20 | import com.networknt.schema.ValidationMessage; 21 | 22 | import static com.networknt.schema.SpecVersion.VersionFlag.V202012; 23 | import static org.eclipse.dcp.schema.SchemaConstants.DCP_PREFIX; 24 | 25 | /** 26 | * Base test class. 27 | */ 28 | public abstract class AbstractSchemaTest { 29 | public static final String PRESENTATION_EXCHANGE_PREFIX = "https://identity.foundation/"; 30 | protected static final String MIN_CONTAINS = "minContains"; 31 | protected static final String REQUIRED = "required"; 32 | protected static final String ONE_OF = "oneOf"; 33 | protected static final String TYPE = "type"; 34 | protected static final String ENUM = "enum"; 35 | private static final String CLASSPATH_SCHEMA = "classpath:/"; 36 | protected JsonSchema schema; 37 | 38 | protected void setUp(String schemaFile) { 39 | var schemaFactory = JsonSchemaFactory.getInstance(V202012, builder -> 40 | builder.schemaMappers(schemaMappers -> 41 | schemaMappers.mapPrefix(DCP_PREFIX, CLASSPATH_SCHEMA) 42 | .mapPrefix(PRESENTATION_EXCHANGE_PREFIX, CLASSPATH_SCHEMA)) 43 | ); 44 | 45 | schema = schemaFactory.getSchema(SchemaLocation.of(DCP_PREFIX + schemaFile)); 46 | } 47 | 48 | 49 | 50 | protected SchemaError errorExtractor(ValidationMessage validationMessage) { 51 | return new SchemaError(validationMessage.getProperty(), validationMessage.getType()); 52 | } 53 | 54 | protected SchemaError error(String property, String type) { 55 | return new SchemaError(property, type); 56 | } 57 | 58 | public record SchemaError(String property, String type) { 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /specifications/diagram.styles.puml: -------------------------------------------------------------------------------- 1 | 2 | 3 | !$blue = "#066DFA" 4 | !$gray = "#98A3AB" 5 | !$lightGray = "#F4F5F9" 6 | !$darkGray = "#747C94" 7 | !$green = "#24DCC1" 8 | !$blueFill = "#E4EBFA" 9 | !$greenFill = "#CFFBDE" 10 | !$borderRed = "#F40000" 11 | !$lightRed = "#FDCCCC" 12 | 13 | skinparam sequence { 14 | ArrowColor Black 15 | LifeLineBorderColor 000000 16 | LifeLineBackgroundColor #A9DCDF 17 | } 18 | 19 | skinparam roundCorner 10 20 | 21 | skinparam ArrowColor #000000 22 | skinparam ArrowHeadColor #000000 23 | skinparam LifeLineBackgroundColor $darkGray 24 | 25 | 26 | skinparam CloudBackgroundColor $lightGray 27 | skinparam CloudBorderColor $gray 28 | skinparam CloudFontColor Black 29 | 30 | skinparam ArtifactBackgroundColor $lightGray 31 | skinparam ArtifactBorderColor $gray 32 | 33 | skinparam ComponentBackgroundColor $blueFill 34 | skinparam ComponentBorderColor $blue 35 | skinparam ComponentFontColor Black 36 | 37 | skinparam DatabaseBackgroundColor $greenFill 38 | skinparam DatabaseBorderColor $green 39 | skinparam DatabaseFontColor Black 40 | 41 | skinparam ParticipantBorderColor $blue 42 | skinparam ParticipantBackgroundColor $blueFill 43 | skinparam SequenceGroupBorderColor #DADADA 44 | skinparam SequenceGroupHeaderFontColor #000000 45 | skinparam BoxPadding 20 46 | skinparam ParticipantPadding 10 47 | 48 | skinparam AgentBackgroundColor White 49 | skinparam AgentBackgroundColor $blueFill 50 | skinparam AgentBorderColor #066DFA 51 | skinparam noteBorderColor FEF3BF 52 | skinparam SequenceBoxBorderColor F2F2F2 53 | skinparam shadowing false 54 | skinparam AgentBorderThickness 1 55 | 56 | skinparam NoteBackgroundColor FEFFDD 57 | 58 | skinparam FrameBackgroundColor $lightGray 59 | skinparam FrameBorderColor $lightGray 60 | skinparam FrameFontColor $darkGray 61 | 62 | skinparam ActivityBackgroundColor $blueFill 63 | 64 | skinparam StateBackgroundColor $blueFill 65 | skinparam StateBorderColor $blue 66 | skinparam StateStartColor $blue 67 | skinparam StateEndColor $blue 68 | skinparam StateFontSize 12 69 | 70 | skinparam ActivityBackgroundColor $blueFill 71 | skinparam ActivityBorderColor $blue 72 | skinparam ActivityEndColor $blue 73 | skinparam ActivityStartColor $blue 74 | skinparam ActivityDiamondBackgroundColor $lightGray 75 | skinparam ActivityDiamondBorderColor $blue 76 | 77 | skinparam PartitionBackgroundColor $lightGray 78 | skinparam PartitionBorderColor $darkGray 79 | skinparam PartitionFontColor $darkGray 80 | 81 | skinparam ClassAttributeFontColor Black 82 | skinparam ClassBorderColor $blue 83 | skinparam ClassBackgroundColor $blueFill 84 | -------------------------------------------------------------------------------- /specifications/identity-trust-sts-api.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | paths: 3 | /token: 4 | post: 5 | operationId: token 6 | requestBody: 7 | content: 8 | application/x-www-form-urlencoded: 9 | encoding: 10 | token: 11 | style: form 12 | audience: 13 | style: form 14 | bearer_access_scope: 15 | style: form 16 | client_secret: 17 | style: form 18 | grant_type: 19 | style: form 20 | schema: 21 | type: object 22 | properties: 23 | token: 24 | type: string 25 | description: VP access token to be added as a claim in the SI token 26 | audience: 27 | type: string 28 | description: Audience for the SI token 29 | bearer_access_scope: 30 | type: string 31 | description: Scope to be added in the VP access token 32 | client_id: 33 | type: string 34 | description: Id of the client requesting an SI token 35 | client_secret: 36 | type: string 37 | description: Secret of the client requesting an SI token 38 | grant_type: 39 | type: string 40 | description: "Type of grant: must be set to client_credentials" 41 | required: 42 | - audience 43 | - client_id 44 | - client_secret 45 | - grant_type 46 | responses: 47 | "200": 48 | content: 49 | application/json: 50 | schema: 51 | $ref: '#/components/schemas/StsTokenResponse' 52 | description: The Self-Issued ID token 53 | "400": 54 | content: 55 | application/json: 56 | schema: 57 | type: array 58 | items: 59 | $ref: '#/components/schemas/StsTokenErrorResponse' 60 | description: Invalid Request 61 | tags: 62 | - Secure Token Service Api 63 | components: 64 | schemas: 65 | StsTokenErrorResponse: 66 | type: object 67 | properties: 68 | error: 69 | type: string 70 | error_description: 71 | type: string 72 | StsTokenResponse: 73 | type: object 74 | properties: 75 | access_token: 76 | type: string 77 | expires_in: 78 | type: integer 79 | format: int64 80 | token_type: 81 | type: string 82 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/context/issuance/IssuanceContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.context.issuance; 16 | 17 | import jakarta.json.JsonObject; 18 | import org.eclipse.dcp.context.fixtures.AbstractJsonLdTest; 19 | import org.junit.jupiter.api.Test; 20 | import org.junit.jupiter.params.ParameterizedTest; 21 | import org.junit.jupiter.params.provider.ValueSource; 22 | 23 | import java.io.IOException; 24 | 25 | public class IssuanceContextTest extends AbstractJsonLdTest { 26 | 27 | @Test 28 | void verifyCredentialRequestMessage() { 29 | verifyRoundTrip("/issuance/example/credential-request-message.json", "/issuance/credential-request-message-schema.json"); 30 | } 31 | 32 | @Test 33 | void verifyCredentialMessage() { 34 | verifyRoundTrip("/issuance/example/credential-message.json", "/issuance/credential-message-schema.json"); 35 | } 36 | 37 | @Test 38 | void verifyCredentialMessageRejected() { 39 | verifyRoundTrip("/issuance/example/credential-message-rejected.json", "/issuance/credential-message-schema.json"); 40 | } 41 | 42 | @Test 43 | void verifyCredentialOfferMessage() { 44 | verifyRoundTrip("/issuance/example/credential-offer-message.json", "/issuance/credential-offer-message-schema.json"); 45 | } 46 | 47 | @Test 48 | void verifyCredentialObject() { 49 | verifyRoundTrip("/issuance/example/credential-object.json", "/issuance/credential-object-schema.json"); 50 | } 51 | 52 | @Test 53 | void verifyIssuerMetadata() { 54 | verifyRoundTrip("/issuance/example/issuer-metadata.json", "/issuance/issuer-metadata-schema.json"); 55 | } 56 | 57 | @Test 58 | void verifyCredentialStatus() { 59 | verifyRoundTrip("/issuance/example/credential-status.json", "/issuance/credential-status-schema.json"); 60 | } 61 | 62 | @ParameterizedTest 63 | @ValueSource(strings = { "RECEIVED", "REJECTED", "ISSUED" }) 64 | void verifyCredentialStatus_withStatus(String status) throws IOException { 65 | var msg = """ 66 | { 67 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 68 | "type": "CredentialStatus", 69 | "issuerPid": "issuerPid", 70 | "holderPid": "holderPid", 71 | "status": "%s" 72 | }""".formatted(status); 73 | 74 | var message = mapper.readValue(msg, JsonObject.class); 75 | verifyRoundTrip(message, "/issuance/credential-status-schema.json"); 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/CredentialStatusSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | import org.junit.jupiter.params.ParameterizedTest; 21 | import org.junit.jupiter.params.provider.ValueSource; 22 | 23 | import static com.networknt.schema.InputFormat.JSON; 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | public class CredentialStatusSchemaTest extends AbstractSchemaTest { 27 | 28 | private static final String CREDENTIAL_STATUS = """ 29 | { 30 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 31 | "type": "CredentialStatus", 32 | "issuerPid": "issuerPid", 33 | "holderPid": "holderPid", 34 | "status": "%s" 35 | }"""; 36 | 37 | private static final String INVALID_CREDENTIAL_STATUS = """ 38 | { 39 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 40 | "type": "CredentialStatus" 41 | }"""; 42 | 43 | private static final String INVALID_CREDENTIAL_STATUS_MESSAGE_NO_TYPE_AND_CONTEXT = """ 44 | { 45 | "issuerPid": "issuerPid", 46 | "holderPid": "holderPid", 47 | "status": "RECEIVED" 48 | }"""; 49 | 50 | @Test 51 | void verifySchema() { 52 | assertThat(schema.validate(CREDENTIAL_STATUS.formatted("INVALID_STATUS"), JSON)) 53 | .extracting(this::errorExtractor) 54 | .containsExactly(error(null, ENUM)); 55 | assertThat(schema.validate(INVALID_CREDENTIAL_STATUS, JSON)) 56 | .extracting(this::errorExtractor) 57 | .containsExactly(error("issuerPid", REQUIRED), error("holderPid", REQUIRED), error("status", REQUIRED)); 58 | 59 | assertThat(schema.validate(INVALID_CREDENTIAL_STATUS_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 60 | .hasSize(2) 61 | .extracting(this::errorExtractor) 62 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 63 | } 64 | 65 | @ParameterizedTest 66 | @ValueSource(strings = { "RECEIVED", "REJECTED", "ISSUED" }) 67 | void verifySchemaStatus(String status) { 68 | assertThat(schema.validate(CREDENTIAL_STATUS.formatted(status), JSON)).isEmpty(); 69 | 70 | } 71 | 72 | @BeforeEach 73 | void setUp() { 74 | setUp("/issuance/credential-status-schema.json"); 75 | } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/CredentialOfferMessageSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | import static org.eclipse.dcp.schema.issuance.CredentialObjectSchemaTest.CREDENTIAL_OBJECT; 24 | 25 | public class CredentialOfferMessageSchemaTest extends AbstractSchemaTest { 26 | 27 | private static final String CREDENTIAL_OFFER_MESSAGE = """ 28 | { 29 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 30 | "type": "CredentialOfferMessage", 31 | "issuer": "issuer", 32 | "credentials": [%s] 33 | }"""; 34 | 35 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_CREDENTIAL_ISSUER = """ 36 | { 37 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 38 | "type": "CredentialOfferMessage", 39 | "credentials": [%s] 40 | }"""; 41 | 42 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_CREDENTIALS = """ 43 | { 44 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 45 | "type": "CredentialOfferMessage", 46 | "issuer": "issuer" 47 | }"""; 48 | 49 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT = """ 50 | { 51 | "issuer": "issuer", 52 | "credentials": [%s] 53 | }"""; 54 | 55 | @Test 56 | void verifySchema() { 57 | assertThat(schema.validate(CREDENTIAL_OFFER_MESSAGE.formatted(CREDENTIAL_OBJECT), JSON)).isEmpty(); 58 | 59 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_CREDENTIAL_ISSUER.formatted(CREDENTIAL_OBJECT), JSON)) 60 | .extracting(this::errorExtractor) 61 | .containsExactly(error("issuer", REQUIRED)); 62 | 63 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_CREDENTIALS, JSON)) 64 | .extracting(this::errorExtractor) 65 | .containsExactly(error("credentials", REQUIRED)); 66 | 67 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT.formatted(CREDENTIAL_OBJECT), JSON)) 68 | .hasSize(2) 69 | .extracting(this::errorExtractor) 70 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 71 | } 72 | 73 | @BeforeEach 74 | void setUp() { 75 | setUp("/issuance/credential-offer-message-schema.json"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /artifacts/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/IssuerMetadataSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | import static org.eclipse.dcp.schema.issuance.CredentialObjectSchemaTest.CREDENTIAL_OBJECT; 24 | 25 | public class IssuerMetadataSchemaTest extends AbstractSchemaTest { 26 | 27 | public static final String ISSUER_METADATA = """ 28 | { 29 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 30 | "type": "IssuerMetadata", 31 | "issuer": "did:web:issuer-url", 32 | "credentialsSupported": [%s] 33 | }"""; 34 | public static final String CREDENTIAL_OBJECT_INCOMPLETE = """ 35 | { 36 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 37 | "type": "CredentialObject", 38 | "credentialType": "VerifiableCredential", 39 | "offerReason": "reissue", 40 | "bindingMethods": [ 41 | "did:web" 42 | ] 43 | } 44 | """; 45 | private static final String INVALID_ISSUER_METADATA = """ 46 | { 47 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 48 | "type": "IssuerMetadata" 49 | }"""; 50 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT = """ 51 | { 52 | "issuer": "did:web:issuer-url", 53 | "credentialsSupported": [%s] 54 | }"""; 55 | 56 | @Test 57 | void verifySchema() { 58 | assertThat(schema.validate(ISSUER_METADATA.formatted(CREDENTIAL_OBJECT), JSON)).isEmpty(); 59 | } 60 | 61 | @Test 62 | void verifySchema_missingIssuerAndCredentialsSupported() { 63 | assertThat(schema.validate(INVALID_ISSUER_METADATA, JSON)) 64 | .extracting(this::errorExtractor) 65 | .containsExactly(error("issuer", REQUIRED), error("credentialsSupported", REQUIRED)); 66 | 67 | } 68 | 69 | @Test 70 | void verifySchema_credentialSupportedIsIncomplete() { 71 | assertThat(schema.validate(ISSUER_METADATA.formatted(CREDENTIAL_OBJECT_INCOMPLETE), JSON)) 72 | .extracting(this::errorExtractor) 73 | .containsExactlyInAnyOrder(error("credentialSchema", REQUIRED), error("profile", REQUIRED)); 74 | } 75 | 76 | @Test 77 | void verifySchema_missingTypeAndContext() { 78 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT.formatted(CREDENTIAL_OBJECT), JSON)) 79 | .hasSize(2) 80 | .extracting(this::errorExtractor) 81 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 82 | } 83 | 84 | @BeforeEach 85 | void setUp() { 86 | setUp("/issuance/issuer-metadata-schema.json"); 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /specifications/dataspace.ecosystem.md: -------------------------------------------------------------------------------- 1 | # Dataspace Ecosystem Overview 2 | 3 | This section describes the core actors and systems in a dataspace ecosystem that are pertinent to this specification. It 4 | adheres to the model defined by the Dataspace Protocol [[dsp-base]]: 5 | 6 | - A Dataspace is a policy-based data sharing context between two or more entities. 7 | - The Dataspace Governance Authority is responsible for operational management of a [=dataspace=], 8 | including [=participant=] registration and designation of trust credential issuers. 9 | - A Participant is a member of the [=dataspace=]. Members MAY take on different roles, which are attested to 10 | by verifiable credentials. 11 | - A Participant Agent performs tasks such as publishing a catalog or engaging in data transfer. Note that a 12 | participant agent is a logical construct and does not necessarily correspond to a single runtime process. 13 | - An Identity Provider is a service that generates identity tokens used to verify the identity of a 14 | [=Participant Agent=]. Each [=participant=] will use their own identity provider to generate a self-signed identity 15 | token. 16 | - A Credential Issuer issues [=Verifiable Credentials=] used by [=participant agents=] to allow access to 17 | assets and verify usage control. 18 | 19 | ## Interrelation to the Dataspace Protocol 20 | 21 | The Dataspace Protocol (DSP) [[dsp-base]] is designed as a layered protocol, which is independent of the 22 | identity and trust system used. The Decentralized Claims Protocol fills this gap by providing such an orthogonal 23 | overlay for identity and trust in a decentralized manner. 24 | 25 | ## Systems 26 | 27 | ### Dataspace Governance Authority Systems 28 | 29 | Registration System 30 | 31 | The registration system is responsible for [=participant=] registration, onboarding, and management in a dataspace. 32 | The registration system is run by the [=Dataspace Governance Authority=] and is outside the scope of this specification. 33 | 34 | ### Participant Agent Systems 35 | 36 | [=Participants=] will run one or more agent systems that interact in the dataspace. These systems MAY offer data 37 | catalogs, perform data transfers, or provide application functionality. A [=participant=] MAY run the following 38 | identity-related agents. Note that this is a logical description and MAY not represent an actual deployment topology. 39 | 40 | Security Token Service (STS). 41 | 42 | The STS creates self-issued authorization tokens that contain identity claims used by [=participant agents=] under the 43 | control of the same [=participant=]. 44 | 45 | Credential Service (CS) 46 | 47 | The CS manages [=Verifiable Credentials=]. This includes read and write endpoints for [=Verifiable Presentations=] 48 | and [=Verifiable Credentials=]. 49 | 50 | DID Service (DIDS). 51 | 52 | The DIDS creates, signs, and publishes DID documents. 53 | 54 | ### Credential Issuer Systems 55 | 56 | Issuer Service (IS) 57 | 58 | The Issuer Service is run by a trust anchor and manages the lifecycle of [=Verifiable Credentials=] in a dataspace. A 59 | dataspace MAY contain multiple Issuer Services run by different trust anchors. The Issuer Service: 60 | 61 | - Issues [=Verifiable Credentials=] for dataspace [=participants=]. 62 | - Manages revocation lists for [=Verifiable Credentials=] types it issues based 63 | on [[[vc-bitstring-status-list-20230427]]]. 64 | - Provides cryptographic material used to verify [=Verifiable Presentations=] and [=Verifiable Credentials=]. 65 | -------------------------------------------------------------------------------- /WEBSITE.md: -------------------------------------------------------------------------------- 1 | ## Static Rendering and Web Deployment 2 | 3 | This repository contains the set of artifacts that make up the normative 4 | and non-normative sections of the Decentralized Claims Protocol. All artifacts are 5 | bundled by the [respec framework](https://www.respec.org) which takes care 6 | of rendering a static website. 7 | 8 | ### Conventions 9 | 10 | The following extensions to the basic markdown syntax are used in this 11 | specification project. Keep them handy and navigating the document will 12 | be easy. 13 | 14 | - Referencing an external specification document. [Respec Docs](https://respec.org/docs/#references-0) 15 | - with identifier inline `[[foreign-spec-id]]` 16 | - with the foreign spec's display name inline `[[[foreign-spec-id]]]` 17 | - referencing a particular section in a remote document works via ordinary markdown links. The reference has to be 18 | added to the `References` section manually (if it's not already there). 19 | - Defining terminology: A term is defined by wrapping it in 20 | `Defineable`. [Respec Docs](https://respec.org/docs/#definitions-and-linking) 21 | - Custom section IDs: If various sections have the same heading, they must be given a unique id manually via 22 | `{#my-custom-section-id}` that can then be used for referencing 23 | it. [Respec Docs](https://respec.org/docs/#example-specifying-a-custom-id-for-a-heading) 24 | - Referencing within the document. Please note that despite separation in multiple markdown files, there is only one 25 | html document. References to sections must be flat `(#section)` instead of path-based 26 | `../specifications/verifiable.presentation.protocol.md#presentation-flow`. 27 | - with the sections number and display name inline `[[[#my-section-id]]]` 28 | - If that's not desired, ordinary links work as well. `[my custom link](#my-section-id)` 29 | - referencing terminology: `[=Defineable=]`. This will work out of the box with Plurals such that `[=Definables=]` 30 | refers to the definition of `Defineable`. 31 | - Code blocks work natively like in markdown. 32 | 33 | ### Rendering in your IDE 34 | 35 | 1. Locally execute `mkdir resources` `cp -r ./artifacts/src/main/resources/* resources` from the repository root. 36 | 2. Open the `index.html` file. 37 | 3. Your IDE should have a feature to display html documents (either in your browser of choice or inline). Use that and 38 | you should always see the updated webpage when saving. 39 | 40 | ### Publishing versions 41 | 42 | When wanting to pin and publish a snapshot in time via a separate url-path, follow the appropriate steps listed below. 43 | 44 | #### Prep commits 45 | 46 | When the content is finished, a release requires a first commit with 47 | 48 | 1. a tag with the exact version string (like `v1.0-RC1`) on the release commit 49 | 2. to change the redirect in `.github/scripts/index.html` to point to latest release candidate 50 | 3. set the `respecConfig.publishDate` in `index.html` to a string like `"2025-02-27"`,` 51 | 4. set the `respecConfig.specStatus` in `index.html` to `base` 52 | 53 | In case of versions with a new namespace, additionally: 54 | 55 | 5. adjust the textual description of the context URI in the base spec 56 | 6. appended w3id referrals 57 | 58 | and then (independently of major/minor) a second commit 59 | 60 | 1. setting the specStatus config option to `unofficial` and 61 | 2. increase the spec version in the title of `index.html` 62 | 3. remove the release date 63 | 64 | #### Push and build 65 | 66 | - Open a PR with both commits. Wait for it to be merged. 67 | - Push the tag to origin/main on Github. 68 | - Rerun the actions. 69 | 70 | You should now see an additional endpoint at `https://eclipse-dataspace-dcp.github.io/decentralized-claims-protocol/my-version-tag/`. 71 | -------------------------------------------------------------------------------- /specifications/dcp.profiles.md: -------------------------------------------------------------------------------- 1 | ## Profiles of the Decentralized Claims Protocol 2 | 3 | Different variations of the Verifiable Credentials Data Model, the revocation system, and proof stack 4 | complicate interoperability. Profiles of the DCP specification help 5 | narrow down those possibilities. 6 | 7 | This specification defines two profiles, which are referenced by an alias. 8 | 9 | ## DCP Profile Definitions 10 | 11 | | alias | VC Data Model | Revocation System | Proof Stack | Remarks | 12 | |-------------------|--------------------------------------------------------------|--------------------------------------------------------------------------|----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| 13 | | `vc20-bssl/jwt` | [VC Data Model 2.0](https://www.w3.org/TR/vc-data-model-2.0) | [BitStringStatusList](https://www.w3.org/TR/vc-bitstring-status-list/) | Enveloped proofs [using JWT/JOSE](https://www.w3.org/TR/vc-jose-cose/#with-jose) | Ignore `ttl`, use `validUntil` (*). No JWE supported. The concrete signature algorithm is not specified, as implementors are expected to handle all reasonably well-known crypto algorithms like RSA, EC and EdDSA | 14 | | `vc11-sl2021/jwt` | [VC Data Model 1.1](https://www.w3.org/TR/vc-data-model) | [StatusList2021](https://www.w3.org/TR/2023/WD-vc-status-list-20230427/) | External proofs using JWT | No JWE supported. The concrete signature algorithm is not specified, as implementors are expected to handle all reasonably well-known crypto algorithms like RSA, EC and EdDSA | 15 | 16 | (*) In its current form, the BitStringStatusList credential data 17 | model [conflicts](https://www.w3.org/TR/vc-bitstring-status-list/#bitstringstatuslistcredential) with the VC DataModel 18 | 2.0, specifically regarding the validity period (`ttl` vs `validUntil`). 19 | 20 | ### Homogeneity requirement 21 | 22 | Verifiable Credentials MUST be _homogenous_. This means the 23 | same data model version and proof mechanism MUST be used for both credentials and presentations. For example, a 24 | verifiable credential secured with an _enveloped proof_ using 25 | JOSE ([VC Data Model 2.0](https://www.w3.org/TR/vc-jose-cose/#with-jose)) is enclosed in a verifiable presentation 26 | that is also secured with JWT/JOSE. 27 | 28 | Heterogeneous sets of credentials MUST be enclosed in multiple presentations such that each presentation only 29 | contains credentials of the same data model and proof mechanism. 30 | 31 | ## Profile Authoring Recommendations 32 | 33 | This non-normative section is intended to provide guidance to authors who want to define their own profile definition. 34 | 35 | At a minimum, the following profile aspects MUST be defined: 36 | 37 | - Verifiable Credential Data Model. 38 | - Revocation System. Specifies how the validity and expiration of Verifiable Credentials is checked. 39 | - Proof stack. Specifies how data integrity of the VC is to be provided. 40 | 41 | In addition, the profile MAY be further constrained, for example, by limiting the number of acceptable cryptographic 42 | algorithms. 43 | 44 | If possible, a single credential format SHOULD be used when defining a profile. -------------------------------------------------------------------------------- /specifications/issuer-holder-verifier-model.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Verifiable Data Registry 4 | Maintains identifiers and schemas 5 | Verify identifiers and use schemas 6 | 7 | 8 | Verifier 9 | Verifies VCs 10 | Register identifiers and use schemas 11 | 12 | 13 | Holder 14 | Acquires and presents VCs 15 | Verify identifiers and use schemas 16 | 17 | Issue credentials 18 | 19 | Present credentials 20 | 21 | 22 | Issuer 23 | Issues VCs 24 | 25 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/presentation/PresentationResponseMessageSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.presentation; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | public class PresentationResponseMessageSchemaTest extends AbstractSchemaTest { 25 | 26 | private static final String PRESENTATION_RESPONSE_MESSAGE = """ 27 | { 28 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 29 | "type": "PresentationResponseMessage", 30 | "presentation": ["presentation1", "presentation2"] 31 | }"""; 32 | 33 | private static final String PRESENTATION_RESPONSE_MESSAGE_WITH_OBJECT = """ 34 | { 35 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 36 | "type": "PresentationResponseMessage", 37 | "presentation": ["presentation1", {"@id": "presentation2"}] 38 | }"""; 39 | 40 | private static final String PRESENTATION_RESPONSE_MESSAGE_WITH_PRESENTATION_SUBMISSION = """ 41 | { 42 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 43 | "type": "PresentationResponseMessage", 44 | "presentation": ["presentation1"], 45 | "presentationSubmission": { 46 | "id": "id", 47 | "definition_id": "definition_id", 48 | "descriptor_map": [] 49 | } 50 | }"""; 51 | 52 | private static final String INVALID_PRESENTATION_RESPONSE_MESSAGE_NO_PRESENTATION = """ 53 | { 54 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 55 | "type": "PresentationResponseMessage" 56 | }"""; 57 | 58 | private static final String INVALID_PRESENTATION_RESPONSE_MESSAGE_NO_TYPE_AND_CONTEXT = """ 59 | { 60 | "presentation": ["presentation1", "presentation2"] 61 | }"""; 62 | 63 | private static final String INVALID_PRESENTATION_RESPONSE_MESSAGE_EMPTY_PRESENTATION_SUBMISSION = """ 64 | { 65 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 66 | "type": "PresentationResponseMessage", 67 | "presentation": ["presentation1"], 68 | "presentationSubmission": { 69 | 70 | } 71 | }"""; 72 | 73 | @Test 74 | void verifySchema() { 75 | assertThat(schema.validate(PRESENTATION_RESPONSE_MESSAGE, JSON)).isEmpty(); 76 | assertThat(schema.validate(PRESENTATION_RESPONSE_MESSAGE_WITH_OBJECT, JSON)).isEmpty(); 77 | assertThat(schema.validate(PRESENTATION_RESPONSE_MESSAGE_WITH_PRESENTATION_SUBMISSION, JSON)).isEmpty(); 78 | assertThat(schema.validate(INVALID_PRESENTATION_RESPONSE_MESSAGE_NO_PRESENTATION, JSON)) 79 | .extracting(this::errorExtractor) 80 | .containsExactly(error("presentation", REQUIRED)); 81 | 82 | assertThat(schema.validate(INVALID_PRESENTATION_RESPONSE_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 83 | .hasSize(2) 84 | .extracting(this::errorExtractor) 85 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 86 | 87 | assertThat(schema.validate(INVALID_PRESENTATION_RESPONSE_MESSAGE_EMPTY_PRESENTATION_SUBMISSION, JSON)) 88 | .hasSize(3) 89 | .extracting(this::errorExtractor) 90 | .contains(error("id", REQUIRED), error("definition_id", REQUIRED), error("descriptor_map", REQUIRED)); 91 | 92 | } 93 | 94 | @BeforeEach 95 | void setUp() { 96 | setUp("/presentation/presentation-response-message-schema.json"); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /pr_etiquette.md: -------------------------------------------------------------------------------- 1 | # Etiquette for pull requests 2 | 3 | Typically, changes to the specification documents should be made by 4 | the [editors](#the-designated-editors-as-of-sept-21-2023), as it is their duty to ensure consistency and proper 5 | linguistic properties. However, if you want to raise pull-requests of your own, please be sure to carefully read the 6 | following sections, and adhere to the rules stated therein. Failing to do so may result in the rejection of your PR. 7 | 8 | ## As an author 9 | 10 | Submitting pull requests in EDC should be done while adhering to a couple of simple rules. 11 | 12 | - Familiarize yourself with the contribution guidelines. 13 | - No surprise PRs please. Before you submit a PR, open a discussion or an issue outlining your planned work and give 14 | people time to comment. It may even be advisable to contact committers using the `@mention` feature. Unsolicited PRs 15 | may get ignored or rejected. 16 | - Don't argue basic principles ("Why don't we use X instead of Y", "how-about-ism") 17 | - Create your working branch in your fork of this repository, and create the PR against the upstream `main` branch 18 | - Create focused PRs: your work should be focused on one particular feature or bug. Do not create broad-scoped PRs that 19 | solve multiple issues as reviewers may reject those PR bombs outright. 20 | - Provide a clear description and motivation in the PR description in GitHub. This makes the reviewer's life much 21 | easier. It is also helpful to outline the broad changes that were made, e.g. "Changes the wording of XYZ-Entity: 22 | use `XYZ` instead of `ABC`". 23 | - All CI checks should be green, especially when your PR is in `"Ready for review"` 24 | - Mark PRs as `"Ready for review"` only when you're prepared to defend your work. By that time you have completed your 25 | work and shouldn't need to push any more commits other than to incorporate review comments. 26 | - Merge conflicts should be resolved by squashing all commits on the PR branch, rebasing onto `main` and 27 | force-pushing. Do this when your PR is ready to review. 28 | - If you require a reviewer's input while it's still in draft, please contact the designated reviewer using 29 | the `@mention` feature and let them know what you'd like them to look at. 30 | - Request a review from one of the committers. Requesting a review from anyone else is still possible, and 31 | sometimes may be advisable, but only committers can merge PRs, so be sure to include them early on. 32 | - Re-request reviews after all remarks have been adopted. This helps reviewers track their work in GitHub. 33 | - If you disagree with a committer's remarks, feel free to object and argue, but if no agreement is reached, you'll have 34 | to either accept the decision or withdraw your PR. 35 | - Be civil and objective. No foul language, insulting or otherwise abusive language will be tolerated. 36 | - The PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). 37 | - The title must follow the format as `(): `. 38 | `build`, `chore`, `ci`, `docs`, `feat`, `fix`, `perf`, `refactor`, `revert`, `style`, `test` are allowed for 39 | the ``. 40 | - The length must be kept under 80 characters. 41 | 42 | ## As a reviewer 43 | 44 | - Please complete reviews within two business days or delegate to another committer, removing yourself as a reviewer. 45 | - If you have been requested as reviewer, but cannot do the review for any reason (lack of time or expertise in a 46 | particular area, etc.) please comment that in the PR and remove yourself as a reviewer, suggesting a stand-in. 47 | - Be pedantic. This is a normative document, so wording, terminology and general formulation are important. 48 | - Don't get dragged into basic arguments ("how-about-ism") 49 | - Use the `suggestion` feature of GitHub for small/simple changes. 50 | - The following could serve you as a review checklist: 51 | - writing style, wording 52 | - simplicity and "uncluttered-ness" of the text 53 | - overall focus of the PR 54 | - Don't just wave through any PR. Please take the time to look at them carefully. 55 | - Be civil and objective. No foul language, insulting or otherwise abusive language will be tolerated. The goal is to 56 | _encourage_ contributions. 57 | 58 | ## The designated editors (as of Sept 21, 2023) 59 | 60 | - Jim Marino (@jimmarino) 61 | 62 | ## Responsible committers 63 | 64 | [Who's involved](https://projects.eclipse.org/projects/technology.dataspace-dcp/who) 65 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/CredentialObjectSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | public class CredentialObjectSchemaTest extends AbstractSchemaTest { 25 | 26 | public static final String CREDENTIAL_OBJECT = """ 27 | { 28 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 29 | "type": "CredentialObject", 30 | "credentialType": "VerifiableCredential", 31 | "credentialSchema": "https://example.com/credentials/credentialSchema", 32 | "offerReason": "reissue", 33 | "bindingMethods": [ 34 | "did:web" 35 | ], 36 | "profile": "vc20-bssl/jwt", 37 | "issuancePolicy": { 38 | "id": "Scalable trust example", 39 | "input_descriptors": [ 40 | { 41 | "id": "pd-id", 42 | "constraints": { 43 | "fields": [ 44 | { 45 | "path": [ 46 | "$.holderIdentifier" 47 | ], 48 | "filter": { 49 | "type": "string", 50 | "pattern": "^BPN[LS][a-zA-Z0-9]{12}$" 51 | } 52 | } 53 | ] 54 | } 55 | } 56 | ] 57 | } 58 | } 59 | """; 60 | 61 | private static final String INVALID_CREDENTIAL_OBJECT = """ 62 | { 63 | "type": "CredentialObject" 64 | }"""; 65 | 66 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT = """ 67 | { 68 | "id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1", 69 | "credentialType": "VerifiableCredential", 70 | "offerReason": "reissue", 71 | "bindingMethods": [ 72 | "did:web" 73 | ], 74 | "profile":"vc20-bssl/jwt", 75 | "issuancePolicy": { 76 | "id": "Scalable trust example", 77 | "input_descriptors": [ 78 | { 79 | "id": "pd-id", 80 | "constraints": { 81 | "fields": [ 82 | { 83 | "path": [ 84 | "$.vc.type" 85 | ], 86 | "filter": { 87 | "type": "string", 88 | "pattern": "^AttestationCredential$" 89 | } 90 | } 91 | ] 92 | } 93 | } 94 | ] 95 | } 96 | }"""; 97 | 98 | @Test 99 | void verifySchema() { 100 | assertThat(schema.validate(CREDENTIAL_OBJECT, JSON)).isEmpty(); 101 | } 102 | 103 | @Test 104 | void verifySchema_missingRequiredFields() { 105 | assertThat(schema.validate(INVALID_CREDENTIAL_OBJECT, JSON)) 106 | .extracting(this::errorExtractor) 107 | .containsExactly( 108 | error("id", REQUIRED)); 109 | } 110 | 111 | @Test 112 | void verifySchema_missingTypeAndContext() { 113 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 114 | .hasSize(1) 115 | .extracting(this::errorExtractor) 116 | .contains(error("type", REQUIRED)); 117 | 118 | } 119 | 120 | @BeforeEach 121 | void setUp() { 122 | setUp("/issuance/credential-object-schema.json"); 123 | } 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /artifacts/src/main/resources/context/dcp.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@version": 1.1, 4 | "@protected": true, 5 | "dcp": "https://w3id.org/dspace-dcp/v1.0/", 6 | "cred": "https://www.w3.org/2018/credentials#", 7 | "xsd": "http://www.w3.org/2001/XMLSchema#", 8 | "id": "@id", 9 | "type": "@type", 10 | "CredentialContainer": { 11 | "@id": "dcp:CredentialContainer", 12 | "@context": { 13 | "payload": { 14 | "@id": "dcp:payload", 15 | "@type": "xsd:string" 16 | } 17 | } 18 | }, 19 | "CredentialMessage": { 20 | "@id": "dcp:CredentialMessage", 21 | "@context": { 22 | "credentials": { 23 | "@id": "dcp:credentials", 24 | "@container": "@set", 25 | "@type": "@json" 26 | }, 27 | "issuerPid": { 28 | "@id": "dcp:issuerPid", 29 | "@type": "@id" 30 | }, 31 | "holderPid": { 32 | "@id": "dcp:holderPid", 33 | "@type": "@id" 34 | }, 35 | "status": { 36 | "@id": "dcp:status", 37 | "@type": "@id" 38 | }, 39 | "rejectionReason": { 40 | "@id": "dcp:rejectionReason" 41 | } 42 | } 43 | }, 44 | "CredentialObject": { 45 | "@id": "dcp:CredentialObject", 46 | "@context": { 47 | "credentialType": { 48 | "@id": "dcp:credentialType" 49 | }, 50 | "credentialSchema": { 51 | "@id": "dcp:credentialSchema" 52 | }, 53 | "offerReason": { 54 | "@id": "dcp:offerReason", 55 | "@type": "xsd:string" 56 | }, 57 | "bindingMethods": { 58 | "@id": "dcp:bindingMethods", 59 | "@type": "xsd:string", 60 | "@container": "@set" 61 | }, 62 | "profile": { 63 | "@id": "dcp:profile", 64 | "@type": "xsd:string" 65 | }, 66 | "issuancePolicy": { 67 | "@id": "dcp:issuancePolicy", 68 | "@type": "@json" 69 | } 70 | } 71 | }, 72 | "CredentialOfferMessage": { 73 | "@id": "dcp:CredentialOfferMessage", 74 | "@context": { 75 | "issuer": { 76 | "@id": "cred:issuer", 77 | "@type": "@id" 78 | }, 79 | "credentials": { 80 | "@id": "dcp:credentials", 81 | "@container": "@set" 82 | } 83 | } 84 | }, 85 | "CredentialRequestMessage": { 86 | "@id": "dcp:CredentialRequestMessage", 87 | "@context": { 88 | "holderPid": { 89 | "@id": "dcp:holderPid", 90 | "@type": "@id" 91 | }, 92 | "credentials": { 93 | "@id": "dcp:credentials", 94 | "@type": "@json" 95 | } 96 | } 97 | }, 98 | "CredentialService": "dcp:CredentialService", 99 | "CredentialStatus": { 100 | "@id": "dcp:CredentialStatus", 101 | "@context": { 102 | "holderPid": { 103 | "@id": "dcp:holderPid", 104 | "@type": "@id" 105 | }, 106 | "issuerPid": { 107 | "@id": "dcp:issuerPid", 108 | "@type": "@id" 109 | }, 110 | "status": { 111 | "@id": "dcp:status", 112 | "@type": "@vocab" 113 | }, 114 | "RECEIVED": "dcp:RECEIVED", 115 | "REJECTED": "dcp:REJECTED", 116 | "ISSUED": "dcp:ISSUED" 117 | } 118 | }, 119 | "IssuerMetadata": { 120 | "@id": "dcp:IssuerMetadata", 121 | "@context": { 122 | "issuer": { 123 | "@id": "cred:issuer", 124 | "@type": "@id" 125 | }, 126 | "credentialsSupported": { 127 | "@id": "dcp:credentialsSupported", 128 | "@container": "@set" 129 | } 130 | } 131 | }, 132 | "IssuerService": "dcp:IssuerService", 133 | "PresentationQueryMessage": { 134 | "@id": "dcp:PresentationQueryMessage", 135 | "@context": { 136 | "presentationDefinition": { 137 | "@id": "dcp:presentationDefinition", 138 | "@type": "@json" 139 | }, 140 | "scope": { 141 | "@id": "dcp:scope", 142 | "@type": "xsd:string", 143 | "@container": "@set" 144 | } 145 | } 146 | }, 147 | "PresentationResponseMessage": { 148 | "@id": "dcp:PresentationResponseMessage", 149 | "@context": { 150 | "presentation": { 151 | "@id": "dcp:presentation", 152 | "@container": "@set", 153 | "@type": "@json" 154 | }, 155 | "presentationSubmission": { 156 | "@id": "dcp:presentationSubmission", 157 | "@type": "@json" 158 | } 159 | } 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/CredentialRequestMessageSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | public class CredentialRequestMessageSchemaTest extends AbstractSchemaTest { 25 | 26 | private static final String CREDENTIAL_REQUEST_MESSAGE = """ 27 | { 28 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 29 | "type": "CredentialRequestMessage", 30 | "holderPid": "holderPid", 31 | "credentials": [ 32 | {"id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1" }, 33 | {"id": "c0f81e68-6d35-4f9d-bc04-51e511b2e46c" } 34 | ] 35 | }"""; 36 | 37 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_HOLDER_REQUEST_ID = """ 38 | { 39 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 40 | "type": "CredentialRequestMessage", 41 | "credentials": [ 42 | {"id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1" }, 43 | {"id": "c0f81e68-6d35-4f9d-bc04-51e511b2e46c" } 44 | ] 45 | }"""; 46 | 47 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_ID_NOT_STRING = """ 48 | { 49 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 50 | "type": "CredentialRequestMessage", 51 | "holderPid": "holderPid", 52 | "credentials": [ 53 | { "id": 42069 }, 54 | { "id": 4711 } 55 | ] 56 | }"""; 57 | 58 | 59 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_EMPTY_ARRAY = """ 60 | { 61 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 62 | "type": "CredentialRequestMessage", 63 | "holderPid": "holderPid", 64 | "credentials": [ 65 | ] 66 | }"""; 67 | 68 | private static final String INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT = """ 69 | { 70 | "holderPid": "holderPid", 71 | "credentials": [ 72 | {"id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1" }, 73 | {"id": "c0f81e68-6d35-4f9d-bc04-51e511b2e46c" } 74 | ] 75 | }"""; 76 | 77 | private static final String CREDENTIAL_REQUEST_MESSAGE_NO_FORMAT = """ 78 | { 79 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 80 | "type": "CredentialRequestMessage", 81 | "holderPid": "holderPid", 82 | "credentials": [ 83 | {"id": "d5c77b0e-7f4e-4fd5-8c5f-28b5fc3f96d1" }, 84 | {"id": "c0f81e68-6d35-4f9d-bc04-51e511b2e46c" } 85 | ] 86 | }"""; 87 | 88 | 89 | @Test 90 | void verifySchema() { 91 | assertThat(schema.validate(CREDENTIAL_REQUEST_MESSAGE, JSON)).isEmpty(); 92 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_EMPTY_ARRAY, JSON)) 93 | .isEmpty(); 94 | 95 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_HOLDER_REQUEST_ID, JSON)) 96 | .extracting(this::errorExtractor) 97 | .containsExactly(error("holderPid", REQUIRED)); 98 | 99 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_ID_NOT_STRING, JSON)) 100 | .extracting(this::errorExtractor) 101 | .containsExactly(error(null, TYPE), error(null, TYPE)); 102 | 103 | assertThat(schema.validate(INVALID_CREDENTIAL_REQUEST_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 104 | .hasSize(2) 105 | .extracting(this::errorExtractor) 106 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 107 | 108 | } 109 | 110 | @BeforeEach 111 | void setUp() { 112 | setUp("/issuance/credential-request-message-schema.json"); 113 | } 114 | 115 | 116 | } 117 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/presentation/PresentationQueryMessageSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.presentation; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | public class PresentationQueryMessageSchemaTest extends AbstractSchemaTest { 25 | 26 | private static final String PRESENTATION_QUERY_MESSAGE = """ 27 | { 28 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 29 | "type": "PresentationQueryMessage", 30 | "scope": ["scope1", "scope2"] 31 | }"""; 32 | 33 | private static final String PRESENTATION_QUERY_MESSAGE_WITH_PRESENTATION_DEF = """ 34 | { 35 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 36 | "type": "PresentationQueryMessage", 37 | "presentationDefinition": { 38 | "id": "presentation1", 39 | "input_descriptors": [ 40 | { 41 | "id": "organization credential", 42 | "format": { 43 | "ldp_vc": { 44 | "proof_type": [ 45 | "Ed25519Signature2018" 46 | ] 47 | } 48 | }, 49 | "constraints": { 50 | "fields": [ 51 | { 52 | "path": [ 53 | "$.type" 54 | ], 55 | "filter": { 56 | "type": "string", 57 | "pattern": "OrganizationCredential" 58 | } 59 | } 60 | ] 61 | } 62 | } 63 | ] 64 | } 65 | }"""; 66 | 67 | private static final String INVALID_PRESENTATION_QUERY_MESSAGE_NO_SCOPE = """ 68 | { 69 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 70 | "type": "PresentationQueryMessage" 71 | }"""; 72 | 73 | private static final String INVALID_PRESENTATION_QUERY_MESSAGE_EMPTY_SCOPE = """ 74 | { 75 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 76 | "type": "PresentationQueryMessage", 77 | "scope": [] 78 | }"""; 79 | 80 | 81 | private static final String INVALID_PRESENTATION_QUERY_MESSAGE_NO_TYPE_AND_CONTEXT = """ 82 | { 83 | "scope": ["scope1", "scope2"] 84 | }"""; 85 | 86 | @Test 87 | void verifySchema() { 88 | assertThat(schema.validate(PRESENTATION_QUERY_MESSAGE, JSON)).isEmpty(); 89 | } 90 | 91 | @Test 92 | void verifySchemaWithPresentationDefinition() { 93 | assertThat(schema.validate(PRESENTATION_QUERY_MESSAGE_WITH_PRESENTATION_DEF, JSON)).isEmpty(); 94 | } 95 | 96 | @Test 97 | void verifySchema_withNoTypeAndContext() { 98 | assertThat(schema.validate(INVALID_PRESENTATION_QUERY_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 99 | .hasSize(2) 100 | .extracting(this::errorExtractor) 101 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 102 | } 103 | 104 | @Test 105 | void verifySchema_withEmptyScope() { 106 | assertThat(schema.validate(INVALID_PRESENTATION_QUERY_MESSAGE_EMPTY_SCOPE, JSON)) 107 | .hasSize(1) 108 | .anyMatch(msg -> msg.getInstanceLocation().toString().endsWith("scope") && 109 | msg.getType().equalsIgnoreCase("minItems")); 110 | } 111 | 112 | @Test 113 | void verifySchema_withNoScope() { 114 | assertThat(schema.validate(INVALID_PRESENTATION_QUERY_MESSAGE_NO_SCOPE, JSON)) 115 | .extracting(this::errorExtractor) 116 | .contains(error("scope", REQUIRED), error("presentationDefinition", REQUIRED)); 117 | } 118 | 119 | @BeforeEach 120 | void setUp() { 121 | setUp("/presentation/presentation-query-message-schema.json"); 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/context/fixtures/AbstractJsonLdTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.context.fixtures; 16 | 17 | import com.apicatalog.jsonld.JsonLdError; 18 | import com.apicatalog.jsonld.JsonLdOptions; 19 | import com.apicatalog.jsonld.document.Document; 20 | import com.apicatalog.jsonld.document.JsonDocument; 21 | import com.apicatalog.jsonld.loader.DocumentLoader; 22 | import com.apicatalog.jsonld.loader.DocumentLoaderOptions; 23 | import com.fasterxml.jackson.databind.JsonNode; 24 | import com.fasterxml.jackson.databind.ObjectMapper; 25 | import com.fasterxml.jackson.datatype.jsonp.JSONPModule; 26 | import com.networknt.schema.JsonSchemaFactory; 27 | import com.networknt.schema.SchemaLocation; 28 | import jakarta.json.Json; 29 | import jakarta.json.JsonObject; 30 | import jakarta.json.JsonStructure; 31 | import org.junit.jupiter.api.BeforeEach; 32 | 33 | import java.io.IOException; 34 | import java.net.URI; 35 | import java.util.HashMap; 36 | import java.util.Map; 37 | 38 | import static com.apicatalog.jsonld.JsonLd.compact; 39 | import static com.apicatalog.jsonld.JsonLd.expand; 40 | import static com.apicatalog.jsonld.lang.Keywords.CONTEXT; 41 | import static com.networknt.schema.SpecVersion.VersionFlag.V202012; 42 | import static java.lang.String.format; 43 | import static org.assertj.core.api.Assertions.assertThat; 44 | import static org.eclipse.dcp.schema.SchemaConstants.DCP_CONTEXT; 45 | import static org.eclipse.dcp.schema.SchemaConstants.DCP_PREFIX; 46 | import static org.eclipse.dcp.schema.fixtures.AbstractSchemaTest.PRESENTATION_EXCHANGE_PREFIX; 47 | 48 | /** 49 | * Base class for Json-Ld expansion and compaction tests. 50 | */ 51 | public abstract class AbstractJsonLdTest { 52 | private static final String CLASSPATH_SCHEMA = "classpath:/"; 53 | private static final String CONTEXT_REFERENCE = format("{\"@context\": [\"%s\"]}", DCP_CONTEXT); 54 | private final Map contextMap = Map.of( 55 | DCP_CONTEXT, "/context/dcp.jsonld", 56 | "https://www.w3.org/ns/odrl.jsonld", "/context/odrl.jsonld" 57 | ); 58 | protected ObjectMapper mapper; 59 | protected JsonStructure compactionContext; 60 | protected JsonLdOptions options; 61 | 62 | @BeforeEach 63 | void setUp() { 64 | mapper = new ObjectMapper(); 65 | mapper.registerModule(new JSONPModule()); 66 | 67 | Map cache = new HashMap<>(); 68 | 69 | contextMap.forEach((key, value) -> { 70 | try (var stream = getClass().getResourceAsStream(value)) { 71 | var context = mapper.readValue(stream, JsonObject.class); 72 | cache.put(key, JsonDocument.of(context)); 73 | } catch (IOException e) { 74 | throw new RuntimeException(e); 75 | } 76 | }); 77 | try { 78 | var documentLoader = new LocalDocumentLoader(cache); 79 | compactionContext = mapper.readValue(CONTEXT_REFERENCE, JsonStructure.class); 80 | options = new JsonLdOptions(); 81 | options.setDocumentLoader(documentLoader); 82 | } catch (IOException e) { 83 | throw new RuntimeException(e); 84 | } 85 | 86 | } 87 | 88 | protected void verifyRoundTrip(String jsonFile, String schemaFile) { 89 | try { 90 | var stream = getClass().getResourceAsStream(jsonFile); 91 | var message = mapper.readValue(stream, JsonObject.class); 92 | verifyRoundTrip(message, schemaFile); 93 | } catch (IOException e) { 94 | throw new RuntimeException(e); 95 | } 96 | } 97 | 98 | protected void verifyRoundTrip(JsonObject message, String schemaFile) { 99 | try { 100 | var schemaFactory = JsonSchemaFactory.getInstance(V202012, builder -> 101 | builder.schemaMappers(schemaMappers -> schemaMappers.mapPrefix(DCP_PREFIX, CLASSPATH_SCHEMA) 102 | .mapPrefix(PRESENTATION_EXCHANGE_PREFIX, CLASSPATH_SCHEMA)) 103 | ); 104 | var schema = schemaFactory.getSchema(SchemaLocation.of(DCP_PREFIX + schemaFile)); 105 | var resultExAnte = schema.validate(mapper.convertValue(message, JsonNode.class)); 106 | assertThat(resultExAnte.isEmpty()).describedAs(String.join(", ", resultExAnte.stream().map(Object::toString).toList())).isTrue(); 107 | 108 | 109 | var context = Json.createObjectBuilder().add(CONTEXT, message.get(CONTEXT)).build(); 110 | var expanded = expand(JsonDocument.of(message)).options(options).get(); 111 | var compacted = compact(JsonDocument.of(expanded), JsonDocument.of(context)).options(options).get(); 112 | 113 | 114 | var resultExPost = schema.validate(mapper.convertValue(compacted, JsonNode.class)); 115 | assertThat(resultExPost.isEmpty()).describedAs(String.join(", ", resultExPost.stream().map(Object::toString).toList())).isTrue(); 116 | assertThat(compacted).isEqualTo(message); 117 | } catch (JsonLdError e) { 118 | throw new RuntimeException(e); 119 | } 120 | } 121 | 122 | private static class LocalDocumentLoader implements DocumentLoader { 123 | private final Map contexts = new HashMap<>(); 124 | 125 | LocalDocumentLoader(Map contexts) { 126 | this.contexts.putAll(contexts); 127 | } 128 | 129 | @Override 130 | public Document loadDocument(URI url, DocumentLoaderOptions options) { 131 | return contexts.get(url.toString()); 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /artifacts/src/test/java/org/eclipse/dcp/schema/issuance/CredentialMessageSchemaTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Metaform Systems, Inc. 3 | * 4 | * This program and the accompanying materials are made available under the 5 | * terms of the Apache License, Version 2.0 which is available at 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Contributors: 11 | * Metaform Systems, Inc. - initial API and implementation 12 | * 13 | */ 14 | 15 | package org.eclipse.dcp.schema.issuance; 16 | 17 | import org.eclipse.dcp.schema.fixtures.AbstractSchemaTest; 18 | import org.junit.jupiter.api.BeforeEach; 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static com.networknt.schema.InputFormat.JSON; 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | public class CredentialMessageSchemaTest extends AbstractSchemaTest { 25 | 26 | private static final String CREDENTIAL_MESSAGE_MESSAGE = """ 27 | { 28 | "@context": [ 29 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 30 | ], 31 | "type": "CredentialMessage", 32 | "credentials": [ 33 | { 34 | "credentialType": "MembershipCredential", 35 | "payload": "", 36 | "format": "jwt" 37 | }, 38 | { 39 | "credentialType": "OrganizationCredential", 40 | "payload": "", 41 | "format": "json-ld" 42 | } 43 | ], 44 | "status": "ISSUED", 45 | "issuerPid": "issuerPid", 46 | "holderPid": "holderPid" 47 | }"""; 48 | 49 | private static final String CREDENTIAL_MESSAGE_MESSAGE_WRONG_STATUS = """ 50 | { 51 | "@context": [ 52 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 53 | ], 54 | "type": "CredentialMessage", 55 | "credentials": [ 56 | { 57 | "credentialType": "MembershipCredential", 58 | "payload": "", 59 | "format": "jwt" 60 | }, 61 | { 62 | "credentialType": "OrganizationCredential", 63 | "payload": "", 64 | "format": "json-ld" 65 | } 66 | ], 67 | "status": "INVALID", 68 | "issuerPid": "issuerPid", 69 | "holderPid": "holderPid" 70 | }"""; 71 | 72 | private static final String CREDENTIAL_MESSAGE_MESSAGE_REJECTION = """ 73 | { 74 | "@context": [ 75 | "https://w3id.org/dspace-dcp/v1.0/dcp.jsonld" 76 | ], 77 | "type": "CredentialMessage", 78 | "status": "REJECTED", 79 | "rejectionReason": "some rejection reason", 80 | "issuerPid": "issuerPid", 81 | "holderPid": "holderPid" 82 | }"""; 83 | 84 | private static final String INVALID_CREDENTIAL_MESSAGE = """ 85 | { 86 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 87 | "type": "CredentialMessage", 88 | "status": "ISSUED" 89 | }"""; 90 | 91 | private static final String INVALID_CREDENTIAL_MESSAGE_INVALID_CREDENTIAL_CONTAINER = """ 92 | { 93 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 94 | "type": "CredentialMessage", 95 | "credentials": [ 96 | { 97 | "credentialType": "MembershipCredential", 98 | "format": "jwt" 99 | } 100 | ], 101 | "status": "ISSUED", 102 | "issuerPid": "issuerPid", 103 | "holderPid": "holderPid" 104 | }"""; 105 | 106 | private static final String INVALID_CREDENTIAL_MESSAGE_NO_STATUS = """ 107 | { 108 | "@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"], 109 | "type": "CredentialMessage", 110 | "credentials": [ 111 | { 112 | "credentialType": "OrganizationCredential", 113 | "payload": "", 114 | "format": "json-ld" 115 | } 116 | ], 117 | "issuerPid": "issuerPid", 118 | "holderPid": "holderPid" 119 | }"""; 120 | 121 | 122 | private static final String INVALID_CREDENTIAL_MESSAGE_NO_TYPE_AND_CONTEXT = """ 123 | { 124 | "credentials": [ 125 | { 126 | "credentialType": "MembershipCredential", 127 | "payload": "", 128 | "format": "jwt" 129 | } 130 | ], 131 | "status": "ISSUED", 132 | "issuerPid": "issuerPid", 133 | "holderPid": "holderPid" 134 | }"""; 135 | 136 | @Test 137 | void verifySchema() { 138 | assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE, JSON)).isEmpty(); 139 | assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE_REJECTION, JSON)).isEmpty(); 140 | assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE, JSON)) 141 | .extracting(this::errorExtractor) 142 | .containsExactly(error("issuerPid", REQUIRED)); 143 | 144 | assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE_INVALID_CREDENTIAL_CONTAINER, JSON)) 145 | .extracting(this::errorExtractor) 146 | .containsExactly(error("payload", REQUIRED)); 147 | 148 | assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE_NO_TYPE_AND_CONTEXT, JSON)) 149 | .hasSize(2) 150 | .extracting(this::errorExtractor) 151 | .contains(error("type", REQUIRED), error("@context", REQUIRED)); 152 | 153 | assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE_NO_STATUS, JSON)) 154 | .hasSize(1) 155 | .extracting(this::errorExtractor) 156 | .contains(error("status", REQUIRED)); 157 | 158 | assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE_WRONG_STATUS, JSON)) 159 | .hasSize(1) 160 | .extracting(this::errorExtractor) 161 | .contains(error(null, ENUM)); // for some reason the property is `null` on enum validation errors 162 | } 163 | 164 | @BeforeEach 165 | void setUp() { 166 | setUp("/issuance/credential-message-schema.json"); 167 | } 168 | 169 | 170 | } 171 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 132 | Eclipse Decentralized Claims Protocol v1.0 133 | 134 | 135 | 139 |

Eclipse Decentralized Claims Protocol
v1.0

140 |
141 |

142 | Dataspaces require the ability to communicate participant identities and credentials to secure data access. This 143 | specification defines a set of protocols for asserting participant identities, issuing verifiable credentials, 144 | and presenting verifiable credentials using a decentralized architecture for verification and trust. 145 |

146 |
147 |
148 |

Status of This Document

149 |

150 | This version (v1.0) of the Decentralized Claims Protocol specification is a release of the specification and 151 | considered to be stable. Further changes shall not affect conformity. All changes made to the specification can 152 | be reviewed in the GitHub repository. 153 | This specification is affiliated with the Eclipse Dataspace Working Group. 154 |

155 |
156 | 157 |
158 |
159 | 160 |
161 |
162 | 163 |
164 |
165 | 166 |
167 |
168 | 169 |
170 |
171 | 172 |
173 |
174 | 175 |
176 | 177 |
178 |
179 | 180 |
181 |

Notes

182 |
183 | 184 | 185 | -------------------------------------------------------------------------------- /specifications/base.protocol.md: -------------------------------------------------------------------------------- 1 | # Base Concepts {#identity-protocol-base} 2 | 3 | This section defines the core identity concepts used by the current specification. 4 | 5 | ## Decentralization 6 | 7 | Decentralization is achieved in the following ways: 8 | 9 | - **Self-Issued ID Tokens** - Each [=participant=] is responsible for creating and cryptographically signing its own 10 | identity tokens. A central identity provider is therefore not required, eliminating a potential source of network 11 | failure. 12 | - **Participant Verifiable Credential and Cryptographic Material Management** - Each [=participant=] is responsible for 13 | storing [=Verifiable Credentials=] and presenting them as [=Verifiable Presentations=]. [=Participant=] are also 14 | responsible for storing and making their cryptographic material available to [=Verifiers=]. This specification defines 15 | how [=Verifiable Credentials=] are presented and verified without the need for a third-party verification service. 16 | - **Multiple Trust Anchors** - [=Participant=] [=Verifiable Credentials=] are signed by a third-party [=issuer=] acting 17 | as a trust anchor using a cryptographic proof. This specification allows for multiple trust anchors in a dataspace. 18 | 19 | ## Identities 20 | 21 | The Dataspace Protocol specification mandates that all participants have a stable identifier (Participant ID). This 22 | specification prescribes the Participant ID MUST be a [=DID=]. 23 | 24 | ## Self-Issued ID Tokens 25 | 26 | [=Participants=] use a Self-Issued ID Token to authenticate themselves and present self-attested claims to a 27 | [=Verifier=]. A Self-Issued ID Token is represented as a JSON Web Token [[rfc7519]] signed with a private key under the 28 | participant's control. 29 | 30 | The following claims MUST be included in the Self-Issued ID Token: 31 | 32 | - The `iss` and `sub` claims MUST be equal and set to the bearer's (participant's) [=DID=]. 33 | - The `aud` MUST be set to the [=Verifier=] [=DID=]. 34 | - The `jti` claim MUST be used to mitigate against replay attacks. 35 | - The `exp` claim MUST be used to express the expiration time on or after which the ID Token MUST NOT be accepted by the 36 | [=verifier=]. Implementers MAY provide for some leeway to account for clock skew. Its value is a JSON [rfc8259] number 37 | representing the number of seconds from 1970-01-01T00:00:00Z as measured in UTC until the date/time. 38 | - The `iat` claim MUST be used to specify the time the JWT was issued. Its value is a JSON number representing the 39 | number of seconds from 1970-01-01T00:00:00Z as measured in UTC. 40 | 41 | ### Verifiable Presentation Access Token 42 | 43 | A Self-Issued ID Token MAY contain an access token as a `token` claim that can be used by the [=Verifier=] to 44 | obtain [=Verifiable Presentations=] from the participant's [=Credential Service=]. The format of the `token` is 45 | implementation-specific and therefore SHOULD be treated as an opaque string by the [=Verifier=]. 46 | 47 | ### Obtaining Self-Issued ID Tokens 48 | 49 | _This section is non-normative._ 50 | 51 | How a Self-Issued ID token is obtained from a [=Secure Token Service=] is implementation-specific. An [=STS=] MAY 52 | support a 53 | variety of APIs, including OAuth 2. 54 | 55 | #### Using the OAuth 2 Client Credential Grant 56 | 57 | A Self-Issued ID Token MAY be obtained by executing a Client Credential Grant as defined in [[[?rfc6749]]] 58 | against a [=Secure Token Service=] endpoint. How the [=participant agent=] obtains the [=STS=] endpoint address is 59 | implementation-specific and beyond the scope of this specification. 60 | 61 | If an `token` is REQUIRED to be included in the Self Issued ID token, the [=participant agent=] will need to request 62 | scopes for the access token. This is dependent on the API used to obtain the Self-Issued ID Token. An [=STS=] 63 | implementation MAY use endpoint parameters as defined in the [[[?rfc6749]]] to convey metadata necessary for the 64 | creation of the `token` claim. In this case, the Self-Issued ID Token request MAY contain a `bearer_access_scope` 65 | authorization request parameter set to a list of space-delimited scopes the `token` claim will be enabled for. If no 66 | `bearer_access_scope` parameter is present, the `token` claim SHOULD not be included. 67 | 68 | 71 | 72 | ### Validating Self-Issued ID Tokens 73 | 74 | The [=Verifier=] MUST validate the Self-Issued ID Token using the following steps: 75 | 76 | 1. The [=Verifier=] MUST assert that the `iss` and `sub` claims have the same DID value. 77 | 2. The [=Verifier=] MUST assert that the `aud` claim is set to the [=Verifier=] [=DID=]. 78 | 3. The [=Verifier=] MUST validate the signature of the Self-Issued ID token by using a key obtained from the resolved 79 | `sub` DID Document. [=DID=] resolution is performed according to the [=DID=] Method specified by the `sub` claim. The 80 | resolved DID document is processed to retrieve the value of the `verificationMethod` property. 81 | - The signing key MUST have `capabilityInvocation` verification relationship with the DID. 82 | - If no `kid` token header is specified and the `verificationMethod` property contains one entry and the entry has the `capabilityInvocation` verification relationship, the verification method is used. 83 | - If no `kid` token header is specified and the `verificationMethod` property contains more than one entry, the token is rejected. 84 | - If a `kid` token header is specified, the verification material from the entry corresponding the `kid` token header is 85 | used. Furthermore, this verification material MUST have `capabilityInvocation` verification relationship. 86 | - If no matching entry is found, the token is rejected. 87 | 4. The [=Verifier=] MUST assert that the `sub` claim value equals the `id` property in the DID Document. 88 | 5. The [=Verifier=] MUST assert the `nbf` claim if present. The [=Verifier=] MAY allow for some leeway to account for 89 | clock skew. 90 | 5. The [=Verifier=] MUST assert that the current time is before the time represented by the `exp` claim. 91 | The [=Verifier=] MAY allow for some leeway to account for clock skew. The `iat` claim MAY be used to reject a token 92 | that was issued much earlier than the current time, thereby limiting the amount of time a `jti` value needs to be 93 | stored. 94 | 6. The [=Verifier=] MUST assert that the `jti` claim value has not been used previously. 95 | 96 | # Schemas, Contexts, and Message Processing 97 | 98 | All protocol messages are normatively defined by a [[json-schema]]. This specification also uses [[[json-ld11]]] and 99 | provides a Json-Ld context to serialize data structures and message types as it facilitates extensibility. The Json-Ld 100 | context is designed to produce message serializations using compaction that validate against the Json Schema for the 101 | given message type. This allows implementations to choose whether to process messages as plain Json or as Json-Ld and 102 | maintain interoperability between those approaches. Extensions that use Json-Ld are encouraged to provide similar 103 | contexts that facilitate this approach to interoperability. 104 | 105 | ## The Decentralized Claims Protocol Context 106 | 107 | The [[[json-ld11]]] context URI for the specification is: `https://w3id.org/dspace-dcp/v1.0/dcp.jsonld`. Future 108 | specification releases SHALL reuse the versioning schema according to the [Semantic Versioning](https://semver.org/) 109 | definitions, concatenated to a `vMAJOR.MINOR` number. The current specifications use `1.0` version. 110 | 111 | # The Base URL 112 | 113 | All endpoint URLs in this specification are relative. The base URL MUST use the HTTPS scheme. The base URL is 114 | implementation-specific and MAY include additional context information such as a sub-path that disambiguates a holder. 115 | -------------------------------------------------------------------------------- /specifications/participant-agent-model.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Verifier 5 | Verifies VCs 6 | 7 | Participant Agent 8 | 9 | 10 | 11 | 12 | Credential Service 13 | 14 | STS 15 | 16 | Participant Agent 17 | 18 | DID Service 19 | Holder 20 | Acquires and presents VCs 21 | 22 | Issue token 23 | 24 | Verify token 25 | 26 | Update DID document 27 | Use schemas 28 | 29 | Verify identifiers and use schemas 30 | Register identifiers 31 | 32 | 33 | 34 | Issuer 35 | Issues VCs 36 | 37 | Issuer Service 38 | 39 | Verify identifiers and use schemas 40 | 41 | Verifiable Data Registry 42 | Maintains identifiers and schemas 43 | 44 | Dataspace Protocol 45 | 46 | DCP Presentation 47 | 48 | DCP Issuance 49 | 50 | -------------------------------------------------------------------------------- /specifications/trust.model.md: -------------------------------------------------------------------------------- 1 | # Trust Model and Information Flow Architecture 2 | 3 | This specification is based on the Issuer-Holder-Verifier model as described in the [VC DataModel version of the selected profile](#profiles-of-the-decentralized-claims-protocol): 4 | 5 | ![alt text 2](specifications/issuer-holder-verifier-model.svg "The Issuer-Holder-Verifier Model") 6 | 7 | In this model, the [=Issuer=] creates a [=Verifiable Credential=] and provides it to the [=Holder=], which can then 8 | present the [=Verifiable Credential=] to the [=Verifier=]. 9 | 10 | The [=Verifier=] decides which [=Verifiable Credentials=] it will accept and the [=Holder=] decides 11 | which [=Verifiable Credentials=] it will present. All parties rely on a [=Verifiable Data Registry=] to obtain 12 | identifier information and metadata about [=Verifiable Credentials=], such as 13 | schemas. Furthermore, parties communicate with each other using the protocols defined in the Dataspace Protocol 14 | specification [[dsp-base]] and this specification. 15 | 16 | The Issuer-Holder-Verifier model is mapped to the following architecture in this specification: 17 | 18 | ![alt text 2](specifications/participant-agent-model.svg "Information Flow Architecture") 19 | 20 | - Identity and claims information is exchanged between a [=Holder=] and a [=Verifier=] in the context of Dataspace 21 | Protocol message interactions [[dsp-base]]. These messages will contain metadata such as Offers and Agreements that 22 | determine the [=Verifiable Credentials=] a [=Holder=] MUST present to a [=Verifier=]. 23 | - The [=Issuer Service=] issues credentials to a [=Holder=]'s [=Credential Service=] using the protocol defined in 24 | Section [[[#credential-issuance-protocol]]]. As part of this process, the [=Issuer Service=] will verify 25 | the [=Holder=]'s identifier using the [=Verifiable Data Registry=]. Since [=DID=]s are mandatory in this 26 | specification, the registry will be used to resolve the [=Holder=]'s DID document and cryptographic material. 27 | - The [=Holder=] runs three logical services: a [=Participant Agent=], an [=STS=], and a [=Credential Service=]. 28 | The [=Participant Agent=] engages in dataspace communications with the [=Verifier=] agent [[dsp-base]]. As part of 29 | these interactions, the [=Participant Agent=] will include a Self-Issued ID Token as defined in 30 | Section [[[#self-issued-id-tokens]]]. This token will be obtained from the [=STS=] controlled by the [=Holder=]. 31 | **Note that the [=STS=] is an internal system and therefore out of scope for the current specification. It MAY be a 32 | standalone service or part of the [=Participant Agent=] or [=Credential Service=].** The Self-Issued ID Token will 33 | contain an access token bound to the [=Verifier=] that will be used to request a [=Verifiable Presentation=]. 34 | The [=Holder=]'s [=Credential Service=] will verify the access token with the [=STS=]. 35 | - The [=Verifier=] runs a [=Participant Agent=] that engages in dataspace message exchanges with the [=Holder=] 36 | agent [[dsp-base]]. When it receives a request, it will resolve the [=Holder=]'s DID document from 37 | the [=Verifiable Data Registry=]. The [=Participant Agent=] will resolve the [=Credential Service=] endpoint from the 38 | DID document. The [=Participant Agent=] will send a request for a [=Verifiable Presentation=] to 39 | the [=Credential Service=] using the protocol defined in Section [[[#verifiable-presentation-protocol]]]. This 40 | request will include the access token as a claim in the Self-Issued ID Token received from the [=Holder=]'s agent. 41 | The [=Participant Agent=] will then match the credentials returned in the [=Verifiable Presentation=] against the 42 | policy constraints associated with the original dataspace request. 43 | 44 | ## Consent 45 | 46 | Consent is the process where the [=Holder=] approves the release of a [=Verifiable Presentation=] and the [=Verifier=] 47 | agrees to allow access to a protected resource. Since the Dataspace Protocol is built on machine-to-machine message 48 | exchange patterns, presentation protocols that rely on end-user (i.e., human) consent are not applicable. The protocols 49 | defined in this specification establish consent in the following way: 50 | 51 | ![alt text 3](specifications/consent-model.svg "Consent in the Decentralized Claims Protocol") 52 | 53 | Consent is handled by first mapping Dataspace Protocol Offer and Agreement policies [[dsp-base]] to a set of 54 | REQUIRED [=Verifiable Credentials=]. The exact mappings are dataspace-specific as policies 55 | and [=Verifiable Credentials=] are typically defined for a particular domain. The expectation is that these mappings are 56 | made available by the [=Dataspace Governance Authority=] to [=Participant Agents=] via 57 | the [=Verifiable Data Registry=]. [=Verifiable Credential=] mapping is done by both the [=Holder=] 58 | and [=Verifier=] [=Participant Agent=] when a Dataspace Protocol message is sent and received. 59 | 60 | When sending a Dataspace Protocol message, the [=Holder=]'s [=Participant Agent=] will determine the REQUIRED 61 | [=Verifiable Credentials=] and issue a Self-Issued ID Token request to the [=STS=], including the list of credentials to 62 | allow the [=Verifier=] to access via the [=Credential Service=]. The returned Self-Issued ID token will contain an 63 | access token bound to the [=Verifier=] as described above. This access token serves as a verifiable mechanism 64 | the [=Credential Service=] uses to determine consent and release credentials to the [=Verifier=]. 65 | 66 | The [=Verifier=] establishes consent by performing the same mapping from metadata to a set 67 | of [=Verifiable Credentials=] during the initial Dataspace Protocol request. At that point, 68 | the [=Verifier=] [=Participant Agent=] can query the [=Credential Service=] for a [=Verifiable Presentation=]. If it 69 | matches the REQUIRED credentials, the [=Verifier=] can consent and grant access to the associated protected resources. 70 | 71 | ## Trust Relationships 72 | 73 | Trust in the Issuer-Holder-Verifier model is established in different ways between each entity. This section identifies 74 | key aspects of those trust relationships. 75 | 76 | **All Entities** 77 | 78 | All entities expect: 79 | 80 | - The [=Verifiable Data Registry=] to be tamper-evident and correctly reflect data controlled by all entities. This MAY 81 | be done through the use of cryptographic resources. 82 | - All [=Verifiable Credentials=] and [=Verifiable Presentations=] to be tamper-proof and support revocation. 83 | - Dataspace Protocol interactions and those defined in this specification to be secure and use Transport Level 84 | Security. 85 | 86 | **Issuer** 87 | 88 | The [=Issuer=] expects: 89 | 90 | - [=Credential Service=] integrity, i.e. that [=Verifiable Credentials=] are securely stored and the service does not 91 | reveal data to unauthorized parties. 92 | 93 | **Holder** 94 | 95 | The [=Holder=] expects: 96 | 97 | - The [=Dataspace Governance Authority=] to provide a secure list of trusted [=Issuer=] [=DID=]s. How this list is provided is out 98 | of scope of the current specification but MAY be part of the [=Verifiable Data Registry=]. 99 | - The [=Dataspace Governance Authority=] to provide a secure list of participant [=DIDs=]. How this list is provided is out 100 | of scope of the current specification but MAY be part of the [=Verifiable Data Registry=]. 101 | - The [=Credential Service=] to maintain integrity and not release data to unauthorized parties. 102 | - The [=Issuer=] to issue credentials correctly, including binding them to the holder in a tamper-proof way, and 103 | maintaining credential integrity. 104 | - The [=Verifier=] not to leak information to third-parties. 105 | 106 | **Verifier** 107 | 108 | The [=Verifier=] expects: 109 | 110 | - The [=Dataspace Governance Authority=] to provide a secure list of trusted [=Issuer=] [=DID=]s. How this list is provided is out 111 | of scope of the current specification but MAY be part of the [=Verifiable Data Registry=]. [=Verifiers=] can 112 | recognize several [=Dataspace Governance Authorities=]. 113 | 114 | - The [=Issuer=] to issue credentials correctly, including binding them to the holder in a tamper-proof way, and 115 | maintaining credential integrity. 116 | 117 | ## Transport Security 118 | 119 | All participants MUST communicate via HTTPS [[rfc9110]]. 120 | -------------------------------------------------------------------------------- /specifications/auth.flow.svg: -------------------------------------------------------------------------------- 1 | Client EntityVerifier EntityClientClientSecure Token ServiceSecure Token ServiceDID ServiceDID ServiceCredential ServiceCredential ServiceVerifierVerifier1request2response incl. access token3request w/ self-issued id token incl. access token4resolve DID5DID document response6request w/ self-issued id token incl. access token7VP response8response -------------------------------------------------------------------------------- /specifications/issuance.flow.svg: -------------------------------------------------------------------------------- 1 | Client EntityIssuer EntityClientClientSecure Token ServiceSecure Token ServiceDID ServiceDID ServiceCredential ServiceCredential ServiceIssuer ServiceIssuer Service1request2response incl. access token3request credential(s) w/ self-issued ID token incl. access token4resolve DID5DID document response6ack7(async) write credential(s)w/ self-issued ID token access token8Validate token andstore credentials -------------------------------------------------------------------------------- /artifacts/src/main/resources/context/odrl.jsonld: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "odrl": "http://www.w3.org/ns/odrl/2/", 4 | "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 5 | "rdfs": "http://www.w3.org/2000/01/rdf-schema#", 6 | "owl": "http://www.w3.org/2002/07/owl#", 7 | "skos": "http://www.w3.org/2004/02/skos/core#", 8 | "dct": "http://purl.org/dc/terms/", 9 | "xsd": "http://www.w3.org/2001/XMLSchema#", 10 | "vcard": "http://www.w3.org/2006/vcard/ns#", 11 | "foaf": "http://xmlns.com/foaf/0.1/", 12 | "schema": "http://schema.org/", 13 | "cc": "http://creativecommons.org/ns#", 14 | "uid": "@id", 15 | "type": "@type", 16 | "Policy": "odrl:Policy", 17 | "Rule": "odrl:Rule", 18 | "profile": { 19 | "@type": "@id", 20 | "@id": "odrl:profile" 21 | }, 22 | "inheritFrom": { 23 | "@type": "@id", 24 | "@id": "odrl:inheritFrom" 25 | }, 26 | "ConflictTerm": "odrl:ConflictTerm", 27 | "conflict": { 28 | "@type": "@vocab", 29 | "@id": "odrl:conflict" 30 | }, 31 | "perm": "odrl:perm", 32 | "prohibit": "odrl:prohibit", 33 | "invalid": "odrl:invalid", 34 | "Agreement": "odrl:Agreement", 35 | "Assertion": "odrl:Assertion", 36 | "Offer": "odrl:Offer", 37 | "Privacy": "odrl:Privacy", 38 | "Request": "odrl:Request", 39 | "Set": "odrl:Set", 40 | "Ticket": "odrl:Ticket", 41 | "Asset": "odrl:Asset", 42 | "AssetCollection": "odrl:AssetCollection", 43 | "relation": { 44 | "@type": "@id", 45 | "@id": "odrl:relation" 46 | }, 47 | "hasPolicy": { 48 | "@type": "@id", 49 | "@id": "odrl:hasPolicy" 50 | }, 51 | "target": { 52 | "@type": "@id", 53 | "@id": "odrl:target" 54 | }, 55 | "output": { 56 | "@type": "@id", 57 | "@id": "odrl:output" 58 | }, 59 | "partOf": { 60 | "@type": "@id", 61 | "@id": "odrl:partOf" 62 | }, 63 | "source": { 64 | "@type": "@id", 65 | "@id": "odrl:source" 66 | }, 67 | "Party": "odrl:Party", 68 | "PartyCollection": "odrl:PartyCollection", 69 | "function": { 70 | "@type": "@vocab", 71 | "@id": "odrl:function" 72 | }, 73 | "PartyScope": "odrl:PartyScope", 74 | "assignee": { 75 | "@type": "@id", 76 | "@id": "odrl:assignee" 77 | }, 78 | "assigner": { 79 | "@type": "@id", 80 | "@id": "odrl:assigner" 81 | }, 82 | "assigneeOf": { 83 | "@type": "@id", 84 | "@id": "odrl:assigneeOf" 85 | }, 86 | "assignerOf": { 87 | "@type": "@id", 88 | "@id": "odrl:assignerOf" 89 | }, 90 | "attributedParty": { 91 | "@type": "@id", 92 | "@id": "odrl:attributedParty" 93 | }, 94 | "attributingParty": { 95 | "@type": "@id", 96 | "@id": "odrl:attributingParty" 97 | }, 98 | "compensatedParty": { 99 | "@type": "@id", 100 | "@id": "odrl:compensatedParty" 101 | }, 102 | "compensatingParty": { 103 | "@type": "@id", 104 | "@id": "odrl:compensatingParty" 105 | }, 106 | "consentingParty": { 107 | "@type": "@id", 108 | "@id": "odrl:consentingParty" 109 | }, 110 | "consentedParty": { 111 | "@type": "@id", 112 | "@id": "odrl:consentedParty" 113 | }, 114 | "informedParty": { 115 | "@type": "@id", 116 | "@id": "odrl:informedParty" 117 | }, 118 | "informingParty": { 119 | "@type": "@id", 120 | "@id": "odrl:informingParty" 121 | }, 122 | "trackingParty": { 123 | "@type": "@id", 124 | "@id": "odrl:trackingParty" 125 | }, 126 | "trackedParty": { 127 | "@type": "@id", 128 | "@id": "odrl:trackedParty" 129 | }, 130 | "contractingParty": { 131 | "@type": "@id", 132 | "@id": "odrl:contractingParty" 133 | }, 134 | "contractedParty": { 135 | "@type": "@id", 136 | "@id": "odrl:contractedParty" 137 | }, 138 | "Action": "odrl:Action", 139 | "action": { 140 | "@type": "@vocab", 141 | "@id": "odrl:action" 142 | }, 143 | "includedIn": { 144 | "@type": "@id", 145 | "@id": "odrl:includedIn" 146 | }, 147 | "implies": { 148 | "@type": "@id", 149 | "@id": "odrl:implies" 150 | }, 151 | "Permission": "odrl:Permission", 152 | "permission": { 153 | "@type": "@id", 154 | "@id": "odrl:permission" 155 | }, 156 | "Prohibition": "odrl:Prohibition", 157 | "prohibition": { 158 | "@type": "@id", 159 | "@id": "odrl:prohibition" 160 | }, 161 | "obligation": { 162 | "@type": "@id", 163 | "@id": "odrl:obligation" 164 | }, 165 | "use": "odrl:use", 166 | "grantUse": "odrl:grantUse", 167 | "aggregate": "odrl:aggregate", 168 | "annotate": "odrl:annotate", 169 | "anonymize": "odrl:anonymize", 170 | "archive": "odrl:archive", 171 | "concurrentUse": "odrl:concurrentUse", 172 | "derive": "odrl:derive", 173 | "digitize": "odrl:digitize", 174 | "display": "odrl:display", 175 | "distribute": "odrl:distribute", 176 | "execute": "odrl:execute", 177 | "extract": "odrl:extract", 178 | "give": "odrl:give", 179 | "index": "odrl:index", 180 | "install": "odrl:install", 181 | "modify": "odrl:modify", 182 | "move": "odrl:move", 183 | "play": "odrl:play", 184 | "present": "odrl:present", 185 | "print": "odrl:print", 186 | "read": "odrl:read", 187 | "reproduce": "odrl:reproduce", 188 | "sell": "odrl:sell", 189 | "stream": "odrl:stream", 190 | "textToSpeech": "odrl:textToSpeech", 191 | "transfer": "odrl:transfer", 192 | "transform": "odrl:transform", 193 | "translate": "odrl:translate", 194 | "Duty": "odrl:Duty", 195 | "duty": { 196 | "@type": "@id", 197 | "@id": "odrl:duty" 198 | }, 199 | "consequence": { 200 | "@type": "@id", 201 | "@id": "odrl:consequence" 202 | }, 203 | "remedy": { 204 | "@type": "@id", 205 | "@id": "odrl:remedy" 206 | }, 207 | "acceptTracking": "odrl:acceptTracking", 208 | "attribute": "odrl:attribute", 209 | "compensate": "odrl:compensate", 210 | "delete": "odrl:delete", 211 | "ensureExclusivity": "odrl:ensureExclusivity", 212 | "include": "odrl:include", 213 | "inform": "odrl:inform", 214 | "nextPolicy": "odrl:nextPolicy", 215 | "obtainConsent": "odrl:obtainConsent", 216 | "reviewPolicy": "odrl:reviewPolicy", 217 | "uninstall": "odrl:uninstall", 218 | "watermark": "odrl:watermark", 219 | "Constraint": "odrl:Constraint", 220 | "LogicalConstraint": "odrl:LogicalConstraint", 221 | "constraint": { 222 | "@type": "@id", 223 | "@id": "odrl:constraint" 224 | }, 225 | "refinement": { 226 | "@type": "@id", 227 | "@id": "odrl:refinement" 228 | }, 229 | "Operator": "odrl:Operator", 230 | "operator": { 231 | "@type": "@vocab", 232 | "@id": "odrl:operator" 233 | }, 234 | "RightOperand": "odrl:RightOperand", 235 | "rightOperand": "odrl:rightOperand", 236 | "rightOperandReference": { 237 | "@type": "xsd:anyURI", 238 | "@id": "odrl:rightOperandReference" 239 | }, 240 | "LeftOperand": "odrl:LeftOperand", 241 | "leftOperand": { 242 | "@type": "@vocab", 243 | "@id": "odrl:leftOperand" 244 | }, 245 | "unit": "odrl:unit", 246 | "dataType": { 247 | "@type": "xsd:anyType", 248 | "@id": "odrl:datatype" 249 | }, 250 | "status": "odrl:status", 251 | "absolutePosition": "odrl:absolutePosition", 252 | "absoluteSpatialPosition": "odrl:absoluteSpatialPosition", 253 | "absoluteTemporalPosition": "odrl:absoluteTemporalPosition", 254 | "absoluteSize": "odrl:absoluteSize", 255 | "count": "odrl:count", 256 | "dateTime": "odrl:dateTime", 257 | "delayPeriod": "odrl:delayPeriod", 258 | "deliveryChannel": "odrl:deliveryChannel", 259 | "elapsedTime": "odrl:elapsedTime", 260 | "event": "odrl:event", 261 | "fileFormat": "odrl:fileFormat", 262 | "industry": "odrl:industry:", 263 | "language": "odrl:language", 264 | "media": "odrl:media", 265 | "meteredTime": "odrl:meteredTime", 266 | "payAmount": "odrl:payAmount", 267 | "percentage": "odrl:percentage", 268 | "product": "odrl:product", 269 | "purpose": "odrl:purpose", 270 | "recipient": "odrl:recipient", 271 | "relativePosition": "odrl:relativePosition", 272 | "relativeSpatialPosition": "odrl:relativeSpatialPosition", 273 | "relativeTemporalPosition": "odrl:relativeTemporalPosition", 274 | "relativeSize": "odrl:relativeSize", 275 | "resolution": "odrl:resolution", 276 | "spatial": "odrl:spatial", 277 | "spatialCoordinates": "odrl:spatialCoordinates", 278 | "systemDevice": "odrl:systemDevice", 279 | "timeInterval": "odrl:timeInterval", 280 | "unitOfCount": "odrl:unitOfCount", 281 | "version": "odrl:version", 282 | "virtualLocation": "odrl:virtualLocation", 283 | "eq": "odrl:eq", 284 | "gt": "odrl:gt", 285 | "gteq": "odrl:gteq", 286 | "lt": "odrl:lt", 287 | "lteq": "odrl:lteq", 288 | "neq": "odrl:neg", 289 | "isA": "odrl:isA", 290 | "hasPart": "odrl:hasPart", 291 | "isPartOf": "odrl:isPartOf", 292 | "isAllOf": "odrl:isAllOf", 293 | "isAnyOf": "odrl:isAnyOf", 294 | "isNoneOf": "odrl:isNoneOf", 295 | "or": "odrl:or", 296 | "xone": "odrl:xone", 297 | "and": "odrl:and", 298 | "andSequence": "odrl:andSequence", 299 | "policyUsage": "odrl:policyUsage" 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /artifacts/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /artifacts/src/test/resources/presentation-exchange/schemas/presentation-definition.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "$schema": "http://json-schema.org/draft-07/schema#", 4 | "title": "Presentation Definition", 5 | "definitions": { 6 | "status_directive": { 7 | "type": "object", 8 | "additionalProperties": false, 9 | "properties": { 10 | "directive": { 11 | "type": "string", 12 | "enum": [ 13 | "required", 14 | "allowed", 15 | "disallowed" 16 | ] 17 | }, 18 | "type": { 19 | "type": "array", 20 | "minItems": 1, 21 | "items": { 22 | "type": "string" 23 | } 24 | } 25 | } 26 | }, 27 | "field": { 28 | "type": "object", 29 | "oneOf": [ 30 | { 31 | "properties": { 32 | "id": { 33 | "type": "string" 34 | }, 35 | "optional": { 36 | "type": "boolean" 37 | }, 38 | "path": { 39 | "type": "array", 40 | "items": { 41 | "type": "string" 42 | } 43 | }, 44 | "purpose": { 45 | "type": "string" 46 | }, 47 | "name": { 48 | "type": "string" 49 | }, 50 | "intent_to_retain": { 51 | "type": "boolean" 52 | }, 53 | "filter": { 54 | "$ref": "http://json-schema.org/draft-07/schema#" 55 | } 56 | }, 57 | "required": [ 58 | "path" 59 | ], 60 | "additionalProperties": false 61 | }, 62 | { 63 | "properties": { 64 | "id": { 65 | "type": "string" 66 | }, 67 | "optional": { 68 | "type": "boolean" 69 | }, 70 | "path": { 71 | "type": "array", 72 | "items": { 73 | "type": "string" 74 | } 75 | }, 76 | "purpose": { 77 | "type": "string" 78 | }, 79 | "intent_to_retain": { 80 | "type": "boolean" 81 | }, 82 | "filter": { 83 | "$ref": "http://json-schema.org/draft-07/schema#" 84 | }, 85 | "name": { 86 | "type": "string" 87 | }, 88 | "predicate": { 89 | "type": "string", 90 | "enum": [ 91 | "required", 92 | "preferred" 93 | ] 94 | } 95 | }, 96 | "required": [ 97 | "path", 98 | "filter", 99 | "predicate" 100 | ], 101 | "additionalProperties": false 102 | } 103 | ] 104 | }, 105 | "input_descriptor": { 106 | "type": "object", 107 | "additionalProperties": false, 108 | "properties": { 109 | "id": { 110 | "type": "string" 111 | }, 112 | "name": { 113 | "type": "string" 114 | }, 115 | "purpose": { 116 | "type": "string" 117 | }, 118 | "format": { 119 | "$ref": "https://identity.foundation/claim-format-registry/schemas/presentation-definition-claim-format-designations.json" 120 | }, 121 | "group": { 122 | "type": "array", 123 | "items": { 124 | "type": "string" 125 | } 126 | }, 127 | "constraints": { 128 | "type": "object", 129 | "additionalProperties": false, 130 | "properties": { 131 | "limit_disclosure": { 132 | "type": "string", 133 | "enum": [ 134 | "required", 135 | "preferred" 136 | ] 137 | }, 138 | "statuses": { 139 | "type": "object", 140 | "additionalProperties": false, 141 | "properties": { 142 | "active": { 143 | "$ref": "#/definitions/status_directive" 144 | }, 145 | "suspended": { 146 | "$ref": "#/definitions/status_directive" 147 | }, 148 | "revoked": { 149 | "$ref": "#/definitions/status_directive" 150 | } 151 | } 152 | }, 153 | "fields": { 154 | "type": "array", 155 | "items": { 156 | "$ref": "#/definitions/field" 157 | } 158 | }, 159 | "subject_is_issuer": { 160 | "type": "string", 161 | "enum": [ 162 | "required", 163 | "preferred" 164 | ] 165 | }, 166 | "is_holder": { 167 | "type": "array", 168 | "items": { 169 | "type": "object", 170 | "additionalProperties": false, 171 | "properties": { 172 | "field_id": { 173 | "type": "array", 174 | "items": { 175 | "type": "string" 176 | } 177 | }, 178 | "directive": { 179 | "type": "string", 180 | "enum": [ 181 | "required", 182 | "preferred" 183 | ] 184 | } 185 | }, 186 | "required": [ 187 | "field_id", 188 | "directive" 189 | ] 190 | } 191 | }, 192 | "same_subject": { 193 | "type": "array", 194 | "items": { 195 | "type": "object", 196 | "additionalProperties": false, 197 | "properties": { 198 | "field_id": { 199 | "type": "array", 200 | "items": { 201 | "type": "string" 202 | } 203 | }, 204 | "directive": { 205 | "type": "string", 206 | "enum": [ 207 | "required", 208 | "preferred" 209 | ] 210 | } 211 | }, 212 | "required": [ 213 | "field_id", 214 | "directive" 215 | ] 216 | } 217 | } 218 | } 219 | } 220 | }, 221 | "required": [ 222 | "id", 223 | "constraints" 224 | ] 225 | }, 226 | "submission_requirement": { 227 | "type": "object", 228 | "oneOf": [ 229 | { 230 | "properties": { 231 | "name": { 232 | "type": "string" 233 | }, 234 | "purpose": { 235 | "type": "string" 236 | }, 237 | "rule": { 238 | "type": "string", 239 | "enum": [ 240 | "all", 241 | "pick" 242 | ] 243 | }, 244 | "count": { 245 | "type": "integer", 246 | "minimum": 1 247 | }, 248 | "min": { 249 | "type": "integer", 250 | "minimum": 0 251 | }, 252 | "max": { 253 | "type": "integer", 254 | "minimum": 0 255 | }, 256 | "from": { 257 | "type": "string" 258 | } 259 | }, 260 | "required": [ 261 | "rule", 262 | "from" 263 | ], 264 | "additionalProperties": false 265 | }, 266 | { 267 | "properties": { 268 | "name": { 269 | "type": "string" 270 | }, 271 | "purpose": { 272 | "type": "string" 273 | }, 274 | "rule": { 275 | "type": "string", 276 | "enum": [ 277 | "all", 278 | "pick" 279 | ] 280 | }, 281 | "count": { 282 | "type": "integer", 283 | "minimum": 1 284 | }, 285 | "min": { 286 | "type": "integer", 287 | "minimum": 0 288 | }, 289 | "max": { 290 | "type": "integer", 291 | "minimum": 0 292 | }, 293 | "from_nested": { 294 | "type": "array", 295 | "minItems": 1, 296 | "items": { 297 | "$ref": "#/definitions/submission_requirement" 298 | } 299 | } 300 | }, 301 | "required": [ 302 | "rule", 303 | "from_nested" 304 | ], 305 | "additionalProperties": false 306 | } 307 | ] 308 | } 309 | }, 310 | "type": "object", 311 | "properties": { 312 | "id": { 313 | "type": "string" 314 | }, 315 | "name": { 316 | "type": "string" 317 | }, 318 | "purpose": { 319 | "type": "string" 320 | }, 321 | "format": { 322 | "$ref": "https://identity.foundation/claim-format-registry/schemas/presentation-definition-claim-format-designations.json" 323 | }, 324 | "frame": { 325 | "type": "object", 326 | "additionalProperties": true 327 | }, 328 | "submission_requirements": { 329 | "type": "array", 330 | "items": { 331 | "$ref": "#/definitions/submission_requirement" 332 | } 333 | }, 334 | "input_descriptors": { 335 | "type": "array", 336 | "items": { 337 | "$ref": "#/definitions/input_descriptor" 338 | } 339 | } 340 | }, 341 | "required": [ 342 | "id", 343 | "input_descriptors" 344 | ], 345 | "additionalProperties": false 346 | } 347 | --------------------------------------------------------------------------------