Amazon Verified Permissions is a fully managed, fine-grained authorization service for custom applications. It uses the Cedar policy language to define permissions and make authorization decisions. Applications call the IsAuthorized or IsAuthorizedWithToken API to evaluate Cedar policies stored in a policy store.
Policy stores are central containers for Cedar policies, schemas, and identity sources. Cedar is an open-source policy language with explicit permit and forbid effects. Authorization follows default-deny: if any forbid policy matches, the result is Deny; else if any permit policy matches, the result is Allow; otherwise Deny.
Key components: Static policies, policy templates, template-linked policies, schemas, identity sources, validation settings (STRICT or OFF)
Identity sources connect external identity providers (Amazon Cognito user pools or custom OIDC providers) to a policy store. The IsAuthorizedWithToken API accepts ID or access tokens directly and maps token claims to Cedar entity attributes for policy evaluation.
Key components: Cognito user pool integration, OIDC provider support, token-to-entity mapping, client/audience validation
Verified Permissions is an application-layer authorization service. It does not directly control AWS resource access (that is IAM's role). However, misconfigurations in Cedar policies, schemas, or identity source mappings can lead to authorization bypass in the applications that rely on it. The primary risks are overly permissive Cedar policies, disabled schema validation, and flawed policy logic.
aws verifiedpermissions list-policy-storesaws verifiedpermissions get-policy-store \
--policy-store-id PSEXAMPLEabcdefg111111aws verifiedpermissions list-policies \
--policy-store-id PSEXAMPLEabcdefg111111aws verifiedpermissions get-policy \
--policy-store-id PSEXAMPLEabcdefg111111 \
--policy-id SPEXAMPLEabcdefg111111aws verifiedpermissions get-schema \
--policy-store-id PSEXAMPLEabcdefg111111aws verifiedpermissions list-identity-sources \
--policy-store-id PSEXAMPLEabcdefg111111aws verifiedpermissions get-identity-source \
--policy-store-id PSEXAMPLEabcdefg111111 \
--identity-source-id ISEXAMPLEabcdefg111111aws verifiedpermissions list-policy-templates \
--policy-store-id PSEXAMPLEabcdefg111111aws verifiedpermissions is-authorized \
--policy-store-id PSEXAMPLEabcdefg111111 \
--principal entityType=User,entityId=alice \
--action actionType=Action,actionId=view \
--resource entityType=Photo,entityId=VacationPhoto94.jpgKey Technique: Enumerate the full policy set with list-policies and get-policy, then analyze Cedar policy logic offline to find gaps -- actions or resources with no corresponding forbid policy and overly broad permit policies.
permit(principal, action, resource);This policy allows any principal to perform any action on any resource. It is the Cedar equivalent of Effect: Allow, Action: *, Resource: * in IAM and should never be used.
permit(
principal in UserGroup::"viewers",
action in Action::"readOnly",
resource in Album::"publicPhotos"
)
when { context.mfaAuthenticated == true };Restricts access to the viewers group, read-only actions, a specific album, and requires MFA authentication in the request context.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "verifiedpermissions:*",
"Resource": "*"
}]
}Grants the ability to create, modify, and delete policies, schemas, and identity sources -- an attacker with this role can rewrite the entire authorization model.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"verifiedpermissions:IsAuthorized",
"verifiedpermissions:IsAuthorizedWithToken",
"verifiedpermissions:BatchIsAuthorized"
],
"Resource": "arn:aws:verifiedpermissions::123456789012:policy-store/PSEXAMPLEabcdefg111111"
}]
}Application role can only make authorization decisions against a specific policy store. Cannot modify policies, schemas, or identity sources.
permit(
principal == User::"jane",
action,
resource
);Uses a human-readable name. If jane leaves and a new person reuses the name, they inherit all permissions. Use UUIDs instead.
permit(
principal == User::"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
action in Action::"readOnly",
resource in Album::"publicPhotos"
);Uses a UUID for the principal identifier, preventing identifier reuse attacks. Also scopes action and resource.
Always enable STRICT validation mode in production to ensure all policies are validated against the schema before being accepted.
aws verifiedpermissions update-policy-store \
--policy-store-id PSEXAMPLEabcdefg111111 \
--validation-settings "mode=STRICT"Grant application roles only IsAuthorized, IsAuthorizedWithToken, and BatchIsAuthorized. Reserve CreatePolicy, UpdatePolicy, DeletePolicy, PutSchema for deployment pipelines and administrators.
{
"Sid": "AuthorizationOnly",
"Effect": "Allow",
"Action": [
"verifiedpermissions:IsAuthorized",
"verifiedpermissions:IsAuthorizedWithToken",
"verifiedpermissions:BatchIsAuthorized"
],
"Resource": "arn:aws:verifiedpermissions::*:policy-store/*"
}IsAuthorized and IsAuthorizedWithToken are data events not logged by default. Enable data event logging to audit all authorization decisions.
Use universally unique identifiers (UUIDs) for all principal and resource identifiers in Cedar policies. Never use human-readable names that can be reassigned.
When configuring a Cognito identity source, specify the exact app client IDs that are permitted. Do not leave client ID restrictions empty, as this accepts tokens from any client in the user pool.
Do not rely solely on the absence of permit policies. Explicitly create forbid policies for sensitive actions to ensure denial even if a broad permit policy is accidentally introduced.
forbid(
principal,
action in Action::"deleteAccount",
resource
)
unless { principal in UserGroup::"superAdmins" };Store Cedar policies in version control. Use CI/CD pipelines to deploy policy changes. Require code review for all policy modifications. This prevents ad-hoc policy changes that could introduce authorization gaps.
Amazon Verified Permissions Security Card • Toc Consulting
Always obtain proper authorization before testing