

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

# Verified Access 中的用户声明传递和签名验证
<a name="user-claims-passing"></a>

 AWS Verified Access 实例成功对用户进行身份验证后，它会将从 IdP 收到的用户声明发送到已验证访问终端节点。用户声明经过签名，以便应用程序可以验证签名，并验证声明是否由 Verified Access 发送。在此过程中，添加以下 HTTP 标头：

`x-amzn-ava-user-context`

此标头包含 JSON Web 令牌 (JWT) 格式的用户声明。JWT 格式包括 base64 URL 编码的标头、负载和签名。Verified Access 使用 ES384 （使用 SHA-384 哈希算法的 ECDSA 签名算法）生成 JWT 签名。

应用程序可以将这些声明用于个性化或其他特定于用户的体验。应用程序开发人员应在使用前自行了解身份提供商提供的每个声明的唯一性和验证级别。通常，`sub` 声明是识别给定用户的最佳方法。

**Topics**
+ [OIDC 用户声明的 JWT](#oidc-sample)
+ [IAM Identity Center 用户声明的 JWT](#IdC-sample)
+ [公钥](#public-keys)
+ [检索和解码 JWT](#sample-code)

## 示例：OIDC 用户声明的签名 JWT
<a name="oidc-sample"></a>

以下示例说明了 OIDC 用户声明的标头和有效负载（JWT 格式）。

标头示例：

```
{
   "alg": "ES384",
   "kid": "12345678-1234-1234-1234-123456789012",
   "signer": "arn:aws:ec2:us-east-1:123456789012:verified-access-instance/vai-abc123xzy321a2b3c", 
   "iss": "OIDC Issuer URL",
   "exp": "expiration" (120 secs)
}
```

有效负载示例：

```
{
   "sub": "xyzsubject",
   "email": "xxx@amazon.com",
   "email_verified": true,
   "groups": [
      "Engineering",
      "finance"
   ],
   "additional_user_context": {
      "aud": "xxx",
      "exp": 1000000000,
      "groups": [
         "group-id-1",
         "group-id-2"
      ],
      "iat": 1000000000,
      "iss": "https://oidc-tp.com/",
      "sub": "xyzsubject",
      "ver": "1.0"
   }
}
```

## 示例：IAM Identity Center 用户声明的签名 JWT
<a name="IdC-sample"></a>

以下示例说明了 IAM Identity Center 用户声明的标头和有效负载（JWT 格式）。

**注意**  
对于 IAM Identity Center，声明中仅包含用户信息。

标头示例：

```
{
   "alg": "ES384",
   "kid": "12345678-1234-1234-1234-123456789012",
   "signer": "arn:aws:ec2:us-east-1:123456789012:verified-access-instance/vai-abc123xzy321a2b3c", 
   "iss": "arn:aws:ec2:us-east-1:123456789012:verified-access-trust-provider/vatp-abc123xzy321a2b3c",
   "exp": "expiration" (120 secs)
}
```

有效负载示例：

```
{
    "user": {
        "user_id": "f478d4c8-a001-7064-6ea6-12423523",
        "user_name": "test-123",
        "email": {
            "address": "test@amazon.com",
            "verified": false
        }
    }
}
```

## 公钥
<a name="public-keys"></a>

由于 Verified Access 实例不会对用户声明加密，因此我们建议将 Verified Access 端点配置为使用 HTTPS。如果将 Verified Access 端点配置为使用 HTTP，请务必使用安全组限制至该端点的流量。

为确保安全，您必须在根据声明进行任何授权之前验证签名，并验证 JWT 标头中的 `signer` 字段是否包含预期的 Verified Access 实例 ARN。

要获取公钥，请从 JWT 标头中获取密钥 ID 并使用它从终端节点查找公钥：

每个终端节点 AWS 区域 如下所示：

`https://public-keys.prod.verified-access.<region>.amazonaws.com/<key-id>`

## 示例：检索和解码 JWT
<a name="sample-code"></a>

以下代码示例说明了如何在 Python 3.9 中获取密钥 ID、公钥和有效负载。

```
import jwt
import requests
import base64
import json

# Step 1: Validate the signer
expected_verified_access_instance_arn = 'arn:aws:ec2:region-code:account-id:verified-access-instance/verified-access-instance-id'

encoded_jwt = headers.dict['x-amzn-ava-user-context']
jwt_headers = encoded_jwt.split('.')[0]
decoded_jwt_headers = base64.b64decode(jwt_headers)
decoded_jwt_headers = decoded_jwt_headers.decode("utf-8")
decoded_json = json.loads(decoded_jwt_headers)
received_verified_access_instance_arn = decoded_json['signer']

assert expected_verified_access_instance_arn == received_verified_access_instance_arn, "Invalid Signer"

# Step 2: Get the key id from JWT headers (the kid field)
kid = decoded_json['kid']

# Step 3: Get the public key from regional endpoint
url = 'https://public-keys.prod.verified-access.' + region + '.amazonaws.com/' + kid
req = requests.get(url)
pub_key = req.text

# Step 4: Get the payload
payload = jwt.decode(encoded_jwt, pub_key, algorithms=['ES384'])
```