Skip to content

Commit

Permalink
docs: add credential rejection message
Browse files Browse the repository at this point in the history
  • Loading branch information
paullatzelsperger authored and arnoweiss committed Feb 27, 2025
1 parent 63164d9 commit 79a9706
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 9 deletions.
7 changes: 7 additions & 0 deletions artifacts/src/main/resources/context/dcp.jsonld
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
"holderPid": {
"@id": "dcp:holderPid",
"@type": "@id"
},
"status": {
"@id": "dcp:status",
"@type": "@id"
},
"rejectionReason": {
"@id": "dcp:rejectionReason"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,21 @@
},
"format": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["ISSUED", "REJECTED"]
},
"rejectionReason": {
"type": "string"
}
},
"required": [
"@context",
"type",
"credentials",
"issuerPid",
"holderPid"
"holderPid",
"status"
]
},
"CredentialContainer": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"@context": [
"https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"
],
"type": "CredentialMessage",
"issuerPid": "issuerPid",
"holderPid": "holderPid",
"status": "REJECTED",
"rejectionReason": "final approval not granted"
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
}
],
"issuerPid": "issuerPid",
"holderPid": "holderPid"
"holderPid": "holderPid",
"status": "ISSUED"
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,51 @@ public class CredentialMessageSchemaTest extends AbstractSchemaTest {
"format": "json-ld"
}
],
"status": "ISSUED",
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";

private static final String CREDENTIAL_MESSAGE_MESSAGE_WRONG_STATUS = """
{
"@context": [
"https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"
],
"type": "CredentialMessage",
"credentials": [
{
"credentialType": "MembershipCredential",
"payload": "<JWT-STRING>",
"format": "jwt"
},
{
"credentialType": "OrganizationCredential",
"payload": "<LD-Object>",
"format": "json-ld"
}
],
"status": "INVALID",
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";

private static final String CREDENTIAL_MESSAGE_MESSAGE_REJECTION = """
{
"@context": [
"https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"
],
"type": "CredentialMessage",
"status": "REJECTED",
"rejectionReason": "some rejection reason",
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";

private static final String INVALID_CREDENTIAL_MESSAGE = """
{
"@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"],
"type": "CredentialMessage"
"type": "CredentialMessage",
"status": "ISSUED"
}""";

private static final String INVALID_CREDENTIAL_MESSAGE_INVALID_CREDENTIAL_CONTAINER = """
Expand All @@ -61,6 +98,22 @@ public class CredentialMessageSchemaTest extends AbstractSchemaTest {
"format": "jwt"
}
],
"status": "ISSUED",
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";

private static final String INVALID_CREDENTIAL_MESSAGE_NO_STATUS = """
{
"@context": ["https://w3id.org/dspace-dcp/v1.0/dcp.jsonld"],
"type": "CredentialMessage",
"credentials": [
{
"credentialType": "OrganizationCredential",
"payload": "<LD-Object>",
"format": "json-ld"
}
],
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";
Expand All @@ -75,16 +128,18 @@ public class CredentialMessageSchemaTest extends AbstractSchemaTest {
"format": "jwt"
}
],
"status": "ISSUED",
"issuerPid": "issuerPid",
"holderPid": "holderPid"
}""";

@Test
void verifySchema() {
assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE, JSON)).isEmpty();
assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE_REJECTION, JSON)).isEmpty();
assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE, JSON))
.extracting(this::errorExtractor)
.containsExactly(error("credentials", REQUIRED), error("issuerPid", REQUIRED), error("holderPid", REQUIRED));
.containsExactly(error("issuerPid", REQUIRED), error("holderPid", REQUIRED));

assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE_INVALID_CREDENTIAL_CONTAINER, JSON))
.extracting(this::errorExtractor)
Expand All @@ -94,6 +149,16 @@ void verifySchema() {
.hasSize(2)
.extracting(this::errorExtractor)
.contains(error("type", REQUIRED), error("@context", REQUIRED));

assertThat(schema.validate(INVALID_CREDENTIAL_MESSAGE_NO_STATUS, JSON))
.hasSize(1)
.extracting(this::errorExtractor)
.contains(error("status", REQUIRED));

assertThat(schema.validate(CREDENTIAL_MESSAGE_MESSAGE_WRONG_STATUS, JSON))
.hasSize(1)
.extracting(this::errorExtractor)
.contains(error(null, ENUM)); // for some reason the property is `null` on enum validation errors
}

@BeforeEach
Expand Down
19 changes: 15 additions & 4 deletions specifications/credential.issuance.protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,28 @@ exact error code is implementation-specific.
| **Schema** | [JSON Schema](./resources/issuance/credential-message-schema.json) |
| **Required** | - `@context`: Specifies a valid Json-Ld context ([[json-ld11]], sect. 3.1) |
| | - `type`: A string specifying the `Credential Message` type. |
| | - `issuerPid`: A string corresponding to the issuance id on the Issuer side. |
| | - `holderPid`: A string corresponding to the issuance id on the Holder side. |
| | - `issuerPid`: A string corresponding to the issuance id on the Issuer side. |
| | - `holderPid`: A string corresponding to the issuance id on the Holder side. |
| | - `status`: A string stating whether the request was successful (`ISSUED`) or rejected (`REJECTED`) |
| | - `credentials`: An array of [Credential Container](#credential-container) Json objects as defined in the following. |
| | - `rejectionReason`: a String containing additional information why a request was rejected. Can be `null`. |

The following is a non-normative example of the [Credential Message](#credential-message) JSON body:
The following is a non-normative example of a [Credential Message](#credential-message) JSON body:

<aside class="example" title="Credential Message">
<aside class="example" title="Credential Message (issued)">
<pre class="json" data-include="./resources/issuance/example/credential-message.json">
</pre>
</aside>

The following example shows a rejected credential request JSON body:
<aside class="example" title="Credential Message (rejected)">
<pre class="json" data-include="./resources/issuance/example/credential-message-rejected.json">
</pre>
</aside>

Note that the `status` applies to the entire request, i.e. a request is considered _rejected_ if at least one credential could not be issued.
Allowed values for the `status` are `"ISSUED"` and `"REJECTED"`. The `rejectionReason` field is optional and should not disclose any confidential information.

### Credential Container

The [Credential Message](#credential-message)'s `credentials` property contains an array of `CredentialContainer`
Expand Down

0 comments on commit 79a9706

Please sign in to comment.