Set a permission on a pod resource, and watch it get enforced
The transcript is from a pod running on a laptop, two commands, not from our deployed host, which needs an authenticated session.
Before: a fresh pod permits everything
$ curl -X PUT http://localhost:3000/hello.ttl -H 'Content-Type: text/turtle' \
--data-raw '<#it> <http://schema.org/name> "hello" .'
201 Created
$ curl -sI http://localhost:3000/hello.ttl | grep -i wac-allow
WAC-Allow: user="append control read write", public="append control read write"
All four modes, to everyone, including control. What the four modes are.
The rule
An access-control document is ordinary data at a predictable URL, the resource's URL plus a
suffix, advertised in the resource's own Link header so a client never has to guess.
$ curl -X PUT http://localhost:3000/hello.ttl.acl -H 'Content-Type: text/turtle' --data-raw '
@prefix acl: <http://www.w3.org/ns/auth/acl#>.
@prefix foaf: <http://xmlns.com/foaf/0.1/>.
<#public> a acl:Authorization;
acl:agentClass foaf:Agent;
acl:accessTo <./hello.ttl>;
acl:mode acl:Read, acl:Control.
'
201 Created
Read it in English: anyone at all (foaf:Agent is the class of everybody) may read this one
resource, and may change its permissions, and, by omission, may not write it.
WAC is deny-by-default. You do not forbid anything; you state what is allowed, and everything you did not state is refused.
After: the same write is refused
$ curl -o /dev/null -w '%{http_code}' http://localhost:3000/hello.ttl
200
$ curl -X PUT http://localhost:3000/hello.ttl -H 'Content-Type: text/turtle' \
--data-raw '<#it> <http://schema.org/name> "overwritten" .'
401
$ curl -sI http://localhost:3000/hello.ttl | grep -i wac-allow
WAC-Allow: user="control read", public="control read"
Reading still works. Writing does not. And the header changed from four modes to two: the server reporting its own decision back to you, which is the part that makes this checkable rather than hopeful.
The control, without which none of the above means anything
A server that had simply started refusing writes would produce exactly the same three lines. So:
$ curl -X PUT http://localhost:3000/sibling.ttl -H 'Content-Type: text/turtle' \
--data-raw '<#x> <http://schema.org/name> "sibling" .'
201 Created
A sibling with no rule of its own still accepts a write. The refusal belongs to the rule on that one resource, not to the server.
We are labouring this because a demonstration without a control is a screenshot, and this estate has already caught itself reading an unproven instrument as a finding.
Why 401 and not 403
The request carried no credentials, so the server invites you to authenticate rather than telling you that you are forbidden. With a session that still lacked write access you would expect the other code.
Do not carry this reasoning over to our deployed host. There, an unknown path also returns 401, so a 401 there does not distinguish "you need to log in", "you may not" and "that does not exist". Our own lexicon suggests an unauthenticated-refusal test as proof that access control works; on our host that half of the test proves nothing. Only the authenticated half does.
What this shows about us, which is less than it looks
You have just watched Solid's access-control model work in Solid's server. Our contribution is that we run it and call it through a client library, and our own interface exposes two of the four modes, which is our limitation, not the server's.
A grant is also not a record of consent, different question entirely.