Manage Access to Data¶
New in solid-client
version: 1.5
Alpha Features
The APIs described on this page are currently available as an Alpha feature. These APIs are available for testing purposes only and not for production use.
Different Solid Servers can support different access
control/authorization mechanisms. To help simplify the handling of
different access control mechanisms, the solid-client
library
provides universal access control APIs that can be used with either
Web Access Control (WAC) or Access
Control Policies (ACP) proposal. You can use
these access control APIs to manage access to a resource.
Note
In addition to the universal access control APIs that can be used
against both Access Control Policies (ACP) and Web Access Control
(WAC), the solid-client
library also provides ACP-specific APIs
and WAC-specific APIs.
When possible, use the universal access control APIs. For situations that require ACP-specific or WAC-specific APIs, see Mechanism-Specific Access Control APIs.
Access Object¶
Using the solid-client
library’s access control APIs, you can
retrieve or modify the access for a resource. Access is an object of
the form:
{ <access mode>: <true|false>, ... }
Where a value of:
true
indicates the access mode has been granted.false
indicates the access mode has not been granted.
The following access modes are available:
Access Mode |
Description |
---|---|
|
The ability to view the contents of a Resource. |
|
The ability to add new data to a Resource. |
|
The ability to add new data to a Resource, and to change or remove existing data. |
|
The ability to view and change the access to a Resource. Note
|
Retrieve Access Data for a Resource¶
The solid-client
library provides the following universal access
control APIs to retrieve the access for a Resource: 1
These functions attempt to fetch the specified Resource, parse its
access data that has been explicitly set for the specified Agent,
Group, or Public, and return a Promise that either resolves to an
access object, or null
if it could not be read.
- If an access object is returned,
The returned access is the access granted directly to that Agent or Group or the Public. That is, the returned access does not include access that may be indirectly set. For example, an Agent has not been directly granted the
write
access to a Resource but is, however, a member of a Group that has been granted thewrite
access. Then, even though the Agent, by being a member of the Group, haswrite
access to the Resource and can modify the Resource, getAgentAccess returnswrite
access asfalse
.The returned access applies only to the specified Resource and not to the Resource’s children. For example, if the getAgentAccess function indicates that an agent has
read
access to the Resourcehttps://example.com/container/
, that does not mean the agent also hasread
access tohttps://example.com/container/child
.
- If
null
is returned, Access data is inaccessible by the user. Reasons for the inaccessibility are varied and can include:
Inadequate access to retrieve the access data (e.g., the user that is calling the API does not have
controlRead
access for that Resource).The access is defined in a way that is incompatible with the access model used by these APIs.
It is recommended that you explicitly check for
null
to handle the failure in your application.
- 1
getAccessFor and getAccessForAll are also available.
Get Public Access¶
The function getPublicAccess returns access granted specifically to the general public; that is, to everyone and not to specific Agents or Groups.
For example, consider a situation where you grant read
access for a
Resource to the public (see setPublicAccess) and you also grant
write
access to specific Agents or Groups for the Resource.
getPublicAccess returns only read
as true
, even though specific Agents or Groups may have additional
access to the Resource.
import {
getPublicAccess,
} from "@inrupt/solid-client/access/universal";
getPublicAccess("https://example.com/resource").then(access => {
// => access is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL is not accessible to the current user.
if (access === null) {
console.log("Could not load access details for this Resource.")
} else {
console.log(
"Can everyone read this Resource:",
access.read,
);
console.log(
"Can everyone add data to this Resource:",
access.append,
);
console.log(
"Can everyone change data in this Resource:",
access.write,
);
console.log(
"Can everyone see and change who has what access to this Resource:",
access.controlRead && access.controlWrite,
);
}
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Get Agent Access¶
The function getAgentAccess returns the access that has been explicitly granted to the specified Agent for the Resource. The function getAgentAccessAll returns this information for each Agent whose access to the Resource has been explicitly set.
These functions do not return access that has been indirectly granted to the Agent, such as access granted to a Group whose members include the Agent or access granted to the Public.
For example, if, for a Resource, you grant read
access specifically
to the Agent (see setAgentAccess) and you also grant
write
access to a Group to which the Agent belongs (see
setGroupAccess),
getAgentAccess returns only read
as true
, even though the Agent has the write
access through the
Group membership.
Additionally, consider a situation where you grant read
access for
a Resource to the public (see setPublicAccess) but you set read
access to false
explicitly for a specific Agent (see
setAgentAccess).
getAgentAccess returns read
as
false
for that Agent. However, in the absence of any other access
rules that may affect the Agent’s read
access, the Agent can
read
the resource since the Public access grants the read
to
the Agent.
import {
getAgentAccess,
} from "@inrupt/solid-client/access/universal";
getAgentAccess(
"https://example.com/resource",
"https://example.pod/profile#webId",
).then(access => {
// => access is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL is not accessible to the current user.
if (access === null) {
console.log("Could not load access details for this Resource.")
} else {
console.log(
"Can [https://example.pod/profile#webId] read this Resource:",
access.read,
);
console.log(
"Can [https://example.pod/profile#webId] add data to this Resource:",
access.append,
);
console.log(
"Can [https://example.pod/profile#webId] change data in this Resource:",
access.write,
);
console.log(
"Can [https://example.pod/profile#webId] see and change " +
"who has what access to this Resource:",
access.controlRead && access.controlWrite,
);
}
});
// Access for all agents can be read with getAgentAccessAll:
getAgentAccessAll(
"https://example.com/resource",
).then(accessByAgent => {
// => accessByAgent is an object with Agent WebIDs as keys,
// and the return value of getAgentAccess as values.
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Get Group Access¶
The function getGroupAccess returns the access that has been explicitly granted to the specified Group for the Resource. The function getGroupAccessAll returns this information for each Group whose access to the Resource has been explicitly set.
These functions do not return access that has been granted directly to specific Agents in the Group nor access granted to the Public or to another Group of which this Group is a member.
For example, if, for a Resource, you grant read
access specifically
to a Group (see setGroupAccess) and you also grant
write
directly to all Agents in the Group (see
setAgentAccess),
getGroupAccess returns only read
as true
, even though all members in the Group may have been
explicitly granted the write
access.
import {
getGroupAccess,
} from "@inrupt/solid-client/access/universal";
getGroupAccess(
"https://example.com/resource",
"https://example.pod/groups#group",
).then(access => {
// => access is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL is not accessible to the current user.
if (access === null) {
console.log("Could not load access details for this Resource.")
} else {
console.log(
"Can members of [https://example.pod/groups#group] read this Resource:",
access.read,
);
console.log(
"Can members of [https://example.pod/groups#group] " +
"add data to this Resource:",
access.append,
);
console.log(
"Can members of [https://example.pod/groups#group] " +
"change data in this Resource:",
access.write,
);
console.log(
"Can members of [https://example.pod/groups#group] " +
"see and change who has what access to this Resource:",
access.controlRead && access.controlWrite,
);
}
});
// Access for all groups can be read with getGroupAccessAll:
getGroupAccessAll(
"https://example.com/resource",
).then(accessByGroup => {
// => accessByGroup is an object with Group URLs as keys,
// and the return value of getGroupAccess as values.
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Changing Access Data for a Resource¶
The solid-client
library provides the following universal access
control APIs to modify the access for a Resource: 2
These functions modify the access that is directly associated with an Agent or a given Group or the general Public. An Agent or a Group can have additional access granted indirectly, such as through access granted to the Public or through access granted to a Group to which the Agent or the Group belongs.
Pass into the function the access object with the specific modes you want to set. Set these modes to
true
to grant that mode.false
to revoke access for that mode. That is, using these functions to set a mode tofalse
removes access granted directly to the given agent/group/public, but does not prevent that access from being granted via other indirect means.
Modes that are unspecified in the access object remain unchanged.
These functions attempt to fetch the specified Resource, parse its
access data, apply the specified access changes (unspecified access
modes remain unchanged), save the access data back to the Pod, and
return a Promise that either resolves to the updated access data, or
null
if it could not be read or changed.
- If an access object is returned,
The returned access applies only to the specified Resource and not to the Resource’s children. For example, if the updated access indicates that an agent has
read
access to the Resourcehttps://example.com/container/
, that does not mean the agent also hasread
access tohttps://example.com/container/child
.
- If
null
is returned, Access data is inaccessible and/or unmodifiable by the user. Reasons for these are varied and can include:
Inadequate access to retrieve or modify the access data (e.g., the person calling the API does not have
controlRead
andcontrolWrite
access for that Resource)The access is defined in a way that is incompatible with the access model used by these APIs.
It is recommended that you explicitly check for
null
to handle the failure in your app.
- 2
setAccessFor is also available.
Change Public Access¶
The function setPublicAccess sets access specifically for the general public; that is for everyone and not for specific Agents or Groups.
Setting an access mode to
true
grants that mode.Setting an access mode to
false
revokes access for that mode for the Public. Agents or Groups may still be granted the access mode directly.Modes that are unspecified in the access object remain unchanged.
For example, if you set read
access to false
for a Resource
using setPublicAccess, and you also grant
read
access to specific Agents or Groups for the Resource,
setPublicAccess returns read
as false
, even though specific Agents or Groups may have read
access to the Resource and can read from the Resource.
import {
setPublicAccess,
} from "@inrupt/solid-client/access/universal";
setPublicAccess(
"https://example.com/resource",
// Grant Read access, removing any previously granted Write access,
// and leave the rest (append, controlRead and controlWrite) the same:
{ read: true, write: false, },
).then(newAccess => {
// => newAccess is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL can not be viewed or changed by the current user.
if (newAccess === null) {
console.log("Could not load or change access details for this Resource.")
} else {
console.log(
"Can everyone can read this Resource:",
newAccess.read,
);
console.log(
"Can everyone add data to this Resource:",
newAccess.append,
);
console.log(
"Can everyone can change data in this Resource:",
newAccess.write,
);
console.log(
"Can everyone see and change who has what access to this Resource:",
newAccess.controlRead && newAccess.controlWrite,
);
}
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Change Agent Access¶
The function setAgentAccess sets access for a specific Agent. The function does not affect access that may have been granted to the Agent indirectly, such as access granted to a Group whose members include the Agent or access granted to the Public.
Setting an access mode to
true
grants that mode.Setting an access mode to
false
revokes access for that mode. The Agent may still be granted the access mode indirectly through the membership of a Group or through general Public access.Modes that are unspecified in the access object remain unchanged.
import {
setAgentAccess,
} from "@inrupt/solid-client/access/universal";
setAgentAccess(
"https://example.com/resource",
"https://example.pod/profile#webId",
// Grant Read access, removing any previously granted Write access,
// and leave the rest (append, controlRead and controlWrite) the same:
{ read: true, write: false, },
).then(newAccess => {
// => newAccess is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL can not be viewed or changed by the current user.
if (newAccess === null) {
console.log("Could not load or change access details for this Resource.")
} else {
console.log(
"Can [https://example.pod/profile#webId] read this Resource:",
newAccess.read,
);
console.log(
"Can [https://example.pod/profile#webId] add data to this Resource:",
newAccess.append,
);
console.log(
"Can [https://example.pod/profile#webId] change data in this Resource:",
newAccess.write,
);
console.log(
"Can [https://example.pod/profile#webId] see and change " +
"who has what access to this Resource:",
newAccess.controlRead && newAccess.controlWrite,
);
}
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Change Group Access¶
The function setGroupAccess sets access for a specific Group. The function does not affect access that may have been granted directly to specific Agents in the Group nor access granted to the Public or to another Group of which this Group is a member.
Setting an access mode to
true
grants that mode.Setting an access mode to
false
revokes access for that mode. The Group may still be granted the access mode indirectly through its membership of another Group or through general Public access.Modes that are unspecified in the access object remain unchanged.
import {
setGroupAccess,
} from "@inrupt/solid-client/access/universal";
setGroupAccess(
"https://example.com/resource",
"https://example.pod/groups#group",
// Grant Read access, removing any previously granted Write access,
// and leave the rest (append, controlRead and controlWrite) the same:
{ read: true, write: false, },
).then(newAccess => {
// => newAccess is an object like
// {
// read: true, append: false, write: false,
// controlRead: false, controlWrite: false
// }
// or null if the ACL can not be viewed or changed by the current user.
if (newAccess === null) {
console.log("Could not load or change access details for this Resource.")
} else {
console.log(
"Can members of [https://example.pod/groups#group] read this Resource:",
newAccess.read,
);
console.log(
"Can members of [https://example.pod/groups#group] "
+ "add data to this Resource:",
newAccess.append,
);
console.log(
"Can members of [https://example.pod/groups#group] "
+ "change data in this Resource:",
newAccess.write,
);
console.log(
"Can members of [https://example.pod/groups#group] " +
"see and change who has what access to this Resource:",
newAccess.controlRead && newAccess.controlWrite,
);
}
});
Note
The returned access applies only to the specified Resource and not to the Resource’s children.
Mechanism-Specific Access Control APIs¶
In addition to the universal access control APIs, the
solid-client
library also provides APIs specific to Access Control
Policies (ACP) and APIs specific to Web Access Control (WAC).
When possible, use the universal access control APIs. However, the universal access control APIs are only available for features/functionalities of WAC and ACP that can be generalized. To handle a WAC-specific or ACP-specific situations that cannot be generalized, use the mechanism-specific APIs, such as:
To handle error conditions that are specific to the access control mechanism. For example, if a WAC-controlled Resource does not have a reachable Fallback ACL, you may want to initialize a Resource-specific ACL anyway.
To use mechanism-specific functionality. For example, in ACP, you can deny (not just revoke/unset) access as well as specify a “creator” access mode. These functionalities are specific to ACP and are not available in WAC.
To specify access that does not have a universal access API equivalent. For example, the universal access APIs only affect or refer to the access of the Resource itself and not its children, if the Resource is a Container.
Note
Using the mechanism-specific APIs, it is possible for you to define an access model that is incompatible with the universal access APIs and, therefore, can only be managed with the mechanism-specific APIs.
For more information on mechanism-specific APIs, see: