# Access Control Policy (ACP)

ESS uses [Access Control Policy (ACP)](https://docs.inrupt.com/reference/glossary#access-control-policies) to manage access to Pod resources. With ACP, Pod owners can define Policies that determine access for their Pod’s resources.

### Policies

Policies determine access for Pod resources. A policy consists of:

* Matcher statements that specify conditions that must be satisfied for the Policy to take effect.
* Access mode statements that specify which access modes are allowed and/or denied to the agent(s) satisfying the Matcher statements.

{% code overflow="wrap" %}

```
If
< allOf | anyOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
< allOf | anyOf | noneOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
…

Then< allow ( [AccessMode(s)](acp.md#acp-access-modes) ) | deny ( [AccessMode(s)](acp.md#acp-access-modes) ) | allow ( [AccessMode(s)](acp.md#acp-access-modes) ) AND deny ( [AccessMode(s)](acp.md#acp-access-modes) ) >

```

{% endcode %}

{% hint style="warning" %}
Important

The **`noneOf()`** expression excludes matches from the **`allOf`** and **`anyOf`** expressions; i.e., you can use the **`noneOf`** expression to refine the **`allOf`** and **`anyOf`** matches.

Because the **`noneOf()`** expression acts as a secondary/supplementary filter to the **`allOf`** and **`anyOf`** expressions, a policy statement with only a **`noneOf(<matchers>)`** condition cannot be satisfied.
{% endhint %}

### Matcher Statements

{% code overflow="wrap" %}

```
< allOf | anyOf > ([Matcher(s)](acp.md#acp-matcher)) evaluate to true, AND
< allOf | anyOf | noneOf > ([Matcher(s)](acp.md#acp-matcher)) evaluates to true, AND
…
```

{% endcode %}

#### Matchers

Matchers specify the conditions under which the Access Policy applies.

ESS supports matching:

<table><thead><tr><th width="114.37109375"></th><th></th></tr></thead><tbody><tr><td>Agents</td><td><ul><li>To match agents by specific <a href="https://docs.inrupt.com/reference/glossary#webid">WebID(s)</a>.</li><li>To match any authenticated agent.</li><li>To match any agent.</li></ul></td></tr><tr><td>Clients</td><td><ul><li>To match by specific <a href="../../authentication#client-identifier-client-id">Client ID(s)</a>.</li><li>To match any client application.</li></ul><p>See also <a href="https://docs.inrupt.com/security/authentication#client-identifier-client-id">Authorization and Clients</a></p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>Note<br>To use Client Matchers, the Policy must also specify an Agent Matcher.</p></div></td></tr><tr><td>Verifiable Credentials</td><td><ul><li>To match by <a href="https://docs.inrupt.com/reference/glossary#verifiable-credential">Verifiable Credential(s)</a> type; e.g., match VC type<strong><code>http://www.w3.org/ns/solid/vc#SolidAccessGrant</code></strong>.</li></ul><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p><strong>Tip</strong></p><p>To enable the use of ESS issued <a href="../../ess/latest/services/service-access-grant/access-grant-vc-jsonld-context">access grants (which are serialized as VCs)</a> , a policy with a VC Matcher is required. For details, see <a href="access-requests-grants">access grants</a> .</p></div></td></tr></tbody></table>

#### allOf, anyOf, noneOf Operators

A policy specifies its matchers in **`allOf()`** , **`anyOf()`** , and **`noneOf()`** operator expressions.

| **`allOf(<matchers>)`**  | Evaluates to true if all of its listed matchers evaluate to true.  |
| ------------------------ | ------------------------------------------------------------------ |
| **`anyOf(<matchers>)`**  | Evaluates to true if any of its listed matchers evaluate to true.  |
| **`noneOf(<matchers>)`** | Evaluates to true if none of its listed matchers evaluate to true. |

{% hint style="warning" %}
Important\
The **`noneOf()`** expression excludes matches from the **`allOf`** and **`anyOf`** expressions; i.e., you can use the **`noneOf`** expression to refine the **`allOf`** and **`anyOf`** matches.

Because the **`noneOf()`** expression acts as a secondary/supplementary filter to the **`allOf`** and **`anyOf`** expressions, a policy statement with only a **`noneOf(<matchers>)`** condition cannot be satisfied.
{% endhint %}

### Access Mode Statements

{% code overflow="wrap" %}

```
< allow ( [AccessMode(s)](acp.md#acp-access-modes) ) | deny ( [AccessMode(s)](acp.md#acp-access-modes) ) |allow ( [AccessMode(s)](acp.md#acp-access-modes) ) AND deny ( [AccessMode(s)](acp.md#acp-access-modes) ) >
```

{% endcode %}

#### Access Modes

Access Modes describe the permissions that can be granted or denied. The available modes are:

| Access Mode  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`Read`**   | <p>Permission to view/retrieve a resource as well as to subscribe to <a href="../../ess/latest/services/service-notification/service-websocket">notifications</a> for the resource.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p>                                                                                                                                                                                                                                                                                                                                                      |
| **`Write`**  | <p>Permission to create a resource, update the content of a resource, and delete a resource.<br><br>Tip:<br>\* To create a resource, you must have <strong><code>Write</code></strong> access on both the resource and the resource’s container.<br>\* To delete a resource, you must have <strong><code>Write</code></strong> access on both the resource and the resource’s container.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p>                                                                                                                                                 |
| **`Append`** | <p>Permission to add content to a resource.<br>If a resource is a <a href="../../../reference/glossary#container">container</a> (analogous to a folder in a file system), the <strong><code>Append</code></strong> permission on the resource allows agents to add new resources (container, RDF resource, non-RDF resource) to the container.<br>If a resource is an <a href="../../reference/rdf">RDF resource</a>, the <strong><code>Append</code></strong> permission on a resource allows agents to add statements to the resource.<br>See also <a href="#crud-access-modes">CRUD Operations and Access Modes</a>.</p> |

#### allow, deny Expressions

A policy statement specifies its access modes in `allow(Access Modes)` or `deny(Access Modes)` expressions:

* The **`allow`** expression specifies the access modes to be granted.
* The **`deny`** expression specifies the access modes to be denied.

An agent is granted an access mode for a resource if:

* The agent satisfies a policy that allows the access mode for the resource, **and**
* The agent does not satisfy any policy that denies that access mode for the resource.

For example:

* If a resource only has a single policy that allows **`Read`** and **`Write`** for an agent, the agent is granted **`Read`** and **`Write`** for the resource.
* If a resource has:
  * A policy that allows **`Read`** and **`Write`** for an agent, and
  * A policy that denies **`Write`** for the same agent,

    Then, the agent is granted **`Read`** access for the resource.

If **no** “allow access” policy is satisfied for a resource, then that resource is inaccessible to the agent. That is, an unsatisfied “deny access” policy does not confer access. For example,

* If a resource has defined only a single policy that denies **`Read`** and the policy is unsatisfied by an agent, that agent still does not have any access to that resource.

#### CRUD Operations and Access Modes

This section summarizes the relationship between Create/Read/Update/Delete (CRUD) operations and the required access modes.

{% tabs %}
{% tab title="Create" %}
To create a resource, the user requires either an **`Append`** or **`Write`** access.

{% hint style="info" %}
Note The creation operation creates the resource (be it container, RDF resource, non-RDF resource) and updates the content of the **parent** container with the new resource’s metadata.
{% endhint %}

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](https://docs.inrupt.com/reference/glossary#container)                       | Either **`Append`** or **`Write`** access on the **parent** container (under which the new container is to be created) allows agents to create a new container. For example, to create `https://storage..../parentcontainer/newContainer/`, either an **`Append`** or a **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/newContainer/`.                                                      |
| [RDF resource](https://docs.inrupt.com/reference/rdf)                                   | Either **`Append`** or **`Write`** access on the **parent** container (under which the new resource is to be created) allows agents to create a RDF resource. For example, to create `https://storage..../parentcontainer/newResource/`, either an **`Append`** or a **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/newResource`.                                                           |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | Either **`Append`** or **`Write`** access on the **parent** container (under which the new resource is to be created) allows agents to create a new [non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource). For example, to create `https://storage..../parentcontainer/foo.jpg`, **`Append`** or **`Write`** access on `https://storage..../parentcontainer/` allows agents to create `https://storage..../parentcontainer/foo.jpg`. |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

{% tab title="Read" %}
For read operations , the user requires `Read` access.

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](https://docs.inrupt.com/reference/glossary#container)                       | **`Read`** access on the target container (analogous to a folder in a file system) allows agents to read/retrieve the container as a resource (not the resource(s) under the container). That is, Read access only affects read operation on the container itself. Reading a container (which stores metadata about the resources contained within the container) allows a client to discover what resources are contained inside the container and their resource type (i.e., analogous to an **`ls`** on a folder in a file system). |
| [RDF resource](https://docs.inrupt.com/reference/rdf)                                   | **`Read`** access on the RDF resource allows agents to read/retrieve the resource (regardless of the access on the parent container). For example, if a resource has as its URL `https://storage..../container/ResourceToRead`, to read/retrieve this resource: The user must have **`Read`** access on `https://storage..../container/ResourceToRead`. The user’s access on `https://storage..../container/` is immaterial.                                                                                                           |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | **`Read`** access on a non-RDF resource allows agents to read/retrieve the resource (regardless of Read access on the container). For example, if a non-RDF resource has as its URL `https://storage..../container/foo.jpg`, to read/retrieve this resource: The user must have **`Read`** access on `https://storage..../container/foo.jpg`. The user’s access on `https://storage..../container/` is immaterial.                                                                                                                     |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |

{% tab title="Update" %}
For update operations, the user requires **`Append`** or **`Write`** access, depending on the specific update operation.

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                               |
| --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](https://docs.inrupt.com/reference/glossary#container)                       | To add resources to the Container, see the Create tab. To delete resources from the Container, see the Delete tab.                                                                                                                                                                                                                                                                                                                        |
| [RDF resource](https://docs.inrupt.com/reference/rdf)                                   | Either **`Append`** or **`Write`** access on an RDF resource allows agents to add content (statements) to the resource. **`Write`** access on an RDF resource allows agents to delete content (statements) from the resource. **`Write`** access on an RDF resource allows agents to modify existing content (statements) in the resource.                                                                                                |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | **`Write`** access on the target resource allows agents to overwrite/replace the resource (regardless of the access on the parent container). For example, if the non-RDF resource has as its URL **`https://storage..../container/foo.jpg`**, to overwrite this resource: The user must have **`Write`** access on **`https://storage..../container/foo.jpg`**. The user’s access on **`https://storage..../container/`** is immaterial. |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                           |

{% tab title="Delete" %}
For delete operations, the user requires `Write` access.

| Resource                                                                                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Container](https://docs.inrupt.com/reference/glossary#container)                       | **`Write`** access on both the parent container and the target container allows agents to delete the target container. For example, to delete `https://storage..../parentcontainer/containerToDelete/`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/containerToDelete/` allows agents to delete `https://storage..../parentcontainer/containerToDelete/`.                     |
| [RDF resource](https://docs.inrupt.com/reference/rdf)                                   | To delete an RDF resource, **`Write`** access on both the parent container and the target resource allows agents to delete the target resource. For example, to delete `https://storage..../parentcontainer/resourceToDelete/`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/resourceToDelete` allows agents to delete `https://storage..../parentcontainer/resourceToDelete`. |
| [Non-RDF resource](https://docs.inrupt.com/sdk/java-sdk/crud-rdf-data#non-rdf-resource) | To delete a non-RDF resource, **`Write`** access on both the parent container and the target resource allows agents to delete the target resource. For example, to delete `https://storage..../parentcontainer/foo.jpg`, **`Write`** access on both `https://storage..../parentcontainer/` and `https://storage..../parentcontainer/foo.jpg` allows agents to delete `https://storage..../parentcontainer/foo.jpg`.                          |
| {% endtab %}                                                                            |                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| {% endtabs %}                                                                           |                                                                                                                                                                                                                                                                                                                                                                                                                                              |

### Access Control Resource

Each Pod resource has an associated Access Control Resource (ACR) that contains the policies that determine access to the Pod resource.

<figure><img src="https://2584838151-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLMLxFYifBOpjrf8rQMX1%2Fuploads%2Fgit-blob-a017ba72b213602f7f34ae9590bd71b5cdddb918%2FACR.svg?alt=media" alt=""><figcaption></figcaption></figure>

The lifecycle of the ACR is bound to the lifecycle of the Pod resource; that is:

* When creating a resource, ESS creates a corresponding ACR.
* When deleting a resource, ESS deletes the corresponding ACR.

If a resource has no Policies that apply to it, the resource is inaccessible. However, the Pod owner can add new policies to provide access to the resource.

### Member Policies

If a resource is a Container, you can also specify Member Policies in the Container’s ACR. Member Policies will be inherited by the Container’s children/descendants.

### Access to ACRs

ESS’ [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) hosts the ACRs. The [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) ‘s [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) determines which clients can write policies to ACRs.

{% hint style="info" %}
Note\
Having read/write/append access to policies for a resource (i.e., write to the resource’s ACR) is distinct from having access to read/write/append the resource itself.
{% endhint %}

In version 2.0, ESS also uses the values in [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) as part of the initial ACP policies that determine the read/write/append access to the Pod and its resource.

Starting in 2.1, ESS uses the values in [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) if set. If unset, ESS uses the values in [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (same as it did in version 2.0).

For details, see [Initial ACP Policies](#initial-policies) .

### Initial ACP Policies

When a Pod is created, like any other Pod resource, an [Access Control Resource](#acp-acr) is also created for the Pod Root. The ACR is initialized with the default [ACP policies](#acp-policies) for the Pod Owner and for Access Grant enablement:

* **Initial Pod Owner policies** give the Pod Owner read and write access to the Pod. These policies also specify a client matcher as well if the **Authorization service’s** configuration for the initial client allow list is set:
  * [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) or if that is unset,
  * [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) .

{% tabs %}
{% tab title="Allow List is Set" %}
{% hint style="info" %}
**Note**

Starting in 2.1, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation) to create the client matcher for the initial ACP policies. If the configuration is unset, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation).
{% endhint %}

Using the value of the Pod owner’s WebID and an initial client allow list, ESS creates the initial policies of the form:

```
If allOf(AgentMatcher and ClientMatcher) evaluates to true, Then allow (Read and Write).
```

Specifically, ESS creates:

Policy 1 for the Pod Root:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , and if the client application’s Client ID has a match in the initial client allow list, allow Read and Write access.

Policy 2 for the Pod Root’s Initial Member Policies:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , and if the client application’s Client ID has a match in the initial client allow list, allow Read and Write access.

For more information on a Container’s Member Policies, see [Member Policies](#member-policies) .
{% endtab %}

{% tab title="Allow List is Not Set" %}
{% hint style="info" %}
**Note**\
Starting in 2.1, ESS uses the values in **Authorization service’s** [`INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation) to create the client matcher for the initial policies. If the configuration is unset, ESS uses the values in its **Authorization service’s** [`INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST) (at the time of Pod creation).
{% endhint %}

If the initial client allow list is empty (when creating the policy), ESS uses the value of the Pod owner’s WebID to create initial policies of the form:

```
If allOf(AgentMatcher) evaluates to true, Then allow (Read and Write).
```

Specifically, ESS creates:

Policy 1 for the Pod Root:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , allow Read and Write access.

Policy 2 for the Pod Root’s Initial Member Policies:If the agent matches the Pod owner’s [WebID](https://docs.inrupt.com/reference/glossary#webid) , allow Read and Write access.

For more information on a Container’s Member Policies, see [Member Policies](#member-policies) .
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
**Disambiguation**\
Both [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) and [Pod Storage Service](https://docs.inrupt.com/ess/latest/services/service-pod-management/service-pod-storage) have a `INRUPT_AUTHORIZATION_CLIENT_ID_ALLOW_LIST` setting.

**Only** the [Authorization Service](https://docs.inrupt.com/ess/latest/services/service-authorization/) setting affects which clients are allowed. The [Pod Storage Service](https://docs.inrupt.com/ess/latest/services/service-pod-management/service-pod-storage) is for [Discovery](https://docs.inrupt.com/ess/latest/services/service-pod-management/service-pod-provision) purposes only.
{% endhint %}

* **Initial Access Grant Enablement policies** allow the use of [Access Grants](https://docs.inrupt.com/security/authorization/access-requests-grants) that grant read/write/append access to the Pod resources. *New in Version 2.2*

  ```
        If allOf(VC Matcher) evaluates to true, Then allow (Read and Write and Append).
  ```

  Specifically, ESS creates:

Policy 3 for the Pod Root:If a presented VC matches the specified type, allow its use for\
Read, Write, and Append access.

Policy 4 for the Pod Root’s Initial Member Policies:If a presented VC matches the specified type, allow its use for\
Read, Write, and Append access.\
See also[`INRUPT_AUTHORIZATION_DEFAULT_ACR_ACCESS_GRANTS_ALLOWED_MODES`](https://docs.inrupt.com/ess/latest/services/service-authorization/#cmdoption-authzconfig-arg-INRUPT_AUTHORIZATION_DEFAULT_ACR_ACCESS_GRANTS_ALLOWED_MODES).

{% hint style="warning" %}
**Important**

The policies only enable the use of [Access Grants](https://docs.inrupt.com/security/authorization/access-requests-grants) for the allowed access modes. To determine the access for an agent using an access grant, ESS uses the *intersection* of:

* The allowed access specified by the policy, and
* The granted access specified in the Access Grant (for the resource specified in the Access Grant).
  {% endhint %}

{% hint style="info" %}
Note\
A Pod’s initial Policies are set when the Pod is provisioned. As such, updates to the various `INRUPT_AUTHORIZATION_DEFAULT_ACR_*` options do not affect existing Pods.

That is, once a Pod’s initial policies have been created, changes to the various `INRUPT_AUTHORIZATION_DEFAULT_ACR_*` options are not reflected in that Pod’s policies.
{% endhint %}

* ESS’ ACP is based on an earlier version of the [Access Control Policy (ACP) Specification](https://solid.github.io/authorization-panel/acp-specification/) .
* Inrupt does not provide support for ESS servers running [Web Access Control (WAC)](https://solid.github.io/web-access-control-spec/) in Production.

### Examples

#### Create Policy to Match Agents and Clients

The following example sets up an **`app-friends-policy`** that allow Read and Write access to any Agent that satisfies the **`match-app-friends`** Matcher conditions; namely, Agents whose WebID matches one of the specified WebIDs and is using an application whose Client Identifier matches the specified Client IDs. When verifying against a policy that specifies a Client Application Matcher, the user must be logged in. A Policy that specifies a Client Application Matcher but no Agent Matcher does not match any agent.

{% code fullWidth="false" %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2, asUrl } from "@inrupt/solid-client";


// ... Various logic, including login logic, omitted for brevity.
// ...


async function setupPolicyToMatchAgentsAndClients(resourceURL) {

  const agentsToMatch = [ "https://id.example.com/chattycarl", "https://id.example.com/busybee" ];
  const clientIDsToMatch = [ "https://myapp.example.net/appid" ];

  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,            // Resource whose ACR to set up
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Initialize a new Matcher.
    let appFriendsMatcher = acp_ess_2.createResourceMatcherFor(
      resourceWithAcr,
      "match-app-friends"
    );

    // 3. For the Matcher, specify the Agent(s) to match.
    agentsToMatch.forEach(agent => {
      appFriendsMatcher = acp_ess_2.addAgent(appFriendsMatcher, agent);
    })

    // 4. For the Matcher, specify the Client ID(s) to match.
    clientIDsToMatch.forEach(clientID => {
      appFriendsMatcher = acp_ess_2.addClient(appFriendsMatcher, clientID);
    })

    // 5. Add the Matcher definition to the Resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
      resourceWithAcr,
      appFriendsMatcher
    );

    // 6. Create a Policy for the Matcher.
    let appFriendsPolicy = acp_ess_2.createResourcePolicyFor(
      resourceWithAcr,
      "app-friends-policy",
    );

    // 7. Add the appFriendsMatcher to the Policy as an allOf() expression.
    // Since using allOf() with a single Matcher, could also use anyOf() expression

    appFriendsPolicy = acp_ess_2.addAllOfMatcherUrl(
      appFriendsPolicy,
      appFriendsMatcher
    );

    // 8. Specify the access modes (e.g., allow Read and Write).
    appFriendsPolicy = acp_ess_2.setAllowModes(appFriendsPolicy,
      { read: true, write: true }
    );

    // 9. Apply the Policy to the resource.
    resourceWithAcr = acp_ess_2.addPolicyUrl(
      resourceWithAcr,
      asUrl(appFriendsPolicy)
    );

    // 10. Add the Policy definition to the resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      appFriendsPolicy
    );

    // 11. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

{% endcode %}

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,            // Resource whose ACR to set up
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.createResourceMatcherFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcematcherfor) to initialize the Matcher that will be used by the policy.

   ```javascript
   let appFriendsMatcher = acp_ess_2.createResourceMatcherFor(
     resourceWithAcr,
     "match-app-friends"
   );
   ```

   When saved, the Matcher URL will be `{ACR URL}#match-app-friends`.
3. [acp\_ess\_2.addAgent](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addagent) to specify the [WebID](about:blank/reference/glossary/#term-WebID) of the agent(s) to match:

   ```javascript
   agentsToMatch.forEach(agent => {
     appFriendsMatcher = acp_ess_2.addAgent(appFriendsMatcher, agent);
   })
   ```
4. [acp\_ess\_2.addClient](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addclient) to specify the [Client ID](about:blank/authenticate-client/#authenticate-client-identifier-document) of the application(s) to match.

   ```javascript
   clientIDsToMatch.forEach(clientID => {
     appFriendsMatcher = acp_ess_2.addClient(appFriendsMatcher, clientID);
   })
   ```
5. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to store the new matcher definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourceMatcher(
     resourceWithAcr,
     appFriendsMatcher
   );
   ```
6. [acp\_ess\_2.createResourcePolicyFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcepolicyfor) to initialize the policy:

   ```javascript
   let appFriendsPolicy = acp_ess_2.createResourcePolicyFor(
     resourceWithAcr,
     "app-friends-policy",
   );
   ```

   When saved, the policy URL will be `{ACR URL}#app-friends-policy`.
7. [acp\_ess\_2.addAllOfMatcherUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addallofmatcherurl) to add the matcher to the policy.

   ```javascript
   // Since using allOf() with a single Matcher, could also use anyOf() expression

   appFriendsPolicy = acp_ess_2.addAllOfMatcherUrl(
     appFriendsPolicy,
     appFriendsMatcher
   );
   ```
8. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to specify that the policy allows `Read` and `Write` modes:

   ```javascript
   appFriendsPolicy = acp_ess_2.setAllowModes(appFriendsPolicy,
     { read: true, write: true }
   );
   ```
9. [acp\_ess\_2.addPolicyUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addpolicyurl) to apply the new policy to the resource:

   ```javascript
   resourceWithAcr = acp_ess_2.addPolicyUrl(
     resourceWithAcr,
     asUrl(appFriendsPolicy)
   );
   ```
10. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to store the new policy definition to the ACR:

    ```javascript
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      appFriendsPolicy
    );
    ```
11. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

    ```javascript
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
    ```

#### Make a Resource Public: Create Public Policy for a Resource

The following example uses the ACP-specific APIs to set up a **`public-policy`** that allows Read access to the public (i.e., everyone) for a resource.

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.
// ...

async function setupPublicReadPolicyForResource(resourceURL) {
  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,              // Resource for which to set up the policies
      { fetch: fetch }          // fetch from the authenticated session
    );

    // 2. Create a Matcher for the Resource.
    let resourcePublicMatcher = acp_ess_2.createResourceMatcherFor(
      resourceWithAcr,
      "match-public"  // Matcher URL will be {ACR URL}#match-public
    );

    // 3. Specify that the matcher matches the Public (i.e., everyone).
    resourcePublicMatcher = acp_ess_2.setPublic(resourcePublicMatcher);

    // 4. Add Matcher to the Resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
      resourceWithAcr,
      resourcePublicMatcher,
    );

    // 5. Create the Policy for the Resource.
    let resourcePolicy = acp_ess_2.createResourcePolicyFor(
      resourceWithAcr,
      "public-policy",  // Policy URL will be {ACR URL}#public-policy
    );

    // 6. Add the Public Matcher to the Policy as an allOf() expression.
    resourcePolicy = acp_ess_2.addAllOfMatcherUrl(
      resourcePolicy,
      resourcePublicMatcher
    );

    // 7. Specify the access modes for the Policy.
    resourcePolicy = acp_ess_2.setAllowModes(
      resourcePolicy,
      { read: true, append: false, write: false },
    );

    // 8. Apply the Policy to the Resource.
    resourceWithAcr = acp_ess_2.addPolicyUrl(
       resourceWithAcr,
       asUrl(resourcePolicy)
     );

    // 9. Add the Policy definition to the Resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
       resourceWithAcr,
       resourcePolicy,
    );

    // 10. Save the ACR for the Resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,              // Resource for which to set up the policies
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.createResourceMatcherFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcematcherfor) to initialize the Matcher that will be used by the policy.

   ```javascript
   let resourcePublicMatcher = acp_ess_2.createResourceMatcherFor(
     resourceWithAcr,
     "match-public"  // Matcher URL will be {ACR URL}#match-public
   );
   ```

   When saved, the Matcher URL will be `{ACR URL}#match-public`.
3. [acp\_ess\_2.setPublic](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setpublic) to specify that the matcher is a Public matcher; i.e., matches everyone.

   ```javascript
   resourcePublicMatcher = acp_ess_2.setPublic(resourcePublicMatcher);
   ```
4. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to store the matcher definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourceMatcher(
     resourceWithAcr,
     resourcePublicMatcher,
   );
   ```
5. [acp\_ess\_2.createResourcePolicyFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#createresourcepolicyfor) to initialize the policy for the Resource:

   ```javascript
   let resourcePolicy = acp_ess_2.createResourcePolicyFor(
     resourceWithAcr,
     "public-policy",  // Policy URL will be {ACR URL}#public-policy
   );
   ```

   When saved, the policy URL will be `{ACR URL}#public-policy`.
6. [acp\_ess\_2.addAllOfMatcherUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addallofmatcherurl) to add the matcher to the policy.

   ```javascript
   resourcePolicy = acp_ess_2.addAllOfMatcherUrl(
     resourcePolicy,
     resourcePublicMatcher
   );
   ```
7. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to specify the access modes for the policy:

   ```javascript
   resourcePolicy = acp_ess_2.setAllowModes(
     resourcePolicy,
     { read: true, append: false, write: false },
   );
   ```
8. [acp\_ess\_2.addPolicyUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#addpolicyurl) to apply the new policy to the resource:

   ```javascript
   resourceWithAcr = acp_ess_2.addPolicyUrl(
      resourceWithAcr,
      asUrl(resourcePolicy)
    );
   ```
9. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to store the new policy definition to the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      resourcePolicy,
   );
   ```
10. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

    ```javascript
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );
    ```

#### View Policies and Matchers for a Resource

The following example uses the ACP-specific APIs to view the ACP policies for a resource.

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2, solidDatasetAsTurtle } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function viewResourceACR(resourceURL) {

  try {
    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    const resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,
      { fetch: fetch }            // fetch from the authenticated session
    );

    // 2a. Get the Access Control Resource (ACR)
    const myACR = await getSolidDataset(
      acp_ess_2.getLinkedAcrUrl(resourceWithAcr),
      { fetch: fetch }
    );
    
    // 2b. Output (formatted as Turtle) its policies and matchers details.
    console.log(solidDatasetAsTurtle(myACR));

    // 3a. Get all policies from the ACR to process policies.
    const myResourcePolicies = acp_ess_2.getResourcePolicyAll(resourceWithAcr);

    // Loop through each policy for processing.
    myResourcePolicies.forEach(policy => {
      //... 
    });

    // 3b. Get a specific policy from the ACR.
    const specificPolicy = acp_ess_2.getResourcePolicy(
      resourceWithAcr,
      "specify-the-name-of-policy-to-get"
    );

    // 4a. Get all matchers from the ACR to process matchers.
    const myResourceMatchers = acp_ess_2.getResourceMatcherAll(resourceWithAcr)

    // Loop through each matcher for processing.
    myResourceMatchers.forEach(matcher => {
      // ... 
    });

    // 4b. Get a specific matcher from the ACR.
    const specificMatcher = acp_ess_2.getResourceMatcher(
      resourceWithAcr,
      "specify-the-name-of-matcher-to-get"
    );


  } catch (error) {
      console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   const resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,
     { fetch: fetch }            // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) with [getLinkedAcrUrl](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getlinkedacrurl) to retrieve the ACR.

   ```javascript
   const myACR = await getSolidDataset(
     acp_ess_2.getLinkedAcrUrl(resourceWithAcr),
     { fetch: fetch }
   );
   ```

   Once you retrieve the ACR as a SolidDataset, you can use [solidDatasetAsTurtle](https://inrupt.github.io/solid-client-js/modules/formats.html#soliddatasetasturtle) to format ACR as [Turtle](https://www.w3.org/TR/turtle/).

   ```javascript
   console.log(solidDatasetAsTurtle(myACR));
   ```
3. [acp\_ess\_2.getResourcePolicyAll](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicyall) to get the policies from the resource’s ACR.

   ```javascript
   const myResourcePolicies = acp_ess_2.getResourcePolicyAll(resourceWithAcr);

   // Loop through each policy for processing.
   myResourcePolicies.forEach(policy => {
     //... 
   });
   ```

   To view a specific policy, you can use [acp\_ess\_2.getResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicy):

   ```javascript
   const specificPolicy = acp_ess_2.getResourcePolicy(
     resourceWithAcr,
     "specify-the-name-of-policy-to-get"
   );
   ```
4. [acp\_ess\_2.getResourceMatcherAll](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcherall) to get all matchers from the resource’s ACR.

   ```javascript
   const myResourceMatchers = acp_ess_2.getResourceMatcherAll(resourceWithAcr)

   // Loop through each matcher for processing.
   myResourceMatchers.forEach(matcher => {
     // ... 
   });
   ```

   To view a specific matcher, you can use [acp\_ess\_2.getResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcher):

   ```javascript
   const specificMatcher = acp_ess_2.getResourceMatcher(
     resourceWithAcr,
     "specify-the-name-of-matcher-to-get"
   );
   ```

#### Delete Existing Policy for a Resource

The following example deletes an existing Policy for a resource.

{% hint style="info" %}
**Tip**

To view existing Policies for a resource, see View Policies and Matchers for a Resource.
{% endhint %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function deletePolicyForResource(resourceURL, policyName) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,           // Resource whose policy you want to delete
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Remove the Policy definition from the ACR
    resourceWithAcr = acp_ess_2.removeResourcePolicy(resourceWithAcr, policyName);

    // 3. Save the ACR for the Resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,           // Resource whose policy you want to delete
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.removeResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeresourcepolicy) to delete the Policy definition from the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.removeResourcePolicy(resourceWithAcr, policyName);
   ```

   [acp\_ess\_2.removeResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeresourcepolicy) can also accept the Policy URL or the Policy itself instead of the Policy name.
3. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

#### Modify Existing Matcher for a Resource

The following example continues from an earlier example. Specifically, the example modifies the **`match-app-friends`** created in [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients) to remove one of the Agents from the match list.

Tip

To view existing Matchers for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function removeAgentFromMatcher(resourceURL) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
        resourceURL,           // Resource whose Matcher you want to modify
        { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Get the Matcher to modify.
    let matcherToModify = acp_ess_2.getResourceMatcher(
        resourceWithAcr,
        "match-app-friends" // Name of the Matcher created in an earlier example.
    );

    // 3. Modify the Matcher; e.g., remove an Agent from the Matcher.

    const agentToRemove="https://id.example.com/chattycarl";
    matcherToModify = acp_ess_2.removeAgent(matcherToModify, agentToRemove);

    // 4. Store the modified Matcher definition to the resource's ACR.
    resourceWithAcr = acp_ess_2.setResourceMatcher(
        resourceWithAcr,
        matcherToModify
    );

    // 5. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
        resourceWithAcr,
        { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

#### **Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
       resourceURL,           // Resource whose Matcher you want to modify
       { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.getResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcematcher) to get the Matcher from the resource’s ACR.

   ```javascript
   let matcherToModify = acp_ess_2.getResourceMatcher(
       resourceWithAcr,
       "match-app-friends" // Name of the Matcher created in an earlier example.
   );
   ```

   The `match-app-friends` was created in an earlier example, [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients).

   Tip

   To view existing Matchers for a resource, see [View Policies and Matchers for a Resource](https://docs.inrupt.com/security/authorization/acp#view-policies-and-matchers-for-a-resource).
3. [acp\_ess\_2.removeAgent](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#removeagent) to remove an Agent’s WebID from the list of the Matcher’s WebIDs to match.

   ```javascript
   policyToModify = acp_ess_2.setAllowModes(policyToModify,
     { write: false }
   );
   ```
4. [acp\_ess\_2.setResourceMatcher](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcematcher) to update the Matcher definition in the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
     resourceWithAcr,
     policyToModify
   );
   ```
5. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```

#### Modify Existing Policy for a Resource

The following example continues from an earlier example. Specifically, the example modifies the **`app-friends-policy`** created in [Create Policy to Match Agents and Client](#create-policy-to-match-agents-and-clients).

{% hint style="info" %}
Tip

To view existing Policies for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).
{% endhint %}

```javascript
import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser';
import { acp_ess_2 } from "@inrupt/solid-client";

// ... Various logic, including login logic, omitted for brevity.

async function modifyAppFriendsPolicy(resourceURL) {

  try {

    // 1. Fetch the SolidDataset with its Access Control Resource (ACR).
    let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
      resourceURL,           // Resource whose Policy you want to modify
      { fetch: fetch }       // fetch from the authenticated session
    );

    // 2. Get the Policy to modify. 
    let policyToModify = acp_ess_2.getResourcePolicy(
      resourceWithAcr,
      "app-friends-policy" // Name of the Policy created in an earlier example.
    );

    // 3. Change the Write access mode to false (from true). Other access modes remain unchanged.
    policyToModify = acp_ess_2.setAllowModes(policyToModify,
      { write: false }
    );

    // 4. Store the modified Policy definition to the resource's ACR. 
    resourceWithAcr = acp_ess_2.setResourcePolicy(
      resourceWithAcr,
      policyToModify
    );

    // 5. Save the modified ACR for the resource.
    const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
      resourceWithAcr,
      { fetch: fetch }          // fetch from the authenticated session
    );

  } catch (error) {
    console.error(error.message);
  }
}
```

**Details**

In particular, the example uses:

1. [acp\_ess\_2.getSolidDatasetWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getsoliddatasetwithacr) to retrieve the SolidDataset (the SolidDataset can be a Container) with its ACR.

   ```javascript
   let resourceWithAcr = await acp_ess_2.getSolidDatasetWithAcr(
     resourceURL,           // Resource whose Policy you want to modify
     { fetch: fetch }       // fetch from the authenticated session
   );
   ```

   To specify policies for files with other structures (such as .pdf or .jpeg files), use [acp\_ess\_2.getFileWithAcr](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getfilewithacr) instead.
2. [acp\_ess\_2.getResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#getresourcepolicy) to get the Policy from the resource’s ACR. The `app-friends-policy` was created in an earlier example, [Create Policy to Match Agents and Clients](#create-policy-to-match-agents-and-clients).

   ```javascript
   let policyToModify = acp_ess_2.getResourcePolicy(
     resourceWithAcr,
     "app-friends-policy" // Name of the Policy created in an earlier example.
   );
   ```

   Tip

   To view existing Policies for a resource, see [View Policies and Matchers for a Resource](#view-policies-and-matchers-for-a-resource).
3. [acp\_ess\_2.setAllowModes](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setallowmodes) to update the Write access mode for the Policy. The other Access Modes for this Policy remain unchanged.

   ```javascript
   policyToModify = acp_ess_2.setAllowModes(policyToModify,
     { write: false }
   );
   ```

   For additional Policy functions, see the [API documentation](https://inrupt.github.io/solid-client-js/).
4. [acp\_ess\_2.setResourcePolicy](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#setresourcepolicy) to update the Policy definition in the ACR:

   ```javascript
   resourceWithAcr = acp_ess_2.setResourcePolicy(
     resourceWithAcr,
     policyToModify
   );
   ```
5. [acp\_ess\_2.saveAcrFor](https://inrupt.github.io/solid-client-js/modules/acp_ess_2.html#saveacrfor) to save the modified ACR.

   ```javascript
   const updatedResourceWithAcr = await acp_ess_2.saveAcrFor(
     resourceWithAcr,
     { fetch: fetch }          // fetch from the authenticated session
   );
   ```
