Added endorsements, but need to generate more examples, fix proofs and add more unit tests to confirm I am grabbing the right schemas, etc...
This commit is contained in:
parent
a7402e5a73
commit
469d60eae3
@ -130,10 +130,6 @@ public class EmbeddedVCInspector extends VCInspector implements SubInspector {
|
|||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: verify embedded endorsements, I believe these are NOT on embedded credentials
|
|
||||||
|
|
||||||
//TODO: verify if User Probes are relevant for embedded content
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,40 @@
|
|||||||
package org.oneedtech.inspect.vc;
|
package org.oneedtech.inspect.vc;
|
||||||
|
|
||||||
|
import static java.lang.Boolean.TRUE;
|
||||||
|
|
||||||
import static org.oneedtech.inspect.core.probe.RunContext.Key.*;
|
import static org.oneedtech.inspect.core.probe.RunContext.Key.*;
|
||||||
import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT;
|
import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT;
|
||||||
|
import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.oneedtech.inspect.core.SubInspector;
|
import org.oneedtech.inspect.core.SubInspector;
|
||||||
import org.oneedtech.inspect.core.probe.GeneratedObject;
|
import org.oneedtech.inspect.core.probe.GeneratedObject;
|
||||||
|
import org.oneedtech.inspect.core.probe.Probe;
|
||||||
import org.oneedtech.inspect.core.probe.RunContext;
|
import org.oneedtech.inspect.core.probe.RunContext;
|
||||||
import org.oneedtech.inspect.core.probe.json.JsonPathEvaluator;
|
import org.oneedtech.inspect.core.probe.json.JsonPathEvaluator;
|
||||||
|
import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe;
|
||||||
import org.oneedtech.inspect.core.report.Report;
|
import org.oneedtech.inspect.core.report.Report;
|
||||||
import org.oneedtech.inspect.core.report.ReportItems;
|
import org.oneedtech.inspect.core.report.ReportItems;
|
||||||
|
import org.oneedtech.inspect.schema.SchemaKey;
|
||||||
import org.oneedtech.inspect.util.json.ObjectMapperCache;
|
import org.oneedtech.inspect.util.json.ObjectMapperCache;
|
||||||
import org.oneedtech.inspect.util.resource.Resource;
|
import org.oneedtech.inspect.util.resource.Resource;
|
||||||
|
import org.oneedtech.inspect.util.resource.UriResource;
|
||||||
|
import org.oneedtech.inspect.util.resource.context.ResourceContext;
|
||||||
|
import org.oneedtech.inspect.vc.Credential.Type;
|
||||||
|
import org.oneedtech.inspect.vc.probe.CredentialParseProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.IssuanceVerifierProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.RevocationListProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.SignatureVerifierProbe;
|
||||||
|
import org.oneedtech.inspect.vc.probe.TypePropertyProbe;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +53,7 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
|
|||||||
* The resource param is the top-level credential that embeds the endorsement, we
|
* The resource param is the top-level credential that embeds the endorsement, we
|
||||||
* expect parentObjects to provide a pointer to the JsonNode we should check
|
* expect parentObjects to provide a pointer to the JsonNode we should check
|
||||||
*/
|
*/
|
||||||
Credential endorsement = (Credential) parentObjects.get(ENDORSEMENT_KEY);
|
Credential verifiableCredential = (Credential) parentObjects.get(ENDORSEMENT_KEY);
|
||||||
|
|
||||||
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
||||||
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
||||||
@ -42,12 +63,78 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
|
|||||||
.put(resource)
|
.put(resource)
|
||||||
.put(JACKSON_OBJECTMAPPER, mapper)
|
.put(JACKSON_OBJECTMAPPER, mapper)
|
||||||
.put(JSONPATH_EVALUATOR, jsonPath)
|
.put(JSONPATH_EVALUATOR, jsonPath)
|
||||||
.put(ENDORSEMENT_KEY, endorsement)
|
.put(ENDORSEMENT_KEY, verifiableCredential)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
List<ReportItems> accumulator = new ArrayList<>();
|
||||||
|
int probeCount = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//detect type (png, svg, json, jwt) and extract json data
|
||||||
|
probeCount++;
|
||||||
|
accumulator.add(new CredentialParseProbe().run(resource, ctx));
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
|
||||||
|
//we expect the above to place a generated object in the context
|
||||||
|
Credential crd = ctx.getGeneratedObject(Credential.ID);
|
||||||
|
|
||||||
|
//type property
|
||||||
|
probeCount++;
|
||||||
|
accumulator.add(new TypePropertyProbe(Type.ClrCredential).run(crd.getJson(), ctx));
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
|
||||||
System.err.println("TODO" + endorsement.toString());
|
//canonical schema and inline schema
|
||||||
|
SchemaKey schema = crd.getSchemaKey().orElseThrow();
|
||||||
return new Report(ctx, new ReportItems(), 1); //TODO
|
for(Probe<JsonNode> probe : List.of(new JsonSchemaProbe(schema), new InlineJsonSchemaProbe(schema))) {
|
||||||
|
probeCount++;
|
||||||
|
accumulator.add(probe.run(crd.getJson(), ctx));
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//signatures, proofs
|
||||||
|
probeCount++;
|
||||||
|
if(crd.getJwt().isPresent()){
|
||||||
|
//The credential originally contained in a JWT, validate the jwt and external proof.
|
||||||
|
accumulator.add(new SignatureVerifierProbe().run(crd, ctx));
|
||||||
|
} else {
|
||||||
|
//The credential not contained in a jwt, must have an internal proof.
|
||||||
|
//TODO: @Miles Need to fix the issuer, Same as with outer CLR
|
||||||
|
//Swap -> "verificationMethod": "https://example.edu/issuers/565049#z6MkwA1498JfoCS3y4y3zggBDAosQEoCi5gsYH2PMXh1cFWK",
|
||||||
|
//To be like -> "verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj",
|
||||||
|
//...but also work properly which old record seems not be doing...
|
||||||
|
|
||||||
|
/*
|
||||||
|
accumulator.add(new ProofVerifierProbe().run(crd, ctx));
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
|
||||||
|
//check refresh service if we are not already refreshed (check just like in external CLR)
|
||||||
|
probeCount++;
|
||||||
|
if(resource.getContext().get(REFRESHED) != TRUE) {
|
||||||
|
Optional<String> newID = checkRefreshService(crd, ctx);
|
||||||
|
if(newID.isPresent()) {
|
||||||
|
//TODO resource.type
|
||||||
|
return this.run(
|
||||||
|
new UriResource(new URI(newID.get()))
|
||||||
|
.setContext(new ResourceContext(REFRESHED, TRUE)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//revocation, expiration and issuance (check just like in external CLR)
|
||||||
|
for(Probe<Credential> probe : List.of(new RevocationListProbe(),
|
||||||
|
new ExpirationVerifierProbe(), new IssuanceVerifierProbe())) {
|
||||||
|
probeCount++;
|
||||||
|
accumulator.add(probe.run(crd, ctx));
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Report(ctx, new ReportItems(accumulator), probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -64,5 +151,25 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static final String ENDORSEMENT_KEY = "ENDORSEMENT_KEY";
|
public static final String ENDORSEMENT_KEY = "ENDORSEMENT_KEY";
|
||||||
|
private static final String REFRESHED = "is.refreshed.credential";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the AchievementCredential or EndorsementCredential has a “refreshService” property and the type of the
|
||||||
|
* RefreshService object is “1EdTechCredentialRefresh”, you should fetch the refreshed credential from the URL
|
||||||
|
* provided, then start the verification process over using the response as input. If the request fails,
|
||||||
|
* the credential is invalid.
|
||||||
|
*/
|
||||||
|
private Optional<String> checkRefreshService(Credential crd, RunContext ctx) {
|
||||||
|
JsonNode refreshServiceNode = crd.getJson().get("refreshService");
|
||||||
|
if(refreshServiceNode != null) {
|
||||||
|
JsonNode serviceTypeNode = refreshServiceNode.get("type");
|
||||||
|
if(serviceTypeNode != null && serviceTypeNode.asText().equals("1EdTechCredentialRefresh")) {
|
||||||
|
JsonNode serviceURINode = refreshServiceNode.get("id");
|
||||||
|
if(serviceURINode != null) {
|
||||||
|
return Optional.of(serviceURINode.asText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user