# Manage Access Grants

Upon receipt of an Access Request, resource owners can use an access management application to approve or deny the Access Request:

* For an approved request, Inrupt’s Enterprise Solid Server (ESS) creates an Access Grant.
* For a denied request, ESS creates an Access Denial.

{% hint style="info" %}
**Access Requests and Grants**

The following Inrupt products are available to support Access Requests and Grants:

* **`solid-client-access-grants`** library for managing Access Requests and Grants
* Inrupt’s Enterprise Solid Server provides support for [Access Requests and Grants](https://docs.inrupt.com/security/authorization/access-requests-grants). ESS serializes the Access Requests and Grants as Verifiable Credentials.
* Inrupt’s [Authorization Management Component](https://docs.inrupt.com/security/authorization/access-requests-grants#authorization-management-component-amc) supports Access Request management.
  {% endhint %}

### Access Grants for Containers

An Access Grant for a [Container](https://docs.inrupt.com/reference/glossary#container) applies both to the Container and its descendants unless explicitly specified otherwise with an **`inherit: false`**.

**`@inrupt/solid-client-access-grants-js`** adds an **`inherit`** option to [approveAccessRequest](https://inrupt.github.io/solid-client-access-grants-js/functions/index.approveAccessRequest.html). For example:

* You can include **`inherit: false`** as an override option to create an approved Access Grant for the Container only, regardless of the specification in the Access Request.
* You can include **`inherit: true`** as an override option to create an approved Access Grant for both the Container and its descendants, regardless of the specification in the Access Request.

### solid-client-access-grants API

Inrupt’s [solid-client-access-grants library](https://inrupt.github.io/solid-client-access-grants-js/) provides various functions for approving or denying Access Requests; for example:

<table data-header-hidden><thead><tr><th width="224.0390625">Key</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://inrupt.github.io/solid-client-access-grants-js/functions/index.approveAccessRequest.html">approveAccessRequest</a></td><td><p>Approves the request and returns an approved Access Grant, serialized as a signed <a href="../../../../reference/glossary#verifiable-credential">Verifiable Credential</a> (VC). The Access Grants may be used to get access to specified resources.</p><p>A server-side code can use the function to create the Grant.</p><div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>ESS uses <a href="../../../security/authorization/acp">ACP policy</a> to enables the use of Access Grants for a resource. The <a href="https://inrupt.github.io/solid-client-access-grants-js/functions/index.approveAccessRequest.html">approveAccessRequest</a> function, by default, creates an ACP policy that enables the use of Access Grant.</p><p>Pods are created with default policies that enable the use of Access Grants.</p><p>When using <a href="https://inrupt.github.io/solid-client-access-grants-js/functions/index.approveAccessRequest.html">approveAccessRequest</a>, you can specify <strong><code>updateAcr: false</code></strong> to prevent the function from creating a separate ACP policy that enables the use of Access Grants.</p></div></td></tr><tr><td><a href="https://inrupt.github.io/solid-client-access-grants-js/functions/index.denyAccessRequest.html">denyAccessRequest</a></td><td><p>Denies the request and returns an Access Denial, serialized as a signed <a href="../../../../reference/glossary#verifiable-credential">Verifiable Credential</a>.</p><p>A server-side code can use the function to deny the request.</p></td></tr></tbody></table>

### Granting Access

The following implements the role of the [access management app](https://docs.inrupt.com/reference/glossary#access-management-application) in the example introduced in Access Requests and Grants. The role of the access management app is to act as a trusted third-party in the Access Request flow.

The access requestor (e.g., ExamplePrinter) sends the Resource Owner (e.g., **`snoringsue`**) to the Resource Owner’s access management app.

{% hint style="info" %}
When sending resource owner to the Access Management app, the requestor adds the following query parameters:

* **`id`** of the Access Request (in the example, the **`id`** of the Access Request VC), and
* **`redirectUrl`**, the URL where the requestor expects the Access Management app to redirect the Resource Owner after the request has been granted or denied.
  {% endhint %}

In order to approve or deny an Access Request:

1. The Resource Owner should log in to the access management app, if not already.
2. The Access Management app displays the Access Request (found in the **`requestVc`** parameter) to the Resource Owner.
   1. If the Access Request id is known, an access management app can also use [getAccessRequest](https://inrupt.github.io/solid-client-access-grants-js/functions/index.getAccessRequest.html) method.
3. The Resource Owner approves or denies the Access Request.

   * If the Resource Owner approves the request, the Access Management app uses [approveAccessRequest](https://inrupt.github.io/solid-client-access-grants-js/functions/index.approveAccessRequest.html) to return the **`id`** of the Access Grant VC. When calling the function, the Access Management application can also include an optional modifications object (such as to specify a subset of the requested resources or permissions or set the **`inherit`** flag).

     ```javascript
     async function getApprovedGrantVC(accessRequestToApprove, resourceOwnerSession){

       // Call `approveAccessRequest` to acquire a Verifiable Credential
       // for the approved Access Grant
       const accessGrant = await approveAccessRequest(
         accessRequestToApprove,
         undefined,  // Optional modifications
         {
           updateAcr: false,
           fetch: resourceOwnerSession.fetch, // From the resource owner's (i.e., snoringsue's) authenticated session
         }
       );
     }
     ```
   * If the Resource Owner denies the request, the Access Management app uses [denyAccessRequest](https://inrupt.github.io/solid-client-access-grants-js/functions/index.denyAccessRequest.html) to return the **`id`** of the Access Denial VC.

   ```javascript
    async function geAccessDenialVC(accessRequestToDeny, resourceOwnerSession){

      // Call `denyAccessRequest`** to create an Access Denial

      const accessDenial = await denyAccessRequest(
        accessRequestToDeny,
        {
          fetch: resourceOwnerSession.fetch, // From the resource owner's (i.e., snoringsue's) authenticated session
        }
      );
    }
   ```
4. Once the user acts on a request, the Access Management app redirects the user to the requesting app using the **`redirectUrl`** parameter received earlier. The **`id`** of the Access Grant/Denial is added to the redirect URL. The requesting app can use [getAccessGrantFromRedirectUrl](https://inrupt.github.io/solid-client-access-grants-js/functions/index.getAccessGrantFromRedirectUrl.html) to get the Access Grant.

   The requesting app can pass the **`id`** of the VC to [getAccessGrant](https://inrupt.github.io/solid-client-access-grants-js/functions/index.getAccessGrant.html) to retrieve the Access Grant.

### Adding custom fields to an Access Grant

Similar to Access Requests (see [Use Access Grants to Access Resources](https://docs.inrupt.com/sdk/javascript-sdk/access-requests-and-grants/use-access-grants-to-access-resources)), it can be useful to add application-specific information into an Access Grant.

**`@inrupt/solid-client-access-grants`** supports adding custom fields to an Access Grant. **`approveAccessRequest`** has a new **`CustomFields`** entry in its **`requestOverride`** argument, accepting a set of **`CustomField`**. A **`CustomField`** is a key/value entry where the key MUST be a URL, and the value a literal (**`string`**, **`boolean`** or **`number`**). The provided values are embedded within the issued Access Grant. The custom fields from the Access Request being approved are also propagated to the issued Access Grant, if not overridden by one of the provide&#x64;**`CustomField`**&#x6F;verrides. A **`CustomField`** override which value is **`undefined`** will result in the custom field not being present in the Access Grant, even if it was part of the Access Request.

If an incorrect **`CustomField`** value is provided, **`AccessGrantError`** is thrown. Invalid **`CustomField`** definitions include not using a **`URL`** as a key, or not using a literal as a value. The TypeScript typing is provided as a guideline.

```javascript
async function getApprovedGrantVC(accessRequestToApprove, resourceOwnerSession){

  // Call `approveAccessRequest` to acquire a Verifiable Credential
  // for the approved Access Grant
  const accessGrant = await approveAccessRequest(
    accessRequestToApprove,
    {
      // This adds a custom field to the issued Access Grant.
      // Custom fields from the Access Request will also be
      // present in the issued Grant.
      customFields: new Set([{
          key: new URL("https://example.com/printer/confirmationId"),
          value: "my-confirmation-id"
      }]),
    },
    {
      updateAcr: false, 
      fetch: resourceOwnerSession.fetch
    }
  );
}
```

### Querying for Access Grants

In **`@inrupt/solid-client-access-grants@v3.2.0`**, the application can use the **`query`** function to query for active (i.e., current and not expired) Access Grants. To use **`query`** for Access Grants, you can pass in a **`AccessGrantFilter`** object that specifies the query filter values (i.e., a combination of the resource, creator, recipient, purpose, and type).

The **`AccessGrantFilter`** object has the following fields:

<table><thead><tr><th width="151">Key</th><th>Description</th></tr></thead><tbody><tr><td><strong><code>type</code></strong></td><td>The Access Credential type (in this case, <strong><code>SolidAccessGrant</code></strong>).</td></tr><tr><td><strong><code>status</code></strong></td><td><p>Optional. Include a credential status in the query object.</p><p>The following values are supported for Access Grants:</p><ul><li><strong><code>Active</code></strong> returns all active access grants: those that have not expired and have not been revoked.</li><li><strong><code>Expired</code></strong> returns all access grants that have expired.</li><li><strong><code>Revoked</code></strong> returns all access grants that have been revoked by the resource owner.</li></ul></td></tr><tr><td><strong><code>fromAgent</code></strong></td><td>Optional. Include the creator of the Access Grant in the query filter. Resource Owner.</td></tr><tr><td><strong><code>toAgent</code></strong></td><td>Optional. Include the recipient of the Access Grant in the query filter. This is the requestor.</td></tr><tr><td><strong><code>resource</code></strong></td><td>Optional. Include the resource in the query object. Use this filter to return Access Requests bound to a specific resource.</td></tr><tr><td><strong><code>purpose</code></strong></td><td>Optional. Include a purpose in the query object. Use this filter to return Access Requests bound to a specific purpose.</td></tr><tr><td><strong><code>issuedWithin</code></strong></td><td><p>Optional. Include a time constraint on the issuance date in the query object. All matched credentials will have been issued within the provided duration value. Certain time constraints are available for use with this method, including:</p><ul><li><strong><code>P1D</code></strong> One day (<strong><code>DURATION.ONE_DAY</code></strong>)</li><li><strong><code>P7D</code></strong> Seven days (<strong><code>DURATION.ONE_WEEK</code></strong>)</li><li><strong><code>P1M</code></strong> One month (<strong><code>DURATION.ONE_MONTH</code></strong>)</li><li><strong><code>P3M</code></strong> Three months (<strong><code>DURATION.THREE_MONTH</code></strong>)</li></ul></td></tr><tr><td><strong><code>revokedWithin</code></strong></td><td><p>Optional. Include a time constraint on the revocation date in the query object. All matched credentials will have been revoked or canceled within the provided duration value. Certain time constraints are available for use with this method, including:</p><ul><li><strong><code>P1D</code></strong> One day (<strong><code>DURATION.ONE_DAY</code></strong>)</li><li><strong><code>P7D</code></strong> Seven days (<strong><code>DURATION.ONE_WEEK</code></strong>)</li><li><strong><code>P1M</code></strong> One month (<strong><code>DURATION.ONE_MONTH</code></strong>)</li><li><strong><code>P3M</code></strong> Three months (<strong><code>DURATION.THREE_MONTH</code></strong>)</li></ul></td></tr></tbody></table>

The result is paginated, so the agent may need to make multiple calls to the **`query`** function to get all of the Access Requests matching the provided filter.

The following example queries for active access grants, given to ExamplePrinter, that provide access for a specific resource for the purpose of photo printing.

```javascript
const page1 = await query({
  type: "SolidAccessGrant",
  status: "Active",
  resource: new URL("https://storage.example.com/some/resource"),
  purpose: new URL("https://purpose.example.com/PhotoPrinting"),
}, {
  fetch: session.fetch,
  queryEndpoint: new URL("https://vc.example.org/query"),
});
if (page1.next !== undefined) {
  const page2 = await query(page1.next, {
    fetch: session.fetch,
    queryEndpoint: new URL("https://vc.example.org/query"),
  });
}
```

**`paginatedQuery`** is a utility provided for iterating through the result pages:

```javascript
const pages = paginatedQuery({
  type: "SolidAccessGrant",
  status: "Active",
  resource: new URL("https://storage.example.com/some/resource"),
  purpose: new URL("https://purpose.example.com/PhotoPrinting"),
}, {
    fetch: session.fetch,
    queryEndpoint: new URL("https://vc.example.org/query"),
});
let i = 0;
for await (const page of pages) {
  console.log(`Page ${i} has ${page.items.length} items.`)
  i += 1;
}
```
