Skip to content

Commit 086b4e6

Browse files
committed
Some work on validating VCs.
1 parent 92a4fdc commit 086b4e6

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

src/main/java/com/danubetech/verifiablecredentials/VerifiableCredential.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import java.io.IOException;
44
import java.net.URI;
5+
import java.net.URISyntaxException;
56
import java.text.ParseException;
67
import java.text.SimpleDateFormat;
78
import java.util.ArrayList;
9+
import java.util.Collections;
810
import java.util.Date;
911
import java.util.LinkedHashMap;
1012
import java.util.List;
@@ -20,6 +22,7 @@
2022
public class VerifiableCredential {
2123

2224
public static final String JSONLD_CONTEXT_CREDENTIALS = "https://www.w3.org/2018/credentials/v1";
25+
public static final String JSONLD_CONTEXT_CREDENTIALS_NO_WWW = "https://w3.org/2018/credentials/v1";
2326
public static final String JSONLD_TYPE_VERIFIABLE_CREDENTIAL = "VerifiableCredential";
2427

2528
public static final String JSONLD_TERM_ID = "id";
@@ -40,11 +43,11 @@ public class VerifiableCredential {
4043
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
4144
}
4245

43-
private VerifiableCredential(LinkedHashMap<String, Object> jsonLdObject) {
46+
private VerifiableCredential(LinkedHashMap<String, Object> jsonLdObject, boolean validate) {
4447

4548
this.jsonLdObject = jsonLdObject;
4649

47-
this.validate();
50+
if (validate) this.validate();
4851
}
4952

5053
public VerifiableCredential() {
@@ -63,14 +66,24 @@ public VerifiableCredential() {
6366
this.jsonLdObject.put(JSONLD_TERM_CREDENTIAL_SUBJECT, credentialSubject);
6467
}
6568

69+
public static VerifiableCredential fromJsonLdObject(LinkedHashMap<String, Object> jsonLdObject, boolean validate) {
70+
71+
return new VerifiableCredential(jsonLdObject, validate);
72+
}
73+
6674
public static VerifiableCredential fromJsonLdObject(LinkedHashMap<String, Object> jsonLdObject) {
6775

68-
return new VerifiableCredential(jsonLdObject);
76+
return fromJsonLdObject(jsonLdObject, true);
77+
}
78+
79+
public static VerifiableCredential fromJsonString(String jsonString, boolean validate) throws JsonParseException, IOException {
80+
81+
return fromJsonLdObject((LinkedHashMap<String, Object>) JsonUtils.fromString(jsonString), validate);
6982
}
7083

7184
public static VerifiableCredential fromJsonString(String jsonString) throws JsonParseException, IOException {
7285

73-
return fromJsonLdObject((LinkedHashMap<String, Object>) JsonUtils.fromString(jsonString));
86+
return fromJsonString(jsonString, true);
7487
}
7588

7689
public LinkedHashMap<String, Object> getJsonLdObject() {
@@ -141,7 +154,10 @@ public void setContext(List<String> context) {
141154

142155
public List<String> getType() {
143156

144-
return (List<String>) this.jsonLdObject.get(JSONLD_TERM_TYPE);
157+
Object object = this.jsonLdObject.get(JSONLD_TERM_TYPE);
158+
if (object instanceof List) return (List<String>) object;
159+
if (object instanceof String) return Collections.singletonList((String) object);
160+
return null;
145161
}
146162

147163
public void setType(List<String> type) {
@@ -225,6 +241,17 @@ private static void validateTrue(boolean valid) throws IllegalStateException {
225241
if (! valid) throw new IllegalStateException();
226242
}
227243

244+
private static void validateUrl(String uri) {
245+
246+
try {
247+
248+
if (! new URI(uri).isAbsolute()) throw new URISyntaxException("Not absolute.", uri);
249+
} catch (URISyntaxException ex) {
250+
251+
throw new RuntimeException(ex.getMessage());
252+
}
253+
}
254+
228255
private static void validateRun(Runnable runnable, String message) throws IllegalStateException {
229256

230257
try {
@@ -238,10 +265,18 @@ private static void validateRun(Runnable runnable, String message) throws Illega
238265

239266
public void validate() throws IllegalStateException {
240267

241-
validateRun(() -> { validateTrue(JSONLD_CONTEXT_CREDENTIALS.equals(this.getContext().get(0))); }, "First value of @context must be https://www.w3.org/2018/credentials/v1");
242-
validateRun(() -> { for (String context : this.getContext()) URI.create(context); }, "@context must be a valid URI");
243-
validateRun(() -> { for (String type : this.getType()) URI.create(type); }, "@type must be a valid URI");
244-
validateRun(() -> { this.getType().contains(JSONLD_TYPE_VERIFIABLE_CREDENTIAL); }, "@type must contain VerifiableCredential");
268+
validateRun(() -> { validateTrue(this.getContext().size() > 0); }, "Bad or missing '@context'.");
269+
validateRun(() -> { validateTrue(this.getType().size() > 0); }, "Bad or missing '@type'.");
270+
validateRun(() -> { validateTrue(this.getIssuer() != null); }, "Bad or missing 'issuer'.");
271+
validateRun(() -> { validateTrue(this.getIssuanceDate() != null); }, "Bad or missing 'issuanceDate'.");
272+
validateRun(() -> { this.getExpirationDate(); }, "Bad 'expirationDate'.");
273+
validateRun(() -> { validateTrue(this.getCredentialSubject() != null); }, "Bad or missing 'credentialSubject'.");
274+
275+
validateRun(() -> { if (this.getId() != null) validateUrl(this.getId()); }, "'@id' must be a valid URI.");
276+
validateRun(() -> { validateUrl(this.getIssuer()); }, "'issuer' must be a valid URI.");
277+
validateRun(() -> { validateTrue(JSONLD_CONTEXT_CREDENTIALS.equals(this.getContext().get(0)) || JSONLD_CONTEXT_CREDENTIALS_NO_WWW.equals(this.getContext().get(0))); }, "First value of @context must be https://www.w3.org/2018/credentials/v1: " + this.getContext().get(0));
278+
validateRun(() -> { for (String context : this.getContext()) validateUrl(context); }, "@context must be a valid URI: " + this.getContext());
279+
validateRun(() -> { validateTrue(this.getType().contains(JSONLD_TYPE_VERIFIABLE_CREDENTIAL)); }, "@type must contain VerifiableCredential: " + this.getType());
245280
}
246281

247282
/*

src/main/java/com/danubetech/verifiablecredentials/jwt/JwtVerifiableCredential.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public static JwtVerifiableCredential fromJwt(String jwt, String algorithm, Publ
5555

5656
JwtClaims jwtPayload = JwtClaims.parse(jws.getPayload());
5757
LinkedHashMap<String, Object> jsonLdObject = (LinkedHashMap<String, Object>) jwtPayload.getClaimValue(JWT_CLAIM_VC);
58-
VerifiableCredential payloadVerifiableCredential = VerifiableCredential.fromJsonLdObject(jsonLdObject);
58+
VerifiableCredential payloadVerifiableCredential = VerifiableCredential.fromJsonLdObject(jsonLdObject, false);
5959

6060
return new JwtVerifiableCredential(jwtPayload, payloadVerifiableCredential);
6161
}
@@ -153,7 +153,7 @@ public VerifiableCredential toVerifiableCredential() throws MalformedClaimExcept
153153

154154
try {
155155

156-
verifiableCredential = VerifiableCredential.fromJsonString(this.getPayloadVerifiableCredential().toJsonString());
156+
verifiableCredential = VerifiableCredential.fromJsonString(this.getPayloadVerifiableCredential().toJsonString(), false);
157157
} catch (IOException ex) {
158158

159159
throw new RuntimeException(ex.getMessage(), ex);

0 commit comments

Comments
 (0)