

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用身份源和令牌保护您的应用程序
<a name="identity-sources"></a>

在 Amazon Verified Perm *issions 中创建代表外部身份提供商 (IdP) 的身份源*，从而快速保护您的应用程序。身份源提供的信息来自使用与您的策略存储有信任关系的 IdP 进行身份验证的用户。当您的应用程序使用来自身份源的令牌发出授权请求时，您的策略存储可以根据用户属性和访问权限做出授权决策。您可以添加 Amazon Cognito 用户池或自定义 OpenID Connect (OIDC) IdP 作为身份来源。

你可以使用具有已验证权限的 [OpenID Connect (OIDC)](https://openid.net/specs/openid-connect-core-1_0.html) 身份提供商 (IdPs)。您的应用程序可以使用符合 OIDC 的身份提供商生成的 JSON Web 令牌 (JWTs) 生成授权请求。令牌中的用户身份映射到委托人 ID。使用 ID 令牌，“已验证权限” 会将属性声明映射到委托人属性。使用访问令牌，这些声明会映射到[上下文](context.md)。使用这两种令牌类型，您可以`groups`将类似的声明映射到委托人组，并构建评估基于角色的访问控制 (RBAC) 的策略。

**注意**  
已验证权限根据来自 IdP 令牌的信息做出授权决定，但不会以任何方式直接与 IdP 交互。

*有关 APIs使用 Amazon Cognito 用户池或 OIDC 身份提供商为 Amazon API Gateway REST 构建授权逻辑的 step-by-step演练，请参阅安全博客上的 “[使用 API Gateway APIs 亚马逊验证权限授权” Amazon Cognito 或自带身份提供商](https://aws.amazon.com/blogs/security/authorize-api-gateway-apis-using-amazon-verified-permissions-and-amazon-cognito/)进行授权。AWS *

**Topics**
+ [选择合适的身份提供商](#choosing-identity-source)
+ [使用 Amazon Cognito 身份来源](identity-sources-cognito.md)
+ [使用 OIDC 身份来源](identity-sources-oidc.md)

## 选择合适的身份提供商
<a name="choosing-identity-source"></a>

虽然经过验证的权限适用于各种各样的 IdPs，但在决定在应用程序中使用哪个权限时，请考虑以下几点：

 Amazon Cognito 在以下情况下使用：  
+ 你在没有现有身份基础架构的情况下构建新的应用程序
+ 你想要具有内置安全功能的 AWS托管用户池
+ 您需要整合社交身份提供商
+ 你想要简化的代币管理

在以下情况下使用 OIDC 提供商：  
+ 你有现有的身份基础架构（Auth0、Okta、Azure AD）
+ 您需要保持集中的用户管理
+ 您有具体的合规要求 IdPs

# 使用 Amazon Cognito 身份来源
<a name="identity-sources-cognito"></a>

经过验证的权限与 Amazon Cognito 用户池密切配合。 Amazon Cognito JWTs 具有可预测的结构。经过验证的权限可以识别这种结构，并从其中包含的信息中获得最大收益。例如，您可以使用 ID 令牌或访问令牌实现基于角色的访问控制 (RBAC) 授权模型。

新的 Amazon Cognito 用户池身份源需要以下信息：
+ 的 AWS 区域。
+ 用户池 ID。
+ 例如，您要与身份源关联的委托人实体类型`MyCorp::User`。
+ 例如，您要与身份源关联的委托人组实体类型`MyCorp::UserGroup`。
+ 您想要授权的用户池 IDs 中的客户端，以便向您的策略存储库发出请求。

由于已验证权限仅适用于相同的 Amazon Cognito 用户池 AWS 账户，因此您无法在其他账户中指定身份来源。例如，Verified Permissions 会将*实体前缀*（您在作用于用户池主体的策略中必须引用的身份源标识符）设置为用户池的 ID。`us-west-2_EXAMPLE`在这种情况下，您可以将该用户池中的用户引用`a1b2c3d4-5678-90ab-cdef-EXAMPLE22222`为 `us-west-2_EXAMPLE|a1b2c3d4-5678-90ab-cdef-EXAMPLE22222`

用户池令牌*声明*可以包含属性、范围、群组 IDs、客户和自定义数据。 [Amazon Cognito JWTs](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)能够在 “已验证权限” 中包含可能有助于做出授权决策的各种信息。这些方法包括：

1. 带有`cognito:`前缀的用户名和群组声明

1. [使用自定义用户属性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes) `custom: prefix`

1. 在运行时添加了自定义声明

1. OIDC 的标准声明，比如和 `sub` `email`

我们将在中的已验证权限政策中详细介绍这些声明以及如何管理这些声明[将 Amazon Cognito 令牌映射到架构](cognito-map-token-to-schema.md)。

**重要**  
尽管您可以在 Amazon Cognito 令牌到期之前将其撤销，但 JWTs 它们被视为具有签名和有效性的独立无状态资源。符合 [JSON Web Token RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) 的服务需要远程验证令牌，无需向发布者进行验证。这意味着，Verified Permissions 可以根据已撤销或向后来被删除的用户颁发的令牌来授予访问权限。为了降低这种风险，我们建议您创建有效期尽可能较短的令牌，并在想要删除授权以终止用户会话时撤消刷新令牌。有关更多信息，请参阅[通过撤消令牌结束用户会话](https://docs.aws.amazon.com/cognito/latest/developerguide/token-revocation.html)

以下示例说明如何创建引用与委托人关联的某些 Amazon Cognito 用户池索赔的策略。

```
permit(
     principal, 
     action, 
     resource == ExampleCo::Photo::"VacationPhoto94.jpg" 
)
when { 
     principal["cognito:username"]) == "alice" &&
     principal["custom:department"]) == "Finance"
};
```

以下示例说明如何创建引用 Cognito 用户池中用户的委托人的策略。请注意，委托人 ID 的形式为`"<userpool-id>|<sub>"`。

```
permit(
     principal == ExampleCo::User::"us-east-1_example|a1b2c3d4-5678-90ab-cdef-EXAMPLE11111", 
     action, 
     resource == ExampleCo::Photo::"VacationPhoto94.jpg" 
);
```

针对已验证权限中的用户池身份源的 Cedar 策略对包含字母数字和下划线 (`_`) 以外的字符的声明名称使用特殊语法。这包括包含`:`字符的用户池前缀声明，例如`cognito:username`和`custom:department`。要编写引用`cognito:username`或`custom:department`声明的保单条件，请分别将其`principal["cognito:username"]`写成和。`principal["custom:department"]`

**注意**  
如果令牌包含带`cognito:`或`custom:`前缀的声明和带有字面值`cognito`或的声明名称`custom`，则带有的授权请求[IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)将失败，并显示为`ValidationException`。

有关映射声明的更多信息，请参阅[将 Amazon Cognito 令牌映射到架构](cognito-map-token-to-schema.md)。有关 Amazon Cognito 用户授权的更多信息，请参阅 Amazon *Cognito 开发者指南中的使用亚马逊*[验证权限进行授](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html)权。

**Topics**
+ [创建 Amazon 认证权限 Amazon Cognito 身份源](cognito-create.md)
+ [编辑 Amazon 已验证权限的 Amazon Cognito 身份来源](cognito-edit.md)
+ [将 Amazon Cognito 令牌映射到架构](cognito-map-token-to-schema.md)
+ [客户和受众验证 Amazon Cognito](cognito-validation.md)

# 创建 Amazon 认证权限 Amazon Cognito 身份源
<a name="cognito-create"></a>

以下过程将身份源添加到现有策略存储中。

在已验证权限控制台中[创建新的策略存储](policy-stores-create.md)时，您也可以创建身份源。在此过程中，您可以自动将身份源令牌中的声明导入实体属性中。选择引**导式设置****或设置方式 API Gateway 和身份提供者**选项。这些选项还会创建初始策略。

**注意**  
在您创建策略存储之前，左侧的导航窗格中不会显示**身份来源**。您创建的身份来源与当前的策略存储相关联。

使用 AWS CLI 或[CreateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_CreateIdentitySource.html)在已验证权限 API [create-identity-source](https://docs.aws.amazon.com/cli/latest/reference/verifiedpermissions/create-identity-source.html)中创建身份源时，可以省略委托人实体类型。但是，空白实体类型会创建实体类型为的身份源`AWS::Cognito`。此实体名称与策略存储架构不兼容。要将 Amazon Cognito 身份与策略存储架构集成，必须将委托人实体类型设置为支持的策略存储实体。

------
#### [ AWS 管理控制台 ]

**要创建 Amazon Cognito 用户群体身份来源，请按以下步骤操作：**

1. 打开已[验证权限控制台](https://console.aws.amazon.com/verifiedpermissions/)。选择您的保单商店。

1. 在左侧的导航窗格中，选择**身份来源**。

1. 选择**创建身份来源**。

1. 在 **Cognito 用户池详细信息**中，选择 AWS 区域 并输入您的身份源的**用户池 ID**。

1. 在**承担者配置**中，对于 “**委托人类型**”，为来自该来源的委托人选择实体类型。连接的 Amazon Cognito 用户群体中的身份将映射到所选的主体类型。

1. 如果要映射用户池`cognito:groups`声明，请在 “**群**组配置**” 中选择 “使用 Cognito 群组**”。选择作为主体类型的父项的实体类型。

1. 在**客户端应用程序验证**中，选择是否验证客户端应用程序 IDs。
   + 要验证客户端应用程序 IDs，请选择 “**仅接受具有匹配客户端应用程序的令牌**” IDs。为每个要验证的客户端应用程序 ID 选择**添加新客户端应用程序 ID**。要删除已添加的客户端应用程序 ID，请选择该客户端应用程序 ID 旁边的**删除**。
   +  IDs如果您**不想验证客户端应用程序**，请选择不验证客户端应用程序 IDs。

1. 选择**创建身份来源**。

1. （可选）如果您的策略存储具有架构，则必须先更新架构，让 Cedar 知道您的身份源创建的主体类型，然后才能引用从 Cedar 策略中的身份或访问令牌中提取的属性。架构中的新增内容必须包含您要在 Cedar 策略中引用的属性。有关将 Amazon Cognito 令牌属性映射到 Cedar 主体属性的更多信息，请参阅[将 Amazon Cognito 令牌映射到架构](cognito-map-token-to-schema.md)。
**注意**  
当您创建**与 [API 关联的策略存储或在创建策略存储](policy-stores-api-userpool.md)时使用设置 API Gateway 和身份提供商**时，Verified Permissions 会查询您的用户池以获取用户属性，并创建一个架构，其中您的委托人类型将填充用户池属性。

1. 创建使用令牌中的信息做出授权决策的策略。有关更多信息，请参阅 [创建 Amazon Verified Permissions 静态策略](policies-create.md)。

现在，您已经创建了身份源、更新了架构并创建了策略，请使用已验证的权限`IsAuthorizedWithToken`来做出授权决定。有关更多信息，请参阅 [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)*Amazon 已验证权限 API 参考指南*。

------
#### [ AWS CLI ]

**要创建 Amazon Cognito 用户群体身份来源，请按以下步骤操作：**  
您可以使用[CreateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_CreateIdentitySource.html)操作创建身份源。以下示例创建了一个可以从 Amazon Cognito 用户池中访问经过身份验证的身份的身份源。

1. 创建一个包含以下 Amazon Cognito 用户池详细信息的`config.txt`文件，供`create-identity-source`命令中的`--configuration`参数使用。

   ```
   {
       "cognitoUserPoolConfiguration": {
           "userPoolArn": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_1a2b3c4d5",
           "clientIds":["a1b2c3d4e5f6g7h8i9j0kalbmc"],
           "groupConfiguration": {
                 "groupEntityType": "MyCorp::UserGroup"
           }
       }
   }
   ```

1. 运行以下命令创建 Amazon Cognito 身份源。

   ```
   $ aws verifiedpermissions create-identity-source \
       --configuration file://config.txt \
       --principal-entity-type "User" \
       --policy-store-id 123456789012
   {
       "createdDate": "2023-05-19T20:30:28.214829+00:00",
       "identitySourceId": "ISEXAMPLEabcdefg111111",
       "lastUpdatedDate": "2023-05-19T20:30:28.214829+00:00",
       "policyStoreId": "PSEXAMPLEabcdefg111111"
   }
   ```

1. （可选）如果您的策略存储具有架构，则必须先更新架构，让 Cedar 知道您的身份源创建的主体类型，然后才能引用从 Cedar 策略中的身份或访问令牌中提取的属性。架构中的新增内容必须包含您要在 Cedar 策略中引用的属性。有关将 Amazon Cognito 令牌属性映射到 Cedar 主体属性的更多信息，请参阅[将 Amazon Cognito 令牌映射到架构](cognito-map-token-to-schema.md)。
**注意**  
当您创建**与 [API 关联的策略存储或在创建策略存储](policy-stores-api-userpool.md)时使用设置 API Gateway 和身份提供商**时，Verified Permissions 会查询您的用户池以获取用户属性，并创建一个架构，其中您的委托人类型将填充用户池属性。

1. 创建使用令牌中的信息做出授权决策的策略。有关更多信息，请参阅 [创建 Amazon Verified Permissions 静态策略](policies-create.md)。

现在，您已经创建了身份源、更新了架构并创建了策略，请使用已验证的权限`IsAuthorizedWithToken`来做出授权决定。有关更多信息，请参阅 [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)*Amazon 已验证权限 API 参考指南*。

------

有关在 Verified Permissions 中为经过身份验证的用户使用 Amazon Cognito 访问令牌和身份令牌的更多信息，请参阅《Amazon Cognito 开发人员指南》中的[使用 Amazon Verified Permissions 进行授权](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html)。**

# 编辑 Amazon 已验证权限的 Amazon Cognito 身份来源
<a name="cognito-edit"></a>

创建身份源后，您可以编辑身份源的某些参数。您无法更改身份源的类型，必须删除身份源并创建一个新的身份源以从 OIDC 或 OIDC 切换 Amazon Cognito 到。 Amazon Cognito如果您的策略存储架构与您的身份源属性相匹配，则请注意，您必须单独更新架构以反映您对身份源所做的更改。

------
#### [ AWS 管理控制台 ]

**更新 Amazon Cognito 身份源**

1. 打开已[验证权限控制台](https://console.aws.amazon.com/verifiedpermissions/)。选择您的保单商店。

1. 在左侧的导航窗格中，选择**身份来源**。

1. 选择要编辑的身份来源的 ID。

1. 选择**编辑**。

1. 在 **Cognito 用户池详细信息**中，选择 AWS 区域 并键入您的身份源的**用户池 ID**。

1. 在**委托人详细信息**中，您可以更新身份源的**委托人类型**。连接的 Amazon Cognito 用户群体中的身份将映射到所选的主体类型。

1. 如果要映射用户池`cognito:groups`声明，请在 “**群**组配置**” 中选择 “使用 Cognito 群组**”。选择作为主体类型的父项的实体类型。

1. 在**客户端应用程序验证**中，选择是否验证客户端应用程序 IDs。
   + 要验证客户端应用程序 IDs，请选择 “**仅接受具有匹配客户端应用程序的令牌**” IDs。为每个要验证的客户端应用程序 ID 选择**添加新客户端应用程序 ID**。要删除已添加的客户端应用程序 ID，请选择该客户端应用程序 ID 旁边的**删除**。
   +  IDs如果您**不想验证客户端应用程序**，请选择不验证客户端应用程序 IDs。

1. 选择**保存更改**。

1. 如果您更改了该身份来源的主体类型，则必须更新架构，以正确反映更新后的主体类型。

如要删除身份来源，您可以选择身份来源旁边的单选按钮，然后选择**删除身份来源**。在文本框中输入 `delete`，然后选择**删除身份来源**，确认删除该身份来源。

------
#### [ AWS CLI ]

**更新 Amazon Cognito 身份源**  
您可以使用[UpdateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_UpdateIdentitySource.html)操作更新身份源。以下示例将指定的身份源更新为使用其他 Amazon Cognito 用户池。

1. 创建一个包含以下 Amazon Cognito 用户池详细信息的`config.txt`文件，供`update-identity-source`命令中的`--configuration`参数使用。

   ```
   {
       "cognitoUserPoolConfiguration": {
           "userPoolArn": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_1a2b3c4d5",
           "clientIds":["a1b2c3d4e5f6g7h8i9j0kalbmc"],
           "groupConfiguration": {
                 "groupEntityType": "MyCorp::UserGroup"
           }
       }
   }
   ```

1. 运行以下命令以更新 Amazon Cognito 身份源。

   ```
   $ aws verifiedpermissions update-identity-source \
       --update-configuration file://config.txt \
       --policy-store-id 123456789012
   {
       "createdDate": "2023-05-19T20:30:28.214829+00:00",
       "identitySourceId": "ISEXAMPLEabcdefg111111",
       "lastUpdatedDate": "2023-05-19T20:30:28.214829+00:00",
       "policyStoreId": "PSEXAMPLEabcdefg111111"
   }
   ```

**注意**  
如果要更改该身份来源的主体类型，必须更新架构，以正确反映更新后的主体类型。

------

# 将 Amazon Cognito 令牌映射到架构
<a name="cognito-map-token-to-schema"></a>

您可能会发现想要将身份源添加到策略存储中，并将地图提供商声明或令牌添加到策略存储架构中。您可以自动执行此过程，方法是使用[引导式设置](policy-stores-create.md)创建带有身份源的策略存储，或者在创建策略存储后手动更新架构。将令牌映射到架构后，您可以创建引用它们的策略。

用户指南的这一部分包含以下信息：
+ 何时可以自动填充策略存储架构的属性
+ 如何在您的已验证权限策略中使用 Amazon Cognito 令牌声明
+ 如何为身份源手动构建架构

通过[引导式设置](policy-stores-create.md)创建的 [API 关联策略存储](policy-stores-api-userpool.md)和带有身份源的策略存储不需要将身份 (ID) 令牌属性手动映射到架构。您可以为用户池中的属性提供经过验证的权限，并创建填充用户属性的架构。在 ID 令牌授权中，已验证权限将声明映射到委托人实体的属性。在以下情况下，您可能需要手动将 Amazon Cognito 令牌映射到您的架构：
+ 您根据示例创建了一个空的策略存储区或策略存储区。
+ 您希望将访问令牌的使用范围扩展到基于角色的访问控制 (RBAC) 之外。
+ 您可以使用已验证的权限 REST API、 AWS 软件开发工具包或创建策略存储 AWS CDK。

要在您的已验证权限策略存储中 Amazon Cognito 用作身份源，您的架构中必须包含提供者属性。架构是固定的，必须与提供者令牌在其中创建的实体[IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)或 [BatchIsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_BatchIsAuthorizedWithToken.html)API 请求相对应。如果您创建策略存储的方式是自动从 ID 令牌中的提供者信息填充架构，那么您就可以编写策略了。如果您创建的策略存储没有身份源架构，则必须向架构中添加与使用 API 请求创建的实体相匹配的提供者属性。然后，您可以使用提供者令牌中的属性来编写策略。

有关在已验证权限中为经过身份验证的用户使用 Amazon Cognito ID 和访问令牌的更多信息，请参阅 Amazon Co *gnito 开发者指南中的使用亚马逊*[验证权限进行授权](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-authorization-with-avp.html)。

**Topics**
+ [将 ID 令牌映射到架构](#cognito-map-id-token)
+ [映射访问令牌](#cognito-map-access-token)
+ [Amazon Cognito 冒号分隔的索赔的替代表示法](#cognito-colon-claims)
+ [关于架构映射的注意事项](#cognito-map-token-to-schema-things-to-know)

## 将 ID 令牌映射到架构
<a name="cognito-map-id-token"></a>

Verified Permissions 将身份令牌声明作为用户的属性进行处理：他们的姓名和头衔、群组成员资格、联系信息。ID 令牌在*基于属性的访问控制* (ABAC) 授权模型中最有用。如果您想让经过验证的权限根据谁提出请求来分析对资源的访问权限，请为您的身份来源选择 ID 令牌。

Amazon Cognito ID 令牌适用于大多数 [OIDC 依赖](https://openid.net/developers/certified-openid-connect-implementations/)方库。它们通过其他索赔扩展了OIDC的功能。您的应用程序可以通过 Amazon Cognito 用户池身份验证 API 操作或用户池托管用户界面对用户进行身份验证。有关更多信息，请参阅*Amazon Cognito 开发者指南*[中的使用 API 和终端节点](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pools-API-operations.html)。Amazon Cognito 身份令牌中的有用声明

*`cognito:username` 和 `preferred_username`*  
用户名的变体。

*`sub`*  
用户的唯一用户标识符 (UUID)

*带`custom:`前缀的索赔*  
自定义用户池属性的前缀，例如`custom:employmentStoreCode`。

*标准声明*  
标准 OIDC 声称类似`email`和。`phone_number`有关更多信息，请参阅 *OpenID Connect Core 1.0 中包含勘误*集 2 的[标准声明](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)。

*`cognito:groups`*  
用户的群组成员资格。在基于角色的访问控制 (RBAC) 的授权模型中，此声明提供了您可以在策略中评估的角色。

*临时索赔*  
声明不是用户的财产，但在运行时由用户池[生成令牌前 Lambda](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html) 触发器添加。临时索赔与标准索赔类似，但不在标准范围内，例如`tenant`或`department`。

在引用带有`:`分隔符的 Amazon Cognito 属性的策略中，引用格式中的属性`principal["cognito:username"]`。角色声明`cognito:groups`是此规则的例外。已验证权限将此声明的内容映射到用户实体的父实体。

有关来自 Amazon Cognito 用户池的 ID 令牌结构的更多信息，请参阅*Amazon Cognito 开发者*[指南中的使用 ID 令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html)。

以下示例 ID 令牌具有四种类型的属性。它包括 Amazon Cognito特定索赔`cognito:username`、自定义索赔`custom:employmentStoreCode`、标准索赔`email`和临时索赔`tenant`。

```
{
    "sub": "91eb4550-XXX",
    "cognito:groups": [
        "Store-Owner-Role",
        "Customer"
    ],
    "email_verified": true,
    "clearance": "confidential",
    "iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_EXAMPLE",
    "cognito:username": "alice",
    "custom:employmentStoreCode": "petstore-dallas",
    "origin_jti": "5b9f50a3-05da-454a-8b99-b79c2349de77",
    "aud": "1example23456789",
    "event_id": "0ed5ad5c-7182-4ecf-XXX",
    "token_use": "id",
    "auth_time": 1687885407,
    "department": "engineering",
    "exp": 1687889006,
    "iat": 1687885407,
    "tenant": "x11app-tenant-1",
    "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN1111111",
    "email": "alice@example.com"
}
```

使用 Amazon Cognito 用户池创建身份源时，您可以指定授权请求中验证权限生成的委托人实体的类型`IsAuthorizedWithToken`。然后，作为评估该请求的一部分，您的策略会测试该主体的属性。您的架构定义身份源的委托人类型和属性，然后您可以在 Cedar 策略中引用它们。

您还可以指定要从 ID 令牌组声明中派生的群组实体的类型。在授权请求中，Verified Permissions 会将每个群组成员的声明映射到该群组实体类型。在策略中，您可以将该组实体引用为委托人。

以下示例说明了如何在 Verified Permissions 架构中反映示例身份令牌中的属性。有关编辑架构的更多信息，请参阅[编辑策略存储架构](schema-edit.md)。如果您的身份来源配置指定了主体类型 `User`，那么，您可以添加类似于以下示例的内容，以使这些属性可用于 Cedar。

```
"User": {
   "shape": {
      "type": "Record",
      "attributes": {
         "cognito:username": {
            "type": "String",
            "required": false
         },
         "custom:employmentStoreCode": {
            "type": "String",
            "required": false
         },
         "email": {
            "type": "String"
         },
         "tenant": {
            "type": "String",
            "required": true
         }
      }
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[反映 Amazon Cognito ID 令牌属性](policies-examples.md#policies-examples-cognito-id)。

## 映射访问令牌
<a name="cognito-map-access-token"></a>

Verified Permissions 处理访问令牌声明，而不是作为操作属性或*上下文*属性的群组声明。除了群组成员资格外，来自您的 IdP 的访问令牌可能还包含有关 API 访问的信息。访问令牌在使用基于角色的访问控制 (RBAC) 的授权模型中很有用。依赖组成员资格以外的访问令牌声明的授权模型需要在架构配置方面付出额外的努力。

Amazon Cognito 访问令牌具有可用于授权的声明：Amazon Cognito 访问令牌中的有用声明

*`client_id`*  
OIDC 依赖方的客户端应用程序的 ID。使用客户端 ID，已验证权限可以验证授权请求是否来自策略存储的允许客户端。在 machine-to-machine（M2M）授权中，请求系统使用客户端密钥对请求进行授权，并提供客户端 ID 和范围作为授权证据。

*`scope`*  
代表令牌持有者的访问权限的 [OAuth 2.0 范围](https://datatracker.ietf.org/doc/html/rfc6749#section-3.3)。

*`cognito:groups`*  
用户的群组成员资格。在基于角色的访问控制 (RBAC) 的授权模型中，此声明提供了您可以在策略中评估的角色。

*临时索赔*  
不是访问权限但是在运行时由用户池[生成令牌前 Lambda](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html) 触发器添加的声明。临时索赔与标准索赔类似，但不在标准范围内，例如`tenant`或`department`。自定义访问令牌会增加您的 AWS 账单成本。

有关来自 Amazon Cognito 用户池的访问令牌结构的更多信息，请参阅*Amazon Cognito 开发者*[指南中的使用访问令牌](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html)。

当 Amazon Cognito 访问令牌传递给 “已验证权限” 时，访问令牌会映射到上下文对象。可以使用 `context.token.attribute_name` 来引用访问令牌的属性。以下示例访问令牌同时包含 `client_id` 和 `scope` 声明。

```
{
    "sub": "91eb4550-9091-708c-a7a6-9758ef8b6b1e",
    "cognito:groups": [
        "Store-Owner-Role",
        "Customer"
    ],
    "iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_EXAMPLE",
    "client_id": "1example23456789",
    "origin_jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN1111111",
    "event_id": "bda909cb-3e29-4bb8-83e3-ce6808f49011",
    "token_use": "access",
    "scope": "MyAPI/mydata.write",
    "auth_time": 1688092966,
    "exp": 1688096566,
    "iat": 1688092966,
    "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN2222222",
    "username": "alice"
}
```

以下示例说明了如何在 Verified Permissions 架构中反映示例访问令牌中的属性。有关编辑架构的更多信息，请参阅[编辑策略存储架构](schema-edit.md)。

```
{
   "MyApplication": {
      "actions": {
         "Read": {
            "appliesTo": {
               "context": {
                  "type": "ReusedContext"
               },
               "resourceTypes": [
                  "Application"
               ],
               "principalTypes": [
                  "User"
               ]
            }
         }
      },
      ...
      ...
      "commonTypes": {
         "ReusedContext": {
            "attributes": {
               "token": {
                  "type": "Record",
                  "attributes": {
                     "scope": {
                        "type": "Set",
                        "element": {
                           "type": "String"
                        }
                     },
                     "client_id": {
                        "type": "String"
                     }
                  }
               }
            },
            "type": "Record"
         }
      }
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[反映 Amazon Cognito 访问令牌属性](policies-examples.md#policies-examples-cognito-access)。

## Amazon Cognito 冒号分隔的索赔的替代表示法
<a name="cognito-colon-claims"></a>

在 Verified Permissi `cognito:groups` ons 启动时， Amazon Cognito 令牌声明的推荐架构会`custom:store`将这些冒号分隔的字符串转换为使用该`.`字符作为层次结构分隔符。这种格式称为*点符号*。例如，在您的政策`principal.cognito.groups`中提及`cognito:groups`变为了。尽管您可以继续使用这种格式，但我们建议您使用[括号表示法](#cognito-map-token-to-schema-things-to-know)来构建架构和策略。在这种格式中，对的引用将`cognito:groups`变`principal["cognito:groups"]`为您的政策。从已验证权限控制台自动生成的用户池 ID 令牌架构使用方括号表示法。

您可以继续在手动构建的架构和 Amazon Cognito 身份源的策略中使用点符号。对于任何其他类型的 OIDC IdP，您不能在架构`:`或策略中使用带点符号或任何其他非字母数字字符。

点符号架构将`:`字符的每个实例嵌套为`cognito`或`custom`初始短语的子项，如以下示例所示：

```
"CognitoUser": {
   "shape": {
      "type": "Record",
      "attributes": {
         "cognito": {
            "type": "Record",
            "required": true,
            "attributes": {
               "username": {
                  "type": "String",
                  "required": true
               }
            }
         },
         "custom": {
            "type": "Record",
            "required": true,
            "attributes": {
               "employmentStoreCode": {
                  "type": "String",
                  "required": true
               }
            }
         },
         "email": {
            "type": "String"
         },
         "tenant": {
            "type": "String",
            "required": true
         }
      }
   }
}
```

有关将针对此架构进行验证并使用点符号的策略示例，请参阅[使用点符号来引用属性](policies-examples.md#policies-examples-dot)。

## 关于架构映射的注意事项
<a name="cognito-map-token-to-schema-things-to-know"></a>

**不同标记类型的属性映射不同**  
在访问令牌授权中，已验证权限将声明映射到[上下文](context.md)。在 ID 令牌授权中，已验证权限将声明映射到委托人属性。对于您在已验证权限控制台中创建的策略存储，只有**空**策略存储和**示例**策略存储才会使您没有身份来源，并要求您在架构中填充用户池属性以进行 ID 令牌授权。访问令牌授权基于基于角色的访问控制 (RBAC) 和群组成员资格声明，不会自动将其他声明映射到策略存储架构。

**身份源属性不是必需的**  
在已验证权限控制台中创建身份源时，不会将任何属性标记为必填属性。这样可以防止丢失的索赔导致授权请求中的验证错误。您可以根据需要将属性设置为 required，但它们必须存在于所有授权请求中。

**RBAC 不需要架构中的属性**  
身份源的架构取决于您在添加身份源时所建立的实体关联。身份源将一个声明映射到用户实体类型，将一个声明映射到群组实体类型。这些实体映射是身份源配置的核心。有了这些最少的信息，您就可以在基于角色的访问控制 (RBAC) 模型中编写对特定用户和用户可能属于的特定组执行授权操作的策略。向架构中添加令牌声明可扩展策略存储的授权范围。来自 ID 令牌的用户属性包含有关用户的信息，这些信息可以为基于属性的访问控制 (ABAC) 授权做出贡献。访问令牌的上下文属性包含诸如 OAuth 2.0 作用域之类的信息，这些信息可以提供来自提供者的额外访问控制信息，但需要进行额外的架构修改。

已验证权限控制台中的 “**使用 API Gateway 和身份提供者****进行设置” 和 “引导式设置**” 选项为架构分配 ID 令牌声明。访问令牌声明的情况并非如此。[要向架构中添加非组访问令牌声明，必须在 JSON 模式下编辑架构并添加 CommonTypes 属性。](https://docs.cedarpolicy.com/schema/json-schema.html#schema-commonTypes)有关更多信息，请参阅 [映射访问令牌](#cognito-map-access-token)。

**选择代币类型**  
您的策略存储与身份源配合的方式取决于身份源配置中的一个关键决定：是处理 ID 还是访问令牌。使用 Amazon Cognito 身份提供商，您可以在创建与 API 关联的策略存储时选择令牌类型。创建与 [API 关联的策略存储](policy-stores-api-userpool.md)时，必须选择是要为 ID 还是访问令牌设置授权。此信息会影响已验证权限应用于您的策略存储的架构属性，以及适用于您的 API 的 Lambda 授权者的语法。 API Gateway 特别是如果您希望从身份令牌声明自动映射到已验证权限控制台中的属性中受益，请在创建身份源之前尽早决定要处理的令牌类型。更改令牌类型需要花费大量精力来重构您的策略和架构。以下主题介绍如何在策略存储中使用 ID 和访问令牌。

**Cedar 解析器要求某些字符使用方括号**  
策略通常以类似的格式引用架构属性`principal.username`。对于令牌声明名称中可能出现的大多数非字母数字字符`:`，例如`.`、或`/`，Verified Permissions 无法解析像或这样的条件值。`principal.cognito:username` `context.ip-address`您必须改为使用`principal["cognito:username"]`或`context["ip-address"]`格式的方括号表示法来格式化这些条件。下划线字符`_`是声明名称中的有效字符，也是该要求的唯一非字母数字例外。

此类型主属性的部分示例架构如下所示：

```
"User": {
   "shape": {
      "type": "Record",
      "attributes": {
         "cognito:username": {
            "type": "String",
            "required": true
         },
         "custom:employmentStoreCode": {
            "type": "String",
            "required": true,
         },
         "email": {
            "type": "String",
            "required": false
         }
      }
   }
}
```

这种类型的上下文属性的部分示例架构如下所示：

```
"GetOrder": {
   "memberOf": [],
   "appliesTo": {
      "resourceTypes": [
         "Order"
      ],
      "context": {
         "type": "Record",
         "attributes": {
            "ip-address": {
               "required": false,
               "type": "String"
            }
		 }
	  },
      "principalTypes": [
         "User"
      ]
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[使用方括号表示法来引用代币属性](policies-examples.md#policies-examples-brackets)。

# 客户和受众验证 Amazon Cognito
<a name="cognito-validation"></a>

向策略存储中添加身份源时，Verified Permissions 具有用于验证 ID 和访问令牌是否按预期使用的配置选项。这种验证发生在 `BatchIsAuthorizedWithToken` API 请求`IsAuthorizedWithToken`的处理过程中。ID 和访问令牌以及 Amazon Cognito 和 OIDC 身份源的行为有所不同。通过 Amazon Cognito 用户池提供商，经过验证的权限可以验证身份和访问令牌中的客户端 ID。通过 OIDC 提供商，经过验证的权限可以验证 ID 令牌中的客户端 ID 和访问令牌中的受众。

例如，*客户端 ID* 是与您的应用程序使用的身份提供商实例关联的标识符`1example23456789`。例如，*受众*是与访问令牌的预期*依赖方*或目标相关联的 URL 路径`https://mytoken.example.com`。使用访问令牌时，`aud`声明始终与受众相关联。

Amazon Cognito ID 令牌的`aud`声明包含[应用程序客户端](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html) ID。访问令牌的`client_id`声明也包含应用程序客户端 ID。

当您在身份源中为**客户端应用程序验证**输入一个或多个值时，Verified Permissions 会将此应用程序客户端 IDs 列表与 ID 令牌`aud`声明或访问令牌`client_id`声明进行比较。已验证权限不会验证 Amazon Cognito 身份来源的依赖方受众 URL。

## 的客户端授权 JWTs
<a name="identity-sources-other-idp"></a>

您可能需要在应用程序中处理 JSON Web 令牌并将其声明传递给已验证权限，而无需使用策略存储标识源。您可以从 JSON Web 令牌 (JWT) 中提取实体属性并将其解析为已验证的权限。

此示例说明如何使用 JWT 从应用程序调用 “已验证权限”。¹

```
async function authorizeUsingJwtToken(jwtToken) {
  
    const payload = await verifier.verify(jwtToken);
   
    let principalEntity = {
        entityType: "PhotoFlash::User", // the application needs to fill in the relevant user type
        entityId: payload["sub"], // the application need to use the claim that represents the user-id
    };
    let resourceEntity = {
        entityType: "PhotoFlash::Photo", //the application needs to fill in the relevant resource type
        entityId: "jane_photo_123.jpg", // the application needs to fill in the relevant resource id
    };
    let action = {
        actionType: "PhotoFlash::Action", //the application needs to fill in the relevant action id
        actionId: "GetPhoto", //the application needs to fill in the relevant action type
    };
    let entities = {
        entityList: [],
    };
    entities.entityList.push(...getUserEntitiesFromToken(payload));
    let policyStoreId = "PSEXAMPLEabcdefg111111"; // set your own policy store id
    
    const authResult = await client
        .isAuthorized({
        policyStoreId: policyStoreId,
        principal: principalEntity,
        resource: resourceEntity,
        action: action,
        entities,
        })
        .promise();
        
    return authResult; 
  
}

function getUserEntitiesFromToken(payload) {
  let attributes = {};
  let claimsNotPassedInEntities = ['aud', 'sub', 'exp', 'jti', 'iss'];
  Object.entries(payload).forEach(([key, value]) => {
    if (claimsNotPassedInEntities.includes(key)) {
        return;
    }
    if (Array.isArray(value)) {
      var attibuteItem = [];
      value.forEach((item) => {
        attibuteItem.push({
          string: item,
        });
      });
      attributes[key] = {
        set: attibuteItem,
      };
    } else if (typeof value === 'string') {
      attributes[key] = {
        string: value,
      } 
    } else if (typeof value === 'bigint' || typeof value ==='number') {
        attributes[key] = {
            long: value,
          } 
    } else if (typeof value === 'boolean') {
        attributes[key] = {
            boolean: value,
       } 
    }

  });

  let entityItem = {
    attributes: attributes,
    identifier: {
      entityType: "PhotoFlash::User",
      entityId: payload["sub"], // the application needs to use the claim that represents the user-id
    }
  };
  return [entityItem];
}
```

¹ 此代码示例使用该[aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify)库来验证由 OID IdPs C JWTs 兼容的签名。

# 使用 OIDC 身份来源
<a name="identity-sources-oidc"></a>

您也可以将任何合规的 OpenID Connect (OIDC) IdP 配置为策略存储的身份源。OIDC 提供商与 Amazon Cognito 用户池类似：它们是作为身份验证的 JWTs 产物生成的。要添加 OIDC 提供商，您必须提供颁发机构 URL

新的 OIDC 身份源需要以下信息：
+ 发行人网址。经过验证的权限必须能够在此 URL 上发现`.well-known/openid-configuration`终端节点。
+ 不包含通配符的 CNAME 记录。例如，`a.example.com`无法映射到`*.example.net`。相反，`*.example.com`无法映射到。`a.example.net`
+ 您要在授权请求中使用的令牌类型。在本例中，您选择了**身份令牌**。
+ 例如，您要与身份源关联的用户实体类型`MyCorp::User`。
+ 例如，您要与身份源关联的群组实体类型`MyCorp::UserGroup`。
+ ID 令牌示例，或 ID 令牌中声明的定义。
+ 要应用于用户和群组实体的前缀 IDs。在 CLI 和 API 中，您可以选择此前缀。例如`MyCorp::User::"auth.example.com|a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"`，在您使用 “使用 **API Gateway 和身份提供者进行设置**” 或 “**引导式设置**” 选项创建的策略存储中，Verified Permissions 会分配颁发者名称减去`https://`的前缀。

有关使用 API 操作授权来自 OIDC 来源的请求的更多信息，请参阅。[可用于授权的 API 操作](authorization.md#authorization-operations)

以下示例说明如何创建允许会计部门员工访问年终报告的策略，该策略具有机密分类且不在卫星办公室的员工可以访问年终报告。已验证权限从委托人 ID 令牌中的声明中派生这些属性。

请注意，在委托人中引用组时，必须使用`in`运算符才能正确评估策略。

```
permit(
     principal in MyCorp::UserGroup::"MyOIDCProvider|Accounting", 
     action, 
     resource in MyCorp::Folder::"YearEnd2024" 
) when { 
     principal.jobClassification == "Confidential" &&
     !(principal.location like "SatelliteOffice*")
};
```

**Topics**
+ [创建 Amazon 已验证权限 OIDC 身份源](oidc-create.md)
+ [编辑 Amazon 已验证权限 OIDC 身份源](oidc-edit.md)
+ [将 OIDC 令牌映射到架构](oidc-map-token-to-schema.md)
+ [OIDC 提供商的客户和受众验证](oidc-validation.md)

# 创建 Amazon 已验证权限 OIDC 身份源
<a name="oidc-create"></a>

以下过程将身份源添加到现有策略存储中。

在已验证权限控制台中[创建新的策略存储](policy-stores-create.md)时，您也可以创建身份源。在此过程中，您可以自动将身份源令牌中的声明导入实体属性中。选择 “引**导式设置”** 或 “**设置方式” API Gateway 和 “身份提供商**” 选项。这些选项还会创建初始策略。

**注意**  
在您创建策略存储之前，左侧的导航窗格中不会显示**身份来源**。您创建的身份来源与当前的策略存储相关联。

使用 AWS CLI 或[CreateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_CreateIdentitySource.html)在已验证权限 API [create-identity-source](https://docs.aws.amazon.com/cli/latest/reference/verifiedpermissions/create-identity-source.html)中创建身份源时，可以省略委托人实体类型。但是，空白实体类型会创建实体类型为的身份源`AWS::Cognito`。此实体名称与策略存储架构不兼容。要将 Amazon Cognito 身份与策略存储架构集成，必须将委托人实体类型设置为支持的策略存储实体。

------
#### [ AWS 管理控制台 ]

**创建 OpenID Connect (OIDC) 身份源**

1. 打开已[验证权限控制台](https://console.aws.amazon.com/verifiedpermissions/)。选择您的保单商店。

1. 在左侧的导航窗格中，选择**身份来源**。

1. 选择**创建身份来源**。

1. 选择**外部 OIDC** 提供商。

1. 在**发卡机构 URL 中，输入您的 OIDC 发行**人的 URL。例如，这是提供授权服务器、签名密钥以及有关您的提供商的其他信息的服务端点`https://auth.example.com`。您的发卡机构 URL 必须托管 OIDC 发现文档，网址为。`/.well-known/openid-configuration`

1. 在**令牌类型**中，选择您希望您的应用程序提交以进行授权的 OIDC JWT 类型。有关更多信息，请参阅 [将 OIDC 令牌映射到架构](oidc-map-token-to-schema.md)。

1. 在将**令牌声明映射到架构实体**中，为身份源选择**用户实体****和用户声明**。**用户实体**是您的策略存储中的一个实体，您想要引用来自 OIDC 提供商的用户。**用户声明**通常`sub`是来自您的身份证或访问令牌的索赔，该令牌包含待评估实体的唯一标识符。来自连接的 OIDC IdP 的身份将映射到选定的主体类型。

1. （可选）在 “将**令牌声明映射到架构实**体” 中，为身份源选择**群**组实体**和群组声明**。**组实体**是**用户实体的[父](https://docs.cedarpolicy.com/overview/terminology.html#term-group)实体**。团体索赔将映射到该实体。**群组声明**通常是来自您的 ID 或访问令牌的声明`groups`，其中包含要评估的实体的字符串、JSON 或以空格分隔的用户组名称字符串。来自连接的 OIDC IdP 的身份将映射到选定的主体类型。

1. 在 “**验证-可选**” 中，输入您 URLs 希望您的策略商店在授权请求中接受的客户 IDs 或受众（如果有）。

1. 选择**创建身份来源**。

1. （可选）如果您的策略存储具有架构，则必须先更新架构，让 Cedar 知道您的身份源创建的主体类型，然后才能引用从 Cedar 策略中的身份或访问令牌中提取的属性。架构中的新增内容必须包含您要在 Cedar 策略中引用的属性。有关将 OIDC 代币属性映射到 Cedar 主体属性的更多信息，请参阅。[将 OIDC 令牌映射到架构](oidc-map-token-to-schema.md)

1. 创建使用令牌中的信息做出授权决策的策略。有关更多信息，请参阅 [创建 Amazon Verified Permissions 静态策略](policies-create.md)。

现在，您已经创建了身份源、更新了架构并创建了策略，请使用已验证的权限`IsAuthorizedWithToken`来做出授权决定。有关更多信息，请参阅 [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)*Amazon 已验证权限 API 参考指南*。

------
#### [ AWS CLI ]

**创建 OIDC 身份源**  
您可以使用[CreateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_CreateIdentitySource.html)操作创建身份源。以下示例创建了可以从 OIDC 身份提供商 (IdP) 访问经过身份验证的身份的身份源。

1. 创建一个包含 OIDC IdP 以下详细信息的`config.txt`文件，供命令的`--configuration`参数使用。`create-identity-source`

   ```
   {
       "openIdConnectConfiguration": {
           "issuer": "https://auth.example.com",
           "tokenSelection": {
                   "identityTokenOnly": {
                           "clientIds":["1example23456789"],
                           "principalIdClaim": "sub"
                   },
           },
           "entityIdPrefix": "MyOIDCProvider",
           "groupConfiguration": {
                 "groupClaim": "groups",
                 "groupEntityType": "MyCorp::UserGroup"
           }
       }
   }
   ```

1. 运行以下命令创建 OIDC 身份源。

   ```
   $ aws verifiedpermissions create-identity-source \
       --configuration file://config.txt \
       --principal-entity-type "User" \
       --policy-store-id 123456789012
   {
       "createdDate": "2023-05-19T20:30:28.214829+00:00",
       "identitySourceId": "ISEXAMPLEabcdefg111111",
       "lastUpdatedDate": "2023-05-19T20:30:28.214829+00:00",
       "policyStoreId": "PSEXAMPLEabcdefg111111"
   }
   ```

1. （可选）如果您的策略存储具有架构，则必须先更新架构，让 Cedar 知道您的身份源创建的主体类型，然后才能引用从 Cedar 策略中的身份或访问令牌中提取的属性。架构中的新增内容必须包含您要在 Cedar 策略中引用的属性。有关将 OIDC 代币属性映射到 Cedar 主体属性的更多信息，请参阅。[将 OIDC 令牌映射到架构](oidc-map-token-to-schema.md)

1. 创建使用令牌中的信息做出授权决策的策略。有关更多信息，请参阅 [创建 Amazon Verified Permissions 静态策略](policies-create.md)。

现在，您已经创建了身份源、更新了架构并创建了策略，请使用已验证的权限`IsAuthorizedWithToken`来做出授权决定。有关更多信息，请参阅 [IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)*Amazon 已验证权限 API 参考指南*。

------

# 编辑 Amazon 已验证权限 OIDC 身份源
<a name="oidc-edit"></a>

创建身份源后，您可以编辑身份源的某些参数。您无法更改身份源的类型，必须删除身份源并创建一个新的身份源以从 OIDC 或 OIDC 切换 Amazon Cognito 到。 Amazon Cognito如果您的策略存储架构与您的身份源属性相匹配，则请注意，您必须单独更新架构以反映您对身份源所做的更改。

------
#### [ AWS 管理控制台 ]

**更新 OIDC 身份源**

1. 打开已[验证权限控制台](https://console.aws.amazon.com/verifiedpermissions/)。选择您的保单商店。

1. 在左侧的导航窗格中，选择**身份来源**。

1. 选择要编辑的身份来源的 ID。

1. 选择**编辑**。

1. 在 **OIDC 提供商详细信息**中，根据需要更改**发行者 URL**。

1. 在将**令牌声明映射到架构属性**中，根据需要更改用户和组声明与策略存储实体类型之间的关联。更改实体类型后，必须更新策略和架构属性以应用于新的实体类型。

1. 在**受众验证**中，添加或删除要强制执行的受众群体值。

1. 选择**保存更改**。

如要删除身份来源，您可以选择身份来源旁边的单选按钮，然后选择**删除身份来源**。在文本框中输入 `delete`，然后选择**删除身份来源**，确认删除该身份来源。

------
#### [ AWS CLI ]

**更新 OIDC 身份源**  
您可以使用[UpdateIdentitySource](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_UpdateIdentitySource.html)操作更新身份源。以下示例将指定的身份源更新为使用其他 OIDC 提供商。

1. 创建一个包含 OIDC IdP 以下详细信息的`config.txt`文件，供命令的`--configuration`参数使用。`update-identity-source`

   ```
   {
       "openIdConnectConfiguration": {
           "issuer": "https://auth2.example.com",
           "tokenSelection": {
                   "identityTokenOnly": {
                           "clientIds":["2example10111213"],
                           "principalIdClaim": "sub"
                   },
           },
           "entityIdPrefix": "MyOIDCProvider",
           "groupConfiguration": {
                 "groupClaim": "groups",
                 "groupEntityType": "MyCorp::UserGroup"
           }
       }
   }
   ```

1. 运行以下命令更新 OIDC 身份源。

   ```
   $ aws verifiedpermissions update-identity-source \
       --update-configuration file://config.txt \
       --policy-store-id 123456789012
   {
       "createdDate": "2023-05-19T20:30:28.214829+00:00",
       "identitySourceId": "ISEXAMPLEabcdefg111111",
       "lastUpdatedDate": "2023-05-19T20:30:28.214829+00:00",
       "policyStoreId": "PSEXAMPLEabcdefg111111"
   }
   ```

**注意**  
如果要更改该身份来源的主体类型，必须更新架构，以正确反映更新后的主体类型。

------

# 将 OIDC 令牌映射到架构
<a name="oidc-map-token-to-schema"></a>

您可能会发现想要将身份源添加到策略存储中，并将地图提供商声明或令牌添加到策略存储架构中。您可以自动执行此过程，方法是使用[引导式设置](policy-stores-create.md)创建带有身份源的策略存储，或者在创建策略存储后手动更新架构。将令牌映射到架构后，您可以创建引用它们的策略。

用户指南的这一部分包含以下信息：
+ 何时可以自动填充策略存储架构的属性
+ 如何为身份源手动构建架构

通过[引导式设置](policy-stores-create.md)创建的 [API 关联策略存储](policy-stores-api-userpool.md)和带有身份源的策略存储不需要将身份 (ID) 令牌属性手动映射到架构。您可以为用户池中的属性提供经过验证的权限，并创建填充用户属性的架构。在 ID 令牌授权中，已验证权限将声明映射到委托人实体的属性。

要使用 OIDC 身份提供商 (IdP) 作为已验证权限策略存储中的身份源，您的架构中必须包含提供者属性。架构是固定的，必须与提供者令牌创建的实体[IsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_IsAuthorizedWithToken.html)或 [BatchIsAuthorizedWithToken](https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_BatchIsAuthorizedWithToken.html)API 请求相对应。如果您创建策略存储的方式是自动从 ID 令牌中的提供者信息填充架构，那么您就可以编写策略了。如果您创建的策略存储没有身份源架构，则必须向架构中添加与使用 API 请求创建的实体相匹配的提供者属性。然后，您可以使用提供者令牌中的属性来编写策略。

**Topics**
+ [将 ID 令牌映射到架构](#oidc-map-id-token)
+ [映射访问令牌](#oidc-map-access-token)
+ [关于架构映射的注意事项](#oidc-map-token-to-schema-things-to-know)

## 将 ID 令牌映射到架构
<a name="oidc-map-id-token"></a>

Verified Permissions 将身份令牌声明作为用户的属性进行处理：他们的姓名和头衔、群组成员资格、联系信息。ID 令牌在*基于属性的访问控制* (ABAC) 授权模型中最有用。如果您想让经过验证的权限根据谁提出请求来分析对资源的访问权限，请为您的身份来源选择 ID 令牌。

使用 OIDC 提供商提供的 ID 令牌与使用 Amazon Cognito ID 令牌大致相同。区别在于索赔。您的 IdP 可能呈现[标准的 OIDC 属性](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims)，或者具有自定义架构。在已验证权限控制台中创建新的策略存储时，可以添加带有示例 ID 令牌的 OIDC 身份源，也可以手动将令牌声明映射到用户属性。由于已验证权限不知道您的 IdP 的属性架构，因此您必须提供此信息。

有关更多信息，请参阅 [创建 Verified Permissions 策略存储](policy-stores-create.md)。

以下是具有 OIDC 身份源的策略存储的示例架构。

```
"User": {
   "shape": {
      "type": "Record",
      "attributes": {
         "email": {
            "type": "String"
         },
         "email_verified": {
            "type": "Boolean"
         },
         "name": {
            "type": "String",
            "required": true
         },
         "phone_number": {
            "type": "String"
         },
         "phone_number_verified": {
            "type": "Boolean"
         }
      }
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[反映 OIDC ID 令牌属性](policies-examples.md#policies-examples-oidc-id)。

## 映射访问令牌
<a name="oidc-map-access-token"></a>

Verified Permissions 处理除组声明之外的访问令牌声明作为操作属性或*上下文*属性。除了群组成员资格外，来自您的 IdP 的访问令牌可能还包含有关 API 访问的信息。访问令牌在使用基于角色的访问控制 (RBAC) 的授权模型中很有用。依赖组成员资格以外的访问令牌声明的授权模型需要在架构配置方面付出额外的努力。

来自外部 OIDC 提供商的大多数访问令牌都与 Amazon Cognito 访问令牌非常一致。传递给 “已验证权限” 时，OIDC 访问令牌会映射到上下文对象。可以使用 `context.token.attribute_name` 来引用访问令牌的属性。以下示例 OIDC 访问令牌包括基本声明示例。

```
{
    "sub": "91eb4550-9091-708c-a7a6-9758ef8b6b1e",
    "groups": [
        "Store-Owner-Role",
        "Customer"
    ],
    "iss": "https://auth.example.com",
    "client_id": "1example23456789",
    "aud": "https://myapplication.example.com"
    "scope": "MyAPI-Read",
    "exp": 1688096566,
    "iat": 1688092966,
    "jti": "a1b2c3d4-e5f6-a1b2-c3d4-TOKEN2222222",
    "username": "alice"
}
```

以下示例说明了如何在 Verified Permissions 架构中反映示例访问令牌中的属性。有关编辑架构的更多信息，请参阅[编辑策略存储架构](schema-edit.md)。

```
{
   "MyApplication": {
      "actions": {
         "Read": {
            "appliesTo": {
               "context": {
                  "type": "ReusedContext"
               },
               "resourceTypes": [
                  "Application"
               ],
               "principalTypes": [
                  "User"
               ]
            }
         }
      },
      ...
      ...
      "commonTypes": {
         "ReusedContext": {
            "attributes": {
               "token": {
                  "type": "Record",
                  "attributes": {
                     "scope": {
                        "type": "Set",
                        "element": {
                           "type": "String"
                        }
                     },
                     "client_id": {
                        "type": "String"
                     }
                  }
               }
            },
            "type": "Record"
         }
      }
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[反映 OIDC 访问令牌属性](policies-examples.md#policies-examples-oidc-access)。

## 关于架构映射的注意事项
<a name="oidc-map-token-to-schema-things-to-know"></a>

**不同标记类型的属性映射不同**  
在访问令牌授权中，已验证权限将声明映射到[上下文](context.md)。在 ID 令牌授权中，已验证权限将声明映射到委托人属性。对于您在已验证权限控制台中创建的策略存储，只有**空**策略存储和**示例**策略存储才会使您没有身份来源，并要求您在架构中填充用户池属性以进行 ID 令牌授权。访问令牌授权基于基于角色的访问控制 (RBAC) 和群组成员资格声明，不会自动将其他声明映射到策略存储架构。

**不需要身份源属性**  
在已验证权限控制台中创建身份源时，不会将任何属性标记为必填属性。这样可以防止丢失的索赔导致授权请求中的验证错误。您可以根据需要将属性设置为 required，但它们必须存在于所有授权请求中。

**RBAC 不需要架构中的属性**  
身份源的架构取决于您在添加身份源时建立的实体关联。身份源将一个声明映射到用户实体类型，将一个声明映射到群组实体类型。这些实体映射是身份源配置的核心。有了这些最少的信息，您就可以在基于角色的访问控制 (RBAC) 模型中编写对特定用户和用户可能属于的特定组执行授权操作的策略。向架构中添加令牌声明可扩展策略存储的授权范围。来自 ID 令牌的用户属性包含可以为基于属性的访问控制 (ABAC) 授权做出贡献的用户信息。访问令牌的上下文属性包含诸如 OAuth 2.0 作用域之类的信息，这些信息可以提供来自提供者的额外访问控制信息，但需要进行额外的架构修改。

已验证权限控制台中的 “**使用 API Gateway 和身份提供者****进行设置” 和 “引导式设置**” 选项为架构分配 ID 令牌声明。访问令牌声明的情况并非如此。[要向架构中添加非组访问令牌声明，必须在 JSON 模式下编辑架构并添加 CommonTypes 属性。](https://docs.cedarpolicy.com/schema/json-schema.html#schema-commonTypes)有关更多信息，请参阅 [映射访问令牌](#oidc-map-access-token)。

**OIDC 团体声称支持多种格式**  
添加 OIDC 提供商时，您可以在 ID 或访问令牌中选择要映射到策略存储中用户的群组成员资格的群组名称。经过验证的权限可以识别以下格式的群组声明：

1. 不带空格的字符串：`"groups": "MyGroup"`

1. 以空格分隔的列表:. `"groups": "MyGroup1 MyGroup2 MyGroup3"` 每个字符串都是一个组。

1. JSON（以逗号分隔）列表：`"groups": ["MyGroup1", "MyGroup2", "MyGroup3"]`

**注意**  
Verified Permissions 将以空格分隔的群组声明中的每个字符串解释为一个单独的群组。要将带有空格字符的组名解释为单个组，请替换或删除声明中的空格。例如，设置名为的群组`My Group`的格式`MyGroup`。

**选择代币类型**  
您的策略存储与身份源配合的方式取决于身份源配置中的一个关键决定：是处理 ID 还是访问令牌。对于 OIDC 提供商，您必须在添加身份源时选择令牌类型。您可以选择 ID 或访问令牌，并且您的选择会将未选择的令牌类型排除在保单存储库中的处理范围之外。特别是如果您希望从身份令牌声明自动映射到已验证权限控制台中的属性中受益，请在创建身份源之前尽早决定要处理的令牌类型。更改令牌类型需要花费大量精力来重构您的策略和架构。以下主题介绍如何在策略存储中使用 ID 和访问令牌。

**Cedar 解析器要求某些字符使用方括号**  
策略通常以类似的格式引用架构属性`principal.username`。对于令牌声明名称中可能出现的大多数非字母数字字符`:`，例如`.`、或`/`，Verified Permissions 无法解析像或这样的条件值。`principal.cognito:username` `context.ip-address`您必须改为使用`principal["cognito:username"]`或`context["ip-address"]`格式的方括号表示法来格式化这些条件。下划线字符`_`是声明名称中的有效字符，也是该要求的唯一非字母数字例外。

此类型主属性的部分示例架构如下所示：

```
"User": {
   "shape": {
      "type": "Record",
      "attributes": {
         "cognito:username": {
            "type": "String",
            "required": true
         },
         "custom:employmentStoreCode": {
            "type": "String",
            "required": true,
         },
         "email": {
            "type": "String",
            "required": false
         }
      }
   }
}
```

这种类型的上下文属性的部分示例架构如下所示：

```
"GetOrder": {
   "memberOf": [],
   "appliesTo": {
      "resourceTypes": [
         "Order"
      ],
      "context": {
         "type": "Record",
         "attributes": {
            "ip-address": {
               "required": false,
               "type": "String"
            }
		 }
	  },
      "principalTypes": [
         "User"
      ]
   }
}
```

有关将针对此架构进行验证的策略示例，请参阅[使用方括号表示法来引用代币属性](policies-examples.md#policies-examples-brackets)。

# OIDC 提供商的客户和受众验证
<a name="oidc-validation"></a>

向策略存储中添加身份源时，Verified Permissions 具有用于验证 ID 和访问令牌是否按预期使用的配置选项。这种验证发生在 `BatchIsAuthorizedWithToken` API 请求`IsAuthorizedWithToken`的处理过程中。ID 和访问令牌以及 Amazon Cognito 和 OIDC 身份源的行为有所不同。通过 Amazon Cognito 用户池提供商，经过验证的权限可以验证身份和访问令牌中的客户端 ID。通过 OIDC 提供商，经过验证的权限可以验证 ID 令牌中的客户端 ID 和访问令牌中的受众。

例如，*客户端 ID* 是与您的应用程序使用的身份提供商实例关联的标识符`1example23456789`。例如，*受众*是与访问令牌的预期*依赖方*或目标相关联的 URL 路径`https://mytoken.example.com`。使用访问令牌时，`aud`声明始终与受众相关联。

OIDC ID 令牌的`aud`声明包含客户端 IDs，例如。`1example23456789`

OIDC 访问令牌的`aud`声明包含令牌的受众网址（例如`https://myapplication.example.com`）和包含客户端 IDs（例如）的`client_id`声明。`1example23456789`

设置策略存储时，请输入一个或多个**受众验证**值，您的政策存储使用该值来验证令牌的受众。
+ **ID 令牌** — 已验证权限通过检查`aud`声明 IDs 中至少有一名客户成员与受众验证值匹配来验证客户端 ID。
+ **访问令牌** — 已验证权限通过检查`aud`声明中的网址是否与受众验证值相匹配来验证受众。如果不存在任何`aud`声明，则可以使用`cid`或`client_id`声明来验证受众。请咨询您的身份提供商，了解正确的受众主张和格式。

## 的客户端授权 JWTs
<a name="oidc-validation-other-idp"></a>

您可能需要在应用程序中处理 JSON Web 令牌并将其声明传递给已验证权限，而无需使用策略存储标识源。您可以从 JSON Web 令牌 (JWT) 中提取实体属性并将其解析为已验证的权限。

此示例说明如何使用 JWT 从应用程序调用 “已验证权限”。¹

```
async function authorizeUsingJwtToken(jwtToken) {
  
    const payload = await verifier.verify(jwtToken);
   
    let principalEntity = {
        entityType: "PhotoFlash::User", // the application needs to fill in the relevant user type
        entityId: payload["sub"], // the application need to use the claim that represents the user-id
    };
    let resourceEntity = {
        entityType: "PhotoFlash::Photo", //the application needs to fill in the relevant resource type
        entityId: "jane_photo_123.jpg", // the application needs to fill in the relevant resource id
    };
    let action = {
        actionType: "PhotoFlash::Action", //the application needs to fill in the relevant action id
        actionId: "GetPhoto", //the application needs to fill in the relevant action type
    };
    let entities = {
        entityList: [],
    };
    entities.entityList.push(...getUserEntitiesFromToken(payload));
    let policyStoreId = "PSEXAMPLEabcdefg111111"; // set your own policy store id
    
    const authResult = await client
        .isAuthorized({
        policyStoreId: policyStoreId,
        principal: principalEntity,
        resource: resourceEntity,
        action: action,
        entities,
        })
        .promise();
        
    return authResult; 
  
}

function getUserEntitiesFromToken(payload) {
  let attributes = {};
  let claimsNotPassedInEntities = ['aud', 'sub', 'exp', 'jti', 'iss'];
  Object.entries(payload).forEach(([key, value]) => {
    if (claimsNotPassedInEntities.includes(key)) {
        return;
    }
    if (Array.isArray(value)) {
      var attibuteItem = [];
      value.forEach((item) => {
        attibuteItem.push({
          string: item,
        });
      });
      attributes[key] = {
        set: attibuteItem,
      };
    } else if (typeof value === 'string') {
      attributes[key] = {
        string: value,
      } 
    } else if (typeof value === 'bigint' || typeof value ==='number') {
        attributes[key] = {
            long: value,
          } 
    } else if (typeof value === 'boolean') {
        attributes[key] = {
            boolean: value,
       } 
    }

  });

  let entityItem = {
    attributes: attributes,
    identifier: {
      entityType: "PhotoFlash::User",
      entityId: payload["sub"], // the application needs to use the claim that represents the user-id
    }
  };
  return [entityItem];
}
```

¹ 此代码示例使用该[aws-jwt-verify](https://github.com/awslabs/aws-jwt-verify)库来验证由 OID IdPs C JWTs 兼容的签名。