Manage Access to Data (WAC)

Not for Production Use

Although Inrupt’s Enterprise Solid Server (ESS) supports Web Access Control (WAC) in compliance with the Solid specification, due to known security issues with WAC, WAC is not recommended for Production environments.

For production, Solid servers using Access Control Policy (ACP) is recommended. For managing access with ACP, see Manage Access to Data (ACP) instead.

With Web Access Control (WAC), Access Control Lists determine the access to Resources stored in Solid Pods.

Access Control List

A Resource’s Access Control Lists (ACLs) determine the access to that Resource. An ACL entry can specify following Access Modes :

Access (i.e. an ACL entry) can be granted to individual agents, to groups, or even to everyone.

For a Resource, you can define:

  • a Resource-specific ACL that applies only to that Resource, and

  • an inheritable ACL that applies to the Resource’s children as a default/fallback ACL if they don’t specify their own Resource-specific ACL.

That is, if a Resource has a Resource-specific ACL, that ACL applies to that Resource and only to that Resource. However, if the Resource-specific ACL does not exist, the Resource’s Container’s inheritable ACL (or if that is unset, then that of its Container’s Container, etc.) acts as the Resource’s fallback ACL. As such, the ACL for a Resource may be defined in separate Resource, and retrieving a Resource with its ACL may result in extra HTTP requests being sent.

Trusted Applications

An application can access a Resource’s or Container’s ACL only if the Authenticated User has Control Access to the applicable Resource or Container, and has authorized the application to manage access on their behalf.

Read Access Information for a Resource

To retrieve the ACL for a resource in addition to the Resource itself, use the getSolidDatasetWithAcl function. The returned value includes the Resource data, the ResourceInfo (i.e., metadata), and the ACL.

Note

The getSolidDatasetWithAcl function may result in many extra HTTP requests being sent.

Read Public Access

From a SolidDataset that has an ACL attached, you can use getPublicAccess to retrieve the access granted to the public in general, regardless of whether they are authenticated or not.

import {
  getSolidDatasetWithAcl,
  getPublicAccess,
} from "@inrupt/solid-client";

const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");
const publicAccess = getPublicAccess(myDatasetWithAcl);

// => an object like
//    { read: true, append: false, write: false, control: true }
//    or null if the ACL is not accessible to the current user.

Reading Agent Access

From a SolidDataset that has an ACL attached, you can use:

  • getAgentAccess to retrieve the access granted to a specific agent:

    import {
      getSolidDatasetWithAcl,
      getAgentAccess,
    } from "@inrupt/solid-client";
    
    const webId = "https://example.com/profile#webid";
    const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");
    const agentAccess = getAgentAccess(myDatasetWithAcl, webId);
    
    // => an object like
    //    { read: true, append: false, write: false, control: true }
    //    or null if the ACL is not accessible to the given user.
    
  • getAgentAccessAll to retrieve access information for all agents that have access:

    import {
      getSolidDatasetWithAcl,
      getAgentAccessAll,
    } from "@inrupt/solid-client";
    
    const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");
    const accessByAgent = getAgentAccessAll(myDatasetWithAcl);
    
    // => an object like
    //    {
    //      "https://example.com/profile#webid":
    //        { read: true, append: false, write: false, control: true },
    //      "https://example.com/other-profile#webid":
    //        { read: true, append: false, write: false, control: false },
    //    }
    

Reading Group Access

From a SolidDataset that has an ACL attached, you can use:

  • getGroupAccess to retrieve the access granted to a specific group:

    import {
      getSolidDatasetWithAcl,
      getGroupAccess,
    } from "@inrupt/solid-client";
    
    const groupUrl = "https://example.com/address-book#friends";
    const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");
    const groupAccess = getGroupAccess(myDatasetWithAcl, groupUrl);
    
    // => an object like
    //    { read: true, append: false, write: false, control: true }
    //    or null if the ACL is not accessible to the given group.
    
  • getGroupAccessAll to retrieve access information for all groups that have access:

    import {
      getSolidDatasetWithAcl,
      getGroupAccessAll,
    } from "@inrupt/solid-client";
    
    const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");
    const accessByGroup = getGroupAccessAll(myDatasetWithAcl);
    
    // => an object like
    //    {
    //      "https://example.com/address-book#family":
    //        { read: true, append: false, write: false, control: true },
    //      "https://example.com/address-book#friends":
    //        { read: true, append: false, write: false, control: false },
    //    }
    

Change Access to a Resource

The following outlines the steps for modifying a Resource-specific ACL. If the Resource does not currently does not have a Resource-specific ACL (i.e., the Resource uses its fallback ACL inherited from its Container), the outline includes creating a Resource-specific ACL, overriding the fallback ACL.

Important

You must have Control Access on the Resource to modify its ACL.

To modify access to a Resource:

  1. Use getSolidDatasetWithAcl to retrieve the Resource and its ACL.

  2. From the retrieved Resource, call getResourceACL to obtain its Resource-specific ACL. The function returns null if the Resource-specific ACL does not exist.

  3. If the Resource-specific ACL exists,

    1. You can create a modified ACL from the existing Resource-specific ACL.

    2. Ensure that the modified ACL includes at least one entry with Control Access.

    3. Save the modified ACL to the Pod.

  4. Otherwise, you can create a new Resource-specific ACL and save. Once you save the new Resource-specific ACL, this ACL overrides the inherited fallback ACL.

    1. To create a new ACL, you can use createAcl to create a new empty ACL.

    2. If you have access to the Resource’s fallback ACL, you can copy the currently applicable rules to a newly-initialised ACL.

    3. Ensure that the modified ACL includes at least one entry with Control Access.

    4. Save the modified ACL to the Pod.

The general process of changing access to a Resource is as follows:

import {
  getSolidDatasetWithAcl,
  hasResourceAcl,
  hasFallbackAcl,
  hasAccessibleAcl,
  createAcl,
  createAclFromFallbackAcl,
  getResourceAcl,
  setAgentResourceAccess,
  saveAclFor,
} from "@inrupt/solid-client";

// Fetch the SolidDataset and its associated ACLs, if available:
const myDatasetWithAcl = await getSolidDatasetWithAcl("https://example.com");

// Obtain the SolidDataset's own ACL, if available,
// or initialise a new one, if possible:
let resourceAcl;
if (!hasResourceAcl(myDatasetWithAcl)) {
  if (!hasAccessibleAcl(myDatasetWithAcl)) {
    throw new Error(
      "The current user does not have permission to change access rights to this Resource."
    );
  }
  if (!hasFallbackAcl(myDatasetWithAcl)) {
    throw new Error(
      "The current user does not have permission to see who currently has access to this Resource."
    );
    // Alternatively, initialise a new empty ACL as follows,
    // but be aware that if you do not give someone Control access,
    // **nobody will ever be able to change Access permissions in the future**:
    // resourceAcl = createAcl(myDatasetWithAcl);
  }
  resourceAcl = createAclFromFallbackAcl(myDatasetWithAcl);
} else {
  resourceAcl = getResourceAcl(myDatasetWithAcl);
}

// Give someone Control access to the given Resource:
const updatedAcl = setAgentResourceAccess(
  resourceAcl,
  "https://some.pod/profile#webId",
  { read: false, append: false, write: false, control: true }
);

// Now save the ACL:
await saveAclFor(myDatasetWithAcl, updatedAcl);

Set Public Access

Given a Resource’s ACL obtained as specified in Change Access to a Resource, you can:

  • Use setPublicResourceAccess to grant Access Modes to everybody (whether logged in or not) for the Resource itself:

    import {
      setPublicResourceAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    
    const updatedAcl = setPublicResourceAccess(
      resourceAcl,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.
    
  • Use setPublicDefaultAccess to grant Access Modes to everybody (whether logged in or not) for the Resource’s children if the Resource is a Container:

    import {
      setPublicDefaultAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    
    const updatedAcl = setPublicDefaultAccess(
      resourceAcl,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.
    

Set Agent Access

Given a Resource’s ACL obtained as specified in Change Access to a Resource, you can:

  • Use setAgentResourceAccess to grant Access Modes to an Agent for the Resource itself:

    import {
      setAgentResourceAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    const webId = "https://example.com/profile#webid";
    
    const updatedAcl = setAgentResourceAccess(
      resourceAcl,
      webId,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.
    
  • Use setAgentDefaultAccess to grant Access Modes to an Agent for the Resource’s children if the Resource is a Container:

    import {
      setAgentDefaultAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    const webId = "https://example.com/profile#webid";
    
    const updatedAcl = setAgentDefaultAccess(
      resourceAcl,
      webId,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.
    

Set Group Access

Given a Resource’s ACL obtained as specified in Change Access to a Resource, you can:

  • Use setGroupResourceAccess to grant Access Modes to a group for the Resource itself:

    import {
      setGroupResourceAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    const groupUrl = "https://example.com/address-book#friends";
    
    const updatedAcl = setGroupResourceAccess(
      resourceAcl,
      groupUrl,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.
    
  • Use setGroupDefaultAccess to grant Access Modes to a group for the Resource’s children if the Resource is a Container:

    import {
      setGroupDefaultAccess,
    } from "@inrupt/solid-client";
    
    const resourceAcl = /* Obtained previously in the section "Change Access to a Resource" */;
    const groupUrl = "https://example.com/address-book#friends";
    
    const updatedAcl = setGroupDefaultAccess(
      resourceAcl,
      groupUrl,
      { read: true, append: true, write: false, control: false },
    );
    
    // `updatedAcl` can now be saved back to the Pod
    // using `saveAclFor()`.