Manage Access to Data

New in solid-client version: 1.5

Beta Features

The APIs described on this page are currently available as a Beta feature. These APIs are available for testing purposes only and not for production use.

Access control/authorization determines which actions an Agent can perform on a Resource. For instance, an agent may have Read Access to a Resource, but not Write Access. Different Solid Servers can support different access control mechanisms; e.g., Access Control Policies (ACP) or Web Access Control (WAC).

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 Access Control Policies (ACP) or Web Access Control (WAC). That is, for Resources that are controlled by either mechanisms, you can use the universal access control APIs to manage access instead of the mechanism-specific APIs.

Mechanism-specific APIs

The solid-client library also provides ACP-specific APIs and WAC-specific APIs. However, 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. The solid-client library handles access as an object of the form:

{
  read: <boolean>,
  append: <boolean>,
  write: <boolean>,
  controlRead: <boolean>,
  controlWrite: <boolean>
}

Where a <boolean> 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

read

The ability to view the contents of a Resource.

append

The ability to add new data to a Resource.

write

The ability to add new data to a Resource, and to change or remove existing data.

controlRead

The ability to view the access to a Resource.

controlWrite

The ability to change the access to a Resource.

Note

  • For Web Access Control, controlRead and controlWrite must be in sync; that is, either both be granted or not. If you grant/unset one but do not also grant/unset the other, solid-client throws an error.

  • For Access Control Policies, controlRead and controlWrite do not have to be in sync.

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.

Note

To use these functions for a resource, the user must have controlRead access for that Resource.

If an access object is returned,

{
  read: <boolean>,
  append: <boolean>,
  write: <boolean>,
  controlRead: <boolean>,
  controlWrite: <boolean>
}
  • 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 the write access. Then, even though the Agent, by being a member of the Group, has write access to the Resource and can modify the Resource, getAgentAccess returns write access as false.

  • 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 Resource https://example.com/container/, that does not mean the agent also has read access to https://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. To use getPublicAccess, pass it the following parameters:

Example

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  getPublicAccess
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Fetch the access explicitly/directly set for the public.
// The returned access can be an object { read: <boolean>, append: <boolean>, ... }
// or null if the access data is inaccessible to the user.
getPublicAccess(
  "https://example.com/resource",   // Resource
  { fetch: fetch }                  // fetch function from authenticated session
).then(access => {
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log("Returned Access:: ", JSON.stringify(access));
    console.log("Everyone", (access.read ? 'CAN' : 'CANNOT'), "read the Resource.");
    console.log("Everyone", (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource.");
    console.log("Everyone", (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource.");
    console.log("Everyone", (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource.");
    console.log("Everyone", (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource.");
  }
});

Returned Access

  • The function returns access granted specifically to the general public 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.

    The function returns only read as true, even though specific Agents or Groups may have additional access to the Resource.

  • The returned access applies only to the specified Resource and not to the Resource’s children.

Get Agent Access for a Resource

For a Specific Agent

The function getAgentAccess returns the access that has been explicitly granted to the specified Agent for the Resource. To use getAgentAccess, pass it the following parameters:

Example
// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  getAgentAccess
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Fetch the access explicitly/directly set for an agent.
// (i.e., omits access inherited through group or public membership).
// The returned access can be an object { read: <boolean>, append: <boolean>, ... } 
// or null if the access data is inaccessible to the user.
getAgentAccess(
  "https://example.com/resource",       // resource  
  "https://example.pod/profile#webId",  // agent
  { fetch: fetch }                      // fetch function from authenticated session
).then(access => {
  logAccessInfo("https://example.pod/profile#webId", access, "https://example.com/resource");
});

function logAccessInfo(agent, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${agent}'s Access:: `, JSON.stringify(access));
    console.log("...", agent, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...", agent, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...", agent, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...", agent, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...", agent, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}
Returned Access
  • The function does 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, consider scenario 1 where:

    • you grant read access specifically to the Agent (see setAgentAccess) for a Resource, and

    • you also grant write access for the Resource to a Group to which the Agent belongs (see setGroupAccess).

    This function returns only read as true, even though the Agent has the write access through the Group membership.

    For example, consider scenario 2 where:

    • you grant read access for a Resource to the Public (see setPublicAccess), and

    • you set read access to false explicitly for a specific Agent (see setAgentAccess) for that Resource.

    For this Agent, the function returns read as false. 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.

  • The returned access applies only to the specified Resource and not to the Resource’s children.

For All Agents with Explicit Access

The function getAgentAccessAll returns the access information for each Agent whose access to the Resource has been explicitly set.

Example
// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  getAgentAccessAll
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Fetch the access for all agents whose access has been explicitly/directly set
// (i.e., omits access inherited through group or public membership).
// The returned access can be an object { read: <boolean>, append: <boolean>, ... } 
// or null if the access data is inaccessible to the user.
getAgentAccessAll(
  "https://example.com/resource", // resource
  { fetch: fetch }                // fetch function from authenticated session
).then(accessByAgent => {
  // => accessByAgent is an object with Agent WebIDs as keys,
  //    and their associated access object {read: <boolean>, ... } as values.
  for (const [agent, access] of Object.entries(accessByAgent)) {
    logAccessInfo(agent, access, resource);
  }
});

function logAccessInfo(agent, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${agent}'s Access:: `, JSON.stringify(access));
    console.log("...", agent, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...", agent, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...", agent, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...", agent, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...", agent, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}
Returned Access
  • The function returns an object with Agent WebIDs as keys and the corresponding access object as the corresponding values.

  • For each returned Agent, the function does 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,

    Consider scenario 1 where:

    • you grant read access specifically to the Agent (see setAgentAccess) for a Resource, and

    • you also grant write access to a Group to which the Agent belongs (see setGroupAccess) for that Resource.

    For this Agent, the function returns only read as true, even though the Agent has the write access through the Group membership.

    Consider scenario 2 where:

    • you grant read access for a Resource to the Public (see setPublicAccess), and

    • you set read access to false explicitly for a specific Agent (see setAgentAccess) for that Resource.

    For this Agent, the function returns read as false. 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.

  • The returned access applies only to the specified Resource and not to the Resource’s children.

Get Group Access

For a Specific Group

The function getGroupAccess returns the access that has been explicitly granted to the specified Group for the Resource. To use getGroupAccess, pass it the following parameters:

Example
// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  getGroupAccess
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Fetch the access explicitly/directly set for a group.
// (i.e., omits access inherited through another group membership or public).
// The returned access can be an object { read: <boolean>, append: <boolean>, ... } 
// or null if the access data is inaccessible to the user.

getGroupAccess(
  "https://example.com/resource",     // Resource
  "https://example.pod/groups#group", // Group
  { fetch: fetch }                    // fetch function from authenticated session
).then(access => {
  logAccessInfo("https://example.pod/groups#group", access, "https://example.com/resource");
});

function logAccessInfo(group, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${group}'s Access:: `, JSON.stringify(access));
    console.log("...Members of", group, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...Members of", group, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...Members of", group, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...Members of", group, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...Members of", group, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}
Returned Access
  • The function does not return access that has been granted directly to specific Agents in the Group nor access granted to the Public or to another Group where this Group is a member.

    For example, consider a situation where:

    • you grant read access specifically to a Group (see setGroupAccess) for a Resource, and

    • you also grant write directly to all Agents in the Group (see setAgentAccess) for that same Resource.

    The function returns only read as true, even though all members in the Group may have been explicitly granted the write access.

  • The returned access applies only to the specified Resource and not to the Resource’s children.

For All Groups with Explicit Access

The function getGroupAccessAll returns this information for each Group whose access to the Resource has been explicitly set.

Example
// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  getGroupAccessAll
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Fetch the access for all groups whose access has been explicitly/directly set
// (i.e., omits access inherited through another group or public membership).
// The returned access can be an object { read: <boolean>, append: <boolean>, ... } 
// or null if the access data is inaccessible to the user.
getGroupAccessAll(
  "https://example.com/resource",  // resource
  { fetch: fetch }                 // fetch function from authenticated session
).then(accessByGroup => {
  // => accessByGroup is an object with Group URLs as keys,
  //    and their associated access object {read: <boolean>, ... } as values.
  for (const [group, access] of Object.entries(accessByGroup)) {
    logAccessInfo(group, access, resource);
  }
});

function logAccessInfo(group, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${group}'s Access:: `, JSON.stringify(access));
    console.log("...Members of", group, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...Members of", group, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...Members of", group, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...Members of", group, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...Members of", group, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}
Returned Access
  • The function returns an object with Group WebIDs as keys and the corresponding access object as the corresponding values.

  • The function does not return access that has been granted directly to specific Agents in the Group nor access granted to the Public or to another Group where this Group is a member.

    For example, consider a situation where:

    • you grant read access specifically to a Group (see setGroupAccess) for a Resource, and

    • you also grant write directly to all Agents in the Group (see setAgentAccess) for that same Resource.

    For that Group, the function returns only read as true, even though all members in the Group may have been explicitly granted the write access.

  • 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 to false 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 Resource https://example.com/container/, that does not mean the agent also has read access to https://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 and controlWrite 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. 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.

  • Modes that are unspecified in the access object remain unchanged.

// ... import statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  setPublicAccess,
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Set access for the general Public (i.e., everyone):
// - Grant Read access
// - Remove any previously granted Write access.
// - Leave the rest (append, controlRead and controlWrite) unchanged.
// The returned access can be an object { read: <boolean>, append: <boolean>, ... }
// or null if the access data is inaccessible to the user.
setPublicAccess(
  "https://example.com/resource",  // Resource
  { read: true, write: false },    // Access object
  { fetch: fetch }                 // fetch function from authenticated session
).then(newAccess => {
  if (newAccess === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log("Returned Access:: ", JSON.stringify(newAccess));
    console.log("Everyone", (newAccess.read ? 'CAN' : 'CANNOT'), "read the Resource.");
    console.log("Everyone", (newAccess.append ? 'CAN' : 'CANNOT'), "add data to the Resource.");
    console.log("Everyone", (newAccess.write ? 'CAN' : 'CANNOT'), "change data in the Resource.");
    console.log("Everyone", (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource.");
    console.log("Everyone", (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource.");
  }
});

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 statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  setAgentAccess,
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Set access for an Agent:
// - Grant Read access
// - Remove any previously granted Write access.
// - Leave the rest (append, controlRead and controlWrite) unchanged.
// The returned access can be an object { read: <boolean>, append: <boolean>, ... }
// or null if the access data is inaccessible to the user.
setAgentAccess(
  "https://example.com/resource",         // Resource
  "https://example.pod/profile#webId",    // Agent
  { read: true, write: false, },          // Access object
  { fetch: fetch }                         // fetch function from authenticated session
).then(newAccess => {
  logAccessInfo("https://example.pod/profile#webId", newAccess, "https://example.com/resource")
});

function logAccessInfo(agent, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${agent}'s Access:: `, JSON.stringify(access));
    console.log("...", agent, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...", agent, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...", agent, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...", agent, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...", agent, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}

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 statement for authentication, which includes the fetch function, is omitted for brevity.

import {
  setGroupAccess,
} from "@inrupt/solid-client/access/universal";

// ... Login logic omitted for brevity.

// Set access for the Group:
// - Grant Read access
// - Remove any previously granted Write access.
// - Leave the rest (append, controlRead and controlWrite) unchanged.
// The returned access can be an object { read: <boolean>, append: <boolean>, ... }
// or null if the access data is inaccessible to the user.
setGroupAccess(
  "https://example.com/resource",     // Resource
  "https://example.pod/groups#group", // Group 
  { read: true, write: false },       // Access object
  { fetch: fetch }                    // fetch function from authenticated session
).then(newAccess => {
  logAccessInfo("https://example.pod/groups#group", newAccess, "https://example.com/resource" );
});

function logAccessInfo(group, access, resource){
  if (access === null) {
    console.log("Could not load access details for this Resource.");
  } else {
    console.log(`${group}'s Access:: `, JSON.stringify(access));
    console.log("...Members of", group, (access.read ? 'CAN' : 'CANNOT'), "read the Resource", resource);
    console.log("...Members of", group, (access.append ? 'CAN' : 'CANNOT'), "add data to the Resource", resource);
    console.log("...Members of", group, (access.write ? 'CAN' : 'CANNOT'), "change data in the Resource", resource);
    console.log("...Members of", group, (access.controlRead ? 'CAN' : 'CANNOT'), "see access to the Resource", resource);
    console.log("...Members of", group, (access.controlWrite ? 'CAN' : 'CANNOT'), "change access to the Resource", resource);
  }
}

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: