diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessDenial.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessDenial.java index ffb9c4d7b83..939e93b1559 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessDenial.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessDenial.java @@ -93,6 +93,7 @@ public static AccessDenial of(final InputStream serialization) { static Set getSupportedTypes() { final Set types = new HashSet<>(); types.add("SolidAccessDenial"); + types.add("vc:SolidAccessDenial"); types.add("http://www.w3.org/ns/solid/vc#SolidAccessDenial"); return Collections.unmodifiableSet(types); } diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrant.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrant.java index ab5ab7e7e75..9728d817535 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrant.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrant.java @@ -93,6 +93,7 @@ public static AccessGrant of(final InputStream serialization) { static Set getSupportedTypes() { final Set types = new HashSet<>(); types.add("SolidAccessGrant"); + types.add("vc:SolidAccessGrant"); types.add("http://www.w3.org/ns/solid/vc#SolidAccessGrant"); return Collections.unmodifiableSet(types); } 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 fd243795185..f754f079466 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 @@ -94,6 +94,7 @@ public class AccessGrantClient { 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 SOLID_VC_NAMESPACE = "http://www.w3.org/ns/solid/vc#"; + private static final String SOLID_VC_QN = "vc:"; private static final String TYPE = "type"; private static final String APPLICATION_JSON = "application/json"; private static final String CONTENT_TYPE = "Content-Type"; @@ -114,6 +115,9 @@ public class AccessGrantClient { private static final URI FQ_ACCESS_GRANT = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_GRANT); private static final URI FQ_ACCESS_REQUEST = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_REQUEST); private static final URI FQ_ACCESS_DENIAL = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_DENIAL); + private static final URI QN_ACCESS_GRANT = URI.create(SOLID_VC_QN + SOLID_ACCESS_GRANT); + private static final URI QN_ACCESS_REQUEST = URI.create(SOLID_VC_QN + SOLID_ACCESS_REQUEST); + private static final URI QN_ACCESS_DENIAL = URI.create(SOLID_VC_QN + SOLID_ACCESS_DENIAL); private static final Set ACCESS_GRANT_TYPES = getAccessGrantTypes(); private static final Set ACCESS_REQUEST_TYPES = getAccessRequestTypes(); private static final Set ACCESS_DENIAL_TYPES = getAccessDenialTypes(); @@ -785,6 +789,7 @@ static boolean isSuccess(final int statusCode) { static Set getAccessRequestTypes() { final Set types = new HashSet<>(); types.add(SOLID_ACCESS_REQUEST); + types.add(QN_ACCESS_REQUEST.toString()); types.add(FQ_ACCESS_REQUEST.toString()); return Collections.unmodifiableSet(types); } @@ -792,6 +797,7 @@ static Set getAccessRequestTypes() { static Set getAccessGrantTypes() { final Set types = new HashSet<>(); types.add(SOLID_ACCESS_GRANT); + types.add(QN_ACCESS_GRANT.toString()); types.add(FQ_ACCESS_GRANT.toString()); return Collections.unmodifiableSet(types); } @@ -799,19 +805,23 @@ static Set getAccessGrantTypes() { static Set getAccessDenialTypes() { final Set types = new HashSet<>(); types.add(SOLID_ACCESS_DENIAL); + types.add(QN_ACCESS_DENIAL.toString()); types.add(FQ_ACCESS_DENIAL.toString()); return Collections.unmodifiableSet(types); } static boolean isAccessGrant(final URI type) { - return SOLID_ACCESS_GRANT.equals(type.toString()) || FQ_ACCESS_GRANT.equals(type); + return SOLID_ACCESS_GRANT.equals(type.toString()) || QN_ACCESS_GRANT.equals(type) + || FQ_ACCESS_GRANT.equals(type); } static boolean isAccessRequest(final URI type) { - return SOLID_ACCESS_REQUEST.equals(type.toString()) || FQ_ACCESS_REQUEST.equals(type); + return SOLID_ACCESS_REQUEST.equals(type.toString()) || QN_ACCESS_REQUEST.equals(type) + || FQ_ACCESS_REQUEST.equals(type); } static boolean isAccessDenial(final URI type) { - return SOLID_ACCESS_DENIAL.equals(type.toString()) || FQ_ACCESS_DENIAL.equals(type); + return SOLID_ACCESS_DENIAL.equals(type.toString()) || QN_ACCESS_DENIAL.equals(type) + || FQ_ACCESS_DENIAL.equals(type); } } diff --git a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessRequest.java b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessRequest.java index 75c4f090b69..5c3b33b6612 100644 --- a/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessRequest.java +++ b/access-grant/src/main/java/com/inrupt/client/accessgrant/AccessRequest.java @@ -94,6 +94,7 @@ public static AccessRequest of(final InputStream serialization) { static Set getSupportedTypes() { final Set types = new HashSet<>(); types.add("SolidAccessRequest"); + types.add("vc:SolidAccessRequest"); types.add("http://www.w3.org/ns/solid/vc#SolidAccessRequest"); return Collections.unmodifiableSet(types); } diff --git a/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessDenialTest.java b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessDenialTest.java new file mode 100644 index 00000000000..e8fd27536a4 --- /dev/null +++ b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessDenialTest.java @@ -0,0 +1,104 @@ +/* + * Copyright Inrupt Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.inrupt.client.accessgrant; + +import static org.junit.jupiter.api.Assertions.*; + +import com.inrupt.client.spi.JsonService; +import com.inrupt.client.spi.ServiceProvider; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.time.Instant; +import java.util.Collections; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +class AccessDenialTest { + + private static final JsonService jsonService = ServiceProvider.getJsonService(); + + @Test + void testReadAccessDenial() throws IOException { + try (final InputStream resource = AccessDenialTest.class.getResourceAsStream("/access_denial1.json")) { + final AccessDenial denial = AccessDenial.of(resource); + assertEquals(Collections.singleton("Read"), denial.getModes()); + assertEquals(URI.create("https://accessgrant.test"), denial.getIssuer()); + final Set expectedTypes = new HashSet<>(); + expectedTypes.add("VerifiableCredential"); + expectedTypes.add("SolidAccessDenial"); + assertEquals(expectedTypes, denial.getTypes()); + assertEquals(Instant.parse("2022-08-27T12:00:00Z"), denial.getExpiration()); + assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), denial.getIssuedAt()); + assertEquals(URI.create("https://accessgrant.test/credential/fc2dbcd9-81d4-4fa4-8fd4-239e16dd83ab"), + denial.getIdentifier()); + assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), denial.getPurposes()); + assertEquals(Collections.singleton( + URI.create("https://storage.test/e973cc3d-5c28-4a10-98c5-e40079289358/")), + denial.getResources()); + assertEquals(URI.create("https://id.test/grantor"), denial.getCreator()); + assertEquals(Optional.of(URI.create("https://id.test/grantee")), denial.getRecipient()); + final Optional status = denial.getStatus(); + assertTrue(status.isPresent()); + status.ifPresent(s -> { + assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier()); + assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential()); + assertEquals(2832, s.getIndex()); + assertEquals("RevocationList2020Status", s.getType()); + }); + } + } + + @Test + void testReadAccessDenialQualifiedName() throws IOException { + try (final InputStream resource = AccessDenialTest.class.getResourceAsStream("/access_denial2.json")) { + final AccessDenial denial = AccessDenial.of(resource); + assertEquals(Collections.singleton("Read"), denial.getModes()); + assertEquals(URI.create("https://accessgrant.test"), denial.getIssuer()); + final Set expectedTypes = new HashSet<>(); + expectedTypes.add("VerifiableCredential"); + expectedTypes.add("vc:SolidAccessDenial"); + assertEquals(expectedTypes, denial.getTypes()); + assertEquals(Instant.parse("2022-08-27T12:00:00Z"), denial.getExpiration()); + assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), denial.getIssuedAt()); + assertEquals(URI.create("https://accessgrant.test/credential/39a4fdd4-44b0-48a5-a9b5-7a9b648e9a67"), + denial.getIdentifier()); + assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), denial.getPurposes()); + assertEquals(Collections.singleton( + URI.create("https://storage.test/d5ef4173-4f12-40b2-9a0e-18fa7cc0dd38/")), + denial.getResources()); + assertEquals(URI.create("https://id.test/grantor"), denial.getCreator()); + assertEquals(Optional.of(URI.create("https://id.test/grantee")), denial.getRecipient()); + final Optional status = denial.getStatus(); + assertTrue(status.isPresent()); + status.ifPresent(s -> { + assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier()); + assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential()); + assertEquals(2832, s.getIndex()); + assertEquals("RevocationList2020Status", s.getType()); + }); + } + } +} diff --git a/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantTest.java b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantTest.java index 3e9f67c3ec0..23fd54d864a 100644 --- a/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantTest.java +++ b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantTest.java @@ -73,6 +73,37 @@ void testReadAccessGrant() throws IOException { } } + @Test + void testReadAccessGrantQualifiedName() throws IOException { + try (final InputStream resource = AccessGrantTest.class.getResourceAsStream("/access_grant4.json")) { + final AccessGrant grant = AccessGrant.of(resource); + assertEquals(Collections.singleton("Read"), grant.getModes()); + assertEquals(URI.create("https://accessgrant.example"), grant.getIssuer()); + final Set expectedTypes = new HashSet<>(); + expectedTypes.add("VerifiableCredential"); + expectedTypes.add("vc:SolidAccessGrant"); + assertEquals(expectedTypes, grant.getTypes()); + assertEquals(Instant.parse("2022-08-27T12:00:00Z"), grant.getExpiration()); + assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), grant.getIssuedAt()); + assertEquals(URI.create("https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626"), + grant.getIdentifier()); + assertEquals(Collections.singleton(URI.create("https://purpose.example/Purpose1")), grant.getPurposes()); + assertEquals(Collections.singleton( + URI.create("https://storage.example/e973cc3d-5c28-4a10-98c5-e40079289358/")), + grant.getResources()); + assertEquals(URI.create("https://id.example/grantor"), grant.getCreator()); + assertEquals(Optional.of(URI.create("https://id.example/grantee")), grant.getRecipient()); + final Optional status = grant.getStatus(); + assertTrue(status.isPresent()); + status.ifPresent(s -> { + assertEquals(URI.create("https://accessgrant.example/status/CVAM#2832"), s.getIdentifier()); + assertEquals(URI.create("https://accessgrant.example/status/CVAM"), s.getCredential()); + assertEquals(2832, s.getIndex()); + assertEquals("RevocationList2020Status", s.getType()); + }); + } + } + @Test void testReadAccessGrantSingletons() throws IOException { try (final InputStream resource = AccessGrantTest.class.getResourceAsStream("/access_grant2.json")) { diff --git a/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessRequestTest.java b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessRequestTest.java index fe3059af83c..3baf4aea9a6 100644 --- a/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessRequestTest.java +++ b/access-grant/src/test/java/com/inrupt/client/accessgrant/AccessRequestTest.java @@ -100,7 +100,6 @@ void testBuilderWithCollections() { assertNull(params.getIssuedAt()); } - @Test void testReadAccessRequest() throws IOException { try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request1.json")) { @@ -132,6 +131,37 @@ void testReadAccessRequest() throws IOException { } } + @Test + void testReadAccessRequestQualifiedName() throws IOException { + try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request3.json")) { + final AccessRequest request = AccessRequest.of(resource); + assertEquals(Collections.singleton("Read"), request.getModes()); + assertEquals(URI.create("https://accessgrant.test"), request.getIssuer()); + final Set expectedTypes = new HashSet<>(); + expectedTypes.add("VerifiableCredential"); + expectedTypes.add("vc:SolidAccessRequest"); + assertEquals(expectedTypes, request.getTypes()); + assertEquals(Instant.parse("2022-08-27T12:00:00Z"), request.getExpiration()); + assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), request.getIssuedAt()); + assertEquals(URI.create("https://accessgrant.test/credential/d604c858-209a-4bb6-a7f8-2f52c9617cab"), + request.getIdentifier()); + assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), request.getPurposes()); + assertEquals(Collections.singleton( + URI.create("https://storage.test/data/")), + request.getResources()); + assertEquals(URI.create("https://id.test/username"), request.getCreator()); + assertEquals(Optional.of(URI.create("https://id.test/agent")), request.getRecipient()); + final Optional status = request.getStatus(); + assertTrue(status.isPresent()); + status.ifPresent(s -> { + assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier()); + assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential()); + assertEquals(2832, s.getIndex()); + assertEquals("RevocationList2020Status", s.getType()); + }); + } + } + @Test void testReadAccessRequestSingletons() throws IOException { try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request2.json")) { diff --git a/access-grant/src/test/resources/access_denial1.json b/access-grant/src/test/resources/access_denial1.json new file mode 100644 index 00000000000..872e786481f --- /dev/null +++ b/access-grant/src/test/resources/access_denial1.json @@ -0,0 +1,36 @@ +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], + "verifiableCredential": [{ + "@context":[ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc-revocation-list-2020/v1", + "https://schema.inrupt.com/credentials/v1.jsonld"], + "id":"https://accessgrant.test/credential/fc2dbcd9-81d4-4fa4-8fd4-239e16dd83ab", + "type":["VerifiableCredential","SolidAccessDenial"], + "issuer":"https://accessgrant.test", + "expirationDate":"2022-08-27T12:00:00Z", + "issuanceDate":"2022-08-25T20:34:05.153Z", + "credentialStatus":{ + "id":"https://accessgrant.test/status/CVAM#2832", + "revocationListCredential":"https://accessgrant.test/status/CVAM", + "revocationListIndex":"2832", + "type":"RevocationList2020Status"}, + "credentialSubject":{ + "id":"https://id.test/grantor", + "providedConsent":{ + "mode":["Read"], + "hasStatus":"https://w3id.org/GConsent#ConsentStatusRefused", + "isProvidedTo":"https://id.test/grantee", + "forPurpose":["https://purpose.test/Purpose1"], + "forPersonalData":["https://storage.test/e973cc3d-5c28-4a10-98c5-e40079289358/"]}}, + "proof":{ + "created":"2022-08-25T20:34:05.236Z", + "proofPurpose":"assertionMethod", + "proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ", + "type":"Ed25519Signature2020", + "verificationMethod":"https://accessgrant.test/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"} + }] +} + diff --git a/access-grant/src/test/resources/access_denial2.json b/access-grant/src/test/resources/access_denial2.json new file mode 100644 index 00000000000..6aa36ce336a --- /dev/null +++ b/access-grant/src/test/resources/access_denial2.json @@ -0,0 +1,36 @@ +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], + "verifiableCredential": [{ + "@context":[ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc-revocation-list-2020/v1", + "https://schema.inrupt.com/credentials/v1.jsonld"], + "id":"https://accessgrant.test/credential/39a4fdd4-44b0-48a5-a9b5-7a9b648e9a67", + "type":["VerifiableCredential","vc:SolidAccessDenial"], + "issuer":"https://accessgrant.test", + "expirationDate":"2022-08-27T12:00:00Z", + "issuanceDate":"2022-08-25T20:34:05.153Z", + "credentialStatus":{ + "id":"https://accessgrant.test/status/CVAM#2832", + "revocationListCredential":"https://accessgrant.test/status/CVAM", + "revocationListIndex":"2832", + "type":"RevocationList2020Status"}, + "credentialSubject":{ + "id":"https://id.test/grantor", + "providedConsent":{ + "mode":["Read"], + "hasStatus":"https://w3id.org/GConsent#ConsentStatusRefused", + "isProvidedTo":"https://id.test/grantee", + "forPurpose":["https://purpose.test/Purpose1"], + "forPersonalData":["https://storage.test/d5ef4173-4f12-40b2-9a0e-18fa7cc0dd38/"]}}, + "proof":{ + "created":"2022-08-25T20:34:05.236Z", + "proofPurpose":"assertionMethod", + "proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ", + "type":"Ed25519Signature2020", + "verificationMethod":"https://accessgrant.test/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"} + }] +} + diff --git a/access-grant/src/test/resources/access_grant4.json b/access-grant/src/test/resources/access_grant4.json new file mode 100644 index 00000000000..ca14c72251e --- /dev/null +++ b/access-grant/src/test/resources/access_grant4.json @@ -0,0 +1,36 @@ +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], + "verifiableCredential": [{ + "@context":[ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc-revocation-list-2020/v1", + "https://schema.inrupt.com/credentials/v1.jsonld"], + "id":"https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626", + "type":["VerifiableCredential","vc:SolidAccessGrant"], + "issuer":"https://accessgrant.example", + "expirationDate":"2022-08-27T12:00:00Z", + "issuanceDate":"2022-08-25T20:34:05.153Z", + "credentialStatus":{ + "id":"https://accessgrant.example/status/CVAM#2832", + "revocationListCredential":"https://accessgrant.example/status/CVAM", + "revocationListIndex":"2832", + "type":"RevocationList2020Status"}, + "credentialSubject":{ + "id":"https://id.example/grantor", + "providedConsent":{ + "mode":["Read"], + "hasStatus":"https://w3id.org/GConsent#ConsentStatusExplicitlyGiven", + "isProvidedTo":"https://id.example/grantee", + "forPurpose":["https://purpose.example/Purpose1"], + "forPersonalData":["https://storage.example/e973cc3d-5c28-4a10-98c5-e40079289358/"]}}, + "proof":{ + "created":"2022-08-25T20:34:05.236Z", + "proofPurpose":"assertionMethod", + "proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ", + "type":"Ed25519Signature2020", + "verificationMethod":"https://accessgrant.example/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"} + }] +} + diff --git a/access-grant/src/test/resources/access_request3.json b/access-grant/src/test/resources/access_request3.json new file mode 100644 index 00000000000..aa0754cc4ec --- /dev/null +++ b/access-grant/src/test/resources/access_request3.json @@ -0,0 +1,36 @@ +{ + "@context": ["https://www.w3.org/2018/credentials/v1"], + "type": ["VerifiablePresentation"], + "verifiableCredential": [{ + "@context":[ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/security/suites/ed25519-2020/v1", + "https://w3id.org/vc-revocation-list-2020/v1", + "https://schema.inrupt.com/credentials/v1.jsonld"], + "id":"https://accessgrant.test/credential/d604c858-209a-4bb6-a7f8-2f52c9617cab", + "type":["VerifiableCredential","vc:SolidAccessRequest"], + "issuer":"https://accessgrant.test", + "expirationDate":"2022-08-27T12:00:00Z", + "issuanceDate":"2022-08-25T20:34:05.153Z", + "credentialStatus":{ + "id":"https://accessgrant.test/status/CVAM#2832", + "revocationListCredential":"https://accessgrant.test/status/CVAM", + "revocationListIndex":"2832", + "type":"RevocationList2020Status"}, + "credentialSubject":{ + "id":"https://id.test/username", + "hasConsent":{ + "mode":["Read"], + "hasStatus":"https://w3id.org/GConsent#ConsentStatusRequested", + "isConsentForDataSubject":"https://id.test/agent", + "forPurpose":["https://purpose.test/Purpose1"], + "forPersonalData":["https://storage.test/data/"]}}, + "proof":{ + "created":"2022-08-25T20:34:05.236Z", + "proofPurpose":"assertionMethod", + "proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ", + "type":"Ed25519Signature2020", + "verificationMethod":"https://accessgrant.test/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"} + }] +} + diff --git a/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java b/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java index 5faa54e39ce..29d37ef43e8 100644 --- a/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java +++ b/integration/base/src/main/java/com/inrupt/client/integration/base/AccessGrantScenarios.java @@ -236,18 +236,28 @@ void accessGrantIssuanceLifecycleTest(final Session resourceOwnerSession, final ).session(resourceOwnerSession); final AccessGrant grant = resourceOwnerAccessGrantClient.grantAccess(request) .toCompletableFuture().join(); + final AccessDenial denial = resourceOwnerAccessGrantClient.denyAccess(request) + .toCompletableFuture().join(); //2. call verify endpoint to verify grant final var grantVerification = resourceOwnerAccessGrantClient.verify(grant).toCompletableFuture().join(); assertTrue(grantVerification.getChecks().size() > 0); assertEquals(grantVerification.getErrors().size(), 0); assertEquals(grantVerification.getWarnings().size(), 0); - final AccessGrant grantFromVcProvider = resourceOwnerAccessGrantClient.fetch(grant.getIdentifier(), AccessGrant.class) .toCompletableFuture().join(); assertEquals(grant.getPurposes(), grantFromVcProvider.getPurposes()); + final var denialVerification = resourceOwnerAccessGrantClient.verify(denial).toCompletableFuture().join(); + assertTrue(denialVerification.getChecks().size() > 0); + assertEquals(denialVerification.getErrors().size(), 0); + assertEquals(denialVerification.getWarnings().size(), 0); + final AccessDenial denialFromVcProvider = + resourceOwnerAccessGrantClient.fetch(denial.getIdentifier(), AccessDenial.class) + .toCompletableFuture().join(); + assertEquals(denial.getPurposes(), denialFromVcProvider.getPurposes()); + //unauthorized request test final SolidSyncClient requesterClient = SolidSyncClient.getClientBuilder().build(); final var err = assertThrows(UnauthorizedException.class, @@ -266,12 +276,19 @@ void accessGrantIssuanceLifecycleTest(final Session resourceOwnerSession, final assertDoesNotThrow(() -> requesterAuthClient.read(sharedTextFileURI, SolidNonRDFSource.class)); assertDoesNotThrow(resourceOwnerAccessGrantClient.revoke(grant).toCompletableFuture()::join); + assertDoesNotThrow(resourceOwnerAccessGrantClient.revoke(denial).toCompletableFuture()::join); //6. call verify endpoint to check the grant is not valid final var revokedGrantVerification = resourceOwnerAccessGrantClient.verify(grant).toCompletableFuture().join(); - assertTrue(grantVerification.getChecks().size() > 0); + assertTrue(revokedGrantVerification.getChecks().size() > 0); assertEquals(revokedGrantVerification.getErrors().size(), 1); - assertEquals(grantVerification.getWarnings().size(), 0); + assertEquals(revokedGrantVerification.getWarnings().size(), 0); + + final var revokedDenialVerification = resourceOwnerAccessGrantClient.verify(denial) + .toCompletableFuture().join(); + assertTrue(revokedDenialVerification.getChecks().size() > 0); + assertEquals(revokedDenialVerification.getErrors().size(), 1); + assertEquals(revokedDenialVerification.getWarnings().size(), 0); // Once revoked, the Access Grant should no longer grant access to the resource. The previously issued access // token may still be valid, so cache is cleared for the test.