

# API-linked policy stores
<a name="policy-stores-api-userpool"></a>

A common use case is to use Amazon Verified Permissions to authorize user access to APIs hosted on Amazon API Gateway. Using a wizard in the AWS console, you can create role-based access policies for users managed in [Amazon Cognito](https://aws.amazon.com/cognito), or any OIDC identity provider (IdP), and deploy an AWS Lambda Authorizer that calls Verified Permissions to evaluate these policies.

To complete the wizard, choose **Set up with API Gateway and an identity provider** when you [create a new policy store](policy-stores-create.md) and follow the steps.

An API-linked policy store is created and it provisions your authorization model and resources for authorization requests. The policy store has an identity source and a Lambda authorizer that connects API Gateway to Verified Permissions. Once the policy store is created, you can authorize API requests based on users’ group memberships. For example, Verified Permissions can grant access only to users who are members of the `Directors` group.

As your application grows, you can implement fine-grained authorization with user attributes and OAuth 2.0 scopes using the [Cedar policy language](https://docs.cedarpolicy.com/). For example, Verified Permissions can grant access only to users who have an `email` attribute in the domain `mycompany.co.uk`. 

After you have set up the authorization model for your API, your remaining responsibility is to authenticate users and generate API requests in your application, and to maintain your policy store.

To see an demo, see [Amazon Verified Permissions - Quick Start Overview and Demo](https://www.youtube.com/watch?v=OBrSrzfuWhQ) on the *Amazon Web Services YouTube channel*.

**Topics**
+ [How Verified Permissions authorizes API requests](#policy-stores-api-userpool-how-it-works)
+ [Considerations for API-linked policy stores](#policy-stores-api-userpool-considerations)
+ [Adding attribute-based access control (ABAC)](#policy-stores-api-userpool-abac)
+ [Moving to production with AWS CloudFormation](policy-stores-api-userpool-considerations-production.md)
+ [Troubleshooting API-linked policy stores](policy-stores-api-userpool-considerations-troubleshooting.md)

**Important**  
Policy stores that you create with the **Set up with API Gateway and an identity source** option in the Verified Permissions console aren’t intended for immediate deployment to production. With your initial policy store, finalize your authorization model and export the policy store resources to CloudFormation. Deploy Verified Permissions to production programmatically with the [AWS Cloud Development Kit (AWS CDK)](https://aws.amazon.com/cdk). For more information, see [Moving to production with AWS CloudFormation](policy-stores-api-userpool-considerations-production.md).

In a policy store that's linked to an API and an identity source, your application presents a user pool token in an authorization header when it makes a request to the API. The identity source of your policy store provides token validation for Verified Permissions. The token forms the `principal` in authorization requests with the [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html) API. Verified Permissions builds policies around the group membership of your users, as presented in a groups claim in identity (ID) and access tokens, for example `cognito:groups` for user pools. Your API processes the token from your application in a Lambda authorizer and submits it to Verified Permissions for an authorization decision. When your API receives the authorization decision from the Lambda authorizer, it passes the request on to your data source or denies the request.

**Components of identity source and API Gateway authorization with Verified Permissions**
+ An [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html) user pool or OIDC IdP that authenticates and groups users. Users' tokens populate the group membership and the principal or context that Verified Permissions evaluates in your policy store.
+ An [API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html) REST API. Verified Permissions defines actions from API paths and API methods, for example `MyAPI::Action::get /photo`.
+ A Lambda function and a [Lambda authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) for your API. The Lambda function takes in bearer tokens from your user pool, requests authorization from Verified Permissions, and returns a decision to API Gateway. The **Set up with API Gateway and an identity source** workflow automatically creates this Lambda authorizer for you.
+ A Verified Permissions policy store. The policy store identity source is your Amazon Cognito user pool or OIDC provider group. The policy store schema reflects the configuration of your API, and the policies link user groups to permitted API actions.
+ An application that authenticates users with your IdP and appends tokens to API requests.

## How Verified Permissions authorizes API requests
<a name="policy-stores-api-userpool-how-it-works"></a>

When you create a new policy store and select the **Set up with API Gateway and an identity source** option, Verified Permissions creates policy store schema and policies. The schema and policies reflect API actions and the user groups that you want to authorize to take the actions. Verified Permissions also creates the Lambda function and [authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html).

![\[A diagram that displays the flow of an authorization request with Amazon API Gateway, Amazon Cognito, and Amazon Verified Permissions.\]](http://docs.aws.amazon.com/verifiedpermissions/latest/userguide/images/api-authorization.png)


1. Your user signs in with your application through Amazon Cognito or another OIDC IdP. The IdP issues ID and access tokens with the user's information.

1. Your application stores the JWTs. For more information, see [Using tokens with user pools](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) in the *Amazon Cognito Developer Guide*..

1. Your user requests data that your application must retrieve from an external API.

1. Your application requests data from a REST API in API Gateway. It appends an ID or access token as a request header.

1. If your API has a cache for the authorization decision, it returns the previous response. If caching is disabled or the API has no current cache, API Gateway passes the request parameters to a [token-based Lambda authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html).

1. The Lambda function sends an authorization request to a Verified Permissions policy store with the [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html) API. The Lambda function passes the elements of an authorization decision:

   1. The user's token as the principal.

   1. The API method combined with the API path, for example `GetPhoto`, as the action.

   1. The term `Application` as the resource.

1. Verified Permissions validates the token. For more information about how Amazon Cognito tokens are validated, see [Authorization with Amazon Verified Permissions](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html) in the *Amazon Cognito Developer Guide*.

1. Verified Permissions evaluates the authorization request against the policies in your policy store and returns an authorization decision.

1. The Lambda authorizer returns an `Allow` or `Deny` response to API Gateway.

1. The API returns data or an `ACCESS_DENIED` response to your application. Your application processes and displays the results of the API request.

## Considerations for API-linked policy stores
<a name="policy-stores-api-userpool-considerations"></a>

When you build an API-linked policy store in the Verified Permissions console, you're creating a test for an eventual production deployment. Before you move to production, establish a fixed configuration for your API and user pool. Consider the following factors:

**API Gateway caches responses**  
In API-linked policy stores, Verified Permissions creates a Lambda authorizer with an **Authorization caching** TTL of 120 seconds. You can adjust this value or turn off caching in your authorizer. In an authorizer with caching enabled, your authorizer returns the same response each time until the TTL expires. This can extend the effective lifetime of user pool tokens by a duration that equals the caching TTL of the requested stage.

**Amazon Cognito groups can be reused**  
Amazon Verified Permissions determines group membership for user pool users from the `cognito:groups` claim in a user's ID or access token. The value of this claim is an array of the friendly names of the user pool groups that the user belongs to. You can't associate user pool groups with a unique identifier.  
User pool groups that you delete and recreate with the same name present to your policy store as the same group. When you delete a group from a user pool, delete all references to the group from your policy store.

**API-derived namespace and schema are point-in-time**  
Verified Permissions captures your API at a *point in time*: it only queries your API when you create your policy store. When the schema or name of your API changes, you must update your policy store and Lambda authorizer, or create a new API-linked policy store. Verified Permissions derives the policy store [namespace](https://docs.cedarpolicy.com/schema/schema.html#schema-namespace) from the name of your API.

**Lambda function has no VPC configuration**  
The Lambda function that Verified Permissions creates for your API authorizer is launched in the default VPC. By default. APIs that have network access restricted to private VPCs can't communicate with the Lambda function that authorizes access requests with Verified Permissions.

**Verified Permissions deploys authorizer resources in CloudFormation**  
To create an API-linked policy store, you must sign in a highly-privileged AWS principal to the Verified Permissions console. This user deploys an CloudFormation stack that creates resources across several AWS services. This principal must have the permission to add and modify resources in Verified Permissions, IAM, Lambda, and API Gateway. As a best practice, don't share these credentials with other administrators in your organization.  
See [Moving to production with AWS CloudFormation](policy-stores-api-userpool-considerations-production.md) for an overview of the resources that Verified Permissions creates.

## Adding attribute-based access control (ABAC)
<a name="policy-stores-api-userpool-abac"></a>

A typical authentication session with an IdP returns ID and access tokens. You can pass either of these token types as a bearer token in application requests to your API. Depending on your choices when you create your policy store, Verified Permissions expects one of the two types of tokens. Both types carry information about the user’s group membership. For more information about token types in Amazon Cognito, see [Using tokens with user pools](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html) in the *Amazon Cognito Developer Guide*.

After you create a policy store, you can add and extend policies. For example, you can add new groups to your policies as you add them to your user pool. Because your policy store is already aware of the way that your user pool presents groups in tokens, you can permit a set of actions for any new group with a new policy.

You might also want to extend the group-based model of policy evaluation into a more precise model based on user properties. User pool tokens contain additional user information that can contribute to authorization decisions.

**ID tokens**  
ID tokens represent a user’s attributes and have a high level of fine-grained access control. To evaluate email addresses, phone numbers, or custom attributes like department and manager, evaluate the ID token.

**Access tokens**  
Access tokens represent a user’s permissions with OAuth 2.0 scopes. To add a layer of authorization or to set up requests for additional resources, evaluate the access token. For example, you can validate that a user is in the appropriate groups *and* carries a scope like `PetStore.read` that generally authorizes access to the API. User pools can add custom scopes to tokens with [resource servers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-define-resource-servers.html) and with [token customization at runtime](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html#user-pool-lambda-pre-token-generation-accesstoken).

See [Mapping Amazon Cognito tokens to schema](cognito-map-token-to-schema.md) and [Mapping OIDC tokens to schema](oidc-map-token-to-schema.md) for example policies that process claims in ID and access tokens.

# Moving to production with AWS CloudFormation
<a name="policy-stores-api-userpool-considerations-production"></a>

API-linked policy stores are a way to quickly build an authorization model for an API Gateway API. They are designed to serve as a testing environment for the authorization component of your application. After you create your test policy store, spend time refining the policies, schema, and Lambda authorizer.

You might adjust the architecture of your API, requiring equivalent adjustments to your policy store schema and policies. API-linked policy stores don't automatically update their schema from API architecture–Verified Permissions only polls the API at the time you create a policy store. If your API changes sufficiently, you might have to repeat the process with a new policy store.

When your application and authorization model are ready for deployment to production, integrate the API-linked policy store that you developed with your automation processes. As a best practice, we recommend that you export the policy store schema and policies into a AWS CloudFormation template that you can deploy to other AWS accounts and AWS Regions.

The results of the API-linked policy store process are an initial policy store and a Lambda authorizer. The Lambda authorizer has several dependent resources. Verified Permissions deploys these resources in an automatically-generated CloudFormation stack. To deploy to production, you must collect the policy store and the Lambda authorizer resources into a template. An API-linked policy store is made of the following resources:<a name="policy-stores-api-userpool-considerations-production-resources"></a>

1. [AWS::VerifiedPermissions::PolicyStore](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-verifiedpermissions-policystore.html): Copy your schema to the `SchemaDefinition` object. Escape `"` characters as `\"`.

1. [AWS::VerifiedPermissions::IdentitySource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-verifiedpermissions-identitysource.html): Copy values from the output of [GetIdentitySource ](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_GetIdentitySource.html)from your test policy store and modify as needed.

1. One or more of [AWS::VerifiedPermissions::Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-verifiedpermissions-policy.html): Copy your policy statement to the `Definition` object. Escape `"` characters as `\"`.

1. [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html), [AWS::IAM::Role](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html), [AWS::IAM::Policy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html), [AWS::ApiGateway::Authorizer](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-authorizer.html), [AWS::Lambda::Permission](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html)

The following template is an example policy store. You can append the Lambda authorizer resources from your existing stack to this template.

```
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "MyExamplePolicyStore": {
            "Type": "AWS::VerifiedPermissions::PolicyStore",
            "Properties": {
                "ValidationSettings": {
                    "Mode": "STRICT"
                },
                "Description": "ApiGateway: PetStore/test",
                "Schema": {
                    "CedarJson": "{\"PetStore\":{\"actions\":{\"get /pets\":{\"appliesTo\":{\"principalTypes\":[\"User\"],\"resourceTypes\":[\"Application\"],\"context\":{\"type\":\"Record\",\"attributes\":{}}}},\"get /\":{\"appliesTo\":{\"principalTypes\":[\"User\"],\"resourceTypes\":[\"Application\"],\"context\":{\"type\":\"Record\",\"attributes\":{}}}},\"get /pets/{petId}\":{\"appliesTo\":{\"context\":{\"type\":\"Record\",\"attributes\":{}},\"resourceTypes\":[\"Application\"],\"principalTypes\":[\"User\"]}},\"post /pets\":{\"appliesTo\":{\"principalTypes\":[\"User\"],\"resourceTypes\":[\"Application\"],\"context\":{\"type\":\"Record\",\"attributes\":{}}}}},\"entityTypes\":{\"Application\":{\"shape\":{\"type\":\"Record\",\"attributes\":{}}},\"User\":{\"memberOfTypes\":[\"UserGroup\"],\"shape\":{\"attributes\":{},\"type\":\"Record\"}},\"UserGroup\":{\"shape\":{\"type\":\"Record\",\"attributes\":{}}}}}}"
                }
            }
        },
        "MyExamplePolicy": {
            "Type": "AWS::VerifiedPermissions::Policy",
            "Properties": {
                "Definition": {
                    "Static": {
                        "Description": "Policy defining permissions for testgroup cognito group",
                        "Statement": "permit(\nprincipal in PetStore::UserGroup::\"us-east-1_EXAMPLE|testgroup\",\naction in [\n  PetStore::Action::\"get /\",\n  PetStore::Action::\"post /pets\",\n  PetStore::Action::\"get /pets\",\n  PetStore::Action::\"get /pets/{petId}\"\n],\nresource);"
                    }
                },
                "PolicyStoreId": {
                    "Ref": "MyExamplePolicyStore"
                }
            },
            "DependsOn": [
                "MyExamplePolicyStore"
            ]
        },
        "MyExampleIdentitySource": {
            "Type": "AWS::VerifiedPermissions::IdentitySource",
            "Properties": {
                "Configuration": {
                    "CognitoUserPoolConfiguration": {
                        "ClientIds": [
                            "1example23456789"
                        ],
                        "GroupConfiguration": {
                            "GroupEntityType": "PetStore::UserGroup"
                        },
                        "UserPoolArn": "arn:aws:cognito-idp:us-east-1:123456789012:userpool/us-east-1_EXAMPLE"
                    }
                },
                "PolicyStoreId": {
                    "Ref": "MyExamplePolicyStore"
                },
                "PrincipalEntityType": "PetStore::User"
            },
            "DependsOn": [
                "MyExamplePolicyStore"
            ]
        }
    }
}
```

# Troubleshooting API-linked policy stores
<a name="policy-stores-api-userpool-considerations-troubleshooting"></a>

Use the information here to help you diagnose and fix common issues when you build Amazon Verified Permissions API-linked policy stores.

**Topics**
+ [I updated my policy but the authorization decision didn't change](#policy-stores-api-userpool-considerations-troubleshooting-update-didnt-change)
+ [I attached the Lambda authorizer to my API but it's not generating authorization requests](#policy-stores-api-userpool-considerations-troubleshooting-attached-not-deployed)
+ [I received an unexpected authorization decision and want to review the authorization logic](#policy-stores-api-userpool-considerations-troubleshooting-review-code)
+ [I want to find logs from my Lambda authorizer](#policy-stores-api-userpool-considerations-troubleshooting-find-logs)
+ [My Lambda authorizer doesn't exist](#policy-stores-api-userpool-considerations-troubleshooting-didnt-deploy)
+ [My API is in a private VPC and can't invoke the authorizer](#policy-stores-api-userpool-considerations-troubleshooting-in-a-vpc)
+ [I want to process additional user attributes in my authorization model](#policy-stores-api-userpool-considerations-troubleshooting-fgac)
+ [I want to add new actions, action context attributes, or resource attributes](#policy-stores-api-userpool-considerations-troubleshooting-action-resource-attributes)

## I updated my policy but the authorization decision didn't change
<a name="policy-stores-api-userpool-considerations-troubleshooting-update-didnt-change"></a>

By default, Verified Permissions configures the Lambda authorizer to cache authorization decisions for 120 seconds. Try again after two minutes, or disable cache on your authorizer. For more information, see [Enabling API caching to enhance responsiveness](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html) in the *Amazon API Gateway Developer Guide*.

## I attached the Lambda authorizer to my API but it's not generating authorization requests
<a name="policy-stores-api-userpool-considerations-troubleshooting-attached-not-deployed"></a>

To begin processing requests, you must deploy the API stage that you attached your authorizer to. For more information, see [Deploying a REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html) in the *Amazon API Gateway Developer Guide*.

## I received an unexpected authorization decision and want to review the authorization logic
<a name="policy-stores-api-userpool-considerations-troubleshooting-review-code"></a>

The API-linked policy store process creates a Lambda function for your authorizer. Verified Permissions automatically builds the logic of your authorization decisions into the authorizer function. You can go back after you create your policy store to review and update the logic in the function.

To locate your Lambda function from the AWS CloudFormation console, choose the **Check deployment** button on the **Overview** page of your new policy store.

You can also locate your function in the AWS Lambda console. Navigate to the console in the AWS Region of your policy store and search for a function name with a prefix of `AVPAuthorizerLambda`. If you have create more than one API-linked policy store, use the **Last modified** time of your functions to correlate them with policy store creation.

## I want to find logs from my Lambda authorizer
<a name="policy-stores-api-userpool-considerations-troubleshooting-find-logs"></a>

Lambda functions collect metrics and log their invocation results in Amazon CloudWatch. To review your logs, [locate your function](#policy-stores-api-userpool-considerations-troubleshooting-review-code) in the Lambda console and choose the **Monitor** tab. Select **View CloudWatch logs** and review the entries in the log group.

For more information about Lambda function logs, see [Using Amazon CloudWatch Logs with AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html) in the *AWS Lambda Developer Guide*.

## My Lambda authorizer doesn't exist
<a name="policy-stores-api-userpool-considerations-troubleshooting-didnt-deploy"></a>

After you complete setup of an API-linked policy store, you must attach the Lambda authorizer to your API. If you can't locate your authorizer in the API Gateway console, the additional resources for your policy store might have failed or not deployed yet. API-linked policy stores deploy these resources in an CloudFormation stack.

Verified Permissions displays a link with the label **Check deployment** at the end of the creation process. If you already navigated away from this screen, go to the CloudFormation console and search recent stacks for a name that's prefixed with `AVPAuthorizer-<policy store ID>`. CloudFormation provides valuable troubleshooting information in the output of a stack deployment.

For help troubleshooting CloudFormation stacks, see [Troubleshooting CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/troubleshooting.html) in the *AWS CloudFormation User Guide*.

## My API is in a private VPC and can't invoke the authorizer
<a name="policy-stores-api-userpool-considerations-troubleshooting-in-a-vpc"></a>

Verified Permissions doesn't support access to Lambda authorizers through VPC endpoints. You must open a network path between your API and the Lambda function that serves as your authorizer.

## I want to process additional user attributes in my authorization model
<a name="policy-stores-api-userpool-considerations-troubleshooting-fgac"></a>

The API-linked policy store process derives Verified Permissions policies from the groups claim in users' tokens. To update your authorization model to consider additional user attributes, integrate those attributes in your policies.

You can map many claims in ID and access tokens from Amazon Cognito user pools to Verified Permissions policy statements. For example, most users have an `email` claim in their ID token. For more information about adding claims from your identity source to policies, see [Mapping Amazon Cognito tokens to schema](cognito-map-token-to-schema.md) and [Mapping OIDC tokens to schema](oidc-map-token-to-schema.md).

## I want to add new actions, action context attributes, or resource attributes
<a name="policy-stores-api-userpool-considerations-troubleshooting-action-resource-attributes"></a>

An API-linked policy store and the Lambda authorizer that it creates are a point-in-time resource. They reflect the state of your API at the time of creation. The policy store schema doesn't assign any context attributes to actions, nor any attributes or parents to the default `Application` resource.

When you add actions—paths and methods—to your API, you must update your policy store to be aware of the new actions. You must also update your Lambda authorizer to process authorization requests for the new actions. You can [start again with a new policy store](policy-stores-create.md) or you can update your existing policy store.

To update your existing policy store, [locate your function](#policy-stores-api-userpool-considerations-troubleshooting-review-code). Examine the logic in the automatically-generated function and update it to process the new actions, attributes, or context. Then [edit your schema](schema-edit.md) to include the new actions and attributes.