From 5ab98b478c8a498c5f8faab1fe7b6d7d7da737d7 Mon Sep 17 00:00:00 2001 From: Timea Turdean <4144203+timea-solid@users.noreply.github.com> Date: Thu, 6 Apr 2023 10:16:57 +0200 Subject: [PATCH 1/4] started work on verfy --- .../client/accessgrant/AccessGrantClient.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java index c53f40f5465..1f398a16fd7 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java @@ -180,6 +180,50 @@ public CompletionStage issue(final URI type, final URI agent, final }); } + /** + * Verify an access grant or request. + * + * @param type the credential type + * @param agent the receiving agent for this credential + * @param resources the resources to which this credential applies + * @param modes the access modes for this credential + * @param purposes the purposes of this credential + * @param expiration the expiration time of this credential + * @return the next stage of completion containing the resulting credential + */ + public CompletionStage verify(final URI type, final URI agent, final Set resources, + final Set modes, final Set purposes, final Instant expiration) { + return v1Metadata().thenCompose(metadata -> { + final Map data; + if (ACCESS_GRANT.equals(type)) { + data = buildAccessGrantv1(agent, resources, modes, expiration, purposes); + } else if (ACCESS_REQUEST.equals(type)) { + data = buildAccessRequestv1(agent, resources, modes, expiration, purposes); + } else { + throw new AccessGrantException("Unsupported grant type: " + type); + } + + final Request req = Request.newBuilder(metadata.verifyEndpoint) + .header(CONTENT_TYPE, APPLICATION_JSON) + .POST(Request.BodyPublishers.ofByteArray(serialize(data))).build(); + + return client.send(req, Response.BodyHandlers.ofInputStream()) + .thenApply(res -> { + try (final InputStream input = res.body()) { + final int status = res.statusCode(); + if (isSuccess(status)) { + return processVerificationResult(input); + } + throw new AccessGrantException("Unable to perform Access Grant verify: HTTP error " + status, + status); + } catch (final IOException ex) { + throw new AccessGrantException( + "Unexpected I/O exception while verifying Access Grant", ex); + } + }); + }); + } + /** * Perform an Access Grant query. * @@ -319,6 +363,10 @@ AccessGrant processVerifiableCredential(final InputStream input, final Set processQueryResponse(final InputStream input, final Set validTypes) throws IOException { final Map data = jsonService.fromJson(input, new HashMap(){}.getClass().getGenericSuperclass()); @@ -520,4 +568,24 @@ static boolean isAccessRequest(final URI type) { return "SolidAccessRequest".equals(type.toString()) || ACCESS_REQUEST.equals(type); } + + /** + * A data objects for verification responses. + */ + public static class VerificationResponse { + /** + * The verification checks that were performed. + */ + public List checks; + + /** + * The verification warnings that were discovered. + */ + public List warnings; + + /** + * The verification errors that were discovered. + */ + public List errors; + } } From c7b2ea677785326196958477b2c2ecafc389876a Mon Sep 17 00:00:00 2001 From: Timea Turdean <4144203+timea-solid@users.noreply.github.com> Date: Thu, 6 Apr 2023 11:14:49 +0200 Subject: [PATCH 2/4] verify proposal --- .../client/accessgrant/AccessGrantClient.java | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java index 1f398a16fd7..9116311f2e1 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java @@ -79,6 +79,7 @@ public class AccessGrantClient { private static final String VC_CONTEXT_URI = "https://www.w3.org/2018/credentials/v1"; private static final String INRUPT_CONTEXT_URI = "https://schema.inrupt.com/credentials/v1.jsonld"; private static final String VERIFIABLE_CREDENTIAL = "verifiableCredential"; + private static final String OPTIONS = "options"; private static final String TYPE = "type"; private static final String APPLICATION_JSON = "application/json"; private static final String CONTENT_TYPE = "Content-Type"; @@ -183,29 +184,20 @@ public CompletionStage issue(final URI type, final URI agent, final /** * Verify an access grant or request. * - * @param type the credential type - * @param agent the receiving agent for this credential - * @param resources the resources to which this credential applies - * @param modes the access modes for this credential - * @param purposes the purposes of this credential - * @param expiration the expiration time of this credential + * @param accessGrant the access grant to verify + * @param options the options to which this credential applies * @return the next stage of completion containing the resulting credential */ - public CompletionStage verify(final URI type, final URI agent, final Set resources, - final Set modes, final Set purposes, final Instant expiration) { + public CompletionStage verify(final AccessGrant accessGrant, final Set options) { return v1Metadata().thenCompose(metadata -> { - final Map data; - if (ACCESS_GRANT.equals(type)) { - data = buildAccessGrantv1(agent, resources, modes, expiration, purposes); - } else if (ACCESS_REQUEST.equals(type)) { - data = buildAccessRequestv1(agent, resources, modes, expiration, purposes); - } else { - throw new AccessGrantException("Unsupported grant type: " + type); - } + + final Map presentation = new HashMap<>(); + presentation.put(VERIFIABLE_CREDENTIAL, accessGrant); + presentation.put(OPTIONS, Arrays.asList(options)); final Request req = Request.newBuilder(metadata.verifyEndpoint) .header(CONTENT_TYPE, APPLICATION_JSON) - .POST(Request.BodyPublishers.ofByteArray(serialize(data))).build(); + .POST(Request.BodyPublishers.ofByteArray(serialize(presentation))).build(); return client.send(req, Response.BodyHandlers.ofInputStream()) .thenApply(res -> { @@ -363,6 +355,22 @@ AccessGrant processVerifiableCredential(final InputStream input, final Set validTypes, final Set options) throws IOException { + final Map data = jsonService.fromJson(input, + new HashMap(){}.getClass().getGenericSuperclass()); + final Set types = AccessGrant.asSet(data.get(TYPE)).orElseThrow(() -> + new AccessGrantException("Invalid Access Grant: no 'type' field")); + types.retainAll(validTypes); + if (!types.isEmpty()) { + final Map presentation = new HashMap<>(); + presentation.put(VERIFIABLE_CREDENTIAL, Arrays.asList(data)); + presentation.put(OPTIONS, Arrays.asList(options)); + return new String(serialize(presentation), UTF_8); + } else { + throw new AccessGrantException("Invalid Access Grant: missing SolidAccessGrant type"); + } + } + VerificationResponse processVerificationResult(final InputStream input) throws IOException { return jsonService.fromJson(input, VerificationResponse.class); } From 75420db5e176048958a360ad8a3514b89380e5f7 Mon Sep 17 00:00:00 2001 From: Timea Turdean <4144203+timea-solid@users.noreply.github.com> Date: Fri, 14 Apr 2023 12:12:16 +0200 Subject: [PATCH 3/4] took out options --- .../client/accessgrant/AccessGrantClient.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java index 79376555aad..fda0d4011f4 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java @@ -81,7 +81,6 @@ public class AccessGrantClient { private static final String VC_CONTEXT_URI = "https://www.w3.org/2018/credentials/v1"; private static final String INRUPT_CONTEXT_URI = "https://schema.inrupt.com/credentials/v1.jsonld"; private static final String VERIFIABLE_CREDENTIAL = "verifiableCredential"; - private static final String OPTIONS = "options"; private static final String TYPE = "type"; private static final String APPLICATION_JSON = "application/json"; private static final String CONTENT_TYPE = "Content-Type"; @@ -208,12 +207,11 @@ public CompletionStage issue(final URI type, final URI agent, final * @param options the options to which this credential applies * @return the next stage of completion containing the resulting credential */ - public CompletionStage verify(final AccessGrant accessGrant, final Set options) { + public CompletionStage verify(final AccessGrant accessGrant) { return v1Metadata().thenCompose(metadata -> { final Map presentation = new HashMap<>(); presentation.put(VERIFIABLE_CREDENTIAL, accessGrant); - presentation.put(OPTIONS, Arrays.asList(options)); final Request req = Request.newBuilder(metadata.verifyEndpoint) .header(CONTENT_TYPE, APPLICATION_JSON) @@ -375,22 +373,6 @@ AccessGrant processVerifiableCredential(final InputStream input, final Set validTypes, final Set options) throws IOException { - final Map data = jsonService.fromJson(input, - new HashMap(){}.getClass().getGenericSuperclass()); - final Set types = AccessGrant.asSet(data.get(TYPE)).orElseThrow(() -> - new AccessGrantException("Invalid Access Grant: no 'type' field")); - types.retainAll(validTypes); - if (!types.isEmpty()) { - final Map presentation = new HashMap<>(); - presentation.put(VERIFIABLE_CREDENTIAL, Arrays.asList(data)); - presentation.put(OPTIONS, Arrays.asList(options)); - return new String(serialize(presentation), UTF_8); - } else { - throw new AccessGrantException("Invalid Access Grant: missing SolidAccessGrant type"); - } - } - VerificationResponse processVerificationResult(final InputStream input) throws IOException { return jsonService.fromJson(input, VerificationResponse.class); } From 879fd1638f4ad71dfc2e6ac130ed55c5be4bc4b2 Mon Sep 17 00:00:00 2001 From: Timea Turdean <4144203+timea-solid@users.noreply.github.com> Date: Fri, 14 Apr 2023 14:17:23 +0200 Subject: [PATCH 4/4] checkstyle fixes --- .../java/com/inrupt/client/accessgrant/AccessGrantClient.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java index fda0d4011f4..b44272fe8a9 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java @@ -204,12 +204,11 @@ public CompletionStage issue(final URI type, final URI agent, final * Verify an access grant or request. * * @param accessGrant the access grant to verify - * @param options the options to which this credential applies * @return the next stage of completion containing the resulting credential */ public CompletionStage verify(final AccessGrant accessGrant) { return v1Metadata().thenCompose(metadata -> { - + final Map presentation = new HashMap<>(); presentation.put(VERIFIABLE_CREDENTIAL, accessGrant);