FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

JCL-474: Link access grants and denials to originating requests by acoburn · Pull Request #1716 · inrupt/solid-client-java · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .java  (6) .json  (2) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ public static class CredentialData {
private final Set<URI> purposes;
private final Set<URI> resources;
private final URI recipient;
private final URI accessRequest;

/**
* Create a collection of user-managed credential data.
Expand All @@ -293,10 +294,25 @@ public static class CredentialData {
*/
public CredentialData(final Set<URI> resources, final Set<String> modes,
final Set<URI> purposes, final URI recipient) {
this(resources, modes, purposes, recipient, null);
}

/**
* Create a collection of user-managed credential data.
*
* @param resources the resources referenced by the credential
* @param modes the access modes defined by this credential
* @param purposes the purposes associated with this credential
* @param recipient the recipient for this credential, may be {@code null}
* @param accessRequest the access request identifier, may be {@code null}
*/
public CredentialData(final Set<URI> resources, final Set<String> modes,
final Set<URI> purposes, final URI recipient, final URI accessRequest) {
this.modes = Objects.requireNonNull(modes, "modes may not be null!");
this.purposes = Objects.requireNonNull(purposes, "purposes may not be null!");
this.resources = Objects.requireNonNull(resources, "resources may not be null!");
this.recipient = recipient;
this.accessRequest = accessRequest;
}

/**
Expand Down Expand Up @@ -334,6 +350,15 @@ public Set<URI> getResources() {
public URI getRecipient() {
return recipient;
}

/**
* Get the access request identifier associated with this credential.
*
* @return the access request identifier, may be {@code null}
*/
public URI getAccessRequest() {
return accessRequest;
}
}

static CredentialMetadata extractMetadata(final Map<String, Object> data) {
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class AccessDenial extends AccessCredential {
private static final Set<String> supportedTypes = getSupportedTypes();
private static final JsonService jsonService = ServiceProvider.getJsonService();

private final URI accessRequest;

/**
* Read a verifiable presentation as an AccessDenial.
*
Expand All @@ -60,6 +62,16 @@ public class AccessDenial extends AccessCredential {
protected AccessDenial(final URI identifier, final String credential, final CredentialData data,
final CredentialMetadata metadata) {
super(identifier, credential, data, metadata);
this.accessRequest = data.getAccessRequest();
}

/**
* Get the corresponding access request identifier.
*
* @return the access request identifier, may be {@code null}
*/
public URI getAccessRequest() {
return accessRequest;
}

/**
Expand Down Expand Up @@ -127,12 +139,14 @@ static AccessDenial parse(final String serialization) throws IOException {
final Optional<URI> other = asUri(consent.get("isProvidedTo"));

final URI recipient = person.orElseGet(() -> controller.orElseGet(() -> other.orElse(null)));
final URI accessRequest = asUri(consent.get("request")).orElse(null);
final Set<String> modes = asSet(consent.get("mode")).orElseGet(Collections::emptySet);
final Set<URI> resources = asSet(consent.get("forPersonalData")).orElseGet(Collections::emptySet)
.stream().map(URI::create).collect(Collectors.toSet());
final Set<URI> purposes = asSet(consent.get("forPurpose")).orElseGet(Collections::emptySet)
.stream().flatMap(AccessCredential::filterUris).collect(Collectors.toSet());
final CredentialData credentialData = new CredentialData(resources, modes, purposes, recipient);
final CredentialData credentialData = new CredentialData(resources, modes, purposes, recipient,
accessRequest);

return new AccessDenial(identifier, serialization, credentialData, credentialMetadata);
} else {
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class AccessGrant extends AccessCredential {
private static final Set<String> supportedTypes = getSupportedTypes();
private static final JsonService jsonService = ServiceProvider.getJsonService();

private final URI accessRequest;

/**
* Read a verifiable presentation as an AccessGrant.
*
Expand All @@ -60,6 +62,16 @@ public class AccessGrant extends AccessCredential {
protected AccessGrant(final URI identifier, final String credential, final CredentialData data,
final CredentialMetadata metadata) {
super(identifier, credential, data, metadata);
this.accessRequest = data.getAccessRequest();
}

/**
* Get the corresponding access request identifier.
*
* @return the access request identifier, may be {@code null}
*/
public URI getAccessRequest() {
return accessRequest;
}

/**
Expand Down Expand Up @@ -126,12 +138,14 @@ static AccessGrant parse(final String serialization) throws IOException {
final Optional<URI> other = asUri(consent.get("isProvidedTo"));

final URI recipient = person.orElseGet(() -> controller.orElseGet(() -> other.orElse(null)));
final URI accessRequest = asUri(consent.get("request")).orElse(null);
final Set<String> modes = asSet(consent.get("mode")).orElseGet(Collections::emptySet);
final Set<URI> resources = asSet(consent.get("forPersonalData")).orElseGet(Collections::emptySet)
.stream().map(URI::create).collect(Collectors.toSet());
final Set<URI> purposes = asSet(consent.get("forPurpose")).orElseGet(Collections::emptySet)
.stream().flatMap(AccessCredential::filterUris).collect(Collectors.toSet());
final CredentialData credentialData = new CredentialData(resources, modes, purposes, recipient);
final CredentialData credentialData = new CredentialData(resources, modes, purposes, recipient,
accessRequest);

return new AccessGrant(identifier, serialization, credentialData, credentialMetadata);
} else {
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public class AccessGrantClient {
private static final String IS_CONSENT_FOR_DATA_SUBJECT = "isConsentForDataSubject";
private static final String FOR_PERSONAL_DATA = "forPersonalData";
private static final String HAS_STATUS = "hasStatus";
private static final String REQUEST = "request";
private static final String MODE = "mode";
private static final String PROVIDED_CONSENT = "providedConsent";
private static final String FOR_PURPOSE = "forPurpose";
Expand Down Expand Up @@ -260,7 +261,8 @@ public CompletionStage<AccessGrant> grantAccess(final AccessRequest request) {
Objects.requireNonNull(request, "Request may not be null!");
return v1Metadata().thenCompose(metadata -> {
final Map<String, Object> data = buildAccessGrantv1(request.getCreator(), request.getResources(),
request.getModes(), request.getPurposes(), request.getExpiration(), request.getIssuedAt());
request.getModes(), request.getPurposes(), request.getExpiration(), request.getIssuedAt(),
request.getIdentifier());
final Request req = Request.newBuilder(metadata.issueEndpoint)
.header(CONTENT_TYPE, APPLICATION_JSON)
.POST(Request.BodyPublishers.ofByteArray(serialize(data))).build();
Expand Down Expand Up @@ -292,7 +294,8 @@ public CompletionStage<AccessDenial> denyAccess(final AccessRequest request) {
Objects.requireNonNull(request, "Request may not be null!");
return v1Metadata().thenCompose(metadata -> {
final Map<String, Object> data = buildAccessDenialv1(request.getCreator(), request.getResources(),
request.getModes(), request.getPurposes(), request.getExpiration(), request.getIssuedAt());
request.getModes(), request.getPurposes(), request.getExpiration(), request.getIssuedAt(),
request.getIdentifier());
final Request req = Request.newBuilder(metadata.issueEndpoint)
.header(CONTENT_TYPE, APPLICATION_JSON)
.POST(Request.BodyPublishers.ofByteArray(serialize(data))).build();
Expand Down Expand Up @@ -799,13 +802,14 @@ static URI asUri(final Object value) {
}

static Map<String, Object> buildAccessDenialv1(final URI agent, final Set<URI> resources, final Set<String> modes,
final Set<URI> purposes, final Instant expiration, final Instant issuance) {
final Set<URI> purposes, final Instant expiration, final Instant issuance, final URI accessRequest) {
Objects.requireNonNull(agent, "Access denial agent may not be null!");
final Map<String, Object> consent = new HashMap<>();
consent.put(MODE, modes);
consent.put(HAS_STATUS, "https://w3id.org/GConsent#ConsentStatusRefused");
consent.put(FOR_PERSONAL_DATA, resources);
consent.put(IS_PROVIDED_TO, agent);
consent.put(REQUEST, accessRequest);
if (!purposes.isEmpty()) {
consent.put(FOR_PURPOSE, purposes);
}
Expand All @@ -829,13 +833,14 @@ static Map<String, Object> buildAccessDenialv1(final URI agent, final Set<URI> r
}

static Map<String, Object> buildAccessGrantv1(final URI agent, final Set<URI> resources, final Set<String> modes,
final Set<URI> purposes, final Instant expiration, final Instant issuance) {
final Set<URI> purposes, final Instant expiration, final Instant issuance, final URI accessRequest) {
Objects.requireNonNull(agent, "Access grant agent may not be null!");
final Map<String, Object> consent = new HashMap<>();
consent.put(MODE, modes);
consent.put(HAS_STATUS, "https://w3id.org/GConsent#ConsentStatusExplicitlyGiven");
consent.put(FOR_PERSONAL_DATA, resources);
consent.put(IS_PROVIDED_TO, agent);
consent.put(REQUEST, accessRequest);
if (!purposes.isEmpty()) {
consent.put(FOR_PURPOSE, purposes);
}
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void testReadAccessDenial() throws IOException {
expectedTypes.add("VerifiableCredential");
expectedTypes.add("SolidAccessDenial");
assertEquals(expectedTypes, denial.getTypes());
assertEquals(URI.create("https://accessrequest.test/5678"), denial.getAccessRequest());
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"),
Expand Down Expand Up @@ -80,6 +81,7 @@ void testReadAccessDenialQualifiedName() throws IOException {
final Set<String> expectedTypes = new HashSet<>();
expectedTypes.add("VerifiableCredential");
expectedTypes.add("vc:SolidAccessDenial");
assertNull(denial.getAccessRequest());
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());
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void testReadAccessGrant() throws IOException {
expectedTypes.add("VerifiableCredential");
expectedTypes.add("SolidAccessGrant");
assertEquals(expectedTypes, grant.getTypes());
assertNull(grant.getAccessRequest());
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"),
Expand Down Expand Up @@ -83,6 +84,7 @@ void testReadAccessGrantQualifiedName() throws IOException {
expectedTypes.add("VerifiableCredential");
expectedTypes.add("vc:SolidAccessGrant");
assertEquals(expectedTypes, grant.getTypes());
assertEquals(URI.create("https://accessrequest.example/1234"), grant.getAccessRequest());
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"),
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"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"],
"https://schema.inrupt.com/credentials/v2.jsonld"],
"id":"https://accessgrant.test/credential/fc2dbcd9-81d4-4fa4-8fd4-239e16dd83ab",
"type":["VerifiableCredential","SolidAccessDenial"],
"issuer":"https://accessgrant.test",
Expand All @@ -21,6 +21,7 @@
"id":"https://id.test/grantor",
"providedConsent":{
"mode":["Read"],
"request": "https://accessrequest.test/5678",
"hasStatus":"https://w3id.org/GConsent#ConsentStatusRefused",
"isProvidedTo":"https://id.test/grantee",
"forPurpose":["https://purpose.test/Purpose1"],
Expand Down
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"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"],
"https://schema.inrupt.com/credentials/v2.jsonld"],
"id":"https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626",
"type":["VerifiableCredential","vc:SolidAccessGrant"],
"issuer":"https://accessgrant.example",
Expand All @@ -20,6 +20,7 @@
"credentialSubject":{
"id":"https://id.example/grantor",
"providedConsent":{
"request":"https://accessrequest.example/1234",
"mode":["Read"],
"hasStatus":"https://w3id.org/GConsent#ConsentStatusExplicitlyGiven",
"isProvidedTo":"https://id.example/grantee",
Expand Down

Back | FazBrowse Home | New Git URL