

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

# 將自訂屬性傳送至 Amazon Cognito，並將其插入字符
<a name="send-custom-attributes-cognito"></a>

*Carlos Alessandro Ribeiro 和 Mauricio Mendoza，Amazon Web Services*

## 總結
<a name="send-custom-attributes-cognito-summary"></a>

將自訂屬性傳送至 Amazon Cognito 身分驗證程序可為應用程式提供額外的內容、啟用更精細的存取控制，並讓您更輕鬆地管理使用者設定檔和身分驗證要求。這些功能在各種應用程式和案例中都很有用，可協助您改善應用程式的整體安全性和功能。

此模式顯示當應用程式需要為[存取字符](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-access-token.html)或[身分 (ID) 字符](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-the-id-token.html)提供額外的內容時，如何將自訂屬性傳送至 Amazon Cognito 身分驗證程序。您可以使用 Node.js 做為後端應用程式。應用程式會從 Amazon Cognito 使用者[集區驗證使用者](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools.html)，並傳遞產生字符所需的自訂屬性。您可以使用 Amazon Cognito [AWS Lambda 的觸發](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)條件來自訂身分驗證程序，而無需進行主要程式碼自訂或大量工作。

**重要**  
此模式中的程式碼和範例不建議用於生產工作負載，因為它們僅用於示範用途。對於生產工作負載，用戶端需要額外的組態。使用此模式做為僅供試行或proof-of-concept參考。

## 先決條件和限制
<a name="send-custom-attributes-cognito-prereqs"></a>

**先決條件**
+ 作用中 AWS 帳戶
+ 建立和管理 Amazon Cognito 使用者集區和 AWS Lambda 函數的許可
+ AWS Command Line Interface (AWS CLI)，[已安裝](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)和[設定](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)
+ 支援 Node.js 的整合式開發環境 (IDE)
+ Node.js 第 18 版或更新版本，[已安裝](https://nodejs.org/en/download/)
+ npm 第 8 版或更新版本，[已安裝](https://docs.npmjs.com/getting-started)
+ TypeScript，[已安裝](https://www.typescriptlang.org/download/)

**限制**
+ 此模式不適用於透過用戶端登入資料驗證流程進行應用程式整合。
+ 產生金鑰前觸發條件只能新增或變更存取字符和身分字符的某些屬性。如需詳細資訊，請參閱 Amazon Cognito 文件中的[產生字符前 Lambda 觸發](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html)程序。

## Architecture
<a name="send-custom-attributes-cognito-architecture"></a>

**目標架構**

下圖顯示此模式的目標架構。它也會顯示 Node.js 應用程式如何與後端搭配使用以更新資料庫。不過，後端資料庫更新超出此模式的範圍。

![\[Node.js 應用程式向 Amazon Cognito 使用者集區發出具有自訂屬性的存取字符。\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/images/pattern-img/9f0855e6-77f9-48c2-846e-f9c317127e1f/images/8c52c88b-8954-4b4c-aed3-fd8c22f84c1d.png)


該圖顯示以下工作流程：

1. Node.js 應用程式會向 Amazon Cognito 使用者集區發出具有自訂屬性的存取字符。

1. Amazon Cognito 使用者集區會啟動預先金鑰產生 Lambda 函數，以自訂存取和 ID 權杖。

1. Node.js 應用程式會透過 Amazon API Gateway 進行 API 呼叫。

**注意**  
此架構中顯示的其他架構元件僅為 ，且超出此模式的範圍。

**自動化和擴展**

您可以使用 、、[HashiCorp Terraform](https://www.terraform.io/docs) 或任何支援的基礎設施即程式碼 (IaC) 工具[AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)，自動佈建 Amazon Cognito 使用者集區[AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/v2/guide/home.html)、 AWS Lambda 函數、資料庫執行個體和其他資源。如果您想要擴展部署，請使用持續整合和持續交付 (CI/CD) 管道，這有助於防止與手動部署相關的錯誤。

## 工具
<a name="send-custom-attributes-cognito-tools"></a>

**AWS 服務**
+ [Amazon API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html) 可協助您建立、發佈、維護、監控和保護任何規模的 REST、HTTP 和 WebSocket APIs。
+ [Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) 為 Web 和行動應用程式提供身分驗證、授權和使用者管理。
+ [Amazon Elastic Container Service (Amazon ECS)](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html) 是快速、可擴展的容器管理服務，可協助您執行、停止和管理叢集上的容器。
+ [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) 是一項運算服務，可協助您執行程式碼，無需佈建或管理伺服器。它只會在需要時執行程式碼並自動擴展，因此您只需支付使用的運算時間。
+ [適用於 JavaScript 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/welcome.html) 提供 JavaScript API AWS 服務。您可以使用它來建置 Node.js 或瀏覽器的程式庫或應用程式。

**其他工具**
+ [Node.js](https://nodejs.org/en/docs/) 是一種事件驅動的 JavaScript 執行期環境，專為建置可擴展的網路應用程式而設計。
+ [npm](https://docs.npmjs.com/about-npm) 是在 Node.js 環境中執行的軟體登錄檔，用於共用或借用套件和管理私有套件的部署。

## 最佳實務
<a name="send-custom-attributes-cognito-best-practices"></a>

我們建議您實作下列最佳實務：
+ **秘密和敏感資料** – 請勿在應用程式中存放秘密或敏感資料。使用應用程式可以從中提取資料的外部系統，例如 [AWS AppConfig](https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html)、 [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html)或 [AWS Systems Manager參數存放區](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)。
+ **標準化部署** – 使用 CI/CD 管道來部署您的應用程式。您可以使用 [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html)和 等服務[AWS CodePipeline](https://docs.aws.amazon.com/codepipeline/latest/userguide/welcome.html)。
+ **權杖過期** – 設定存取權杖的簡短過期日期。
+ **使用安全連線** – 用戶端應用程式與後端之間的所有通訊都應使用 SSL/TLS 加密。使用 [AWS Certificate Manager (ACM)](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) 來產生和管理 SSL/TLS 憑證，並使用 [Amazon CloudFront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html) 或 [Elastic Load Balancing ](https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/what-is-load-balancing.html)來處理 SSL/TLS 終止。
+ **驗證使用者輸入** – 確保所有使用者輸入都經過驗證，以防止注入攻擊和其他安全漏洞。使用輸入驗證程式庫和服務，例如 Amazon API Gateway 和 [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/what-is-aws-waf.html#waf-intro)，以防止常見的攻擊向量。
+ **使用 IAM 角色** – 使用 [AWS Identity and Access Management (IAM)](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) 角色來控制對 AWS 資源的存取，並確保只有獲得授權的使用者才能存取。遵循最低權限原則，並確保每個使用者只有執行其角色所需的許可。
+ **使用密碼政策** – 設定符合您安全要求的密碼政策，例如長度下限、複雜性和過期時間。使用 Secrets Manager 或 AWS Systems Manager 參數存放區安全地存放和管理密碼。
+ **啟用多重要素驗證 (MFA)** – 為所有使用者啟用 MFA，以提供額外的安全層，並降低未經授權的存取風險。使用 [AWS IAM Identity Center](https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html)或 Amazon Cognito 來啟用 MFA 和其他身分驗證方法。
+ **安全地存放敏感資訊** – 使用 [AWS Key Management Service (AWS KMS)](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html) 或其他加密服務安全地存放敏感資訊，例如密碼和存取權杖。
+ **使用強式身分驗證方法** – 若要提高身分驗證程序的安全性，請使用強式身分驗證方法，例如生物識別驗證或多重要素驗證。
+ **監控可疑活動** – 使用 [AWS CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html) 和其他監控工具來監控可疑活動和潛在的安全威脅。設定異常活動的自動提醒，並使用 [Amazon GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/what-is-guardduty.html) 或 [AWS Security Hub CSPM](https://docs.aws.amazon.com/securityhub/latest/userguide/what-is-securityhub.html) 來偵測潛在威脅。
+ **定期檢閱和更新安全政策** – 定期檢閱和更新安全政策和程序，以確保它們符合您不斷變化的安全需求和最佳實務。使用 AWS Config 來追蹤和稽核安全政策和程序的變更。
+ **自動化註冊** – 請勿啟用 Amazon Cognito 使用者集區的自動註冊。如需詳細資訊，請參閱[使用 Amazon Cognito 使用者集區降低使用者註冊詐騙和 SMS 輸出的風險 ](https://aws.amazon.com/blogs/security/reduce-risks-of-user-sign-up-fraud-and-sms-pumping-with-amazon-cognito-user-pools/)(AWS 部落格文章）。

如需其他最佳實務，請參閱 [Amazon Cognito 文件中的 Amazon Cognito 使用者集區的安全最佳實務](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-security-best-practices.html)。 Amazon Cognito 

## 史詩
<a name="send-custom-attributes-cognito-epics"></a>

### 設定 AWS 資源
<a name="set-up-the-aws-resources"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立使用者集區。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html)如需如何在 中設定使用者集區的詳細資訊和指示 AWS 管理主控台，請參閱[使用者集區入門](https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-user-pools.html)和[將更多功能和安全性選項新增至您的使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-next-steps.html)。若要降低成本，請使用 Essentials 計劃或 Lite 計劃來測試此模式。如需詳細資訊，請參閱 [Amazon Cognito 定價](https://aws.amazon.com/cognito/pricing/)。 | 應用程式開發人員、AWS DevOps | 
| 將使用者新增至使用者集區。 | 輸入下列命令，在 Amazon Cognito 使用者集區中建立一個使用者：<pre>aws cognito-idp sign-up \<br />   --client-id <ClientID> \<br />   --username <jane@example.com> \<br />   --password <PASSWORD> \<br />   --user-attributes Name="email",Value="<jane@example.com>" Name="name",Value="<Jane>"</pre> | 應用程式開發人員、AWS DevOps | 
| 將應用程式用戶端新增至使用者集區。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html) | AWS 系統管理員、AWS 管理員、AWS DevOps、應用程式開發人員 | 
| 建立 Lambda 觸發程序以產生預先權杖。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html) | AWS DevOps，應用程式開發人員 | 
| 自訂使用者集區工作流程。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html)如需詳細資訊，請參閱 Amazon Cognito 文件中的[使用 Lambda 觸發程序自訂使用者集區工作流程](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)。 | AWS DevOps，應用程式開發人員 | 

### 建立 Node.js 應用程式
<a name="create-the-node-js-application"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 Node.js 應用程式。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html) | 應用程式開發人員 | 
| 實作身分驗證邏輯。 | [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/prescriptive-guidance/latest/patterns/send-custom-attributes-cognito.html)您可以建立自己的 TypeScript 檔案，或修改您的使用案例所需的範例。 | 應用程式開發人員 | 
| 設定環境變數和組態檔案。 | 在終端機中，輸入下列命令來建立環境變數：<pre>export USERNAME="<COGNITO_USER_NAME>"<br />export PASSWORD="<COGNITO_USER_PASSWORD>"<br />export USER_POOL_ID="<COGNITO_USER_ID>"<br />export CLIENT_ID="<COGNITO_CLIENT_ID>"</pre>請勿硬式編碼秘密或公開您的登入資料。 | 應用程式開發人員 | 
| 執行應用程式。 | 輸入下列命令來執行應用程式並確認其正常運作：<pre>npm run build<br />npm start</pre> | 應用程式開發人員 | 
| 確認自訂屬性已插入字符中。 | 使用 IDE 的偵錯功能來檢視存取和 ID 字符。確認已新增自訂屬性。如需範例權杖，請參閱此模式[的其他資訊](#send-custom-attributes-cognito-additional)區段。 | 應用程式開發人員 | 

## 疑難排解
<a name="send-custom-attributes-cognito-troubleshooting"></a>


| 問題 | 解決方案 | 
| --- | --- | 
| 嘗試驗證使用者時無效的用戶端 ID | 當您使用用戶端 ID 搭配產生的用戶端秘密時，通常會發生此錯誤。您必須建立未連接秘密的用戶端 ID。如需詳細資訊，請參閱[應用程式用戶端的應用程式特定設定](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html)。 | 

## 相關資源
<a name="send-custom-attributes-cognito-resources"></a>
+ [使用 Lambda 觸發來自訂使用者集區工作流程](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html) (Amazon Cognito 文件）
+ 權[杖產生前 Lambda 觸發](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-pre-token-generation.html)程序 (Amazon Cognito 文件）
+ [CognitoIdentityProviderClient](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/cognito-identity-provider/) (適用於 JavaScript 的 AWS SDK 文件）
+ [cognito-idp](https://awscli.amazonaws.com/v2/documentation/api/2.0.34/reference/cognito-idp/index.html#cli-aws-cognito-idp) (AWS CLI 文件）

## 其他資訊
<a name="send-custom-attributes-cognito-additional"></a>

**範例 TypeScript 檔案**

下列程式碼範例是 TypeScript 檔案，使用 AWS SDK 將自訂屬性傳送至 Amazon Cognito 來叫用身分驗證程序：

```
import * as AmazonCognitoIdentity from "amazon-cognito-identity-js";

const userPoolId: string = process.env.USER_POOL_ID ?? '';
const clientId: string = process.env.CLIENT_ID ?? '';

const poolData = {
  UserPoolId: userPoolId,
  ClientId: clientId
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

export const loginWithCognitoSDK = function (userName: string, password: string) {
  const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({
    Username: userName,
    Password: password,
    ClientMetadata: {
        customGroup: "MyCustomGroup",
        customApplicationData: "Custom data from a custom application"
    }
  });
  const userData = {
    Username: userName,
    Pool: userPool
  };

  const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);

  // Authenticate the user using the authenticationDetails object
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: function (result: any) {},
    onFailure: function (err: any) {},
  });
}
loginWithCognitoSDK(process.env.USERNAME ?? '', process.env.PASSWORD ?? '');
```

此範例使用適用於 JavaScript 的 SDK 中的`AuthenticationDetails`模型來提供使用者名稱、密碼和 `ClientMetadada`。在 Amazon Cognito 中驗證之後，可以從存取和 ID 字符擷取用戶端中繼資料。

**Lambda 函數範例**

下列程式碼範例是連結至 Amazon Cognito [產生前字符](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html)的 Lambda 函數。它可協助您自訂 Amazon Cognito 使用的存取字符和 ID 字符。權杖會透過架構之間的整合傳遞。此範例包含名為 的自訂宣告屬性，`customApplicationData`以及名為 的自訂群組名稱`MyCustomGroup`：

```
export const handler = async(event, context, callback) => {
    event.response = {
        claimsOverrideDetails: {
            claimsToAddOrOverride: { customApplicationData: event.request.clientMetadata.customApplicationData },
            groupOverrideDetails: { groupsToOverride: [event.request.clientMetadata.customGroup] }
        }
    };
    callback(null, event);
};
```

**存取字符範例**

您可以解碼存取權杖，以視覺化已新增的自訂屬性。以下是存取字符的範例：

```
{
  "sub": "6daf331f-4451-48b4-abde-774579299204",
  "cognito:groups": [
    "MyCustomGroup"
  ],
  "iss": "https://cognito-idp.<REGION>.amazonaws.com/<USERPOOL_ID>",
  "client_id": "<YOUR_CLIENT_ID>",
  "origin_jti": "acff7e91-09f9-4fde-8eec-38b0f8c47cdc",
  "event_id": "c5113a9c-1f01-435b-9b73-a5cd3e88514e",
  "token_use": "access",
  "scope": "aws.cognito.signin.user.admin",
  "auth_time": 1677979246,
  "exp": 1677982846,
  "iat": 1677979246,
  "jti": "5c9c2708-a871-4428-bd9b-18ad261bea90",
  "username": "<USER_NAME>"
}
```

**範例 ID 字符**

您可以解碼存取權杖，以視覺化已新增的自訂屬性。以下是存取字符的範例：

```
{
  "sub": "6daf331f-4451-48b4-abde-774579299204",
  "cognito:groups": [
    "MyCustomGroup"
  ],
  "iss": "https://cognito-idp.<REGION>.amazonaws.com/<USERPOOL_ID>",
  "cognito:username": "<USER_NAME>",
  "origin_jti": "acff7e91-09f9-4fde-8eec-38b0f8c47cdc",
  "customApplicationData": "Custom data from a custom application",
  "aud": "<YOUR_CLIENT_ID>",
  "event_id": "c5113a9c-1f01-435b-9b73-a5cd3e88514e",
  "token_use": "id",
  "auth_time": 1677979246,
  "exp": 1677982846,
  "iat": 1677979246,
  "jti": "f7ca006b-f25b-44d2-a7a4-6e6423f4201f",
  "email": "<USER_EMAIL>"
}
```