Manage Access to Data (ACP)

Access Control Policies (ACP) determine the access to Resources stored in Solid Pods. ACP is an alternative to Access Control Lists and is being proposed for inclusion in the Solid specifications.

Solid Server Support

Access Control Resource (ACR)

Every Resource has an associated Access Control Resource (ACR). The Access Control Resource contains the Access Policy that applies to its associated Resource. If the Resource is a Container, its ACR can include Policies that applies to its children (i.e., Member Policies).

Access Policy

An Access Policy defines the agents’ access to a resource. Specifically, the Access Policy allows or denies the specified access modes to agents based on how they match the conditions in the listed access rules; i.e.,

If <all | any | none> of the access rules are true for an agent, < allow | deny > the specified access modes to a resource.

ACP Access Rules

Access Rules specify agent match conditions. Agent match conditions can be any of the following:

  • Agent is in a list of WebIDs.

  • Agent is the creator of the resource.

  • Agent has authenticated.

  • Agent can be anyone (i.e., Public).

  • Agent is a member of one of the listed groups.

A policy can specify that <all | any | none> of the access rules match an agent.

ACP Access Modes

Access Modes describe the type of permissions (i.e., access) to a resource. The following Access Modes are available:

Access Mode

Description

Read

View data.

Append

Add data.

Write

Add, update, and delete data.

Accessing the APIs

The ACP-specific functions are exported as properties on the acp_v1 export. That is, to use the function(s), you import them with an import of acp_v1.

For example, to use the getAcrPolicyUrlAll, you import acp_v1:

import {
  acp_v1
} from "@inrupt/solid-client";

// ...
const acrPolicyUrl = acp_v1.getAcrPolicyUrlAll(resource);
// ...

Managing Access Controls

The API provides the following WithAcr functions to retrieve the Access Control Resource (ACR) with the Resource: getSolidDatasetWithAcr, getFileWithAcr, and getResourceInfoWithAcr.

To the retrieved Resource with ACR, you can use addAcrPolicyUrl function to add the Policy to the Resource’s ACR or use the addMemberAcrPolicyUrl function to add the Policy to the ACR of the Resource’s children. For example:

import {
  acp_v1
} from "@inrupt/solid-client";

const resourceWithAcr = await acp_v1.getSolidDatasetWithAcr(
  "https://example.pod/resource",
);
let changedResourceWithAcr = acp_v1.addAcrPolicyUrl(
  resourceWithAcr,
  "https://example.pod/policies#acr-policy",
);
let changedResourceWithAcr = acp_v1.addMemberAcrPolicyUrl(
  changedResourceWithAcr,
  "https://example.pod/policies#acr-member-policy",
);

To access existing Policies that apply to an ACR or to the Resource’s children, use getAcrPolicyUrlAll and getMemberAcrPolicyUrlAll, respectively.

To remove existing Policies, use removeAcrPolicyUrl and removeMemberAcrPolicyUrl (for individual Policies) or removeAcrPolicyUrlAll and removeMemberAcrPolicyUrlAll (for all currently applied Policies).

Access Controls

To retrieve existing Access Controls from a Resource with ACR, use getControl and getControlAll. To create a new Access Control, you can use createControl.

You can add or remove Policies to the Access Control using addPolicyUrl or removePolicyUrl. To manage Access Controls that apply to the children of the given Resource, use the MemberPolicy function variants; e.g., addMemberPolicyUrl, removeMemberAcrPolicyUrlAll, etc.

You can add Access Control to the ACR using setControl.

For example, the following creates a new Access Control, applies the Policy with the URL https://example.pod/policies#a-policy to the Access Control, and adds the Access Control to the Resource with ACR.

const emptyControl = acp_v1.createControl();
const controlWithPolicy = acp_v1.addPolicyUrl(
  emptyControl,
  "https://example.pod/policies#a-policy",
);

const changedResourceWithAcr = acp_v1.setControl(
  resourceWithAcr,
  controlWithPolicy,
);

Then, to save the Access Control Resource back to the Pod, you can use saveAcrFor as in the following example:

import {
  acp_v1
} from "@inrupt/solid-client";

const resourceWithAcr = await acp_v1.getSolidDatasetWithAcr(
  "https://example.pod/resource",
);
let changedResourceWithAcr = acp_v1.addAcrPolicyUrl(
  resourceWithAcr,
  "https://example.pod/policies#acr-policy",
);
let changedResourceWithAcr = acp_v1.addMemberAcrPolicyUrl(
  changedResourceWithAcr,
  "https://example.pod/policies#acr-member-policy",
);

const emptyControl = acp_v1.createControl();
const controlWithPolicy = acp_v1.addPolicyUrl(
  emptyControl,
  "https://example.pod/policies#a-policy",
);

changedResourceWithAcr = acp_v1.setControl(
  changedResourceWithAcr,
  controlWithPolicy,
);

const updatedResourceWithAcr = await saveAcrFor(changedResourceWithAcr);

Managing Access Policies

To manage Access Policies, the following functions are available: createPolicy to create Access Policies, getPolicy and getPolicyAll to retrieve Access Policies, removePolicy to remove Access Policy from a Resource, and setPolicy to add the Policy to a Resource.

Note

Access Controls require that a Policy has a full, known URL by which it can be referred. You must specify this URL to createPolicy when creating a Policy.

View Modes

To view what Modes (Read, Append, or Write) are allowed by a Policy, use the getAllowModes function. The function returns an object with the boolean properties read, append and write:

const policy = acp_v1.getPolicy(
  solidDataset,
  "https://example.pod/policies#a-policy",
);
const allowedModes = acp_v1.getAllowModes(policy);
// e.g. =>
// { read: true, append: false, write: false }

Similarly, you can use getDenyModes to obtain a similar object describing which Modes are denied by a Policy.

Modify Modes

To change which Modes a Policy allows, use the setAllowModes function, passing it an object with boolean properties read, append and write:

const policy = acp_v1.createPolicy("https://example.pod/policies#a-policy");
const updatedPolicy = acp_v1.setAllowModes(
  policy,
  { read: true, append: false, write: false },
);

Similarly, you can use setDenyModes to change which Modes a Policy denies.

Managing Access Rules

To manage Access Rules, the following functions are available: createRule to create Access Rules, getRule and getRuleAll to retrieve Access Rules from a Resource, removeRule to remove Access Rule from a Resource, and setRule to add the Rule to a Resource.

Note

Access Controls require that a Rule has a full, known URL by which it can be referred. You must specify this URL to createRule when creating a Rule.

Manage Rules for Specific Agents/Groups

To manage the Agents for a Rule (i.e., to whom the Rule applies), you can use getAgentAll, addAgent, setAgent, and removeAgent:

const rule = acp_v1.createRule("https://example.pod/rules#a-rule");
const changedRule = acp_v1.addAgent(
  rule,
  "https://other.pod/profile/card#me",
);
const addedAgents = acp_v1.getAgentAll(changedRule);
// => ["https://other.pod/profile/card#me"]

To manage the Groups for a Rule, you can use the Group variants of the functions, e.g., getGroupAll, etc.

Manage Rules for Public, Any Authenticated User, or the Creator of a Resource

Additionally, to inspect whether a Rule applies to everybody, to any authenticated user, or just the creator of a Resource, you can use the hasPublic function, the hasAuthenticated function and the hasCreator function, respectively. To set whether a Rule applies to everybody, any authenticated user, or the creator of a Resource, use the corresponding setPublic, setAuthenticated and setCreator functions:

const rule = acp_v1.getRule(
  solidDataset,
  "https://example.pod/rules#a-rule",
);
let changedRule = acp_v1.setPublic(rule, false);
changedRule = acp_v1.setAuthenticated(changedRule, true);
changedRule = acp_v1.setCreator(changedRule, false);
// `changedRule` does not include everybody,
// but it does include everybody who is authenticated.

Manage Required/Optional/Forbidden Rules

A policy can specify that <all | any | none> of the access rules match an agent.

To access rules that the policy specifies with the all condition, use the required rule functions; e.g., getRequiredRuleUrlAll, addRequiredRuleUrl, setRequiredRuleUrl, and removeRequiredRuleUrl.

To access rules that the policy specifies with the any condition, use the Optional variants of the functions; e.g.,``getOptionalRuleUrlAll``.

To access rules that the policy specifies with the none condition, use the Forbidden variants of the functions; e.g.,``setForbiddenRuleUrl``.

const policy = acp_v1.policy(
  solidDataset,
  "https://example.pod/policies#a-policy",
);
// Replace existing required Rules by the Rule at
// https://example.pod/rules#a-rule
let changedPolicy = acp_v1.setRequiredRuleUrl(
  policy,
  "https://example.pod/rules#a-rule",
);
// Add the Rule at
// https://example.pod/rules#another-rule
// to the existing optional Rules:
let changedPolicy = acp_v1.addOptionalRuleUrl(
  changedPolicy,
  "https://example.pod/rules#another-rule",
);