Verified Access 中的使用者宣告傳遞和簽章驗證 - AWS 已驗證的存取

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

Verified Access 中的使用者宣告傳遞和簽章驗證

AWS Verified Access 執行個體成功驗證使用者後,會將從 IdP 收到的使用者宣告傳送至 Verified Access 端點。使用者宣告會經過簽署,讓應用程式可以驗證簽章,並驗證宣告是由 Verified Access 傳送。在此過程中,會新增下列 HTTP 標頭:

x-amzn-ava-user-context

此標頭包含 JSON Web 字符 (JWT) 格式的使用者宣告。JWT 格式包含使用 base64 URL 編碼的標頭、承載和簽章。Verified Access 使用 ES384 (使用 SHA-384 雜湊演算法的 ECDSA 簽章演算法) 來產生 JWT 簽章。

應用程式可以將這些宣告用於個人化或其他使用者特定的體驗。應用程式開發人員應在使用前,自行了解身分提供者所提供每個宣告的唯一性和驗證程度。一般而言,sub宣告是識別指定使用者的最佳方式。

範例:OIDC 使用者宣告的已簽署 JWT

下列範例示範 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" ] }

範例:IAM Identity Center 使用者宣告的已簽署 JWT

下列範例示範 JWT 格式的 IAM Identity Center 使用者宣告的標頭和承載會是什麼樣子。

注意

對於 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 } } }

公有金鑰

由於 Verified Access 執行個體不會加密使用者宣告,我們建議您設定 Verified Access 端點以使用 HTTPS。如果您將 Verified Access 端點設定為使用 HTTP,請務必使用安全群組限制端點的流量。

為了確保安全性,您必須先驗證簽章,才能根據宣告進行任何授權,並驗證 JWT 標頭中的 signer 欄位是否包含預期的已驗證存取執行個體 ARN。

若要取得公有金鑰,請從 JWT 標頭取得金鑰 ID,並用其在端點查閱公有金鑰。

每個 的端點 AWS 區域 如下:

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

範例:擷取和解碼 JWT

下列程式碼範例示範如何在 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'])