Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

15 Commits

Repository files navigation

Solid Web Access Control

This library implements checking Web Access Control rules in plain Java, (... sips coffee ...).

Software using this code needs to

  • define the bi-directional mapping between a resource and its corresponding .acl using the interface Example
  • provide a map between a resource URI string and an its corresponding RDF dataset as a Map<String, Dataset>.

Why is the resource-.acl mapping bi-directional? Why can't we use one .acl to rule them all? acl:Control allows modification of access control rules which have the same acl:target as the control rule. Allowing multiple rules with different targets, i.e. allowing one .acl to be authoritative for multiple target resources makes enforcing the control right unnecessarily complicated: You can't allow HTTP PUT or DELETE, if there exist rules for other resources, and you have to do in-depth checks of HTTP PATCH to not modify rules for other resources.

You can do this. But I chose not to.

For .acl checking using the (resource - RDF dataset) map, we check if the .acl dataset is present in the map. We then assume that the triples describing access control rules are placed in the default graph.

Example usage:

/** * Check the rules! If webid == null, then the request is assumed to be * unauthenticated. If webid != null, then the request is assumed to be * authenticated. * * @param resource the target of the HTTP request of an agent * @param method the HTTP action to be executed on the target resource * @param body MUST not be null, for PATCH the body should always be * provided, otherwise shouldnt * @param webid if != null, it is assumed to be authenticated * @param envResourceMap appplication environment resource map * @param envResourceAclMap application environement resource to * corresponding aclRDF map * @return the URI String of the matching access control rule or * {@code null} if none matches * */publicstaticStringcheckAccessControl(Stringresource, Stringmethod, Stringbody, Stringwebid, Map<String, Dataset> envResourceMap, WacMappingenvResourceAclMap) {
// get the query builder for the resource (may look for inherited rules)WacQueryBuilderqueryBuilder = WacQueryBuilder
.newBuilder(envResourceMap, envResourceAclMap)
.forRequest(resource, method, body)
.byAgent(webid);
WacQuery[] queries = queryBuilder.build();
for (WacQueryquery : queries) {
StringruleMatch = query.exec();
if (ruleMatch == null) {
continue;
}
returnruleMatch;
}
returnnull;
}

By the way, WAC does not really define behaviour for the HTTP method OPTIONS. OPTIONS is common for CORS pre-flight requests. Be sure to hanlde OPTIONS manually. Otherwise you may keep wondering why your code does not work.

Want to run an example directly? Naybe something like:

/** * example usage * * @param args */publicstaticvoidmain(String[] args) {
// mock application environmentWacMappingenvResourceAclMap = newResourceAclMap(); // ! IMPLEMENTATION DEPENDENTMap<String, Dataset> envResourceMap = newHashMap(); // ! IMPLEMENTATION DEPENDENTStringresource = "http://localhost:8080/marmotta/ldp/test";
Stringacl = envResourceAclMap.getAcl(resource);
System.out.println("ACL: " + acl);
StringsomeAcl = """ @prefix acl: <http://www.w3.org/ns/auth/acl#> <#testAgentGroupAccess> a acl:Authorization; acl:agent <http://example.org/webid>; acl:accessTo <test>; acl:mode acl:Write. """;
// Create an RDF dataset by parsing the Turtle dataDatasetdataset = DatasetFactory.create();
ModelaclRDF = dataset.getDefaultModel();
InputStreamstream = newByteArrayInputStream(someAcl.getBytes(StandardCharsets.UTF_8));
RDFDataMgr.read(aclRDF, stream, acl, Lang.TTL);
// Access the datasetSystem.out.println("RDF Dataset:");
dataset.getDefaultModel().write(System.out, "TTL"); // Example: Turtle formatenvResourceMap.put(acl, dataset);
// mock a HTTP requestStringwebid = "http://example.org/webid";
Stringmethod = "PATCH";
Stringbody = """ @prefix solid: <http://www.w3.org/ns/solid/terms#>. @prefix ex: <http://www.example.org/terms#>. _:rename a solid:InsertDeletePatch; solid:where { ?person ex:familyName \"Garcia\". }; solid:inserts { ?person ex:givenName \"Alex\". }; solid:deletes { ?person ex:givenName \"Claudia\". }. """;
// check WAC rulesStringruleGrantingAccess = checkAccessControl(resource, method, body, webid, envResourceMap, envResourceAclMap);
// resultSystem.out.println("\nAccess granted? " + ((ruleGrantingAccess == null) ? "No." : "Yes: " + ruleGrantingAccess));
// happy hackingSystem.exit(0);
}

Sure, after cloning this repository, with Maven:

mvn package
mvn exec:java

Tests?

Sure, after cloning this repository, with Maven:

mvn package

Then, find the test coverage report at target/site/jacoco/index.html.

Dependencies

We rely on Apache Jena for handling the RDF.

About

This library implements checking Web Access Control rules.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Contributors

Languages