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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ static CredentialMetadata extractMetadata(final Map data) {
statusTypes.contains(REVOCATION_LIST_2020_STATUS)).map(x ->
asRevocationList2020(credentialStatus))).orElse(null);

final Map subject = asMap(data.get("credentialSubject")).orElseThrow(() ->
final Map<String, Object> subject = asMap(data.get("credentialSubject")).orElseThrow(() ->
new IllegalArgumentException("Missing or invalid credentialSubject field"));

final URI creator = asUri(subject.get("id")).orElseThrow(() ->
Expand All @@ -324,8 +324,8 @@ static CredentialMetadata extractMetadata(final Map data) {
return new CredentialMetadata(issuer, creator, types, expiration, status);
}

static Map extractConsent(final Map data, final String property) {
final Map subject = asMap(data.get("credentialSubject")).orElseThrow(() ->
static Map<String, Object> extractConsent(final Map data, final String property) {
final Map<String, Object> subject = asMap(data.get("credentialSubject")).orElseThrow(() ->
new IllegalArgumentException("Missing or invalid credentialSubject field"));
return asMap(subject.get(property)).orElseThrow(() ->
// Unsupported structure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ static AccessDenial parse(final String serialization) throws IOException {
final Map<String, Object> data = jsonService.fromJson(in,
new HashMap<String, Object>(){}.getClass().getGenericSuperclass());

final List<Map> vcs = getCredentialsFromPresentation(data, supportedTypes);
final List<Map<String, Object>> vcs = getCredentialsFromPresentation(data, supportedTypes);
if (vcs.size() != 1) {
throw new IllegalArgumentException(
"Invalid Access Denial: ambiguous number of verifiable credentials");
}
final Map vc = vcs.get(0);
final Map<String, Object> vc = vcs.get(0);

if (asSet(data.get(TYPE)).orElseGet(Collections::emptySet).contains("VerifiablePresentation")) {
final URI identifier = asUri(vc.get("id")).orElseThrow(() ->
Expand All @@ -119,7 +119,7 @@ static AccessDenial parse(final String serialization) throws IOException {


// Extract V1 Access Denial data, using gConsent
final Map consent = extractConsent(vc, "providedConsent");
final Map<String, Object> consent = extractConsent(vc, "providedConsent");

final Optional<URI> person = asUri(consent.get("isProvidedToPerson"));
final Optional<URI> controller = asUri(consent.get("isProvidedToController"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,12 @@ static AccessGrant parse(final String serialization) throws IOException {
final Map<String, Object> data = jsonService.fromJson(in,
new HashMap<String, Object>(){}.getClass().getGenericSuperclass());

final List<Map> vcs = getCredentialsFromPresentation(data, supportedTypes);
final List<Map<String, Object>> vcs = getCredentialsFromPresentation(data, supportedTypes);
if (vcs.size() != 1) {
throw new IllegalArgumentException(
"Invalid Access Grant: ambiguous number of verifiable credentials");
}
final Map vc = vcs.get(0);
final Map<String, Object> vc = vcs.get(0);

if (asSet(data.get(TYPE)).orElseGet(Collections::emptySet).contains("VerifiablePresentation")) {
final URI identifier = asUri(vc.get("id")).orElseThrow(() ->
Expand All @@ -186,7 +186,7 @@ static AccessGrant parse(final String serialization) throws IOException {
final CredentialMetadata credentialMetadata = extractMetadata(vc);

// Extract V1 Access Grant data, using gConsent
final Map consent = extractConsent(vc, "providedConsent");
final Map<String, Object> consent = extractConsent(vc, "providedConsent");

final Optional<URI> person = asUri(consent.get("isProvidedToPerson"));
final Optional<URI> controller = asUri(consent.get("isProvidedToController"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ public class AccessGrantClient {
private static final String FOR_PERSONAL_DATA = "forPersonalData";
private static final String HAS_STATUS = "hasStatus";
private static final String MODE = "mode";
private static final String PROVIDED_CONSENT = "providedConsent";
private static final String FOR_PURPOSE = "forPurpose";
private static final String EXPIRATION_DATE = "expirationDate";
private static final String CREDENTIAL = "credential";
private static final URI ACCESS_GRANT = URI.create("http://www.w3.org/ns/solid/vc#SolidAccessGrant");
private static final URI ACCESS_REQUEST = URI.create("http://www.w3.org/ns/solid/vc#SolidAccessRequest");
private static final URI ACCESS_DENIAL = URI.create("http://www.w3.org/ns/solid/vc#SolidAccessDenial");
Expand Down Expand Up @@ -592,26 +596,24 @@ <T extends AccessCredential> List<T> processQueryResponse(final InputStream inpu
final Map<String, Object> data = jsonService.fromJson(input,
new HashMap<String, Object>(){}.getClass().getGenericSuperclass());
final List<T> grants = new ArrayList<>();
if (data.get(VERIFIABLE_CREDENTIAL) instanceof Collection) {
for (final Object item : (Collection) data.get(VERIFIABLE_CREDENTIAL)) {
Utils.asMap(item).ifPresent(credential ->
Utils.asSet(credential.get(TYPE)).ifPresent(types -> {
types.retainAll(validTypes);
if (!types.isEmpty()) {
final Map<String, Object> presentation = new HashMap<>();
presentation.put(CONTEXT, Arrays.asList(VC_CONTEXT_URI));
presentation.put(TYPE, Arrays.asList("VerifiablePresentation"));
presentation.put(VERIFIABLE_CREDENTIAL, Arrays.asList(credential));
if (AccessGrant.class.equals(clazz)) {
grants.add((T) AccessGrant.of(new String(serialize(presentation), UTF_8)));
} else if (AccessRequest.class.equals(clazz)) {
grants.add((T) AccessRequest.of(new String(serialize(presentation), UTF_8)));
} else if (AccessDenial.class.equals(clazz)) {
grants.add((T) AccessDenial.of(new String(serialize(presentation), UTF_8)));
}
for (final Object item : getCredentials(data)) {
Utils.asMap(item).ifPresent(credential ->
Utils.asSet(credential.get(TYPE)).ifPresent(types -> {
types.retainAll(validTypes);
if (!types.isEmpty()) {
final Map<String, Object> presentation = new HashMap<>();
presentation.put(CONTEXT, Arrays.asList(VC_CONTEXT_URI));
presentation.put(TYPE, Arrays.asList("VerifiablePresentation"));
presentation.put(VERIFIABLE_CREDENTIAL, Arrays.asList(credential));
if (AccessGrant.class.equals(clazz)) {
grants.add((T) AccessGrant.of(new String(serialize(presentation), UTF_8)));
} else if (AccessRequest.class.equals(clazz)) {
grants.add((T) AccessRequest.of(new String(serialize(presentation), UTF_8)));
} else if (AccessDenial.class.equals(clazz)) {
grants.add((T) AccessDenial.of(new String(serialize(presentation), UTF_8)));
}
}));
}
}
}));
}

return grants;
Expand Down Expand Up @@ -661,6 +663,14 @@ byte[] serialize(final Map<String, Object> data) {
}
}

static Collection<Object> getCredentials(final Map<String, Object> data) {
final Object credential = data.get(VERIFIABLE_CREDENTIAL);
if (credential instanceof Collection) {
return (Collection) credential;
}
return Collections.emptyList();
}

static List<Map<String, Object>> buildQuery(final URI issuer, final URI type, final URI agent, final URI resource,
final String mode) {
final List<Map<String, Object>> queries = new ArrayList<>();
Expand Down Expand Up @@ -693,7 +703,7 @@ static void buildQuery(final List<Map<String, Object>> queries, final URI issuer
final Map<String, Object> subject = new HashMap<>();
if (!consent.isEmpty()) {
if (isAccessGrant(type) || isAccessDenial(type)) {
subject.put("providedConsent", consent);
subject.put(PROVIDED_CONSENT, consent);
} else if (isAccessRequest(type)) {
subject.put("hasConsent", consent);
}
Expand Down Expand Up @@ -745,21 +755,21 @@ static Map<String, Object> buildAccessDenialv1(final URI agent, final Set<URI> r
consent.put(FOR_PERSONAL_DATA, resources);
consent.put(IS_PROVIDED_TO_PERSON, agent);
if (!purposes.isEmpty()) {
consent.put("forPurpose", purposes);
consent.put(FOR_PURPOSE, purposes);
}

final Map<String, Object> subject = new HashMap<>();
subject.put("providedConsent", consent);
subject.put(PROVIDED_CONSENT, consent);

final Map<String, Object> credential = new HashMap<>();
credential.put(CONTEXT, Arrays.asList(VC_CONTEXT_URI, INRUPT_CONTEXT_URI));
if (expiration != null) {
credential.put("expirationDate", expiration.truncatedTo(ChronoUnit.SECONDS).toString());
credential.put(EXPIRATION_DATE, expiration.truncatedTo(ChronoUnit.SECONDS).toString());
}
credential.put(CREDENTIAL_SUBJECT, subject);

final Map<String, Object> data = new HashMap<>();
data.put("credential", credential);
data.put(CREDENTIAL, credential);
return data;
}

Expand All @@ -772,21 +782,21 @@ static Map<String, Object> buildAccessGrantv1(final URI agent, final Set<URI> re
consent.put(FOR_PERSONAL_DATA, resources);
consent.put(IS_PROVIDED_TO_PERSON, agent);
if (!purposes.isEmpty()) {
consent.put("forPurpose", purposes);
consent.put(FOR_PURPOSE, purposes);
}

final Map<String, Object> subject = new HashMap<>();
subject.put("providedConsent", consent);
subject.put(PROVIDED_CONSENT, consent);

final Map<String, Object> credential = new HashMap<>();
credential.put(CONTEXT, Arrays.asList(VC_CONTEXT_URI, INRUPT_CONTEXT_URI));
if (expiration != null) {
credential.put("expirationDate", expiration.truncatedTo(ChronoUnit.SECONDS).toString());
credential.put(EXPIRATION_DATE, expiration.truncatedTo(ChronoUnit.SECONDS).toString());
}
credential.put(CREDENTIAL_SUBJECT, subject);

final Map<String, Object> data = new HashMap<>();
data.put("credential", credential);
data.put(CREDENTIAL, credential);
return data;
}

Expand All @@ -800,7 +810,7 @@ static Map<String, Object> buildAccessRequestv1(final URI agent, final Set<URI>
consent.put(IS_CONSENT_FOR_DATA_SUBJECT, agent);
}
if (!purposes.isEmpty()) {
consent.put("forPurpose", purposes);
consent.put(FOR_PURPOSE, purposes);
}

final Map<String, Object> subject = new HashMap<>();
Expand All @@ -809,12 +819,12 @@ static Map<String, Object> buildAccessRequestv1(final URI agent, final Set<URI>
final Map<String, Object> credential = new HashMap<>();
credential.put(CONTEXT, Arrays.asList(VC_CONTEXT_URI, INRUPT_CONTEXT_URI));
if (expiration != null) {
credential.put("expirationDate", expiration.truncatedTo(ChronoUnit.SECONDS).toString());
credential.put(EXPIRATION_DATE, expiration.truncatedTo(ChronoUnit.SECONDS).toString());
}
credential.put(CREDENTIAL_SUBJECT, subject);

final Map<String, Object> data = new HashMap<>();
data.put("credential", credential);
data.put(CREDENTIAL, credential);
return data;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public Optional<Credential> getCredential(final URI name, final URI uri) {
if (isAncestor(entry.getKey(), uri)) {
final AccessGrant grant = entry.getValue();
return Optional.of(new Credential("", grant.getIssuer(), Base64.getUrlEncoder().withoutPadding()
.encodeToString(grant.getRawGrant().getBytes(UTF_8)),
.encodeToString(grant.serialize().getBytes(UTF_8)),
grant.getExpiration(), session.getPrincipal().orElse(null), null));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ static AccessRequest parse(final String serialization) throws IOException {
final Map<String, Object> data = jsonService.fromJson(in,
new HashMap<String, Object>(){}.getClass().getGenericSuperclass());

final List<Map> vcs = getCredentialsFromPresentation(data, supportedTypes);
final List<Map<String, Object>> vcs = getCredentialsFromPresentation(data, supportedTypes);
if (vcs.size() != 1) {
throw new IllegalArgumentException(
"Invalid Access Request: ambiguous number of verifiable credentials");
}
final Map vc = vcs.get(0);
final Map<String, Object> vc = vcs.get(0);

if (asSet(data.get(TYPE)).orElseGet(Collections::emptySet).contains("VerifiablePresentation")) {
final URI identifier = asUri(vc.get("id")).orElseThrow(() ->
Expand All @@ -117,7 +117,7 @@ static AccessRequest parse(final String serialization) throws IOException {
final CredentialMetadata credentialMetadata = extractMetadata(vc);

// V1 Access Request, using gConsent
final Map consent = extractConsent(vc, "hasConsent");
final Map<String, Object> consent = extractConsent(vc, "hasConsent");

final URI recipient = asUri(consent.get("isConsentForDataSubject")).orElse(null);
final Set<String> modes = asSet(consent.get("mode")).orElseGet(Collections::emptySet);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class Utils {
private static final String TYPE = "type";
private static final String REVOCATION_LIST_2020_STATUS = "RevocationList2020Status";

public static Status asRevocationList2020(final Map credentialStatus) {
public static Status asRevocationList2020(final Map<String, Object> credentialStatus) {
try {
int idx = -1;
final Object index = credentialStatus.get("revocationListIndex");
Expand Down Expand Up @@ -72,9 +72,11 @@ public static Optional<URI> asUri(final Object value) {
return Optional.empty();
}

public static Optional<Map> asMap(final Object value) {
public static Optional<Map<String, Object>> asMap(final Object value) {
if (value instanceof Map) {
return Optional.of((Map) value);
@SuppressWarnings("unchecked")
final Map<String, Object> v = (Map<String, Object>) value;
return Optional.of(v);
}
return Optional.empty();
}
Expand All @@ -96,13 +98,14 @@ public static Optional<Set<String>> asSet(final Object value) {
return Optional.empty();
}

public static List<Map> getCredentialsFromPresentation(final Map<String, Object> data,
public static List<Map<String, Object>> getCredentialsFromPresentation(final Map<String, Object> data,
final Set<String> supportedTypes) {
final List<Map> credentials = new ArrayList<>();
final List<Map<String, Object>> credentials = new ArrayList<>();
if (data.get("verifiableCredential") instanceof Collection) {
for (final Object item : (Collection) data.get("verifiableCredential")) {
if (item instanceof Map) {
final Map vc = (Map) item;
@SuppressWarnings("unchecked")
final Map vc = (Map<String, Object>) item;
if (asSet(vc.get(TYPE)).filter(types ->
types.stream().anyMatch(supportedTypes::contains)).isPresent()) {
credentials.add(vc);
Expand All @@ -113,7 +116,6 @@ public static List<Map> getCredentialsFromPresentation(final Map<String, Object>
return credentials;
}


private Utils() {
// prevent instantiation
}
Expand Down