---
title: "AWS Verified Permissions"
description: "Use AWS Verified Permissions for MainSDK access - Cedar policy stores, IAM setup, main.yaml, local testing with built-in Cedar, and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/aws-verified-permissions"
updated: "2026-10-28"
---

# AWS Verified Permissions

> Use AWS Verified Permissions for MainSDK access - Cedar policy stores, IAM setup, main.yaml, local testing with built-in Cedar, and swapping.

Canonical: https://mainsdk.dev/docs/integrations/aws-verified-permissions · Updated: 2026-10-28

AWS Verified Permissions is a managed authorization service from AWS that evaluates Cedar policies held in a policy store. Behind [`access`](https://mainsdk.dev/docs/interfaces/access), it answers "may this subject do this action to this resource?" from a store your team manages in AWS. Pick it when your company already keeps its Cedar policies in Verified Permissions, or wants policy changes managed and audited in AWS rather than in your repo. If you just want Cedar, the built-in `cedar` driver runs the same language in process with no network call.

## Interfaces it serves

### Permissions (`access`)

- Status: Building for 0.3 · ships as a stable API
- Driver: `avp` (AWS Verified Permissions)
- Docs: https://mainsdk.dev/docs/interfaces/access.md

```yaml
access:
  driver: avp
```

Swap to another provider: `cedar`, `opa`, `openfga`, `spicedb`, `cerbos`, `permit`, `oso`.

## Before you start

You need an AWS account.

1. **Create a policy store** in the AWS Region that fits your residency needs. Check that Verified Permissions is offered in that Region.
2. **Define a schema** for your entity types and actions, and add your Cedar policies to the store.
3. **Grant your app access** through an IAM role with permission to call the authorization actions on that policy store, and nothing broader. Prefer a role your runtime assumes over long-lived access keys.
4. **Note the policy store ID**; the driver needs it.

## Configure

```yaml title="main.yaml"
access:
  driver: avp
  models: [rbac, abac]
  fresh-after-write: true
  unreachable: { deny: true, cache: 30s }
  # [TBD] connection keys (policy store ID, Region, credentials)
```

The `access` spec does not define connection keys for remote engines yet. Any credential will take a `secret:` reference; a literal key fails `mainsdk check`.

## Use it

```ts title="app/api/orders/[id]/route.ts"
import { access, auth, db } from "mainsdk";

export async function PATCH(req: Request, { params }: { params: { id: string } }) {
  const session = await auth.require(req);
  const order = await db.orders.for(session.user).get(params.id);

  const decision = await access.check({ subject: session.user, action: "orders.update", resource: order });
  if (!decision.allow) return new Response("Forbidden", { status: 403 });

  return Response.json(await db.orders.for(session.user).update(order.id, await req.json()));
}
```

## Local development and testing

- **No AWS account:** develop on the built-in `cedar` driver, which `mainsdk dev` runs in process.
- **Policy tests:** `mainsdk test access` runs your policy tests, and `policyTest` from `@mainsdk/testing` asserts a decision and the rule behind it.
- **Tests:** `createTestApp()` puts `access` on its in-memory fake. `chaos.on("access", { outage: true })` simulates Verified Permissions being unreachable; checks deny with `MAIN-ACCESS-0007`.

## What MainSDK adds on top

- Deny by default, with no bypass path.
- Denies when Verified Permissions is unreachable, with only a short cache of earlier allows that you set.
- Lists filtered at the database, not after fetching rows.
- Every decision written to the audit log with the policy version.

See [Permissions](https://mainsdk.dev/docs/interfaces/access).

## Limits and notes

- The `access` spec lists Permit.io, Oso and AWS Verified Permissions as drivers that come later in phases 1-2 through the driver kit, beyond their capability profiles.
- Verified Permissions decides over the network, unlike the built-in Cedar engine. Each driver declares this in its capability profile.
- If your app uses a capability the driver's profile lacks, such as relations, `mainsdk check` fails with `MAIN-ACCESS-0004`.
- Choose the AWS Region to match MainSDK's region for your users (US, EU or India) where your residency rules require it.
- `access.raw()` returns the engine client; `mainsdk check` lists every use.

## Swap to or from it

```yaml title="main.yaml"
access:
  driver: cedar   # was avp
```

> **Warning:** Your policies live in the Verified Permissions store. They are Cedar, the same language as the built-in engine, but how a policy store maps onto your `policies/` folder is not specified yet [TBD]. Copy them into git and run `mainsdk test access` on the new driver before you switch.

## FAQ

**Why use Verified Permissions when Cedar is built in?** When policies are managed centrally in AWS, by a team other than the app's developers, or shared across services. Otherwise built-in Cedar avoids the network call.

**Do I keep my existing policy store?** Yes. Existing Cedar policy stores run in place (`byo-policy`).

## Next

- [Permissions](https://mainsdk.dev/docs/interfaces/access) and [Policy decisions](https://mainsdk.dev/docs/interfaces/policy)
- [Open Policy Agent](https://mainsdk.dev/docs/integrations/open-policy-agent), [Cerbos](https://mainsdk.dev/docs/integrations/cerbos) and [OpenFGA](https://mainsdk.dev/docs/integrations/openfga)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
