

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

# 使用 Lambda 觸發程序來自訂使用者集區工作流程
<a name="cognito-user-pools-working-with-lambda-triggers"></a>

Amazon Cognito 使用 AWS Lambda 函數來修改使用者集區的身分驗證行為。您可以將使用者集區設定為在首次註冊之前、完成驗證後以及介於兩者之間的幾個階段，自動調用 Lambda 函數。您的函數可以修改身分驗證流程的預設行為、提出 API 請求來修改您的使用者集區或其他 AWS 資源，以及與外部系統通訊。Lambda 函數中的程式碼是您自己的程式碼。Amazon Cognito 會將事件資料傳送到您的函數，等待函數處理資料，而且在大多數情況下會預期回應事件，反映您想要對工作階段進行的任何變更。

在請求和回應事件系統中，您可以引入自己的驗證挑戰、在使用者集區和其他身分存放區之間遷移使用者、自訂訊息，以及修改 JSON Web 權杖 (JWT)。

Lambda 觸發程序可以自訂 Amazon Cognito 在您的使用者集區中啟動動作後，傳送給使用者的回應。例如，您可以阻止本來會成功的使用者登入。他們也可以針對您的 AWS 環境、外部 API、資料庫或身分存放區執行執行期操作。例如，遷移使用者觸發程序可以結合外部動作與 Amazon Cognito 中的變更：您可以查詢外部目錄中的使用者資訊，然後根據該外部資訊為新使用者設定屬性。

當您將 Lambda 觸發程序指派給使用者集區時，Amazon Cognito 會中斷其預設流程，從您的函數請求資訊。Amazon Cognito 會產生 JSON *事件*並將其傳遞到您的函數。此事件包含使用者建立使用者帳戶、登入、重設密碼或更新屬性之請求的相關資訊。然後，您的函數有機會採取行動，或將事件原封不動地傳回。傳回的事件未修改會通知使用者集區，以繼續執行事件的預設動作。例如，您的註冊前觸發可以自動確認`PreSignUp_SignUp`觸發來源的使用者，但外部和管理員建立的使用者傳回的事件保持不變。

下表摘錄一些使用 Lambda 觸發程序來自訂使用者集區操作的方法：


****  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

**Topics**
+ [Lambda 觸發程序的須知事項](#important-lambda-considerations)
+ [新增使用者集區 Lambda 觸發條件](#triggers-working-with-lambda)
+ [使用者集區 Lambda 觸發程序事件](#cognito-user-pools-lambda-trigger-event-parameter-shared)
+ [使用者集區 Lambda 觸發程序的常用參數](#cognito-user-pools-lambda-trigger-syntax-shared)
+ [用戶端中繼資料](#working-with-lambda-trigger-client-metadata)
+ [將 API 操作連線至 Lambda 觸發程序](#lambda-triggers-by-event)
+ [將 Lambda 觸發程序連接至使用者集區功能操作](#working-with-lambda-trigger-sources)
+ [註冊前 Lambda 觸發程序](user-pool-lambda-pre-sign-up.md)
+ [確認後 Lambda 觸發程序](user-pool-lambda-post-confirmation.md)
+ [身分驗證前 Lambda 觸發程序](user-pool-lambda-pre-authentication.md)
+ [身分驗證後 Lambda 觸發程序](user-pool-lambda-post-authentication.md)
+ [傳入聯合 Lambda 觸發](user-pool-lambda-inbound-federation.md)
+ [自訂身分驗證挑戰 Lambda 觸發程序](user-pool-lambda-challenge.md)
+ [產生權杖前 Lambda 觸發程序](user-pool-lambda-pre-token-generation.md)
+ [遷移使用者 Lambda 觸發程序](user-pool-lambda-migrate-user.md)
+ [自訂訊息 Lambda 觸發程序](user-pool-lambda-custom-message.md)
+ [自訂寄件者 Lambda 觸發程序](user-pool-lambda-custom-sender-triggers.md)

## Lambda 觸發程序的須知事項
<a name="important-lambda-considerations"></a>

準備用於 Lambda 函數的使用者集區時，請考慮下列事項：
+ Amazon Cognito 傳送給您的 Lambda 觸發程序的事件可能會隨著新功能而變更。JSON 階層中回應和請求元素的位置可能會變更，或者可能會新增元素名稱。在 Lambda 函數中，您可以期望收到本指南中所述的輸入元素鍵值對，但更嚴格的輸入驗證可能會導致函數失敗。
+ 您可以選擇 Amazon Cognito 傳送至某些觸發程序的多個版本事件之一。某些版本可能會要求您接受 Amazon Cognito 定價的變更。如需定價的詳細資訊，請參閱 [Amazon Cognito 定價](https://aws.amazon.com/cognito/pricing/)。若要在 中自訂存取權杖[產生權杖前 Lambda 觸發程序](user-pool-lambda-pre-token-generation.md)，您必須使用 *Lite* 以外的功能計劃來設定使用者集區，並更新 Lambda 觸發組態以使用事件版本 2。
+ 除了[自訂寄件者 Lambda 觸發程序](user-pool-lambda-custom-sender-triggers.md)之外，Amazon Cognito 會同步叫用 Lambda 函數。當 Amazon Cognito 呼叫您的 Lambda 函數時，該函數必須在 5 秒內回應。如果沒有，而且可以重試呼叫，Amazon Cognito 可能會重試呼叫。如果所有重試嘗試都失敗，則函數會逾時。您無法變更此 5 秒逾時值。如需詳細資訊，請參閱《 AWS Lambda 開發人員指南》中的 [Lambda 程式設計模型](https://docs.aws.amazon.com/lambda/latest/dg/foundation-progmodel.html)。

  Amazon Cognito 不會重試傳回[調用錯誤](https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_Errors)且 HTTP 狀態碼為 500-599 的函數呼叫。這些代碼表示發生組態問題，導致 Lambda 無法啟動該函數。如需詳細資訊，請參閱[錯誤處理和自動重試 AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-retries.html)。
+ 您無法在 Lambda 觸發程式組態中宣告函數版本。Amazon Cognito 使用者集區預設會調用最新版本的函數。但是，您可以將函數版本與別名相關聯，並在 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html) 或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) API 請求中將觸發程式 `LambdaArn` 設為別名 ARN。此選項無法用於 AWS 管理主控台中。若要進一步了解別名，請參閱 *AWS Lambda 開發人員指南*中的 [Lambda 函數別名](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html)。
+ 若刪除 Lambda 觸發程序，必須更新使用者集區內對應的觸發程序。例如，若您刪除驗證後觸發，便須在對應的使用者集區內，將 **Post authentication (身分驗證後)** 觸發設為 **none (無)**。
+ 如果您的 Lambda 函數未將請求和回應參數傳回至 Amazon Cognito，或傳回錯誤，則驗證事件不會成功。您可以在函數中傳回錯誤，以防止使用者註冊、驗證、產生權杖，或進行驗證流程中調用 Lambda 觸發程序的任何其他階段。

  受管登入會傳回 Lambda 觸發在登入提示上方產生為錯誤文字的錯誤。Amazon Cognito 使用者集區 API 會使用 `[trigger] failed with error [error text from response]` 格式傳回觸發程序錯誤。最佳實務是僅在您希望使用者看到的 Lambda 函數中產生錯誤。使用類似 `print()` 的輸出方法將任何敏感或偵錯資訊記錄到 CloudWatch Logs。如需範例，請參閱 [註冊前範例：如果使用者名稱少於五個字元，則拒絕註冊](user-pool-lambda-pre-sign-up.md#aws-lambda-triggers-pre-registration-example-3)。
+ 您可以在另一個 中新增 Lambda 函數， AWS 帳戶 做為使用者集區的觸發條件。您必須使用 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html) 和 [UpdateUserPool](https://docs.aws.amazon.com/) API 操作，或其在 CloudFormation 和 中的對等項目來新增跨帳戶觸發 AWS CLI。您無法在 中新增跨帳戶函數 AWS 管理主控台。
+ 當您在 Amazon Cognito 主控台中新增 Lambda 觸發程序時，Amazon Cognito 會在您的函數中新增以資源為基礎的政策，以允許您的使用者集區叫用該函數。在 Amazon Cognito 主控台外部建立 Lambda 觸發程序時，包括跨帳戶之間的函數，您必須為 Lambda 函數新增基於資源政策的許可。您新增的許可必須允許 Amazon Cognito 以代表您的使用者集區叫用函數。您可以[從 Lambda 主控台新增許可](https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html)或使用 Lambda [AddPermission](https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html) API 操作。

**以 Lambda 資源為基礎的政策範例**  
下列 Lambda 資源型政策範例允許 Amazon Cognito 叫用 Lambda 函數的有限功能。執行此操作時，Amazon Cognito 只能代表 `aws:SourceArn` 條件中的使用者集區和 `aws:SourceAccount` 條件中的帳戶叫用函數。

------
#### [ JSON ]

****  

  ```
  {
      "Version":"2012-10-17",		 	 	 
      "Id": "default",
      "Statement": [
          {
              "Sid": "LambdaCognitoIdpTrust",
              "Effect": "Allow",
              "Principal": {
                  "Service": "cognito-idp.amazonaws.com"
              },
              "Action": "lambda:InvokeFunction",
              "Resource": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
              "Condition": {
                  "StringEquals": {
                      "AWS:SourceAccount": "111122223333"
                  },
                  "ArnLike": {
                      "AWS:SourceArn": "arn:aws:cognito-idp:us-east-1:111122223333:userpool/us-east-1_EXAMPLE"
                  }
              }
          }
      ]
  }
  ```

------

## 新增使用者集區 Lambda 觸發條件
<a name="triggers-working-with-lambda"></a>

**使用主控台新增使用者集區 Lambda 觸發程序**

1. 使用 [Lambda 主控台](https://console.aws.amazon.com/lambda/home)建立 Lambda 函數。如需 Lambda 函數的詳細資訊，請參閱《[AWS Lambda 開發人員指南](https://docs.aws.amazon.com/lambda/latest/dg/)》。

1. 前往 [Amazon Cognito 主控台](https://console.aws.amazon.com/cognito/home)，然後選擇 **User Pools** (使用者集區)。

1. 從清單中選擇現有的使用者集區，或[建立使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 選擇**延伸項目**選單並尋找 **Lambda 觸發**條件。

1. 選擇 **Add a Lambda trigger** (新增 Lambda 觸發程序)。

1. 根據您要自訂的身分驗證階段，選取 Lambda 觸發程序 **Category** (類別)。

1. 選取**指派 Lambda 函數**，然後選取與使用者集區 AWS 區域 相同的函數。
**注意**  
如果您的 AWS Identity and Access Management (IAM) 登入資料具有更新 Lambda 函數的許可，Amazon Cognito 會新增 Lambda 資源型政策。使用此政策，Amazon Cognito 可以叫用您選取的函數。如果登入的憑證沒有足夠的 IAM 許可，則您必須個別更新以資源為基礎的政策。如需詳細資訊，請參閱[Lambda 觸發程序的須知事項](#important-lambda-considerations)。

1. 選擇 **Save changes** (儲存變更)。

1. 您可以使用 Lambda 主控台中的 CloudWatch 記錄您的 Lambda 函數。如需詳細資訊，請參閱[存取 Lambda 的 CloudWatch Logs](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-logs.html)。

## 使用者集區 Lambda 觸發程序事件
<a name="cognito-user-pools-lambda-trigger-event-parameter-shared"></a>

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。Lambda 函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。如果您的函數在不修改的情況下傳回輸入事件，Amazon Cognito 會繼續進行預設行為。以下顯示所有 Lambda 觸發輸入事件常見的參數。如需觸發條件特定的事件語法，請檢閱本指南 區段中每個觸發條件的事件結構描述。

------
#### [ JSON ]

```
{
    "version": "string",
    "triggerSource": "string",
    "region": AWSRegion,
    "userPoolId": "string",
    "userName": "string",
    "callerContext": 
        {
            "awsSdkVersion": "string",
            "clientId": "string"
        },
    "request":
        {
            "userAttributes": {
                "string": "string",
                ....
            }
        },
    "response": {}
}
```

------

## 使用者集區 Lambda 觸發程序的常用參數
<a name="cognito-user-pools-lambda-trigger-syntax-shared"></a>

**version**  
Lambda 函數的版本編號。

**triggerSource**  
觸發 Lambda 函數的事件名稱。如需每個 triggerSource 的說明，請參閱 [將 Lambda 觸發程序連接至使用者集區功能操作](#working-with-lambda-trigger-sources)。

**region**  
 AWS 區域 做為`AWSRegion`執行個體。

**userPoolId**  
使用者集區的 ID。

**使用者名稱**  
目前使用者的使用者名稱。

**callerContext**  
有關請求和程式碼環境的中繼資料。它包含欄位 **awsSdkVersion** 和 **clientId**。    
**awsSdkVersion**  
產生請求的 AWS SDK 版本。  
****clientId****  
使用者集區應用程式用戶端的 ID。

**請求**  
使用者 API 請求的詳細資訊。它包括下列欄位，以及觸發程序特有的任何請求參數。例如，Amazon Cognito 傳送至預先身分驗證觸發程序的事件也會包含一個 `userNotFound` 參數。您可以處理此參數的值，以便在使用者嘗試使用未註冊的使用者名稱登入時採取自訂動作。    
**userAttributes**  
一或多組使用者屬性名稱和值的鍵/值對，例如 `"email": "john@example.com"`。

**回應**  
此參數不包含原始請求中的任何資訊。您的 Lambda 函數必須將整個事件傳回給 Amazon Cognito，並將任何傳回參數新增至 `response`。若要查看函數可以包含哪些傳回參數，請參閱您要使用之觸發程序的文件。

## 用戶端中繼資料
<a name="working-with-lambda-trigger-client-metadata"></a>

您可以在 API 操作和[權杖端點](token-endpoint.md)請求中將自訂參數提交至 Lambda 觸發函數。使用用戶端中繼資料，您的應用程式可以收集請求來源環境的其他資訊。當您將用戶端中繼資料傳遞至 Lambda 函數時，他們可以處理其他資料，並在記錄或自訂身分驗證流程時使用它。用戶端中繼資料是您選擇的字串對，並以 JSON 鍵值格式設計。

**用戶端中繼資料範例使用案例**
+ 在註冊時將地理位置資料傳遞至[註冊前觸發](user-pool-lambda-pre-sign-up.md)條件，並防止從不需要的位置登入。
+ 將租戶 ID 資料傳遞至[自訂挑戰觸發條件](user-pool-lambda-challenge.md)，並向來自不同業務單位的客戶發出不同的挑戰。
+ 將使用者的字符傳遞至[字符產生前觸發](user-pool-lambda-pre-token-generation.md)程序，並產生代表 M2M 請求的委託人日誌。如需請求範例，請參閱 [具有基本授權的用戶端憑證具有 POST 內文授權的用戶端憑證](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。

以下是將用戶端中繼資料傳遞至註冊前觸發程序的範例。

------
#### [ SignUp request ]

以下是範例 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-ValidationData) 請求，其中包含 Amazon Cognito 傳遞給註冊前觸發條件的用戶端中繼資料。

```
POST HTTP/1.1
Host: cognito-idp.us-east-1.amazonaws.com
X-Amz-Date: 20230613T200059Z
Accept-Encoding: gzip, deflate, br
X-Amz-Target: AWSCognitoIdentityProviderService.SignUp
User-Agent: <UserAgentString>
Authorization: AWS4-HMAC-SHA256 Credential=<Credential>, SignedHeaders=<Headers>, Signature=<Signature>
Content-Length: <PayloadSizeBytes>

{
    "ClientId": "1example23456789",
    "Username": "mary_major",
    "Password": "<Password>",
    "SecretHash": "<Secret hash>",
    "ClientMetadata": { 
        "IpAddress" : "192.0.2.252",
        "GeoLocation" : "Netherlands (Kingdom of the) [NL]"
    }
    "UserAttributes": [
        {
            "Name": "name",
            "Value": "Mary"
        },
        {
            "Name": "email",
            "Value": "mary_major@example.com"
        },
        {
            "Name": "phone_number",
            "Value": "+12065551212"
        }
    ],
}
```

------
#### [ Lambda trigger input event ]

請求會導致您的註冊前函數出現以下請求內文。

```
{
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "region": "us-west-2",
    "request": {
        "clientMetadata": {
            "GeoLocation": "Netherlands (Kingdom of the) [NL]",
            "IpAddress": "192.0.2.252"
        },
        "userAttributes": {
            "email": "mary_major@example.com",
            "name": "Mary",
            "phone_number": "+12065551212"
        },
        "validationData": null
    },
    "response": {
        "autoConfirmUser": false,
        "autoVerifyEmail": false,
        "autoVerifyPhone": false
    },
    "triggerSource": "PreSignUp_SignUp",
    "userName": "mary_major2",
    "userPoolId": "us-west-2_EXAMPLE",
    "version": "1"
}
```

------

**machine-to-machine(M2M) 用戶端登入資料的用戶端中繼資料**  
您可以在 M2M 請求中傳遞[用戶端中繼資料](#working-with-lambda-trigger-client-metadata)。用戶端中繼資料是來自使用者或應用程式環境的其他資訊，有助於 的結果[產生權杖前 Lambda 觸發程序](user-pool-lambda-pre-token-generation.md)。在使用者主體的身分驗證操作中，您可以將用戶端中繼資料傳遞至 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 請求內文中的權杖產生前觸發器。由於應用程式會透過對 的直接請求，為 M2M 執行產生存取字符的流程[權杖端點](token-endpoint.md)，因此具有不同的模型。在用戶端登入資料的字符請求 POST 內文中，將具有用戶端中繼資料物件 URL 編碼 (`x-www-form-urlencoded`) 的 `aws_client_metadata` 參數傳遞至字串。如需請求範例，請參閱 [具有基本授權的用戶端憑證具有 POST 內文授權的用戶端憑證](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。以下是傳遞鍵/值對 的範例參數`{"environment": "dev", "language": "en-US"}`。

```
aws_client_metadata=%7B%22environment%22%3A%20%22dev%22,%20%22language%22%3A%20%22en-US%22%7D
```

**臨時使用者屬性： `validationData`**  
有些身分驗證操作也有 `validationData` 參數。如同用戶端中繼資料，這是將 Amazon Cognito 不會自動收集的外部資訊傳遞至 Lambda 觸發程序的機會。驗證資料欄位旨在為您的 Lambda 函數提供註冊和登入操作中的其他使用者內容。[SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html#CognitoUserPools-SignUp-request-ValidationData) 和 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html#CognitoUserPools-AdminCreateUser-request-ValidationData) 會傳遞`validationData`至[註冊前觸發](user-pool-lambda-pre-sign-up.md)條件。[InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#CognitoUserPools-InitiateAuth-request-ClientMetadata) 和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html#CognitoUserPools-AdminInitiateAuth-request-ClientMetadata) `ClientMetadata` 會將輸入事件`validationData`中的 API 請求內文傳遞至身分[驗證前](user-pool-lambda-pre-authentication.md)和[遷移使用者](user-pool-lambda-migrate-user.md)觸發。

若要將 API 操作映射至它們可以傳遞用戶端中繼資料的函數，請參閱以下觸發來源區段。

## 將 API 操作連線至 Lambda 觸發程序
<a name="lambda-triggers-by-event"></a>

以下各節說明 Amazon Cognito 從使用者集區中的活動呼叫的 Lambda 觸發程序。

當您的應用程式透過 Amazon Cognito 使用者集區 API、受管登入或使用者集區端點登入使用者時，Amazon Cognito 會根據工作階段內容叫用您的 Lambda 函數。如需有關 Amazon Cognito 使用者集區 API 和使用者集區端點的詳細資訊，請參閱 [了解 API、OIDC 和受管登入頁面身分驗證](authentication-flows-public-server-side.md#user-pools-API-operations)。接下來各節中的表格描述了導致 Amazon Cognito 叫用函數的事件，以及 Amazon Cognito 在請求中包含的 `triggerSource` 字串。

**Topics**
+ [Amazon Cognito API 中的 Lambda 觸發程序](#lambda-triggers-native-users-native-api)
+ [受管登入中 Amazon Cognito 本機使用者的 Lambda 觸發條件](#lambda-triggers-native-users-hosted-UI)
+ [適用於聯合身分使用者的 Lambda 觸發程序](#lambda-triggers-for-federated-users)

### Amazon Cognito API 中的 Lambda 觸發程序
<a name="lambda-triggers-native-users-native-api"></a>

下表說明當您的應用程式建立、登入或更新本機使用者時，Amazon Cognito 可呼叫 Lambda 觸發程序的來源字串。


**Amazon Cognito API 中的本機使用者觸發程序來源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

### 受管登入中 Amazon Cognito 本機使用者的 Lambda 觸發條件
<a name="lambda-triggers-native-users-hosted-UI"></a>

下表說明當本機使用者使用受管登入登入使用者集區時，Amazon Cognito 可以叫用之 Lambda 觸發條件的來源字串。


**受管登入中的本機使用者觸發來源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

### 適用於聯合身分使用者的 Lambda 觸發程序
<a name="lambda-triggers-for-federated-users"></a>

您可以使用以下 Lambda 觸發程序，為使用聯合身分提供者登入的使用者自訂使用者集區工作流程。

**注意**  
聯合身分使用者可以使用受管登入來登入，或者您可以對 產生請求[授權端點](authorization-endpoint.md)，以靜音方式將他們重新導向至身分提供者登入頁面。您不能使用 Amazon Cognito 使用者集區 API 登入聯合身分使用者。


**聯合身分使用者觸發程序來源**  
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html)

聯合身分登入不會叫用使用者集區中的任何 [自訂身分驗證挑戰 Lambda 觸發程序](user-pool-lambda-challenge.md)、[遷移使用者 Lambda 觸發程序](user-pool-lambda-migrate-user.md)、[自訂訊息 Lambda 觸發程序](user-pool-lambda-custom-message.md) 或 [自訂寄件者 Lambda 觸發程序](user-pool-lambda-custom-sender-triggers.md)。

## 將 Lambda 觸發程序連接至使用者集區功能操作
<a name="working-with-lambda-trigger-sources"></a>

每個 Lambda 觸發程序都在您的使用者集區中扮演一個功能角色。例如，觸發程序可以修改您的註冊流程，或新增自訂身分驗證挑戰。Amazon Cognito 傳送至 Lambda 函數的事件可反映組成該功能角色的多個動作之一。例如，Amazon Cognito 會在您的使用者註冊以及您建立使用者時，叫用預先註冊觸發程序。相同功能角色在這些不同情況中都有自己的 `triggerSource` 值。Lambda 函數可以根據呼叫它的操作，以不同的方式處理傳入事件。

當事件對應於觸發程序來源時，Amazon Cognito 也會叫用所有指派的函數。例如，當使用者登入您指派了遷移使用者和預先身分驗證觸發程序的使用者集區時，他們會同時啟動兩者。


**註冊、確認和登入 (身分驗證) 觸發程序**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 註冊前 | PreSignUp\$1SignUp | 註冊前。 | 
| 註冊前 | PreSignUp\$1AdminCreateUser | 註冊前 (當管理員建立新使用者時)。 | 
| 註冊前 | PreSignUp\$1ExternalProvider | 外部身分提供者註冊前。 | 
| 貼文確認 | PostConfirmation\$1ConfirmSignUp | 註冊後確認。 | 
| 貼文確認 | PostConfirmation\$1ConfirmForgotPassword | 忘記密碼後確認。 | 
| 身分驗證前 | PreAuthentication\$1Authentication | 身分驗證前。 | 
| 身分驗證後 | PostAuthentication\$1Authentication | 身分驗證後。 | 


**自訂身分驗證挑戰觸發程序**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 定義身分驗證挑戰 | DefineAuthChallenge\$1Authentication | 定義驗證挑戰。 | 
| 建立身分驗證挑戰 | CreateAuthChallenge\$1Authentication | 建立驗證挑戰。 | 
| 確認驗證挑戰 | VerifyAuthChallengeResponse\$1Authentication | 確認驗證挑戰回應。 | 


**聯合觸發**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 傳入聯合 | InboundFederation\$1ExternalProvider | 傳入聯合。 | 


**產生權杖前觸發程序**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 產生權杖前 | TokenGeneration\$1HostedAuth |  Amazon Cognito 會從受管登入頁面驗證使用者。 | 
| 產生權杖前 | TokenGeneration\$1Authentication | 使用者身分驗證或權杖重新整理完成。 | 
| 產生權杖前 | TokenGeneration\$1NewPasswordChallenge | 管理員建立使用者。當使用者必須變更臨時密碼時，Amazon Cognito 會叫用此功能。 | 
| 產生權杖前 | TokenGeneration\$1AuthenticateDevice | 使用者裝置的身分驗證結束時。 | 
| 產生權杖前 | TokenGeneration\$1RefreshTokens | 使用者嘗試重新整理身分和存取權杖時。 | 


**遷移使用者觸發程序**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 使用者遷移 | UserMigration\$1Authentication | 在登入時的使用者遷移。 | 
| 使用者遷移 | UserMigration\$1ForgotPassword | 忘記密碼流程時的使用者遷移。 | 


**自訂訊息觸發程序**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 自訂訊息 | CustomMessage\$1SignUp | 當使用者在使用者集區註冊時的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1AdminCreateUser | 當您以管理員身分建立使用者，而且 Amazon Cognito 向這些使用者發送臨時密碼時的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1ResendCode | 當現有使用者請求新確認代碼時的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1ForgotPassword | 當使用者請求密碼重設時的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1UpdateUserAttribute | 當使用者變更其電子郵件地址或電話號碼，而且 Amazon Cognito 傳送驗證碼時的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1VerifyUserAttribute | 當使用者新增電子郵件地址或電話號碼，而且 Amazon Cognito 傳送驗證碼的自訂訊息。 | 
| 自訂訊息 | CustomMessage\$1Authentication | 當已設定簡訊 MFA 的使用者登入時的自訂訊息。 | 


**自訂寄件者觸發條件**  

| 觸發條件 | triggerSource 值 | 事件 | 
| --- | --- | --- | 
| 自訂寄件者 |  `CustomEmailSender_SignUp` `CustomSmsSender_SignUp`  | 當使用者在您的使用者集區中註冊時。 | 
| 自訂寄件者 |  `CustomEmailSender_AdminCreateUser` `CustomSmsSender_AdminCreateUser`  | 當您以管理員身分建立使用者時，Amazon Cognito 會傳送臨時密碼給他們。 | 
| 自訂寄件者 |  `CustomEmailSender_ForgotPassword` `CustomSmsSender_ForgotPassword`  | 當您的使用者請求重設密碼時。 | 
| 自訂寄件者 |  `CustomEmailSender_UpdateUserAttribute` `CustomSmsSender_UpdateUserAttribute`  | 當使用者變更其電子郵件地址或電話號碼，且 Amazon Cognito 傳送驗證碼時。 | 
| 自訂寄件者 |  `CustomEmailSender_VerifyUserAttribute` `CustomSmsSender_VerifyUserAttribute`  | 當使用者新增電子郵件地址或電話號碼，且 Amazon Cognito 傳送驗證碼時。 | 
| 自訂寄件者 |  `CustomEmailSender_Authentication` `CustomSmsSender_Authentication`  | 已設定 SMS 或電子郵件 MFA 或 OTP 的使用者登入時。 | 
| 自訂寄件者 | CustomEmailSender\$1AccountTakeOverNotification | 當您的威脅防護設定對使用者的登入嘗試採取自動動作，且風險層級的動作包含通知。 | 

# 註冊前 Lambda 觸發程序
<a name="user-pool-lambda-pre-sign-up"></a>

您可能想要在具有自助註冊選項的使用者集區中自訂註冊程序。預先註冊觸發程序的一些常見用途是執行新使用者的自訂分析和記錄、套用安全性和控管標準，或將第三方 IdP 的使用者連結至[合併的使用者設定檔](cognito-user-pools-identity-federation-consolidate-users.md)。您可能也有不需要進行[驗證和確認](signing-up-users-in-your-app.md)的信任使用者。

在 Amazon Cognito 完成建立新的[本機](cognito-terms.md#terms-localuser)或[聯合身分](cognito-terms.md#terms-federateduser)使用者之前，它會啟用註冊前 Lambda 函數。傳送至此函數之請求物件`userAttributes`中的 包含本機使用者註冊所提供的屬性，或已成功從聯合身分使用者的提供者屬性映射的屬性。您的使用者集區會在使用 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html) 進行自助註冊時叫用此觸發，或使用受信任[身分提供者](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-federated)首次登入，以及使用 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) 建立使用者時叫用此觸發。在註冊過程中，您可以使用此函數來分析具有自訂邏輯的登入事件，以及修改或拒絕新使用者。

**Topics**
+ [註冊前 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-pre-signup)
+ [註冊前範例：自動確認來自已註冊網域的使用者](#aws-lambda-triggers-pre-registration-example)
+ [註冊前範例：自動確認及自動驗證所有使用者](#aws-lambda-triggers-pre-registration-example-2)
+ [註冊前範例：如果使用者名稱少於五個字元，則拒絕註冊](#aws-lambda-triggers-pre-registration-example-3)

## 註冊前 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "validationData": {
            "string": "string",
            . . .
         },
        "clientMetadata": {
            "string": "string",
            . . .
         }
    },

    "response": {
        "autoConfirmUser": "boolean",
        "autoVerifyPhone": "boolean",
        "autoVerifyEmail": "boolean"
    }
}
```

------

### 註冊前請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup-request"></a>

**userAttributes**  
代表使用者屬性的一或多組名稱/值。屬性名稱是索引鍵。

**validationData**  
您的應用程式在建立新使用者的請求中傳遞給 Amazon Cognito 的一或多個鍵值對與使用者屬性資料。在 [AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html) 或 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html) API 請求的 ValidationData 參數中，將此資訊傳送至 Lambda 函數。  
Amazon Cognito 不會將您的 ValidationData 資料設定為您建立之使用者的屬性。ValidationData 是您為了預先註冊 Lambda 觸發程式而提供的臨時使用者資訊。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於註冊前觸發程序所指定。您可以使用下列 API 動作中的 ClientMetadata 參數，將此資料傳遞至您的 Lambda 函數：[AdminCreateUser](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html)、[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)、[ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html) 和 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)。

### 註冊前回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-signup-response"></a>

如果您想要自動確認使用者，可以在回應中將 `autoConfirmUser`設定為 `true`。您可以將 `autoVerifyEmail`設定為 `true`，以自動驗證使用者的電子郵件。您可以將 `autoVerifyPhone`設定為 `true`，以自動驗證使用者的電話號碼。

**注意**  
`AdminCreateUser` API 觸發尚未註冊的 Lambda 函數時，Amazon Cognito 會忽略回應參數 `autoVerifyPhone`、`autoVerifyEmail` 和 `autoConfirmUser`。

**autoConfirmUser**  
設定為 `true`以自動確認使用者，否則設定為 `false`。

**autoVerifyEmail**  
設定為 `true` 以設定為已驗證註冊使用者的電子郵件地址，否則設定為 `false`。如果 `autoVerifyEmail`設定為 `true`，`email` 屬性必須包含有效的非 null 值。否則會發生錯誤，而且使用者將無法完成註冊。  
如果選取 `email` 屬性做為別名，則在設定 `autoVerifyEmail` 時，將會為使用者的電子郵件地址建立別名。如果使用該電子郵件地址的別名已存在，則會將別名移至新使用者，而舊使用者的電子郵件地址會標記為未驗證。如需詳細資訊，請參閱[自訂登入屬性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

**autoVerifyPhone**  
設定為 `true`以設定為已驗證註冊使用者的電話號碼，否則設定為 `false`。如果 `autoVerifyPhone`設定為 `true`，`phone_number` 屬性必須包含有效的非 null 值。否則會發生錯誤，而且使用者將無法完成註冊。  
如果選取 `phone_number`屬性做為別名，則在設定 `autoVerifyPhone` 時，將會為使用者的電話號碼建立別名。如果使用該電話號碼的別名已存在，則會將別名移至新使用者，而舊使用者的電話號碼會標記為未驗證。如需詳細資訊，請參閱[自訂登入屬性](user-pool-settings-attributes.md#user-pool-settings-aliases)。

## 註冊前範例：自動確認來自已註冊網域的使用者
<a name="aws-lambda-triggers-pre-registration-example"></a>

這是範例 Lambda 觸發程式碼。在 Amazon Cognito 處理註冊請求之前，會立即叫用註冊前觸發條件。它會使用自訂屬性 **custom:domain**，自動確認來自特定電子郵件網域的新使用者。不在自訂網域中的任何新使用者都會新增到這個使用者集區，但不會自動確認。

------
#### [ Node.js ]

```
export const handler = async (event, context, callback) => {
  // Set the user pool autoConfirmUser flag after validating the email domain
  event.response.autoConfirmUser = false;

  // Split the email address so we can compare domains
  var address = event.request.userAttributes.email.split("@");

  // This example uses a custom attribute "custom:domain"
  if (event.request.userAttributes.hasOwnProperty("custom:domain")) {
    if (event.request.userAttributes["custom:domain"] === address[1]) {
      event.response.autoConfirmUser = true;
    }
  }

  // Return to Amazon Cognito
  callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    # It sets the user pool autoConfirmUser flag after validating the email domain
    event['response']['autoConfirmUser'] = False

    # Split the email address so we can compare domains
    address = event['request']['userAttributes']['email'].split('@')

    # This example uses a custom attribute 'custom:domain'
    if 'custom:domain' in event['request']['userAttributes']:
        if event['request']['userAttributes']['custom:domain'] == address[1]:
            event['response']['autoConfirmUser'] = True

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "email": "testuser@example.com",
            "custom:domain": "example.com"
        }
    },
    "response": {}
}
```

------

## 註冊前範例：自動確認及自動驗證所有使用者
<a name="aws-lambda-triggers-pre-registration-example-2"></a>

此範例會確認所有使用者並設定使用者的 `email` 和 `phone_number` 屬性以驗證屬性是否存在。此外，如果啟用別名，則當設定自動驗證時，將會為 `phone_number`和 `email` 建立別名。

**注意**  
如果使用相同電話號碼的別名已存在，則會將別名移至新使用者，而舊使用者的 `phone_number`會標記為未驗證。電子郵件地址也是一樣。若要防止發生這種情況，您可以使用這些使用者集區[ListUsers API](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html)，查看是否有現有的使用者已經使用新使用者的電話號碼或電子郵件地址做為別名。

------
#### [ Node.js ]

```
exports.handler = (event, context, callback) => {
  // Confirm the user
  event.response.autoConfirmUser = true;

  // Set the email as verified if it is in the request
  if (event.request.userAttributes.hasOwnProperty("email")) {
    event.response.autoVerifyEmail = true;
  }

  // Set the phone number as verified if it is in the request
  if (event.request.userAttributes.hasOwnProperty("phone_number")) {
    event.response.autoVerifyPhone = true;
  }

  // Return to Amazon Cognito
  callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    # Confirm the user
    event['response']['autoConfirmUser'] = True

    # Set the email as verified if it is in the request
    if 'email' in event['request']['userAttributes']:
        event['response']['autoVerifyEmail'] = True

    # Set the phone number as verified if it is in the request
    if 'phone_number' in event['request']['userAttributes']:
        event['response']['autoVerifyPhone'] = True

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
  "request": {
    "userAttributes": {
      "email": "user@example.com",
      "phone_number": "+12065550100"
    }
  },
  "response": {}
}
```

------

## 註冊前範例：如果使用者名稱少於五個字元，則拒絕註冊
<a name="aws-lambda-triggers-pre-registration-example-3"></a>

此範例會檢查註冊請求中的使用者名稱長度。如果使用者輸入的名稱長度少於五個字元，則範例會傳回錯誤。

------
#### [ Node.js ]

```
export const handler = (event, context, callback) => {
    // Impose a condition that the minimum length of the username is 5 is imposed on all user pools.
    if (event.userName.length < 5) {
        var error = new Error("Cannot register users with username less than the minimum length of 5");
        // Return error to Amazon Cognito
        callback(error, event);
    }
    // Return to Amazon Cognito
    callback(null, event);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    if len(event['userName']) < 5:
        raise Exception("Cannot register users with username less than the minimum length of 5")
    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
  "userName": "rroe",
  "response": {}
}
```

------

# 確認後 Lambda 觸發程序
<a name="user-pool-lambda-post-confirmation"></a>

Amazon Cognito 會在已註冊的使用者確認其使用者帳戶後，調用此觸發程序。在您的確認後 Lambda 函數中，您可以傳送自訂訊息或新增自訂 API 請求。例如，您可以查詢外部系統並對使用者填入其他屬性。Amazon Cognito 只會針對在您的使用者集區中註冊的使用者調用此觸發程序，而不會針對您使用管理員憑證建立的使用者帳戶調用此觸發程序。

請求中包含已確認使用者的目前屬性。您的使用者集區會在 [ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html)、[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html) 和 [ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html) 上叫用您的文章確認函數。當使用者在[受管登入](cognito-user-pools-managed-login.md)中確認註冊或密碼重設時，此觸發也會執行。

**Topics**
+ [確認後 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-post-confirmation)
+ [確認後範例](#aws-lambda-triggers-post-confirmation-example)

## 確認後 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
            "userAttributes": {
                "string": "string",
                . . .
            },
            "clientMetadata": {
            	"string": "string",
            	. . .
            }
        },
    "response": {}
}
```

------

### 確認後請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation-request"></a>

**userAttributes**  
代表使用者屬性的一或多個鍵值組。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於確認後觸發程序所指定。您可以使用下列 API 動作中的 ClientMetadata 參數，將此資料傳遞至您的 Lambda 函數：[AdminConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminConfirmSignUp.html)、[ConfirmForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmForgotPassword.html)、[ConfirmSignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmSignUp.html) 和 [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)。

### 確認後回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-confirmation-response"></a>

回應中不應有額外的傳回資訊。

## 確認後範例
<a name="aws-lambda-triggers-post-confirmation-example"></a>

這個範例 Lambda 函數會使用 Amazon SES，將確認電子郵件訊息傳送給您的使用者。如需詳細資訊，請參閱《[Amazon Simple Storage Service 開發人員指南](https://docs.aws.amazon.com/ses/latest/DeveloperGuide/)》。

------
#### [ Node.js ]

```
// Import required AWS SDK clients and commands for Node.js. Note that this requires
// the `@aws-sdk/client-ses` module to be either bundled with this code or included
// as a Lambda layer.
import { SES, SendEmailCommand } from "@aws-sdk/client-ses";
const ses = new SES();

const handler = async (event) => {
  if (event.request.userAttributes.email) {
    await sendTheEmail(
      event.request.userAttributes.email,
      `Congratulations ${event.userName}, you have been confirmed.`,
    );
  }
  return event;
};

const sendTheEmail = async (to, body) => {
  const eParams = {
    Destination: {
      ToAddresses: [to],
    },
    Message: {
      Body: {
        Text: {
          Data: body,
        },
      },
      Subject: {
        Data: "Cognito Identity Provider registration completed",
      },
    },
    // Replace source_email with your SES validated email address
    Source: "<source_email>",
  };
  try {
    await ses.send(new SendEmailCommand(eParams));
  } catch (err) {
    console.log(err);
  }
};

export { handler };
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "email": "user@example.com",
            "email_verified": true
        }
    },
    "response": {}
}
```

------

# 身分驗證前 Lambda 觸發程序
<a name="user-pool-lambda-pre-authentication"></a>

Amazon Cognito 會在使用者嘗試登入時叫用此觸發程序，因此您可以建立自訂驗證來執行預先準備的動作。例如，您可以拒絕身分驗證請求，或將工作階段資料記錄到外部系統。

**注意**  
除非使用者集區應用程式用戶端`PreventUserExistenceErrors`的設定設為 ，否則當使用者不存在時，此 Lambda 觸發不會啟用`ENABLED`。現有身分驗證工作階段的續約也不會啟用此觸發。

**Topics**
+ [流程概觀](#user-pool-lambda-pre-authentication-1)
+ [身分驗證前 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-pre-auth)
+ [身分驗證前範例](#aws-lambda-triggers-pre-authentication-example)

## 流程概觀
<a name="user-pool-lambda-pre-authentication-1"></a>

![\[註冊前身分驗證 Lambda 觸發程序 – 用戶端流程\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-pre-authentication-1.png)


此請求包括來自應用程式傳遞至使用者集區 `InitiateAuth` 和 `AdminInitiateAuth` API 操作的 `ClientMetadata` 值的用戶端驗證資料。

如需詳細資訊，請參閱[範例身分驗證工作階段](authentication.md#amazon-cognito-user-pools-authentication-flow)。

## 身分驗證前 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "validationData": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {}
}
```

------

### 身分驗證前請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth-request"></a>

**userAttributes**  
代表使用者屬性的一或多組名稱/值。

**userNotFound**  
當您將使用者集區的 `PreventUserExistenceErrors` 設定為 `ENABLED` 時，Amazon Cognito 會填入此布林值。

**validationData**  
一或多個鍵值組，包含使用者登入請求中的驗證資料。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) 和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) API 動作中的 ClientMetadata 參數。

### 身分驗證前回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-auth-response"></a>

Amazon Cognito 不會處理函數在回應中傳回的任何新增資訊。您的函數可傳回錯誤以拒絕登入嘗試，或者使用 API 操作以查詢和修改您的資源。

## 身分驗證前範例
<a name="aws-lambda-triggers-pre-authentication-example"></a>

此範例函數可防止使用者使用特定的應用程式用戶端登入您的使用者集區。由於預先驗證 Lambda 函數在使用者具有現有工作階段時不會叫用，因此該函數只會防止您要封鎖的應用程式用戶端 ID 展開新的工作階段。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (
    event.callerContext.clientId === "user-pool-app-client-id-to-be-blocked"
  ) {
    throw new Error("Cannot authenticate users from this user pool app client");
  }

  return event;
};

export { handler };
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    if event['callerContext']['clientId'] == "<user pool app client id to be blocked>":
        raise Exception("Cannot authenticate users from this user pool app client")

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "callerContext": {
        "clientId": "<user pool app client id to be blocked>"
    },
    "response": {}
}
```

------

# 身分驗證後 Lambda 觸發程序
<a name="user-pool-lambda-post-authentication"></a>

身分驗證後觸發不會變更使用者的身分驗證流程。Amazon Cognito 會在身分驗證完成後，在使用者收到字符之前叫用此 Lambda。當您想要新增身分驗證事件的自訂後置處理時，請新增身分驗證後觸發條件，例如記錄或使用者設定檔調整，這些調整將反映在下一次登入時。

未將請求內文傳回 Amazon Cognito 的身分驗證後 Lambda 仍可能導致身分驗證無法完成。如需詳細資訊，請參閱[Lambda 觸發程序的須知事項](cognito-user-pools-working-with-lambda-triggers.md#important-lambda-considerations)。

**Topics**
+ [身分驗證流程概觀](#user-pool-lambda-post-authentication-1)
+ [身分驗證後 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-post-auth)
+ [身分驗證後範例](#aws-lambda-triggers-post-authentication-example)

## 身分驗證流程概觀
<a name="user-pool-lambda-post-authentication-1"></a>

![\[身分驗證後 Lambda 觸發程序 – 用戶端流程\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-post-authentication-1.png)


如需詳細資訊，請參閱[範例身分驗證工作階段](authentication.md#amazon-cognito-user-pools-authentication-flow)。

## 身分驗證後 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
             "string": "string",
             . . .
         },
         "newDeviceUsed": boolean,
         "clientMetadata": {
             "string": "string",
             . . .
            }
        },
    "response": {}
}
```

------

### 身分驗證後請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth-request"></a>

**newDeviceUsed**  
此旗標指出使用者是否已在新的裝置登入。唯有當使用者集區的記住裝置值為 `Always` 或 `User Opt-In` 時，Amazon Cognito 才會設定此旗標。

**userAttributes**  
代表使用者屬性的一或多組名稱/值。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於身分驗證後觸發程序所指定。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 動作中的 ClientMetadata 參數。Amazon Cognito 不包含其傳遞至身分驗證後函數的請求中的 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作的 ClientMetadata 參數中的資料。

### 身分驗證後回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-post-auth-response"></a>

Amazon Cognito 不預期會在回應中收到任何其他傳回的資訊。您的函數可使用 API 操作來查詢和修改您的資源，或將事件中繼資料記錄到外部系統。

## 身分驗證後範例
<a name="aws-lambda-triggers-post-authentication-example"></a>

這個身分驗證後範本 Lambda 函數，會將成功登入的資料傳送到 CloudWatch Logs。

------
#### [ Node.js ]

```
const handler = async (event) => {
  // Send post authentication data to Amazon CloudWatch logs
  console.log("Authentication successful");
  console.log("Trigger function =", event.triggerSource);
  console.log("User pool = ", event.userPoolId);
  console.log("App client ID = ", event.callerContext.clientId);
  console.log("User ID = ", event.userName);

  return event;
};

export { handler };
```

------
#### [ Python ]

```
import os
def lambda_handler(event, context):

    # Send post authentication data to Cloudwatch logs
    print ("Authentication successful")
    print ("Trigger function =", event['triggerSource'])
    print ("User pool = ", event['userPoolId'])
    print ("App client ID = ", event['callerContext']['clientId'])
    print ("User ID = ", event['userName'])

    # Return to Amazon Cognito
    return event
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
  "triggerSource": "testTrigger",
  "userPoolId": "testPool",
  "userName": "testName",
  "callerContext": {
      "clientId": "12345"
  },
  "response": {}
}
```

------

# 傳入聯合 Lambda 觸發
<a name="user-pool-lambda-inbound-federation"></a>

傳入聯合觸發會在使用外部身分提供者的身分驗證程序期間轉換聯合身分使用者屬性。當使用者透過設定的身分提供者進行身分驗證時，此觸發可讓您透過攔截和轉換身分驗證程序中的資料來修改外部 SAML 和 OIDC 提供者的回應，以程式設計方式控制 Amazon Cognito 使用者集區如何處理聯合身分使用者及其屬性。

在建立新使用者或更新現有的聯合身分使用者設定檔之前，使用此觸發條件來新增、覆寫或隱藏屬性。此觸發會接收原始身分提供者屬性做為輸入，並傳回 Amazon Cognito 套用至使用者設定檔的修改屬性。

**Topics**
+ [流程概觀](#cognito-user-pools-lambda-trigger-inbound-federation-flow)
+ [傳入聯合 Lambda 觸發參數](#cognito-user-pools-lambda-trigger-syntax-inbound-federation)
+ [傳入聯合範例：群組成員資格管理](#aws-lambda-triggers-inbound-federation-example-groups)
+ [傳入聯合範例：截斷大型屬性](#aws-lambda-triggers-inbound-federation-example-truncate)
+ [傳入聯合範例：記錄聯合事件](#aws-lambda-triggers-inbound-federation-example-logging)

## 流程概觀
<a name="cognito-user-pools-lambda-trigger-inbound-federation-flow"></a>

當使用者向外部身分提供者進行身分驗證時，Amazon Cognito 會在建立或更新使用者設定檔之前叫用傳入聯合觸發條件。觸發程序會從身分提供者接收原始屬性，並在 Amazon Cognito 存放它們之前進行轉換。新聯合身分使用者和透過聯合再次登入的現有使用者都會發生此流程。

![\[傳入聯合 Lambda 觸發流程\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-inbound-federation.png)


## 傳入聯合 Lambda 觸發參數
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": AWSRegion,
    "userPoolId": "string",
    "userName": "string",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "string",
        "providerType": "string",
        "attributes": {
            "tokenResponse": {
                "access_token": "string",
                "token_type": "string",
                "expires_in": "string"
            },
            "idToken": {
                "sub": "string",
                "email": "string",
                "email_verified": "string"
            },
            "userInfo": {
                "email": "string",
                "given_name": "string",
                "family_name": "string"
            },
            "samlResponse": {
                "string": "string"
            }
        }
    },
    "response": {
        "userAttributesToMap": {
            "string": "string"
        }
    }
}
```

------

### 傳入聯合請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation-request"></a>

**providerName**  
外部身分提供者的名稱。

**providerType**  
外部身分提供者的類型。有效值：`OIDC`、`SAML`、`Facebook`、`Google`、`SignInWithApple`、`LoginWithAmazon`。

**屬性**  
處理之前從身分提供者收到的原始屬性。結構會根據提供者類型而有所不同。

**attributes.tokenResponse**  
來自`/token`端點的 OAuth 字符回應資料。僅適用於 OIDC 和社交供應商。包含 `access_token`、`id_token`、`refresh_token`、`expires_in`、 `token_type`和 `scope`。

**attributes.idToken**  
解碼和驗證的 ID 字符 JWT 宣告。僅適用於 OIDC 和社交供應商。包含已驗證的使用者身分資訊，包括 `sub`（唯一的使用者識別符）`email`、、`name`、 `iss` （發行者）、 `aud` （對象）、 `exp`（過期） 和 `iat`（發行時間）。

**attributes.userInfo**  
來自 UserInfo 端點的延伸使用者設定檔資訊。僅適用於 OIDC 和社交供應商。包含詳細的設定檔屬性，例如 `given_name`、`family_name`、`address`、 `picture`和其他提供者特定欄位。如果 IdP 不支援 UserInfo 端點或端點呼叫失敗，則可能是空的。

**attributes.samlResponse**  
SAML 聲明屬性。僅適用於 SAML 供應商。包含來自 SAML 回應的屬性。

### 傳入聯合回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-inbound-federation-response"></a>

**userAttributesToMap**  
要套用至使用者設定檔的使用者屬性。

**重要**  
您必須在回應中包含要保留的所有使用者屬性，包括您未修改的屬性。`userAttributesToMap` 回應中未包含的任何屬性都會遭到捨棄，不會存放在使用者設定檔中。這同時適用於已修改和未修改的屬性。

**空的回應行為**  
如果您傳回 `{}`的空物件`userAttributesToMap`，身分提供者的所有原始屬性都會保持不變。這可做為無操作，就像從未執行 Lambda 函數一樣。這與省略屬性不同，這會捨棄它們。

**提供者特定的屬性**  
的結構會根據 `request.attributes`而有所不同`providerType`。OIDC 和社交提供者包括 `tokenResponse`、 `idToken`和 `userInfo` 物件。SAML 供應商僅包含 `samlResponse` 物件。

## 傳入聯合範例：群組成員資格管理
<a name="aws-lambda-triggers-inbound-federation-example-groups"></a>

此範例說明如何將聯合身分提供者群組映射至 Amazon Cognito 使用者集區群組。此函數會從聯合回應中擷取群組成員資格，並自動將使用者新增至對應的 Amazon Cognito 群組，無需進行身分驗證後觸發。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const { providerType, attributes } = event.request;
    
    // Extract user attributes based on provider type
    let userAttributesFromIdp = {};
    if (providerType === 'SAML') {
        userAttributesFromIdp = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        userAttributesFromIdp = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    // Extract groups from federated response
    const federatedGroups = userAttributesFromIdp.groups?.split(',') || [];
    
    // Map federated groups to Cognito groups
    const groupMapping = {
        'Domain Admins': 'Administrators',
        'Engineering': 'Developers',
        'Sales': 'SalesTeam'
    };
    
    // Filter to only in-scope groups
    const mappedGroups = federatedGroups
        .map(group => groupMapping[group.trim()])
        .filter(group => group); // Remove undefined values
    
    // Pass through attributes with mapped groups as custom attribute
    const attributesToMap = {
        ...userAttributesFromIdp,
        'custom:user_groups': mappedGroups.join(',')
    };
    
    // Remove original groups attribute
    delete attributesToMap.groups;
    
    event.response.userAttributesToMap = attributesToMap;
    return event;
};
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "userPoolId": "us-east-1_XXXXXXXXX",
    "request": {
        "providerName": "CorporateAD",
        "providerType": "SAML",
        "attributes": {
            "samlResponse": {
                "email": "jane.smith@company.com",
                "given_name": "Jane",
                "family_name": "Smith",
                "groups": "Engineering,Domain Admins",
                "department": "Engineering"
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

## 傳入聯合範例：截斷大型屬性
<a name="aws-lambda-triggers-inbound-federation-example-truncate"></a>

此範例示範如何截斷超過 Amazon Cognito 儲存限制的屬性值。此函數會檢查身分提供者的每個屬性。如果屬性值超過 2048 個字元，則會截斷該值並新增省略號來表示截斷。所有其他屬性都會傳遞不變。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const MAX_ATTRIBUTE_LENGTH = 2048;
    
    // Get the identity provider attributes based on provider type
    const { providerType, attributes } = event.request;
    let idpAttributes = {};
    
    if (providerType === 'SAML') {
        idpAttributes = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        idpAttributes = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    const userAttributes = {};
    
    // Process each attribute
    for (const [key, value] of Object.entries(idpAttributes)) {
        if (typeof value === 'string' && value.length > MAX_ATTRIBUTE_LENGTH) {
            // Truncate the value and add ellipsis
            userAttributes[key] = value.substring(0, MAX_ATTRIBUTE_LENGTH - 3) + '...';
            console.log(`Truncated attribute ${key} from ${value.length} to ${userAttributes[key].length} characters`);
        } else {
            // Keep the original value
            userAttributes[key] = value;
        }
    }
    
    // Return the modified attributes
    event.response.userAttributesToMap = userAttributes;
    return event;
};
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": "us-east-1",
    "userPoolId": "us-east-1_XXXXXXXXX",
    "userName": "ExampleProvider_12345",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "ExampleProvider",
        "providerType": "OIDC",
        "attributes": {
            "tokenResponse": {
                "access_token": "abcDE...",
                "token_type": "Bearer",
                "expires_in": "3600"
            },
            "idToken": {
                "sub": "12345",
                "email": "user@example.com"
            },
            "userInfo": {
                "email": "user@example.com",
                "given_name": "Example",
                "family_name": "User",
                "bio": "This is a very long biography that contains more than 2048 characters..."
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

## 傳入聯合範例：記錄聯合事件
<a name="aws-lambda-triggers-inbound-federation-example-logging"></a>

此範例說明如何記錄用於監控和偵錯的聯合身分驗證事件。此範例函數會擷取聯合身分使用者及其屬性的詳細資訊，以提供身分驗證程序的可見性。

------
#### [ Node.js ]

```
exports.handler = async (event) => {
    const { providerName, providerType, attributes } = event.request;
    
    // Extract user attributes based on provider type
    let userAttributesFromIdp = {};
    if (providerType === 'SAML') {
        userAttributesFromIdp = attributes.samlResponse || {};
    } else {
        // For OIDC and Social providers, merge userInfo and idToken
        userAttributesFromIdp = {
            ...(attributes.userInfo || {}),
            ...(attributes.idToken || {})
        };
    }
    
    // Log federated authentication details
    console.log(JSON.stringify({
        timestamp: new Date().toISOString(),
        providerName,
        providerType,
        userEmail: userAttributesFromIdp.email,
        attributeCount: Object.keys(userAttributesFromIdp).length,
        attributes: userAttributesFromIdp
    }));
    
    // Pass through all attributes unchanged
    event.response.userAttributesToMap = userAttributesFromIdp;
    return event;
};
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "version": "string",
    "triggerSource": "InboundFederation_ExternalProvider",
    "region": "us-east-1",
    "userPoolId": "us-east-1_XXXXXXXXX",
    "userName": "CorporateAD_john.doe",
    "callerContext": {
        "awsSdkVersion": "string",
        "clientId": "string"
    },
    "request": {
        "providerName": "CorporateAD",
        "providerType": "SAML",
        "attributes": {
            "samlResponse": {
                "email": "john.doe@company.com",
                "given_name": "John",
                "family_name": "Doe",
                "department": "Engineering",
                "employee_id": "EMP12345"
            }
        }
    },
    "response": {
        "userAttributesToMap": {}
    }
}
```

------

預期的 CloudWatch Logs 輸出：

------
#### [ JSON ]

```
{
    "timestamp": "2025-01-14T21:17:40.153Z",
    "providerName": "CorporateAD",
    "providerType": "SAML",
    "userEmail": "john.doe@company.com",
    "attributeCount": 5,
    "attributes": {
        "email": "john.doe@company.com",
        "given_name": "John",
        "family_name": "Doe",
        "department": "Engineering",
        "employee_id": "EMP12345"
    }
}
```

------

# 自訂身分驗證挑戰 Lambda 觸發程序
<a name="user-pool-lambda-challenge"></a>

當您為 Amazon Cognito 使用者集區建置身分驗證流程時，您可能會發現您想要將身分驗證模型延伸到內建流程之外。自訂挑戰觸發程序的一個常見使用案例是實作使用者名稱、密碼和多重要素驗證 (MFA) 以外的其他安全檢查。自訂挑戰是您可以使用 Lambda 支援的程式設計語言產生的任何問題和回應。例如，您可能想要要求使用者先解決 CAPTCHA 或回答安全問題，才能進行身分驗證。另一個潛在需求是整合特殊身分驗證因素或裝置。或者，您可能已經開發了使用硬體安全金鑰或生物識別裝置對使用者進行身分驗證的軟體。自訂挑戰的身分驗證成功定義是 Lambda 函數接受的正確答案：固定字串，例如外部 API 的滿意回應。

您可以使用自訂挑戰開始身分驗證，並完全控制身分驗證程序，或者您可以在應用程式收到自訂挑戰之前執行使用者名稱密碼身分驗證。

自訂身分驗證挑戰 Lambda 觸發條件：

**[定義](user-pool-lambda-define-auth-challenge.md)**  
啟動挑戰序列。決定您是否要啟動新的挑戰、將身分驗證標記為完成，或停止身分驗證嘗試。

**[建立](user-pool-lambda-create-auth-challenge.md)**  
向應用程式發出使用者必須回答的問題。此函數可能會顯示安全問題或 CAPTCHA 的連結，您的應用程式應顯示給您的使用者。

**[驗證](user-pool-lambda-verify-auth-challenge-response.md)**  
知道預期的答案，並將其與應用程式在挑戰回應中提供的答案進行比較。函數可能會呼叫 CAPTCHA 服務的 API，以擷取使用者嘗試解決方案的預期結果。

這三個 Lambda 函數會串連在一起，以呈現完全由您控制且屬於您自己的設計的身分驗證機制。由於自訂身分驗證需要用戶端和 Lambda 函數中的應用程式邏輯，因此您無法在受管登入中處理自訂身分驗證。此身分驗證系統需要額外的開發人員工作。您的應用程式必須使用使用者集區 API 執行身分驗證流程，並使用在自訂身分驗證挑戰中心轉譯問題的自訂建立登入介面來處理產生的挑戰。

![\[挑戰 Lambda 觸發程序\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-challenges.png)


如需實作自訂身分驗證的詳細資訊，請參閱 [自訂身分驗證流程與挑戰](amazon-cognito-user-pools-authentication-flow-methods.md#Custom-authentication-flow-and-challenges)

API 操作 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) 或 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 與 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) 或 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 之間的身分驗證。在此流程中，使用者身分驗證會透過回答連續挑戰，直到驗證失敗或者使用者發出字符為止。挑戰回應可能是新的挑戰。在這種情況下，您的應用程式會視需要回應新挑戰的次數。當定義身分驗證挑戰函數分析目前為止的結果、判斷所有挑戰都已回答，並傳回 時，就會發生身分驗證成功`IssueTokens`。

**Topics**
+ [自訂挑戰流程中的 SRP 身分驗證](#user-pool-lambda-challenge-srp-authentication)
+ [定義驗證挑戰 Lambda 觸發程序](user-pool-lambda-define-auth-challenge.md)
+ [建立驗證挑戰 Lambda 觸發程序](user-pool-lambda-create-auth-challenge.md)
+ [確認驗證挑戰回應 Lambda 觸發程序](user-pool-lambda-verify-auth-challenge-response.md)

## 自訂挑戰流程中的 SRP 身分驗證
<a name="user-pool-lambda-challenge-srp-authentication"></a>

您可以讓 Amazon Cognito 在發出自訂挑戰之前驗證使用者密碼。當您在自訂挑戰流程中執行 SRP 驗證時，會執行[請求率配額](quotas.md#category_operations.title)驗證類別中關聯的任何 Lambda 觸發程序。下列為此程序的概觀：

1. 您的應用程式使用 `AuthParameters` 對應透過呼叫 `InitiateAuth` 或 `AdminInitiateAuth` 啟動登入。參數必須包含 `CHALLENGE_NAME: SRP_A,` 以及 `SRP_A` 和 `USERNAME` 的值。

1. Amazon Cognito 以包含 `challengeName: SRP_A` 和 `challengeResult: true` 初始工作階段，叫用您的定義驗證挑戰 Lambda 觸發程序。

1. 收到這些輸入後，您的 Lambda 函數會以 `challengeName: PASSWORD_VERIFIER`、`issueTokens: false`、`failAuthentication: false` 回應。

1. 如果密碼驗證成功，Amazon Cognito 會再次以包含 `challengeName: PASSWORD_VERIFIER` 和 `challengeResult: true` 的新工作階段，叫用您的 Lambda 函數。

1. 您的 Lambda 函數會以 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 回應，啟動您的自訂挑戰。如果您不想透過密碼驗證開始自訂驗證流程，您可以使用 `AuthParameters` 對應 (包括 `CHALLENGE_NAME: CUSTOM_CHALLENGE`) 啟動登入。

1. 除非已回答所有挑戰，否則挑戰迴圈會不斷重複。

以下是在具有 SRP 流程的自訂身分驗證之前啟動`InitiateAuth`請求的範例。

```
{
    "AuthFlow": "CUSTOM_AUTH",
    "ClientId": "1example23456789",
    "AuthParameters": {
        "CHALLENGE_NAME": "SRP_A",
        "USERNAME": "testuser",
        "SRP_A": "[SRP_A]",
        "SECRET_HASH": "[secret hash]"
    }
}
```

### 自訂身分驗證 SRP 流程中的密碼重設
<a name="user-pool-lambda-challenge-force-password-change"></a>

當使用者處於 `FORCE_CHANGE_PASSWORD` 狀態時，您的自訂身分驗證流程必須整合密碼變更步驟，同時保持身分驗證挑戰的完整性。Amazon Cognito [會在挑戰期間調用您的定義身分驗證](user-pool-lambda-define-auth-challenge.md)`NEW_PASSWORD_REQUIRED`挑戰 Lambda 觸發條件。在此案例中，使用自訂挑戰流程和 SRP 身分驗證登入的使用者如果處於密碼重設狀態，則可以設定新密碼。

當使用者處於 `RESET_REQUIRED`或 `FORCE_CHANGE_PASSWORD` 狀態時，他們必須使用 [回應](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html#API_RespondToAuthChallenge_RequestParameters)`NEW_PASSWORD_REQUIRED`挑戰`NEW_PASSWORD`。在搭配 SRP 的自訂身分驗證中，Amazon Cognito 會在使用者完成 SRP `NEW_PASSWORD_REQUIRED`挑戰後傳回`PASSWORD_VERIFIER`挑戰。您的定義身分驗證挑戰觸發會在`session`陣列中接收兩個挑戰結果，並在使用者成功變更密碼後繼續進行其他自訂挑戰。

您的定義驗證挑戰 Lambda 觸發程序必須透過 SRP 身分驗證、密碼重設和後續自訂挑戰來管理挑戰序列。觸發會在 `session` 參數中收到一系列已完成的挑戰，包括 `PASSWORD_VERIFIER`和 `NEW_PASSWORD_REQUIRED`結果。如需實作範例，請參閱 [定義驗證挑戰範例](user-pool-lambda-define-auth-challenge.md#aws-lambda-triggers-define-auth-challenge-example)。

#### 身分驗證流程步驟
<a name="user-pool-lambda-challenge-password-flow-steps"></a>

對於需要在自訂挑戰之前驗證其密碼的使用者，程序遵循下列步驟：

1. 您的應用程式使用 `AuthParameters` 對應透過呼叫 `InitiateAuth` 或 `AdminInitiateAuth` 啟動登入。參數必須包含 `CHALLENGE_NAME: SRP_A`、 和 `SRP_A`和 的值`USERNAME`。

1. Amazon Cognito 以包含 `challengeName: SRP_A` 和 `challengeResult: true` 初始工作階段，叫用您的定義驗證挑戰 Lambda 觸發程序。

1. 收到這些輸入後，您的 Lambda 函數會以 `challengeName: PASSWORD_VERIFIER`、`issueTokens: false`、`failAuthentication: false` 回應。

1. 如果密碼驗證成功，會發生以下兩種情況之一：  
**對於處於正常狀態的使用者：**  
Amazon Cognito 會使用包含 `challengeName: PASSWORD_VERIFIER`和 的新工作階段再次調用 Lambda 函數`challengeResult: true`。  
您的 Lambda 函數會以 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 回應，啟動您的自訂挑戰。  
**對於處於 `RESET_REQUIRED`或 `FORCE_CHANGE_PASSWORD` 狀態的使用者：**  
Amazon Cognito 會使用包含 `challengeName: PASSWORD_VERIFIER`和 的工作階段來叫用 Lambda 函數`challengeResult: true`。  
您的 Lambda 函數應以 `challengeName: NEW_PASSWORD_REQUIRED`、`issueTokens: false` 和 `failAuthentication: false` 回應。  
成功變更密碼後，Amazon Cognito 會使用包含 `PASSWORD_VERIFIER`和 `NEW_PASSWORD_REQUIRED`結果的工作階段來叫用 Lambda 函數。  
您的 Lambda 函數會以 `challengeName: CUSTOM_CHALLENGE`、`issueTokens: false` 和 `failAuthentication: false` 回應，啟動您的自訂挑戰。

1. 除非已回答所有挑戰，否則挑戰迴圈會不斷重複。

如果您不想透過密碼驗證開始自訂驗證流程，您可以使用 `AuthParameters` 對應 (包括 `CHALLENGE_NAME: CUSTOM_CHALLENGE`) 啟動登入。

#### 工作階段管理
<a name="user-pool-lambda-challenge-session-management"></a>

身分驗證流程會透過一系列工作階段 IDs和挑戰結果來維持工作階段連續性。每個挑戰回應都會產生新的工作階段 ID，以防止工作階段重複使用錯誤，這對多重驗證流程特別重要。

挑戰結果會依時間順序儲存在 Lambda 觸發器收到的工作階段陣列中。對於處於 `FORCE_CHANGE_PASSWORD` 狀態的使用者，工作階段陣列包含：

1. `session[0]` - 初始`SRP_A`挑戰

1. `session[1]` - `PASSWORD_VERIFIER`結果

1. `session[2]` - `NEW_PASSWORD_REQUIRED`結果

1. 後續元素 - 其他自訂挑戰的結果

#### 範例身分驗證流程
<a name="user-pool-lambda-challenge-example-flow"></a>

下列範例示範`FORCE_CHANGE_PASSWORD`狀態為 必須同時完成密碼變更和自訂 CAPTCHA 挑戰之使用者的完整自訂身分驗證流程。

1. **InitiateAuth 請求**

   ```
   {
       "AuthFlow": "CUSTOM_AUTH",
       "ClientId": "1example23456789",
       "AuthParameters": {
           "CHALLENGE_NAME": "SRP_A",
           "USERNAME": "testuser",
           "SRP_A": "[SRP_A]"
       }
   }
   ```

1. **InitiateAuth 回應**

   ```
   {
       "ChallengeName": "PASSWORD_VERIFIER",
       "ChallengeParameters": {
           "USER_ID_FOR_SRP": "testuser"
       },
       "Session": "[session_id_1]"
   }
   ```

1. **使用 的 RespondToAuthChallenge 請求 `PASSWORD_VERIFIER`**

   ```
   {
       "ChallengeName": "PASSWORD_VERIFIER",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "PASSWORD_CLAIM_SIGNATURE": "[claim_signature]",
           "PASSWORD_CLAIM_SECRET_BLOCK": "[secret_block]",
           "TIMESTAMP": "[timestamp]",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_1]"
   }
   ```

1. **RespondToAuthChallenge 回應與`NEW_PASSWORD_REQUIRED`挑戰**

   ```
   {
       "ChallengeName": "NEW_PASSWORD_REQUIRED",
       "ChallengeParameters": {},
       "Session": "[session_id_2]"
   }
   ```

1. **使用 的 RespondToAuthChallenge 請求 `NEW_PASSWORD_REQUIRED`**

   ```
   {
       "ChallengeName": "NEW_PASSWORD_REQUIRED",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "NEW_PASSWORD": "[password]",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_2]"
   }
   ```

1. **使用 CAPTCHA 自訂挑戰的 RespondToAuthChallenge 回應**

   ```
   {
       "ChallengeName": "CUSTOM_CHALLENGE",
       "ChallengeParameters": {
           "captchaUrl": "url/123.jpg"
       },
       "Session": "[session_id_3]"
   }
   ```

1. **RespondToAuthChallenge 請求與 CAPTCHA 自訂挑戰的答案**

   ```
   {
       "ChallengeName": "CUSTOM_CHALLENGE",
       "ClientId": "1example23456789",
       "ChallengeResponses": {
           "ANSWER": "123",
           "USERNAME": "testuser"
       },
       "Session": "[session_id_3]"
   }
   ```

**6. 最終成功回應**

```
{
    "AuthenticationResult": {
        "AccessToken": "eyJra456defEXAMPLE",
        "ExpiresIn": 3600,
        "IdToken": "eyJra789ghiEXAMPLE",
        "RefreshToken": "eyJjd123abcEXAMPLE",
        "TokenType": "Bearer"
    },
    "ChallengeParameters": {}
}
```

# 定義驗證挑戰 Lambda 觸發程序
<a name="user-pool-lambda-define-auth-challenge"></a>

定義身分驗證挑戰觸發是 Lambda 函數，可在自訂身分驗證流程中維護挑戰序列。它宣告挑戰序列成功或失敗，並在序列尚未完成時設定下一個挑戰。

![\[挑戰 Lambda 觸發程序\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-challenges1.png)


**定義身分驗證挑戰**  
 Amazon Cognito 會叫用此觸發程序來啟動[自訂身分驗證流程](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow)。

此 Lambda 觸發程序的請求包含 `session`。`session` 參數是一個陣列，其中包含目前身分驗證程序期間向使用者提出的所有挑戰。該要求也包含對應的結果。`session` 陣列依照時間順序存放挑戰詳細內容 (`ChallengeResult`)。挑戰 `session[0]` 代表使用者收到的第一個挑戰。

**Topics**
+ [定義驗證挑戰 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-define-auth-challenge)
+ [定義驗證挑戰範例](#aws-lambda-triggers-define-auth-challenge-example)

## 定義驗證挑戰 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
                . . .
        },
        "session": [
            ChallengeResult,
            . . .
        ],
        "clientMetadata": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {
        "challengeName": "string",
        "issueTokens": boolean,
        "failAuthentication": boolean
    }
}
```

------

### 定義驗證挑戰請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge-request"></a>

 當 Amazon Cognito 叫用您的 Lambda 函數時，Amazon Cognito 會提供以下參數：

**userAttributes**  
代表使用者屬性的一或多組名稱/值。

**userNotFound**  
當您的使用者集區用戶端的 `PreventUserExistenceErrors` 設定為 `ENABLED` 時，Amazon Cognito 將會填入的布林值。值 `true` 表示使用者 ID (使用者名稱、電子郵件地址和其他詳細資訊) 與任何現有使用者不相符。當 `PreventUserExistenceErrors` 設定為 `ENABLED`，該服務不會通知應用程式有不存在的使用者。我們建議您的 Lambda 函數維持相同的使用者體驗並考慮延遲。如此一來，當使用者存在或不存在時，呼叫者無法偵測到不同的行為。

**工作階段**  
`ChallengeResult` 元素的陣列。每個都包含下列元素：    
**challengeName**  
下列挑戰類型之一：`CUSTOM_CHALLENGE`、`SRP_A`、`PASSWORD_VERIFIER`、`SMS_MFA`、`EMAIL_OTP``SOFTWARE_TOKEN_MFA`、`DEVICE_SRP_AUTH`、`DEVICE_PASSWORD_VERIFIER`、 或 `ADMIN_NO_SRP_AUTH`。  
當您定義驗證挑戰函式為已設定多重要素驗證的使用者發出`PASSWORD_VERIFIER`挑戰時，Amazon Cognito 會追蹤 `SMS_MFA`、 `EMAIL_OTP`或 `SOFTWARE_TOKEN_MFA`挑戰。這些是多重要素驗證碼的提示。在您的 函數中，包含處理來自 `SMS_MFA`、 `EMAIL_OTP`和 `SOFTWARE_TOKEN_MFA`挑戰的輸入事件。您不需要在定義驗證挑戰函數中叫用任何 MFA 挑戰。  
當您的函數正在確定使用者是否成功驗證，以及是否該發出權杖時，請務必檢查您定義驗證挑戰函數中的 `challengeName`，並且驗證是否與期望值相符。  
**challengeResult**  
如果使用者順利完成挑戰，則設定為 `true`，否則設定為 `false`。  
**challengeMetadata**  
您的自訂挑戰名稱。唯有在 `challengeName` 為 `CUSTOM_CHALLENGE` 時使用。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於定義驗證挑戰觸發程序所指定。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 操作中的 `ClientMetadata` 參數。叫用定義驗證挑戰函數的請求不包含傳遞至 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作的 ClientMetadata 參數中的資料。

### 定義驗證挑戰回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-define-auth-challenge-response"></a>

在回應中，您可以傳回身分驗證程序的下一個階段。

**challengeName**  
包含下一個挑戰名稱的字串。如果您想要向使用者提出新的挑戰，請在這裡指定挑戰名稱。

**issueTokens**  
如果您判斷使用者已完成身分驗證挑戰，請設定為 `true`。如果使用者未成功完成挑戰，請設定為 `false`。

**failAuthentication**  
如果您要結束目前的身分驗證程序，請設定為 `true`。若要繼續目前的身分驗證程序，請設定為 `false`。

## 定義驗證挑戰範例
<a name="aws-lambda-triggers-define-auth-challenge-example"></a>

此範例會定義一系列用來進行身分驗證的挑戰，且唯有在使用者完成所有挑戰時，才會發出權杖。當使用者使用 `SRP_A`和 `PASSWORD_VERIFIER`挑戰完成 SRP 身分驗證時，此函數`CUSTOM_CHALLENGE`會將叫用建立身分驗證挑戰觸發條件的 傳遞給他們。結合我們的[建立身分驗證挑戰範例](user-pool-lambda-create-auth-challenge.md#aws-lambda-triggers-create-auth-challenge-example)，此序列為挑戰 3 提供 CAPTCHA 挑戰，並為挑戰 4 提供安全問題。

使用者解決 CAPTCHA 並回答安全問題後，此函數會確認您的使用者集區可以發出權杖。不需要 SRP 身分驗證；您也可以將 CAPTCHA 和安全問題設定為挑戰一和挑戰二。如果您的定義身分驗證挑戰函數未宣告 SRP 挑戰，則使用者的成功完全取決於其對自訂提示的回應。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (
    event.request.session.length === 1 &&
    event.request.session[0].challengeName === "SRP_A"
  ) {
    event.response.issueTokens = false;
    event.response.failAuthentication = false;
    event.response.challengeName = "PASSWORD_VERIFIER";
  } else if (
    event.request.session.length === 2 &&
    event.request.session[1].challengeName === "PASSWORD_VERIFIER" &&
    event.request.session[1].challengeResult === true
  ) {
    event.response.issueTokens = false;
    event.response.failAuthentication = false;
    event.response.challengeName = "CUSTOM_CHALLENGE";
  } else if (
    event.request.session.length === 3 &&
    event.request.session[2].challengeName === "CUSTOM_CHALLENGE" &&
    event.request.session[2].challengeResult === true
  ) {
    event.response.issueTokens = false;
    event.response.failAuthentication = false;
    event.response.challengeName = "CUSTOM_CHALLENGE";
  } else if (
    event.request.session.length === 4 &&
    event.request.session[3].challengeName === "CUSTOM_CHALLENGE" &&
    event.request.session[3].challengeResult === true
  ) {
    event.response.issueTokens = true;
    event.response.failAuthentication = false;
  } else {
    event.response.issueTokens = false;
    event.response.failAuthentication = true;
  }

  return event;
};

export { handler };
```

------

# 建立驗證挑戰 Lambda 觸發程序
<a name="user-pool-lambda-create-auth-challenge"></a>

建立身分驗證挑戰觸發程序是一種 Lambda 函數，具有定義身分驗證挑戰觸發程序所宣告之每個挑戰的詳細資訊。它會處理定義身分驗證挑戰觸發程序宣告的挑戰名稱`publicChallengeParameters`，並傳回應用程式必須呈現給使用者的 。然後`privateChallengeParameters`，此函數為您的使用者集區提供使用者集區傳遞給驗證身分驗證挑戰觸發條件之挑戰 的答案。如果您的定義身分驗證挑戰觸發程序管理挑戰序列，您的建立身分驗證挑戰觸發程序會管理挑戰內容。

![\[挑戰 Lambda 觸發程序\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-challenges2.png)


**建立身分驗證挑戰**  
如果自訂挑戰已指定為 **Define Auth Challenge (定義驗證挑戰)** 觸發程序的一部分，Amazon Cognito 就會在 **Define Auth Challenge (定義驗證挑戰)** 之後叫用此觸發程序。它會建立[自訂身分驗證流程](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow)。

叫用此 Lambda 觸發程序可以建立要向使用者提出的挑戰。此 Lambda 觸發程序的請求包含 `challengeName` 和 `session`。`challengeName`是要向使用者提出之下一個挑戰的名稱字串。此屬性的值是設定在「定義驗證挑戰 Lambda 觸發程序」中。

除非所有挑戰都已回答，否則挑戰迴圈會不斷重複。

**Topics**
+ [建立驗證挑戰 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-create-auth-challenge)
+ [建立驗證挑戰範例](#aws-lambda-triggers-create-auth-challenge-example)

## 建立驗證挑戰 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-create-auth-challenge"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "challengeName": "string",
        "session": [
            ChallengeResult,
            . . .
        ],
        "clientMetadata": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {
        "publicChallengeParameters": {
            "string": "string",
            . . .
        },
        "privateChallengeParameters": {
            "string": "string",
            . . .
        },
        "challengeMetadata": "string"
    }
}
```

------

### 建立驗證挑戰請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-create-auth-challenge-request"></a>

**userAttributes**  
代表使用者屬性的一或多組名稱/值。

**userNotFound**  
當您的使用者集區用戶端的 `PreventUserExistenceErrors` 設定為 `ENABLED` 時，將會填入此布林值。

**challengeName**  
新挑戰的名稱。

**工作階段**  
工作階段元素是 `ChallengeResult`元素陣列，每個陣列都包含下列元素：    
**challengeName**  
挑戰類型。其中之一：`"CUSTOM_CHALLENGE"`、`"PASSWORD_VERIFIER"`、`"SMS_MFA"`、`"DEVICE_SRP_AUTH"`、`"NEW_PASSWORD_REQUIRED"`、 `"DEVICE_PASSWORD_VERIFIER"`或 `"ADMIN_NO_SRP_AUTH"`。  
**challengeResult**  
如果使用者順利完成挑戰，則設定為 `true`，否則設定為 `false`。  
**challengeMetadata**  
您的自訂挑戰名稱。唯有在 `challengeName` 為 `"CUSTOM_CHALLENGE"` 時使用。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於建立驗證挑戰觸發程序所指定。您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 動作中的 ClientMetadata 參數，將此資料傳遞至您的 Lambda 函數。叫用建立身分驗證挑戰函數的請求不包含傳遞至 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作的 ClientMetadata 參數中的資料。

### 建立驗證挑戰回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-create-auth-challenge-response"></a>

**publicChallengeParameters**  
可讓用戶端應用程式用在要向使用者提出的挑戰中的一或多個鍵值組。此參數應包含所有必要資訊，以準確地向使用者提出挑戰。

**privateChallengeParameters**  
此參數僅供「確認驗證挑戰回應 Lambda 觸發程序」使用。此參數應包含驗證使用者對挑戰的回應時，所有必要的資訊。換言之，`publicChallengeParameters`參數包含向使用者提出的問題，而 `privateChallengeParameters` 包含問題的有效答案。

**challengeMetadata**  
您的自訂挑戰名稱 (如果這是自訂挑戰)。

## 建立驗證挑戰範例
<a name="aws-lambda-triggers-create-auth-challenge-example"></a>

此函數有兩個自訂挑戰，對應到[定義身分驗證挑戰範例中](user-pool-lambda-define-auth-challenge.md#aws-lambda-triggers-define-auth-challenge-example)的挑戰序列。前兩個挑戰是 SRP 身分驗證。對於第三個挑戰，此函數會在挑戰回應中傳回 CAPTCHA URL 到您的應用程式。您的應用程式會在指定的 URL 轉譯 CAPTCHA，並傳回使用者的輸入。CAPTCHA 影像的 URL 會以 "`captchaUrl`" 新增至公有挑戰參數，而預期的答案會新增至私有挑戰參數。

對於第四個挑戰，此函數會傳回安全性問題。您的應用程式會呈現問題，並提示使用者回答。使用者解決這兩個自訂挑戰後，定義身分驗證挑戰觸發程序會確認您的使用者集區可以發出權杖。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.request.challengeName !== "CUSTOM_CHALLENGE") {
    return event;
  }

  if (event.request.session.length === 2) {
    event.response.publicChallengeParameters = {};
    event.response.privateChallengeParameters = {};
    event.response.publicChallengeParameters.captchaUrl = "url/123.jpg";
    event.response.privateChallengeParameters.answer = "5";
  }

  if (event.request.session.length === 3) {
    event.response.publicChallengeParameters = {};
    event.response.privateChallengeParameters = {};
    event.response.publicChallengeParameters.securityQuestion =
      "Who is your favorite team mascot?";
    event.response.privateChallengeParameters.answer = "Peccy";
  }

  return event;
};

export { handler };
```

------

# 確認驗證挑戰回應 Lambda 觸發程序
<a name="user-pool-lambda-verify-auth-challenge-response"></a>

驗證身分驗證挑戰觸發程序是一種 Lambda 函數，可將使用者提供的回應與已知答案進行比較。此函數會告知使用者集區使用者是否正確回答挑戰。當驗證身分驗證挑戰觸發條件以 `answerCorrect`的 回應時`true`，身分驗證序列可以繼續。

![\[挑戰 Lambda 觸發程序\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/images/lambda-challenges3.png)


**驗證身分驗證挑戰回應**  
Amazon Cognito 會叫用此觸發程序來驗證使用者對自訂驗證挑戰的回應是否有效。這屬於使用者集區[自訂身分驗證流程](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html#amazon-cognito-user-pools-custom-authentication-flow)的一部分。

此觸發程序的請求包含 `privateChallengeParameters`和 `challengeAnswer` 參數。「建立驗證挑戰 Lambda 觸發程序」傳回 `privateChallengeParameters` 值，其中包含預期的使用者回應。`challengeAnswer`參數包含使用者對挑戰的回應。

回應包含 `answerCorrect` 屬性。如果使用者成功完成挑戰，Amazon Cognito 會將屬性值設定為 `true`。如果使用者未能成功完成挑戰，Amazon Cognito 會將此值設定為 `false`。

除非使用者已回答所有挑戰，否則挑戰迴圈會不斷重複。

**Topics**
+ [確認驗證挑戰 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-verify-auth-challenge)
+ [確認驗證挑戰回應範例](#aws-lambda-triggers-verify-auth-challenge-response-example)

## 確認驗證挑戰 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-verify-auth-challenge"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "privateChallengeParameters": {
            "string": "string",
            . . .
        },
        "challengeAnswer": "string",
        "clientMetadata": {
            "string": "string",
            . . .
        },
        "userNotFound": boolean
    },
    "response": {
        "answerCorrect": boolean
    }
}
```

------

### 確認驗證挑戰請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-verify-auth-challenge-request"></a>

**userAttributes**  
此參數包含代表使用者屬性的一或多個名稱/值對。

**userNotFound**  
當 Amazon Cognito 將您的使用者集區用戶端的 `PreventUserExistenceErrors` 設定為 `ENABLED` 時，Amazon Cognito 會填入此布林值。

**privateChallengeParameters**  
此參數來自建立身分驗證挑戰觸發程序。為了確定使用者是否已通過挑戰，Amazon Cognito 會將此參數與使用者的 **challengeAnswer** 進行比較。  
此參數包含驗證使用者對挑戰的回應時，所有必要的資訊。此訊息包含亞 Amazon Cognito 向使用者提出的問題 (`publicChallengeParameters`)，以及問題的有效答案 (`privateChallengeParameters`)。只有「確認身分驗證挑戰回應 Lambda 觸發程序」會使用此參數。

**challengeAnswer**  
此參數值是使用者對挑戰回應的答案。

**clientMetadata**  
此參數包含您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於確認身分驗證挑戰觸發程序所指定。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 操作中的 ClientMetadata 參數。Amazon Cognito 不包含其傳遞至確認身分驗證挑戰函數之請求中的 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作中的 ClientMetadata 參數的資料。

### 確認驗證挑戰回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-verify-auth-challenge-response"></a>

**answerCorrect**  
如果使用者成功完成挑戰，Amazon Cognito 會將此參數設定為 `true`。如果使用者未能成功完成挑戰，Amazon Cognito 會將此參數設定為 `false`。

## 確認驗證挑戰回應範例
<a name="aws-lambda-triggers-verify-auth-challenge-response-example"></a>

此驗證驗證挑戰函數會檢查使用者對挑戰的回應是否符合預期的回應。使用者的答案是由您應用程式的輸入定義，而偏好的答案是由建立[身分驗證挑戰觸發](user-pool-lambda-create-auth-challenge.md#aws-lambda-triggers-create-auth-challenge-example)回應的回應`privateChallengeParameters.answer`中定義的。正確答案和指定的答案都是此函數輸入事件的一部分。

在此範例中，如果使用者的回應符合預期的回應，Amazon Cognito 會將 `answerCorrect` 參數設定為 `true`。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (
    event.request.privateChallengeParameters.answer ===
    event.request.challengeAnswer
  ) {
    event.response.answerCorrect = true;
  } else {
    event.response.answerCorrect = false;
  }

  return event;
};

export { handler };
```

------

# 產生權杖前 Lambda 觸發程序
<a name="user-pool-lambda-pre-token-generation"></a>

由於 Amazon Cognito 會在產生權杖之前叫用此觸發程序，因此您可以自訂使用者集區的權杖宣告。透過第一版或 `V1_0` 預先產生權杖觸發事件的**基本功能**，您可以自訂身份 (ID) 權杖。在具有 Essentials 或 Plus 功能計劃的使用者集區中，您可以使用存取權杖自訂產生第 2 版或`V2_0`觸發事件，以及針對machine-to-machine(M2M) 用戶端憑證授予使用存取權杖自訂產生第 3 版或`V3_0`觸發事件。

Amazon Cognito 會將 `V1_0` 事件作為請求傳送至您的函數，其中包含會寫入 ID 權杖的資料。`V2_0` 或 `V3_0`事件是單一請求，其中包含 Amazon Cognito 將寫入身分和存取字符的資料。若要自訂這兩個權杖，您必須更新函數以使用觸發程序第 2 版或第 3 版，並在相同的回應中傳送這兩個權杖的資料。

Amazon Cognito 會將第 2 版事件回應套用至從使用者身分驗證存取字符，其中人工使用者已將登入資料提供給您的使用者集區。第 3 版事件回應適用於來自使用者身分驗證和機器身分驗證的存取權杖，其中自動化系統會使用應用程式用戶端秘密授權存取權杖請求。除了產生的存取權杖之外，第 2 版和第 3 版的事件是相同的。

在 Amazon Cognito 將權杖發佈到您的應用程式之前，此 Lambda 觸發程序可以新增、移除和修改身分與存取權杖中的某些宣告。若要使用此功能，請從 Amazon Cognito 使用者集區主控台來連結一個 Lambda 函數，或是透過 AWS Command Line Interface (AWS CLI) 來更新您的使用者集區 `LambdaConfig`。

## 活動版本
<a name="user-pool-lambda-pre-token-generation-event-versions"></a>

您的使用者集區可以將不同版本的權杖產生前觸發事件交付至 Lambda 函數。`V1_0` 觸發會交付參數以修改 ID 字符。`V2_0` 或 `V3_0`觸發器會交付下列項目的參數。

1. `V1_0` 觸發的函數。

1. 自訂存取權杖的功能。

1. 將複雜資料類型傳遞至 ID 和存取權杖宣告值的能力：
   + String
   + 數字
   + Boolean
   + 字串、數字、布林值或任何這些值的組合陣列
   + JSON

**注意**  
在 ID 字符中，您可以將複雜的物件填入宣告值，但 `phone_number_verified`、`updated_at`、 `email_verified`和 除外`address`。

使用者集區預設會交付`V1_0`事件。若要將使用者集區設定為傳送`V2_0`事件，請在 Amazon Cognito 主控台中設定觸發時，為使用者身分選擇基本功能的觸發**事件版本** \$1 存取權杖自訂。 ****若要產生`V3_0`事件，請選擇****基本功能 \$1 使用者和機器身分的存取權杖自訂****。您也可以在 [UpdateUserPool ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) 或 [CreateUserPool ](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html) API 請求`LambdaVersion`的 [LambdaConfig](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html#CognitoUserPools-UpdateUserPool-request-LambdaConfig) 參數中設定 的值。事件版本 1、2 和 3 可在 **Essentials** 和 **Plus** 功能計劃中使用。第 3 版事件的 M2M 操作具有與每月作用中使用者 (MAU) 公式不同的定價結構。如需詳細資訊，請參閱 [Amazon Cognito 定價](https://aws.amazon.com/cognito/pricing/)。

**注意**  
在 2024 年 11 月 22 日或之前在 1800 GMT 使用**進階安全功能**選項操作的使用者集區，以及保留在 **Lite** 功能層的使用者集區，可以存取事件版本一和兩個產生權杖前觸發。此舊版中*沒有*進階安全功能的使用者集區可存取事件版本 1。第 3 版*僅適用於* Essentials 和 Plus。

## 宣告和範圍參考
<a name="user-pool-lambda-pre-token-generation-excluded-claims"></a>

Amazon Cognito 限制您可以在存取權和身分權杖中新增、修改或隱藏的宣告和範圍。下表說明 Lambda 函數可以和無法修改的宣告，以及影響宣告存在或值的觸發事件參數。


| 取得 | 預設字符類型 | 可以新增 嗎？ | 可以修改嗎？ | 可以隱藏嗎？ | 事件參數 - 新增或修改 | 事件參數 - 抑制 | 身分類型 | 事件版本 | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 不在使用者集區字符結構描述中的任何宣告 | 無 | 是 | 是 | N/A | claimsToAddOrOverride | claimsToSuppress | 使用者、機器[1](#cognito-pretoken-machine-ids-tier-note) | 全部[2](#cognito-pretoken-id-access-versions-note) | 
| scope | 存取 | 是 | 是 | 是 | scopesToAdd | scopesToSuppress | 使用者、機器[1](#cognito-pretoken-machine-ids-tier-note) | v2\$10, v3\$10 | 
| cognito:groups | ID、存取 | 是 | 是 | 是 | groupsToOverride | claimsToSuppress | 使用者 | 全部[2](#cognito-pretoken-id-access-versions-note) | 
| cognito:preferred\$1role | ID | 是 | 是 | 是 | preferredRole | claimsToSuppress[3](#cognito-pretoken-suppress-groups-note) | 使用者 | 全部 | 
| cognito:roles | ID | 是 | 是 | 是 | iamRolesToOverride | claimsToSuppress[3](#cognito-pretoken-suppress-groups-note) | 使用者 | 全部 | 
| cognito:username | ID | 否 | 否 | 否 | N/A | N/A | 使用者 | N/A | 
| 具有cognito:字首的任何其他宣告 | 無 | 否 | 否 | 否 | N/A | N/A | N/A | N/A | 
| username | 存取 | 否 | 否 | 否 | N/A | N/A | 使用者 | v2\$10, v3\$10 | 
| sub | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者 | N/A | 
| 標準 OIDC 屬性 | ID | 是 | 是 | 是 | claimsToAddOrOverride | claimsToSuppress | 使用者 | 全部 | 
| custom: 屬性 | ID | 是 | 是 | 是 | claimsToAddOrOverride | claimsToSuppress | 使用者 | 全部 | 
| dev: 屬性 | ID | 否 | 否 | 是 | N/A | claimsToSuppress | 使用者 | 全部 | 
| identities | ID | 否 | 否 | 否 | N/A | N/A | 使用者 | N/A | 
| aud[4](#cognito-pretoken-aud-note) | ID | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| client\$1id | 存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| event\$1id | 存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| device\$1key | 存取 | 否 | 否 | 否 | N/A | N/A | 使用者 | N/A | 
| version | 存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| acr | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| amr | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| at\$1hash | ID | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| auth\$1time | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| azp | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| exp | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| iat | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| iss | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| jti | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| nbf | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| nonce | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| origin\$1jti | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 
| token\$1use | ID、存取 | 否 | 否 | 否 | N/A | N/A | 使用者、機器 | N/A | 

 1 機器身分的存取字符僅適用於觸發器輸入事件`v3_0`的 。事件第 3 版僅適用於 **Essentials** 和 **Plus** 功能層。**Lite** 層上的使用者集區可以接收`v1_0`事件。**Lite** 層上具有進階安全功能的使用者集區可以接收 `v1_0`和 `v2_0`事件。

2 將您的權杖產生前觸發條件設定為僅限 `v1_0` ID 權杖的事件版本，`v2_0`適用於 ID 和存取權杖，`v3_0`適用於具有機器身分功能的 ID 和存取權杖。

 3 若要隱藏 `cognito:preferred_role`和 `cognito:roles`宣告，請將 `cognito:groups`新增至 `claimsToSuppress`。

 4 您可以新增 `aud`宣告來存取字符，但其值必須符合目前工作階段的應用程式用戶端 ID。您可以從 `event.callerContext.clientId` 的請求事件中中衍生出用戶端 ID。

## 自訂身分權杖
<a name="user-pool-lambda-pre-token-generation-idtoken"></a>

透過產生字符前 Lambda 觸發程序的所有事件版本，您可以從使用者集區自訂身分 (ID) 字符的內容。ID 權杖提供來自受信任身分來源的使用者屬性，以便登入 Web 或行動應用程式。如需 ID 權杖的詳細資訊，請參閱 [了解身分 (ID) 字符](amazon-cognito-user-pools-using-the-id-token.md)。

產生權杖前 Lambda 觸發程序搭配 ID 權杖的使用方式如下。
+ 在執行階段變更您的使用者從身分集區請求的 IAM 角色。
+ 從外部來源新增使用者屬性。
+ 新增或取代現有的使用者屬性值。
+ 禁止披露使用者屬性，因為使用者的授權範圍以及您授予應用程式用戶端的屬性的讀取存取權限，這些屬性可能會傳遞給您的應用程式。

## 自訂存取權杖
<a name="user-pool-lambda-pre-token-generation-accesstoken"></a>

使用事件版本 2 和三個產生權杖前 Lambda 觸發程序，您可以從使用者集區自訂存取權杖的內容。存取權杖授權使用者從受存取保護的資源 (例如 Amazon Cognito 權杖授權的 API 操作和第三方 API) 擷取資訊。對於具有用戶端憑證授予的machine-to-machine(M2M) 授權，Amazon Cognito 只會在您的使用者集區設定為第 3 版 (`V3_0`) 事件時調用權杖產生前觸發。如需存取權杖的詳細資訊，請參閱 [了解存取權杖](amazon-cognito-user-pools-using-the-access-token.md)。

產生權杖前 Lambda 觸發程序搭配存取權杖的使用方式包括下列項目。
+ 在`scope`宣告中新增或隱藏範圍。例如，您可以將範圍新增至僅指派範圍 `aws.cognito.signin.user.admin` 的 Amazon Cognito 使用者集區 API 身份驗證所產生的存取權杖。
+ 變更使用者集區群組中的使用者成員資格。
+ 新增尚未存在於 Amazon Cognito 存取權杖中的宣告。
+ 禁止披露宣告，否則宣告會傳遞給您的應用程式。

若要支援使用者集區中的存取自訂，您必須設定使用者集區以產生觸發請求的更新版本。更新您的使用者集區，如下列流程所示。

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

**若要支援產生權杖前 Lambda 觸發程序中的存取權杖自訂**

1. 前往 [Amazon Cognito 主控台](https://console.aws.amazon.com/cognito/home)，然後選擇 **User Pools** (使用者集區)。

1. 從清單中選擇現有的使用者集區，或[建立使用者集區](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-as-user-directory.html)。

1. 選擇**延伸項目**功能表並尋找 **Lambda 觸發**條件。

1. 新增或編輯**產生權杖前觸發程序**。

1. 在**指派 Lambda 函數**下選擇一個 Lambda 函數。

1. 為**使用者身分選擇基本功能 \$1 存取權杖自訂**的**觸發事件版本**，或**為使用者和機器身分選擇基本功能 \$1 存取權杖自訂**。此設定會更新 Amazon Cognito 傳送至您函數的請求參數，以包含用於存取權杖自訂的欄位。

------
#### [ User pools API ]

**若要支援產生權杖前 Lambda 觸發程序中的存取權杖自訂**

產生 [CreateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateUserPool.html) 或 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) API 請求。您必須為不想設定為預設值的所有參數指定一個值。如需詳細資訊，請參閱[更新使用者集區和應用程式用戶端組態](cognito-user-pool-updating.md)。

在請求的 `LambdaVersion` 參數中包含以下內容。`LambdaVersion` 值 `V2_0`會導致您的使用者集區新增參數，並將變更套用至存取權杖。`LambdaVersion` 的值`V3_0`會產生與 相同的事件`V2_0`，但也會導致您的使用者集區將變更**套用至 M2M 存取權杖。若要叫用特定函數版本，請使用 Lambda 函數 ARN，並將函數版本作為 `LambdaArn` 的值。

```
"PreTokenGenerationConfig": { 
   "LambdaArn": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction",
   "LambdaVersion": "V3_0"
},
```

------

**machine-to-machine(M2M) 用戶端登入資料的用戶端中繼資料**  
您可以在 M2M 請求中傳遞[用戶端中繼資料](cognito-user-pools-working-with-lambda-triggers.md#working-with-lambda-trigger-client-metadata)。用戶端中繼資料是來自使用者或應用程式環境的其他資訊，有助於 的結果[產生權杖前 Lambda 觸發程序](#user-pool-lambda-pre-token-generation)。在使用者主體的身分驗證操作中，您可以將用戶端中繼資料傳遞至 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 請求內文中的權杖產生前觸發器。由於應用程式會透過對 的直接請求，為 M2M 執行產生存取字符的流程[權杖端點](token-endpoint.md)，因此具有不同的模型。在用戶端登入資料的字符請求 POST 內文中，將具有用戶端中繼資料物件 URL 編碼 (`x-www-form-urlencoded`) 的 `aws_client_metadata` 參數傳遞至字串。如需請求範例，請參閱 [具有基本授權的用戶端憑證具有 POST 內文授權的用戶端憑證](token-endpoint.md#exchanging-client-credentials-for-an-access-token-in-request-body)。以下是傳遞鍵/值對 的範例參數`{"environment": "dev", "language": "en-US"}`。

```
aws_client_metadata=%7B%22environment%22%3A%20%22dev%22,%20%22language%22%3A%20%22en-US%22%7D
```

**其他資源**
+ [如何在 Amazon Cognito 使用者集區中自訂存取權杖](https://aws.amazon.com/blogs/security/how-to-customize-access-tokens-in-amazon-cognito-user-pools/)

**Topics**
+ [活動版本](#user-pool-lambda-pre-token-generation-event-versions)
+ [宣告和範圍參考](#user-pool-lambda-pre-token-generation-excluded-claims)
+ [自訂身分權杖](#user-pool-lambda-pre-token-generation-idtoken)
+ [自訂存取權杖](#user-pool-lambda-pre-token-generation-accesstoken)
+ [產生權杖前 Lambda 觸發程序來源](#user-pool-lambda-pre-token-generation-trigger-source)
+ [產生權杖前 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-pre-token-generation)
+ [觸發權杖前事件版本二範例：新增和抑制宣告，範圍和群組](#aws-lambda-triggers-pre-token-generation-example-version-2-overview)
+ [權杖產生前事件第 2 版範例：使用複雜物件新增宣告](#aws-lambda-triggers-pre-token-generation-example-version-2-complex-objects)
+ [產生權杖前事件版本一範例：新增宣告及抑制現有宣告](#aws-lambda-triggers-pre-token-generation-version-1-add-claim)
+ [產生權杖前事件版本一範例：修改使用者的群組成員資格](#aws-lambda-triggers-pre-token-generation-version-1-change-group)

## 產生權杖前 Lambda 觸發程序來源
<a name="user-pool-lambda-pre-token-generation-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| TokenGeneration\$1HostedAuth | 從 Amazon Cognito 受管登入頁面進行身分驗證期間呼叫。 | 
| TokenGeneration\$1Authentication | 在使用者身分驗證流程完成之後呼叫。 | 
| TokenGeneration\$1NewPasswordChallenge | 在管理員建立使用者之後呼叫。當使用者必須變更臨時密碼時，會叫用此流程。 | 
| TokenGeneration\$1ClientCredentials | 在 M2M 用戶端憑證授予後呼叫。您的使用者集區只會在您的事件版本為 時傳送此事件V3\$10。 | 
| TokenGeneration\$1AuthenticateDevice | 在使用者裝置的身分驗證結束時呼叫。 | 
| TokenGeneration\$1RefreshTokens | 當使用者嘗試重新整理身分和存取權杖時呼叫。 | 

## 產生權杖前 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。當您將產生權杖前 Lambda 觸發程序新增至使用者集區時，您可以選擇觸發程序版本。此版本決定 Amazon Cognito 是否將請求傳遞至您的 Lambda 函數 以及用於存取權杖自訂的其他參數。

------
#### [ Version one ]

第 1 版權杖可以在 ID 權杖中設定群組成員資格、IAM 角色和新宣告。群組成員資格覆寫也適用於存取權杖中的`cognito:groups`宣告。

```
{
    "request": {
        "userAttributes": {"string": "string"},
        "groupConfiguration": {
                "groupsToOverride": [
                    "string",
                    "string"
                ],
                "iamRolesToOverride": [
                    "string",
                    "string"
                ],
                "preferredRole": "string"
        },
        "clientMetadata": {"string": "string"}
    },
    "response": {
        "claimsOverrideDetails": {
            "claimsToAddOrOverride": {"string": "string"},
            "claimsToSuppress": [
                "string",
                "string"
            ],
            "groupOverrideDetails": {
                "groupsToOverride": [
                    "string",
                    "string"
                ],
                "iamRolesToOverride": [
                    "string",
                    "string"
                ],
                "preferredRole": "string"
            }
        }
    }
}
```

------
#### [ Versions two and three ]

第 2 版和第 3 版請求事件會新增自訂存取權杖的欄位。使用者集區會套用第 3 版事件的變更，以存取機器身分的字符。這些版本也新增對回應物件中複雜`claimsToOverride`資料類型的支援。您的 Lambda 函數可以傳回值為 的下列資料類型`claimsToOverride`：
+ String
+ 數字
+ Boolean
+ 字串、數字、布林值或任何這些值的組合陣列
+ JSON

```
{
    "request": {
        "userAttributes": {
            "string": "string"
        },
        "scopes": ["string", "string"],
        "groupConfiguration": {
            "groupsToOverride": ["string", "string"],
            "iamRolesToOverride": ["string", "string"],
            "preferredRole": "string"
        },
        "clientMetadata": {
            "string": "string"
        }
    },
    "response": {
        "claimsAndScopeOverrideDetails": {
            "idTokenGeneration": {
                "claimsToAddOrOverride": {
                    "string": [accepted datatype]
                },
                "claimsToSuppress": ["string", "string"]
            },
            "accessTokenGeneration": {
                "claimsToAddOrOverride": {
                    "string": [accepted datatype]
                },
                "claimsToSuppress": ["string", "string"],
                "scopesToAdd": ["string", "string"],
                "scopesToSuppress": ["string", "string"]
            },
            "groupOverrideDetails": {
                "groupsToOverride": ["string", "string"],
                "iamRolesToOverride": ["string", "string"],
                "preferredRole": "string"
            }
        }
    }
}
```

------

### 產生權杖前請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation-request"></a>


| 名稱 | 描述 | 最小觸發事件版本 | 
| --- |--- |--- |
| userAttributes |  您的使用者在使用者集區中的設定檔屬性。  | 1 | 
| groupConfiguration |  包含目前群組組態的輸入物件。物件包含 `groupsToOverride`、`iamRolesToOverride` 和 `preferredRole`。  | 1 | 
| groupsToOverride |  您的用戶所屬的[使用者集區](cognito-user-pools-user-groups.md#cognito-user-pools-user-groups.title)。  | 1 | 
| iamRolesToOverride |  您可以將使用者集區群組與 AWS Identity and Access Management (IAM) 角色建立關聯。此元素是使用者所屬群組中所有 IAM 角色的清單。  | 1 | 
| preferredRole |  您可以為使用者集區群組設定[優先順序](cognito-user-pools-user-groups.md#assigning-precedence-values-to-groups.title)。此元素包含 `groupsToOverride` 元素中優先度最高之群組的 IAM 角色名稱。  | 1 | 
| clientMetadata |  針對權杖產生前觸發程序，您可以做為 Lambda 函數的自訂輸入來指定與提供的一個或多個鍵值組。 若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 操作中的 ClientMetadata 參數。Amazon Cognito 不包含來自其傳遞至權杖產生前函數的請求中的 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作中的 `ClientMetadata` 參數的資料。  | 1 | 
| scopes |  存取字符範圍。存取權杖中存在的範圍是使用者請求的使用者集區標準範圍和自訂範圍，以及您授權應用程式用戶端發佈的範圍。  | 2 | 

### 產生權杖前回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-pre-token-generation-response"></a>


| 名稱 | 描述 | 最小觸發事件版本 | 
| --- |--- |--- |
| claimsOverrideDetails | A container for all elements in a V1\$10 trigger event. | 1 | 
| claimsAndScopeOverrideDetails |  或 `V2_0``V3_0`觸發事件中所有元素的容器。  | 2 | 
| idTokenGeneration |  您要在使用者 ID 權杖中覆寫、新增或抑制的宣告。此 ID 字符的父項自訂值只會出現在事件版本 2 及更高版本中，但子元素會出現在版本 1 事件中。  | 2 | 
| accessTokenGeneration |  您想要在使用者的存取權杖中覆寫、新增或抑制的宣告和範圍。此存取字符自訂值的父項只會出現在事件版本 2 及更高版本中。  | 2 | 
| claimsToAddOrOverride |  您要新增或修改的一或多個宣告及其值的映射。對於與群組相關的宣告，請改用 `groupOverrideDetails`。 在事件版本 2 和更新版本中，此元素會出現在 `accessTokenGeneration`和 下`idTokenGeneration`。  | 1[*](#cognito-pretoken-complex-objects-note) | 
| claimsToSuppress |  您希望 Amazon Cognito 抑制的宣告清單。如果您的函數抑制並取代了宣告值，則 Amazon Cognito 將抑制宣告。 在事件版本 2 和更新版本中，此元素會出現在 `accessTokenGeneration`和 下`idTokenGeneration`。  | 1 | 
| groupOverrideDetails |  包含目前群組組態的輸出物件。物件包含 `groupsToOverride`、`iamRolesToOverride` 和`preferredRole`。 您的函數將使用您提供的物件取代 `groupOverrideDetails` 物件。如果您在回應中提供空的或空物件，則 Amazon Cognito 會抑制這些群組。若要將現有群組組態保留原狀，請將請求的 `groupConfiguration` 物件值複製到回應中的 `groupOverrideDetails` 物件。然後將其傳回服務。 Amazon Cognito ID 權杖和存取權杖都包含 `cognito:groups` 宣告。您的 `groupOverrideDetails` 物件取代存取權杖以及 ID 權杖中的 `cognito:groups` 宣告。群組覆寫是第 1 版事件可以對存取字符進行的唯一變更。  | 1 | 
| scopesToAdd |  您要新增至使用者存取字符中`scope`宣告的範圍清單。您無法新增包含一或多個空白字元的範圍值。  | 2 | 
| scopesToSuppress |  您要從使用者存取權杖中的`scope`宣告中移除的範圍清單。  | 2 | 

 \$1 第一版事件的回應物件可以傳回字串。第 2 版和第 3 版事件的回應物件可能會傳回[複雜的物件](#user-pool-lambda-pre-token-generation-event-versions)。

## 觸發權杖前事件版本二範例：新增和抑制宣告，範圍和群組
<a name="aws-lambda-triggers-pre-token-generation-example-version-2-overview"></a>

此範例會對使用者的權杖進行下列修改。

1. 在 ID 權杖中將其 `family_name` 設置為 `Doe`。

1. 防止 `email` 和 `phone_number` 宣告出現在 ID 權杖中。

1. 將其 ID 權杖 `cognito:roles` 宣告設置為 `"arn:aws:iam::123456789012:role\/sns_callerA","arn:aws:iam::123456789012:role\/sns_callerC","arn:aws:iam::123456789012:role\/sns_callerB"`。

1. 將其 ID 權杖 `cognito:preferred_role` 宣告設置為 `arn:aws:iam::123456789012:role/sns_caller`。

1. 將範圍 `openid`、`email` 和 `solar-system-data/asteroids.add` 新增到存取權杖。

1. 抑制存取權杖的範圍 `phone_number` 和 `aws.cognito.signin.user.admin`。移除 `phone_number` 可防止從 `userInfo` 中擷取使用者的電話號碼。移除 `aws.cognito.signin.user.admin` 可防止使用者透過 Amazon Cognito 使用者集區 API 讀取和修改自身設定檔的 API 請求。
**注意**  
如存取權杖中的剩餘範圍包含 `openid` 與至少一個標準範圍，從範圍中刪除 `phone_number` 僅會防止擷取用戶的電話號碼。如需詳細資訊，請參閱[關於範圍](cognito-user-pools-define-resource-servers.md#cognito-user-pools-define-resource-servers-about-scopes)。

1. 將其 ID 和存取權杖 `cognito:groups` 宣告設置為 `"new-group-A","new-group-B","new-group-C"`。

------
#### [ JavaScript ]

```
export const handler = function(event, context) {
  event.response = {
    "claimsAndScopeOverrideDetails": {
      "idTokenGeneration": {
        "claimsToAddOrOverride": {
          "family_name": "Doe"
        },
        "claimsToSuppress": [
          "email",
          "phone_number"
        ]
      },
      "accessTokenGeneration": {
        "scopesToAdd": [
          "openid",
          "email",
          "solar-system-data/asteroids.add"
        ],
        "scopesToSuppress": [
          "phone_number",
          "aws.cognito.signin.user.admin"
        ]
      },
      "groupOverrideDetails": {
        "groupsToOverride": [
          "new-group-A",
          "new-group-B",
          "new-group-C"
        ],
        "iamRolesToOverride": [
          "arn:aws:iam::123456789012:role/new_roleA",
          "arn:aws:iam::123456789012:role/new_roleB",
          "arn:aws:iam::123456789012:role/new_roleC"
        ],
        "preferredRole": "arn:aws:iam::123456789012:role/new_role",
      }
    }
  };
  // Return to Amazon Cognito
  context.done(null, event);
};
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "version": "2",
    "triggerSource": "TokenGeneration_Authentication",
    "region": "us-east-1",
    "userPoolId": "us-east-1_EXAMPLE",
    "userName": "JaneDoe",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "request": {
        "userAttributes": {
            "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
            "cognito:user_status": "CONFIRMED",
            "email_verified": "true",
            "phone_number_verified": "true",
            "phone_number": "+12065551212",
            "family_name": "Zoe",
            "email": "Jane.Doe@example.com"
        },
        "groupConfiguration": {
            "groupsToOverride": ["group-1", "group-2", "group-3"],
            "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1", "arn:aws:iam::123456789012:role/sns_caller2", "arn:aws:iam::123456789012:role/sns_caller3"],
            "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller"]
        },
        "scopes": [
            "aws.cognito.signin.user.admin", "openid", "email", "phone"
        ]
    },
    "response": {
        "claimsAndScopeOverrideDetails": []
    }
}
```

------

## 權杖產生前事件第 2 版範例：使用複雜物件新增宣告
<a name="aws-lambda-triggers-pre-token-generation-example-version-2-complex-objects"></a>

此範例會對使用者的權杖進行下列修改。

1. 將數字、字串、布林值和 JSON 類型的宣告新增至 ID 字符。這是第 2 版觸發事件提供給 ID 字符的唯一變更。

1. 將數字、字串、布林值和 JSON 類型的宣告新增至存取權杖。

1. 將三個範圍新增至存取權杖。

1. 隱藏 ID 和存取權杖中的`email`宣告。

1. 隱藏存取字符中的`aws.cognito.signin.user.admin`範圍。

------
#### [ JavaScript ]

```
export const handler = function(event, context) {

    var scopes = ["MyAPI.read", "MyAPI.write", "MyAPI.admin"]
    var claims = {}
    claims["aud"]= event.callerContext.clientId;
    claims["booleanTest"] = false;
    claims["longTest"] = 9223372036854775807;
    claims["exponentTest"] = 1.7976931348623157E308;
    claims["ArrayTest"] = ["test", 9223372036854775807, 1.7976931348623157E308, true];
    claims["longStringTest"] = "\{\
        \"first_json_block\": \{\
            \"key_A\": \"value_A\",\
            \"key_B\": \"value_B\"\
        \},\
        \"second_json_block\": \{\
            \"key_C\": \{\
                \"subkey_D\": [\
                    \"value_D\",\
                    \"value_E\"\
                ],\
                \"subkey_F\": \"value_F\"\
            \},\
            \"key_G\": \"value_G\"\
        \}\
    \}";
    claims["jsonTest"] = {
    	"first_json_block": {
    		"key_A": "value_A",
    		"key_B": "value_B"
    	},
    	"second_json_block": {
    		"key_C": {
    			"subkey_D": [
    				"value_D",
    				"value_E"
    			],
    			"subkey_F": "value_F"
    		},
    		"key_G": "value_G"
    	}
    };
    event.response = {
        "claimsAndScopeOverrideDetails": {
            "idTokenGeneration": {
                "claimsToAddOrOverride": claims,
                "claimsToSuppress": ["email"]
            },
            "accessTokenGeneration": {
                "claimsToAddOrOverride": claims,
                "claimsToSuppress": ["email"],
                "scopesToAdd": scopes,
                "scopesToSuppress": ["aws.cognito.signin.user.admin"]
            }
        }
    };
    console.info("EVENT response\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v, 2))
    console.info("EVENT response size\n" + JSON.stringify(event, (_, v) => typeof v === 'bigint' ? v.toString() : v).length)
    // Return to Amazon Cognito
    context.done(null, event);
};
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
    "version": "2",
    "triggerSource": "TokenGeneration_HostedAuth",
    "region": "us-west-2",
    "userPoolId": "us-west-2_EXAMPLE",
    "userName": "JaneDoe",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "1example23456789"
    },
    "request": {
        "userAttributes": {
            "sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
            "cognito:user_status": "CONFIRMED"
            "email_verified": "true",
            "phone_number_verified": "true",
            "phone_number": "+12065551212",
            "email": "Jane.Doe@example.com"
        },
        "groupConfiguration": {
            "groupsToOverride": ["group-1", "group-2", "group-3"],
            "iamRolesToOverride": ["arn:aws:iam::123456789012:role/sns_caller1"],
            "preferredRole": ["arn:aws:iam::123456789012:role/sns_caller1"]
        },
        "scopes": [
            "aws.cognito.signin.user.admin",
            "phone",
            "openid",
            "profile",
            "email"
        ]
    },
    "response": {
        "claimsAndScopeOverrideDetails": []
    }
}
```

------

## 產生權杖前事件版本一範例：新增宣告及抑制現有宣告
<a name="aws-lambda-triggers-pre-token-generation-version-1-add-claim"></a>

此範例使用版本 1 觸發事件和「產生權杖前 Lambda 函數」來新增宣告及抑制現有宣告。

------
#### [ Node.js ]

```
const handler = async (event) => {
  event.response = {
    claimsOverrideDetails: {
      claimsToAddOrOverride: {
        my_first_attribute: "first_value",
        my_second_attribute: "second_value",
      },
      claimsToSuppress: ["email"],
    },
  };

  return event;
};

export { handler };
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：由於程式碼 範例 會處理任何請求參數，因此可以使用具有空白請求的測試事件。如需有關常見請求參數的詳細資訊，請參閱 [使用者集區 Lambda 觸發程序事件](cognito-user-pools-working-with-lambda-triggers.md#cognito-user-pools-lambda-trigger-event-parameter-shared)。

------
#### [ JSON ]

```
{
  "request": {},
  "response": {}
}
```

------

## 產生權杖前事件版本一範例：修改使用者的群組成員資格
<a name="aws-lambda-triggers-pre-token-generation-version-1-change-group"></a>

此範例使用版本 1 觸發事件和「產生權杖前 Lambda 函數」來修改使用者的群組成員資格。

------
#### [ Node.js ]

```
const handler = async (event) => {
  event.response = {
    claimsOverrideDetails: {
      groupOverrideDetails: {
        groupsToOverride: ["group-A", "group-B", "group-C"],
        iamRolesToOverride: [
          "arn:aws:iam::XXXXXXXXXXXX:role/sns_callerA",
          "arn:aws:iam::XXXXXXXXX:role/sns_callerB",
          "arn:aws:iam::XXXXXXXXXX:role/sns_callerC",
        ],
        preferredRole: "arn:aws:iam::XXXXXXXXXXX:role/sns_caller",
      },
    },
  };

  return event;
};

export { handler };
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
  "request": {},
  "response": {}
}
```

------

# 遷移使用者 Lambda 觸發程序
<a name="user-pool-lambda-migrate-user"></a>

當使用者使用密碼登入時或在忘記密碼流程時，該使用者不存在於使用者集區中，Amazon Cognito 會叫用此觸發程序。Lambda 函數成功傳回後，Amazon Cognito 會在使用者集區中建立使用者。如需使用使用者遷移 Lambda 觸發程序進行身分驗證流程的詳細資訊，請參閱[透過使用者遷移 Lambda 觸發程序匯入使用者](cognito-user-pools-import-using-lambda.md)。

若要在登入時將使用者從現有使用者目錄遷移至 Amazon Cognito 使用者集區，或在忘記密碼流程時使用此 Lambda 觸發程序。

**Topics**
+ [遷移使用者 Lambda 觸發程序來源](#user-pool-lambda-migrate-user-trigger-source)
+ [遷移使用者 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-user-migration)
+ [範例：搭配現有密碼來遷移使用者](#aws-lambda-triggers-user-migration-example-1)

## 遷移使用者 Lambda 觸發程序來源
<a name="user-pool-lambda-migrate-user-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| UserMigration\$1Authentication[1](#cognito-migrate-user-passwordless-note) | 登入時的使用者遷移。 | 
| UserMigration\$1ForgotPassword | 忘記密碼流程時的使用者遷移。 | 

1 當使用者使用[無密碼登入](amazon-cognito-user-pools-authentication-flow-methods.md#amazon-cognito-user-pools-authentication-flow-methods-passwordless)進行身分驗證時，Amazon Cognito 不會叫用此觸發。

## 遷移使用者 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "userName": "string",
    "request": {
        "password": "string",
        "validationData": {
            "string": "string",
            . . .
        },
        "clientMetadata": {
            "string": "string",
      	. . .
        }
    },
    "response": {
        "userAttributes": {
            "string": "string",
            . . .
        },
        "finalUserStatus": "string",
        "messageAction": "string",
        "desiredDeliveryMediums": [ "string", . . .],
        "forceAliasCreation": boolean,
        "enableSMSMFA": boolean
    }
}
```

------

### 遷移使用者請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration-request"></a>

**使用者名稱**  
使用者在登入時輸入的使用者名稱。

**password**  
使用者在登入時輸入的密碼。Amazon Cognito 不會在由忘記密碼流程啟動的請求中傳送此值。

**validationData**  
一或多個鍵值組，包含使用者登入請求中的驗證資料。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) 和 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) API 動作中的 ClientMetadata 參數。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數用於遷移使用者觸發程序。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html) API 動作中的 ClientMetadata 參數。

### 遷移使用者回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-user-migration-response"></a>

**userAttributes**  
此欄位為必填。  
此欄位必須包含一或多個 Amazon Cognito 存放在您使用者集區中的使用者描述檔中並作為使用者屬性使用的名稱值組。您可以同時包含標準和自訂使用者屬性。自訂屬性需要 `custom:` 字首以便與標準屬性區分。如需詳細資訊，請參閱[自訂屬性](https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-attributes.html#user-pool-settings-custom-attributes.html)。  
若要在忘記密碼流程中重設密碼，使用者必須擁有經驗證的電子郵件地址或經驗證的電話號碼。Amazon Cognito 會將包含重設密碼代碼的訊息，傳送至使用者屬性中的電子郵件地址或電話號碼。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/user-pool-lambda-migrate-user.html)

**finalUserStatus**  
您可以將此參數設定為 `CONFIRMED` 以自動確認您的使用者，如此一來使用者即可使用先前的密碼登入。當您將使用者設定為 `CONFIRMED`，使用者無需進行額外的動作就能登入。如果您沒有將此屬性設定為 `CONFIRMED`，它被設定為 `RESET_REQUIRED`。  
`RESET_REQUIRED` 的 `finalUserStatus` 意味著使用者在登入時必須於遷移後立即變更密碼，並且您的用户端應用程式必須在身分驗證流程中處理 `PasswordResetRequiredException`。  
Amazon Cognito 不會強制執行您在使用 Lambda 觸發程序進行遷移期間為使用者集區設定的密碼強度政策。如果密碼不符合您設定的密碼政策，Amazon Cognito 仍會接受密碼，以便繼續遷移使用者。若要強制執行密碼強度政策，並拒絕不符合政策的密碼，請驗證程式碼中的密碼強度。如果密碼不符合政策，就將 finalUserStatus 設定為 `RESET_REQUIRED`。

**messageAction**  
您可以將此參數設定為 `SUPPRESS` 以拒絕傳送 Amazon Cognito 通常會向新使用者傳送的歡迎訊息。如果您的函數未傳回此參數，Amazon Cognito 會傳送歡迎訊息。

**desiredDeliveryMediums**  
您可以將此參數設定為 `EMAIL` 以透過電子郵件傳送歡迎訊息，或是設為 `SMS` 以透過簡訊傳送歡迎訊息。如果您的函數未傳回此參數，Amazon Cognito 會透過簡訊傳送歡迎訊息。

**forceAliasCreation**  
如果您將此參數設定為 `TRUE`，而 UserAttributes 參數中的電話號碼或電子郵件地址已存在做為不同使用者的別名，則 API 呼叫會將別名從之前的使用者遷移到新建立的使用者。先前的使用者將無法再使用該別名登入。  
如果您將此參數設定為 `FALSE`，而且別名已存在，Amazon Cognito 不會遷移使用者，並且會將錯誤傳回用户端應用程式。  
如果您未傳回此參數，Amazon Cognito 會假定其值為「false」。

**enableSMSMFA**  
將此參數設定為 `true`，以要求遷移的使用者完成 SMS 文字訊息多重要素驗證 (MFA) 才能登入。您的使用者集區必須啟用 MFA。請求參數中的用戶屬性必須包含電話號碼，否則該用戶的遷移將失敗。

## 範例：搭配現有密碼來遷移使用者
<a name="aws-lambda-triggers-user-migration-example-1"></a>

此範例 Lambda 函數會使用現有密碼遷移使用者，並避免歡迎訊息從 Amazon Cognito 中出現。

------
#### [ Node.js ]

```
exports.handler = (event, context, callback) => {
  var user;

  if (event.triggerSource == "UserMigration_Authentication") {
    // authenticate the user with your existing user directory service
    user = authenticateUser(event.userName, event.request.password);
    if (user) {
      event.response.userAttributes = {
        email: user.emailAddress,
        email_verified: "true",
      };
      event.response.finalUserStatus = "CONFIRMED";
      event.response.messageAction = "SUPPRESS";
      context.succeed(event);
    } else {
      // Return error to Amazon Cognito
      callback("Bad password");
    }
  } else if (event.triggerSource == "UserMigration_ForgotPassword") {
    // Lookup the user in your existing user directory service
    user = lookupUser(event.userName);
    if (user) {
      event.response.userAttributes = {
        email: user.emailAddress,
        // required to enable password-reset code to be sent to user
        email_verified: "true",
      };
      event.response.messageAction = "SUPPRESS";
      context.succeed(event);
    } else {
      // Return error to Amazon Cognito
      callback("Bad password");
    }
  } else {
    // Return error to Amazon Cognito
    callback("Bad triggerSource " + event.triggerSource);
  }
};
```

------

# 自訂訊息 Lambda 觸發程序
<a name="user-pool-lambda-custom-message"></a>

當您具有要傳送給使用者的電子郵件和簡訊的外部標準時，或您想要在執行時間將自己的邏輯套用至使用者訊息的格式時，請將自訂訊息觸發條件新增至您的使用者集區。自訂訊息 Lambda 會在您的使用者集區傳送所有電子郵件和簡訊之前收到訊息的內容。然後，您的 Lambda 函數有機會修改訊息內容和主旨。

Amazon Cognito 會在傳送電子郵件或電話驗證訊息或多重要素驗證 (MFA) 碼之前，叫用此觸發程序。您可以使用自訂的訊息觸發程序來動態自訂訊息。

請求中包含 `codeParameter`。此字串作為 Amazon Cognito 提供給使用者的代碼的預留位置。請將 `codeParameter` 字串插入訊息內文中您要顯示驗證碼的位置。Amazon Cognito 收到此回應時，會以實際的驗證碼取代 `codeParameter` 字串。

**注意**  
具有`CustomMessage_AdminCreateUser`觸發來源之自訂訊息 Lambda 函數的輸入事件包含使用者名稱和驗證碼。由於管理員建立的使用者必須同時收到其使用者名稱和密碼，因此函數的回應必須包含使用者名稱和密碼的預留位置變數。訊息的預留位置是 `request.usernameParameter`和 的值`request.codeParameter`。這些值通常是 `{username}`和 `{####}`；最佳實務是參考輸入值，而不是硬式編碼變數名稱。

**Topics**
+ [自訂訊息 Lambda 觸發程序來源](#cognito-user-pools-lambda-trigger-syntax-custom-message-trigger-source)
+ [自訂訊息 Lambda 觸發程序參數](#cognito-user-pools-lambda-trigger-syntax-custom-message)
+ [用於註冊的自訂訊息範例](#aws-lambda-triggers-custom-message-example)
+ [管理員建立使用者的自訂訊息範例](#aws-lambda-triggers-custom-message-admin-example)

## 自訂訊息 Lambda 觸發程序來源
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-trigger-source"></a>


| triggerSource 值 | 事件 | 
| --- | --- | 
| CustomMessage\$1SignUp | 自訂訊息 - 在註冊後傳送確認碼。 | 
| CustomMessage\$1AdminCreateUser | 自訂訊息 - 傳送臨時密碼給新使用者。 | 
| CustomMessage\$1ResendCode | 自訂訊息 - 重新傳送確認碼給現有的使用者。 | 
| CustomMessage\$1ForgotPassword | 自訂訊息 - 傳送「忘記密碼」請求的確認碼。 | 
| CustomMessage\$1UpdateUserAttribute | 自訂訊息 - 當使用者的電子郵件或電話號碼變更時，此觸發程序會自動傳送驗證碼給使用者。無法用於其他屬性。 | 
| CustomMessage\$1VerifyUserAttribute | 自訂訊息 - 當使用者為新的電子郵件或電話號碼手動請求驗證碼時，此觸發程序會傳送驗證碼給使用者。 | 
| CustomMessage\$1Authentication | 自訂訊息 - 在身分驗證期間傳送 MFA 代碼。 | 

## 自訂訊息 Lambda 觸發程序參數
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "userAttributes": {
            "string": "string",
            . . .
        }
        "codeParameter": "####",
        "usernameParameter": "string",
        "clientMetadata": {
            "string": "string",
            . . .
        }
    },
    "response": {
        "smsMessage": "string",
        "emailMessage": "string",
        "emailSubject": "string"
    }
}
```

------

### 自訂訊息請求參數
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-request"></a>

**userAttributes**  
代表使用者屬性的一或多組名稱/值。

**codeParameter**  
可讓您在自訂訊息中用來做為驗證碼預留位置的字串。

**usernameParameter**  
使用者名稱。Amazon Cognito 會在管理員建立的使用者所產生的請求中納入此參數。

**clientMetadata**  
您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組，該函數是您用於自訂訊息觸發程序所指定。叫用自訂訊息函數的請求不包括傳遞至 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) 中的 ClientMetadata 參數的 API 操作的資料。若要將此資料傳遞至您的 Lambda 函數，您可以在下列 API 動作中使用 ClientMetadata 參數：  
+  [AdminResetUserPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminResetUserPassword.html) 
+  [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 
+  [AdminUpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminUpdateUserAttributes.html)
+  [ForgotPassword](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ForgotPassword.html)
+  [GetUserAttributeVerificationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_GetUserAttributeVerificationCode.html)
+  [ResendConfirmationCode](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ResendConfirmationCode.html)
+  [SignUp](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_SignUp.html)
+  [UpdateUserAttributes](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserAttributes.html)

### 自訂訊息回應參數
<a name="cognito-user-pools-lambda-trigger-syntax-custom-message-response"></a>

在回應中，指定自訂文字以用於傳遞給使用者的訊息中。如需 Amazon Cognito 套用至這些參數的字串限制，請參閱 [MessageTemplateType](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_MessageTemplateType.html)。

**smsMessage**  
要傳送給使用者的自訂簡訊。必須包含您在請求中收到的 `codeParameter` 值。

**emailMessage**  
要傳送給使用者的自訂電子郵件訊息。您可以在 `emailMessage` 參數中使用 HTML 格式化。必須包含在請求中收到的 `codeParameter` 值作為變數 `{####}`。只有在使用者集區的 `EmailSendingAccount` 屬性為 `DEVELOPER` 時，Amazon Cognito 才可以使用 `emailMessage` 參數。如果使用者集區的 `EmailSendingAccount` 屬性不是 `DEVELOPER`，並且傳回 `emailMessage` 參數，Amazon Cognito 會產生 400 錯誤代碼 `com.amazonaws.cognito.identity.idp.model.InvalidLambdaResponseException`。當您選擇使用 Amazon Simple Email Service (Amazon SES) 傳送電子郵件訊息時，使用者集區的 `EmailSendingAccount` 屬性為 `DEVELOPER`。否則，該值為 `COGNITO_DEFAULT`。

**emailSubject**  
自訂訊息的主旨行。如果使用者集區的 EmailSendingAccount 屬性為 `DEVELOPER`，那麼您只能使用 `emailSubject` 參數。如果使用者集區的 `EmailSendingAccount` 屬性不是 `DEVELOPER`，並且 Amazon Cognito 傳回 `emailSubject` 參數，Amazon Cognito 會產生 400 錯誤代碼 `com.amazonaws.cognito.identity.idp.model.InvalidLambdaResponseException`。當您選擇使用 Amazon Simple Email Service (Amazon SES) 傳送電子郵件訊息時，使用者集區的 `EmailSendingAccount` 屬性為 `DEVELOPER`。否則，該值為 `COGNITO_DEFAULT`。

## 用於註冊的自訂訊息範例
<a name="aws-lambda-triggers-custom-message-example"></a>

此 Lambda 函數可讓您在服務要求應用程式傳送驗證碼給使用者時，自訂電子郵件或簡訊的訊息。

Amazon Cognito 可在多個事件中叫用 Lambda 觸發程序：註冊後、重新傳送驗證碼、恢復忘記的密碼，或驗證使用者屬性。回應同時包含簡訊和電子郵件的訊息。訊息必須包含代碼參數 `"####"`。此參數是使用者接收驗證碼的預留位置。

一封電子郵件的長度上限為 20,000 個 UTF-8 字元，此長度包括驗證碼。您可以在這些電子郵件訊息中使用 HTML 標籤。

簡訊的長度上限為 140 個 UTF-8 字元。此長度包括驗證碼。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.triggerSource === "CustomMessage_SignUp") {
    const message = `Thank you for signing up. Your confirmation code is ${event.request.codeParameter}.`;
    event.response.smsMessage = message;
    event.response.emailMessage = message;
    event.response.emailSubject = "Welcome to the service.";
  }
  return event;
};

export { handler };
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
	"version": "1",
	"region": "us-west-2",
	"userPoolId": "us-west-2_EXAMPLE",
	"userName": "test-user",
	"callerContext": {
		"awsSdkVersion": "aws-sdk-unknown-unknown",
		"clientId": "1example23456789"
	},
	"triggerSource": "CustomMessage_SignUp",
	"request": {
		"userAttributes": {
			"sub": "a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
			"cognito:user_status": "CONFIRMED",
			"email_verified": "true",
			"phone_number_verified": "true",
			"phone_number": "+12065551212",
			"email": "test-user@example.com"
		},
		"codeParameter": "{####}",
		"linkParameter": "{##Click Here##}",
		"usernameParameter": "None"
	},
	"response": {
		"smsMessage": "None",
		"emailMessage": "None",
		"emailSubject": "None"
	}
}
```

------

## 管理員建立使用者的自訂訊息範例
<a name="aws-lambda-triggers-custom-message-admin-example"></a>

Amazon Cognito 傳送至此範例自訂訊息 Lambda 函數的請求，其`triggerSource`值為 `CustomMessage_AdminCreateUser`，使用者名稱和臨時密碼。函數`${event.request.codeParameter}`會從請求中的臨時密碼填入，以及`${event.request.usernameParameter}`從請求中的使用者名稱填入。

您的自訂訊息必須將 `codeParameter`和 的值插入回應物件`emailMessage`中的 `usernameParameter``smsMessage`和 。在此範例中，函數會將相同的訊息寫入回應欄位 `event.response.smsMessage`和 `event.response.emailMessage`。

一封電子郵件的長度上限為 20,000 個 UTF-8 字元。此長度包括驗證碼。您可以在這些電子郵件中使用 HTML 標籤。簡訊的長度上限為 140 個 UTF-8 字元。此長度包括驗證碼。

回應同時包含簡訊和電子郵件的訊息。

------
#### [ Node.js ]

```
const handler = async (event) => {
  if (event.triggerSource === "CustomMessage_AdminCreateUser") {
    const message = `Welcome to the service. Your user name is ${event.request.usernameParameter}. Your temporary password is ${event.request.codeParameter}`;
    event.response.smsMessage = message;
    event.response.emailMessage = message;
    event.response.emailSubject = "Welcome to the service";
  }
  return event;
};

export { handler };
```

------

Amazon Cognito 會將事件資訊傳遞至您的 Lambda 函數。此函數會將相同事件物件傳回 Amazon Cognito，並在回應中附上任何變更。在 Lambda 主控台中，您可使用與 Lambda 觸發程序相關聯的資料來設定測試事件。下列是此程式碼範例的測試事件：

------
#### [ JSON ]

```
{
  "version": 1,
  "triggerSource": "CustomMessage_AdminCreateUser",
  "region": "<region>",
  "userPoolId": "<userPoolId>",
  "userName": "<userName>",
  "callerContext": {
      "awsSdk": "<calling aws sdk with version>",
      "clientId": "<apps client id>",
      ...
  },
  "request": {
      "userAttributes": {
          "phone_number_verified": false,
          "email_verified": true,
           ...
      },
      "codeParameter": "####",
      "usernameParameter": "username"
  },
  "response": {
      "smsMessage": "<custom message to be sent in the message with code parameter and username parameter>"
      "emailMessage": "<custom message to be sent in the message with code parameter and username parameter>"
      "emailSubject": "<custom email subject>"
  }
}
```

------

# 自訂寄件者 Lambda 觸發程序
<a name="user-pool-lambda-custom-sender-triggers"></a>

Lambda 會在使用者集區中觸發`CustomEmailSender`和`CustomSMSSender`支援第三方電子郵件和簡訊通知。您可以選擇簡訊和電子郵件供應商，傳送通知給 Lambda 函數程式碼中的使用者。當 Amazon Cognito 傳送邀請、MFA 代碼、確認碼、驗證碼和臨時密碼給使用者時，事件會啟用您設定的 Lambda 函數。Amazon Cognito 會將代碼和臨時密碼 (秘密) 傳送至您啟用的 Lambda 函數。Amazon Cognito 會使用 AWS KMS 客戶受管金鑰和 來加密這些秘密 AWS Encryption SDK。 AWS Encryption SDK 是用戶端加密程式庫，可協助您加密和解密一般資料。

**[CustomEmailSender](user-pool-lambda-custom-email-sender.md)**  
Amazon Cognito 會叫用此觸發程序，傳送電子郵件通知給使用者。

**[CustomSMSSender](user-pool-lambda-custom-sms-sender.md)**  
Amazon Cognito 會叫用此觸發，傳送簡訊通知給使用者。

## 加密概念
<a name="user-pool-lambda-custom-sender-triggers-resources"></a>

Amazon Cognito 不會在傳送至自訂寄件者觸發條件的事件中以純文字傳送使用者的代碼。Lambda 函數必須解密事件中的程式碼。下列概念是您的函數必須用來取得可交付給使用者的程式碼的加密架構。

**AWS KMS**  
AWS KMS 是一項受管服務，可用來建立和控制 AWS KMS 金鑰。這些金鑰可加密您的資料。如需詳細資訊，請參閱[什麼是 AWS Key Management Service？](/kms/latest/developerguide/overview.html)。

**KMS 金鑰**  
KMS 金鑰是密碼編譯金鑰的邏輯表示。KMS 金鑰包含金鑰 ID、建立日期、說明和金鑰狀態等中繼資料。KMS 金鑰也包含可用來加密和解密資料的金鑰材料。如需詳細資訊，請參閱刪除 [AWS KMS 金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys)。

**對稱 KMS 金鑰**  
對稱 KMS 金鑰是 256 位元的加密金鑰，不會在未加密的情況下退出 AWS KMS 。若要使用對稱 KMS 金鑰，您必須呼叫 AWS KMS。Amazon Cognito 使用對稱金鑰。相同的金鑰可用於加密和解密。如需詳細資訊，請參閱[對稱 KMS 金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)。

## 自訂寄件者 Lambda 觸發程序的須知事項
<a name="user-pool-lambda-custom-sender-triggers-things-to-know"></a>
+ 若要使用這些 Lambda 觸發程序設定使用者集區，您可以使用 AWS CLI 或 SDK。無法透過 Amazon Cognito 主控台使用這些組態。

  `UpdateUserPool` 操作會設定 Lambda 組態。請求此操作需要使用者集區的所有參數，*以及*您要變更的參數。如果您未提供所有相關的參數，Amazon Cognito 會將任何遺漏參數的值設定為其預設值。如以下 CLI AWS 範例所示，包含您要新增至使用者集區或保留在使用者集區中的所有 Lambda 函數的項目。如需詳細資訊，請參閱[更新使用者集區和應用程式用戶端組態](cognito-user-pool-updating.md)。

  ```
      #Send this parameter in an 'aws cognito-idp update-user-pool' CLI command, including any existing 
      #user pool configurations. This snippet also includes a pre sign-up trigger for syntax reference. The pre sign-up trigger
      #doesn't have a role in custom sender triggers.
                
        --lambda-config "PreSignUp=lambda-arn, \
                         CustomSMSSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         CustomEmailSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         KMSKeyID=key-id"
  ```

  對於使用`UpdateUserPool`下列程式碼片段的 JSON `LambdaConfig` 內文的請求， 會指派自訂簡訊和電子郵件寄件者函數。

  ```
  "LambdaConfig": {
     "KMSKeyID": "arn:aws:kms:us-east-1:111122223333:key/a6c4f8e2-0c45-47db-925f-87854bc9e357",
     "CustomEmailSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     },
     "CustomSMSSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     }
  ```
+ 若要使用 `update-user-pool` AWS CLI 命令移除自訂寄件者 Lambda 觸發條件，請從 省略 `CustomSMSSender`或 `CustomEmailSender` 參數`--lambda-config`，並包含您想要與使用者集區搭配使用的所有其他觸發條件。

  若要使用 `UpdateUserPool` API 請求移除自訂寄件者 Lambda 觸發條件，請從包含其他使用者集區組態的請求內文省略 `CustomSMSSender` 或 `CustomEmailSender` 參數。
+ Amazon Cognito 會在使用者臨時密碼中逸出 HTML 預留字元，例如 `&lt;` (`<`) 和 `&gt;` (`>`)。這些字元可能會出現在 Amazon Cognito 傳送至您自訂電子郵件寄件者功能的臨時密碼中，但不會出現在臨時驗證碼中。若要傳送臨時密碼，您的 Lambda 函數必須在解密密碼後以及將訊息傳送給使用者之前取消逸出這些字元。

## 啟用自訂寄件者 Lambda 觸發條件
<a name="enable-custom-sender-lambda-trigger"></a>

若要使用自訂邏輯來傳送使用者集區的簡訊或電子郵件訊息，請設定自訂寄件者觸發條件。接下來的程序會將自訂 SMS 觸發器、自訂電子郵件觸發器或兩者指派給您的使用者集區。新增自訂寄件者觸發條件後，Amazon Cognito 一律會傳送使用者屬性，包括電話號碼和一次性程式碼到您的 Lambda 函數，而不是傳送簡訊或電子郵件訊息的預設行為。

1. 在 AWS Key Management Service () 中建立[對稱加密金鑰](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#symmetric-cmks)AWS KMS。Amazon Cognito 會產生秘密，包括暫時密碼、驗證碼、身分驗證一次性密碼和確認碼，然後使用此 KMS 金鑰透過 加密秘密[AWS Encryption SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html)。然後，您可以使用 Lambda 函數 AWS Encryption SDK 中的 來解密秘密，並以純文字傳送給使用者。

1. 建立或更新使用者集區的 IAM 主體會針對 Amazon Cognito 用來加密程式碼的 KMS 金鑰建立一次性授權。為您的 KMS 金鑰授予此主體`CreateGrant`許可。若要讓此範例 KMS 金鑰政策有效，更新使用者集區的管理員必須使用 IAM 角色 的擔任角色工作階段登入`arn:aws:iam::111222333444:role/my-example-administrator-role`。

   將下列針對您環境修改的資源型政策套用至您的 KMS 金鑰。

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
       {
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws:iam::111122223333:role/my-example-administrator-role"
           },
           "Action": "kms:CreateGrant",
           "Resource": "arn:aws:kms:us-west-2:111122223333:key/1example-2222-3333-4444-999example",
           "Condition": {
               "StringEquals": {
                  "kms:EncryptionContext:userpool-id": "us-west-2_EXAMPLE"
               }
           }
       },
       {
           "Sid": "Allow Lambda to decrypt",
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws:iam::111122223333:role/my-lambda-function-role"
           },
           "Action": "kms:Decrypt",
           "Resource": "*"
       }]
   }
   ```

------

1. 為自訂寄件者觸發程序建立 Lambda 函數。Amazon Cognito 使用 [AWS 加密 SDK](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html) 來加密授權使用者 API 請求的秘密、臨時密碼和授權碼。

   1. 指派至少具有 KMS 金鑰`kms:Decrypt`許可的 [Lambda 執行角色](https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html)。

   1. 編寫 Lambda 函數程式碼來傳送訊息。函數的輸入事件包含秘密。在您的函數中，使用 解密秘密， AWS Encryption SDK 並處理任何相關的中繼資料。然後將代碼、您自己的自訂訊息和目的地電話號碼傳送到遞送訊息的自訂 API。

   1. 將 AWS Encryption SDK 新增至 Lambda 函數。如需詳細資訊，請參閱 [AWS 加密軟體 SDK 程式設計語言](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/programming-languages.html)。若要更新 Lambda 套件，請完成下列步驟。

      1. 將 Lambda 函數在 AWS 管理主控台匯出為 .zip 檔案。

      1. 開啟您的 函數並新增 AWS Encryption SDK。如需詳細資訊和下載連結，請參閱 *AWS Encryption SDK 開發人員指南*中的 [AWS Encryption SDK 程式設計語言](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/programming-languages.html)。

      1. 使用 SDK 相依性壓縮您的函數，然後將函數上傳至 Lambda。如需詳細資訊，請參閱 *AWS Lambda 開發人員指南*中的[以 .zip 封存檔形式部署 Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/configuration-function-zip.html#configuration-function-create)。

1. 授予 Amazon Cognito 服務委託人 `cognito-idp.amazonaws.com` 存取權，以叫用 Lambda 函數。

   下列 AWS CLI 命令會授予 Amazon Cognito 叫用 Lambda 函數的許可：

   ```
   aws lambda add-permission --function-name lambda_arn --statement-id "CognitoLambdaInvokeAccess" --action lambda:InvokeFunction --principal cognito-idp.amazonaws.com
   ```

1. 使用新增自訂寄件者 Lambda 觸發條件的`LambdaConfig`參數產生 [UpdateUserPool](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) API 請求。您無法在 Amazon Cognito 主控台中新增此類型的觸發條件。自訂寄件者觸發條件需要 `KMSKeyID`和 `CustomSMSSender`或 `CustomEmailSender`（或兩者） 的`LambdaConfig`參數。

# 自訂電子郵件寄件者 Lambda 觸發程序
<a name="user-pool-lambda-custom-email-sender"></a>

若您將自訂電子郵件寄件者觸發程序指派至使用者集區，Amazon Cognito 會在使用者事件要求傳送電子郵件訊息時，調用 Lambda 函數而非其預設行為。透過自訂寄件者觸發，您的 AWS Lambda 函數可以透過您選擇的方法和提供者傳送電子郵件通知給使用者。您函數的自訂程式碼必須從您的使用者集區處理並傳遞所有電子郵件訊息。

此觸發程序適用於您可能想要更好地控制使用者集區傳送電子郵件訊息的方式的情況。您的 Lambda 函數可以自訂對 Amazon SES API 操作的呼叫，例如當您想要管理多個已驗證的身分或跨 時 AWS 區域。您的函數也可能將訊息重新導向至另一個交付媒體或第三方服務。

若要了解如何設定自訂電子郵件寄件者觸發條件，請參閱 [啟用自訂寄件者 Lambda 觸發條件](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger)。

## 自訂電子郵件寄件者 Lambda 觸發程序來源
<a name="trigger-source"></a>

下表說明 Lambda 程式碼中自訂電子郵件觸發程序來源的觸發事件。


| `TriggerSource value` | 事件 | 
| --- | --- | 
| CustomEmailSender\$1SignUp | 使用者註冊後，Amazon Cognito 會傳送歡迎訊息。 | 
| CustomEmailSender\$1Authentication | 使用者登入，Amazon Cognito 會傳送電子郵件 OTP 或 MFA 代碼。 | 
| CustomEmailSender\$1ForgotPassword | 使用者請求代碼以重置其密碼。 | 
| CustomEmailSender\$1ResendCode | 使用者請求替換帳戶確認碼。 | 
| CustomEmailSender\$1UpdateUserAttribute | 使用者更新電子郵件地址或電話號碼屬性，Amazon Cognito 會傳送代碼來驗證屬性。 | 
| CustomEmailSender\$1VerifyUserAttribute | 使用者建立新的電子郵件地址或電話號碼屬性，Amazon Cognito 會傳送代碼來驗證屬性。 | 
| CustomEmailSender\$1AdminCreateUser | 您可以在使用者集區中建立新使用者，Amazon Cognito 會將臨時密碼傳送給使用者。 | 
| CustomEmailSender\$1AccountTakeOverNotification | Amazon Cognito 偵測到有人嘗試接管使用者帳戶，並向使用者傳送通知。 | 

## 自訂電子郵件寄件者 Lambda 觸發程序參數
<a name="custom-email-sender-parameters"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "type": "customEmailSenderRequestV1",
        "code": "string",
        "clientMetadata": {
            "string": "string",
             . . .
            },
        "userAttributes": {
            "string": "string",
            . . .
         }
}
```

------

### 自訂電子郵件寄件者請求參數
<a name="custom-email-sender-request-parameters"></a>

**type**  
請求版本。對於自訂電子郵件寄件者事件，此字串的值一律為 `customEmailSenderRequestV1`。

**code**  
您的函數可以解密並傳送給您使用者的加密代碼。

**clientMetadata**  
您可以做為自訂電子郵件寄件者 Lambda 函數觸發程序的自訂輸入提供的一個或多個鍵值組。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 動作中的 ClientMetadata 參數。Amazon Cognito 不包含其傳遞至身分驗證後函數的請求中的 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作的 ClientMetadata 參數中的資料。  
Amazon Cognito 會在具有下列觸發來源的事件中`ClientMetadata`傳送至自訂電子郵件觸發函數：  
+ `CustomEmailSender_ForgotPassword`
+ `CustomEmailSender_SignUp`
+ `CustomEmailSender_Authentication`
Amazon Cognito 不會`ClientMetadata`以來源 傳送觸發事件`CustomEmailSender_AccountTakeOverNotification`。

**userAttributes**  
代表使用者屬性的一個或多個鍵值組。

### 自訂電子郵件寄件者回應參數
<a name="custom-email-sender-response-parameters"></a>

Amazon Cognito 不預期會在自訂電子郵件寄件者回應中收到任何其他傳回的資訊。您的 Lambda 函數必須解譯事件並解密程式碼，然後傳遞訊息內容。典型的 函數會組合電子郵件訊息，並將其導向至第三方 SMTP 轉送。

## 程式碼範例
<a name="custom-email-sender-code-examples"></a>

下列 Node.js 範例處理您的自訂電子郵件寄件者 Lambda 函數中的電子郵件訊息事件。此範例假設您的函數定義了兩個環境變數。

**`KEY_ID`**  
您要用來加密和解密使用者程式碼的 KMS 金鑰 ID。

**`KEY_ARN`**  
您想要用來加密和解密使用者程式碼的 KMS 金鑰的 Amazon Resource Name (ARN)。

**部署此函數**

1. 在開發人員工作區中安裝最新版本的 NodeJS。

1. 在工作區中建立新的 NodeJS 專案。

1. 使用 初始化您的專案`npm init -y`。

1. 建立 Lambda 函數的指令碼：`touch index.mjs`。

1. 將下列範例的內容貼到 `index.mjs`。

1. 下載專案相依性： AWS Encryption SDK`npm install @aws-crypto/client-node`。

1. 將專案目錄壓縮為檔案：`zip -r my_deployment_package.zip .`。

1. [將 ZIP 檔案部署到您的 函數](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html)。

此範例函數會解密程式碼，對於註冊事件，則模擬傳送電子郵件訊息到使用者的電子郵件地址。

```
import { KmsKeyringNode, buildClient, CommitmentPolicy } from '@aws-crypto/client-node';

// Configure the encryption SDK client with the KMS key from the environment variables
const { encrypt, decrypt } = buildClient(
    CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
);

const generatorKeyId = process.env.KEY_ID;
const keyIds = [process.env.KEY_ARN];
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

// Example function to simulate sending email.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an email message to 'emailaddress' with body 'message'.
const sendEmail = async (emailAddress, message) => {
    // Log the destination with the email address masked.
    console.log(`Simulating email send to ${emailAddress.replace(/[^@.]/g, '*')}`);
    // Log the message with the code masked.
    console.log(`Message content: ${message.replace(/\b\d{6,8}\b/g, '********')}`);
    // Simulate API delay
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log('Email sent successfully');
    return true;
};

export const handler = async (event) => {
    try {
        // Decrypt the secret code using encryption SDK
        let plainTextCode;
        if (event.request.code) {
            const { plaintext, messageHeader } = await decrypt(keyring, Buffer.from(event.request.code, 'base64'));
            plainTextCode = Buffer.from(plaintext).toString('utf-8');
        }

        // Handle different trigger sources
        if (event.triggerSource == 'CustomEmailSender_SignUp') {
            const emailAddress = event.request.userAttributes.email;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendEmail(emailAddress, message);
        }
        else if (event.triggerSource == 'CustomEmailSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomEmailSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomEmailSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_AdminCreateUser') {
            // Handle admin create user
        }
        else if (event.triggerSource == 'CustomEmailSender_Authentication') {
            // Handle authentication
        }
        else if (event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification') {
            // Handle account takeover notification
        }

        return;
    } catch (error) {
        console.error('Error in custom email sender:', error);
        throw error;
    }
};
```

# 自訂 SMS 寄件者 Lambda 觸發程序
<a name="user-pool-lambda-custom-sms-sender"></a>

若您將自訂簡訊寄件者觸發程序指派至使用者集區，Amazon Cognito 會在使用者事件要求傳送簡訊時，調用 Lambda 函數而非其預設行為。透過自訂寄件者觸發，您的 AWS Lambda 函數可以透過您選擇的方法和提供者傳送簡訊通知給使用者。您函數的自訂程式碼必須從您的使用者集區處理並傳遞所有簡訊。

此觸發程序適用於您可能想要更好地控制使用者集區傳送 SMS 訊息的方式的情況。您的 Lambda 函數可以自訂對 Amazon SNS API 操作的呼叫，例如當您想要管理多個起始 IDs 或跨 時 AWS 區域。您的函數也可能將訊息重新導向至另一個交付媒體或第三方服務。

若要了解如何設定自訂電子郵件寄件者觸發條件，請參閱 [啟用自訂寄件者 Lambda 觸發條件](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger)。

## 自訂簡訊寄件者 Lambda 觸發程序來源
<a name="trigger-source"></a>

下表說明 Lambda 程式碼中自訂簡訊觸發程序來源的觸發事件。


| `TriggerSource value` | 事件 | 
| --- | --- | 
| CustomSMSSender\$1SignUp | 使用者註冊後，Amazon Cognito 會傳送歡迎訊息。 | 
| CustomSMSSender\$1ForgotPassword | 使用者請求代碼以重置其密碼。 | 
| CustomSMSSender\$1ResendCode | 使用者請求新的程式碼以確認其註冊。 | 
| CustomSMSSender\$1VerifyUserAttribute | 使用者建立新的電子郵件地址或電話號碼屬性，Amazon Cognito 會傳送代碼來驗證屬性。 | 
| CustomSMSSender\$1UpdateUserAttribute | 使用者更新電子郵件地址或電話號碼屬性，Amazon Cognito 會傳送代碼來驗證屬性。 | 
| CustomSMSSender\$1Authentication | 使用者登入，Amazon Cognito 會傳送 SMS OTP 或 MFA 代碼。 | 
| CustomSMSSender\$1AdminCreateUser | 您可以在使用者集區中建立新使用者，Amazon Cognito 會將臨時密碼傳送給使用者。 | 

## 自訂 SMS 寄件者 Lambda 觸發程序參數
<a name="custom-sms-sender-parameters"></a>

Amazon Cognito 傳遞至此 Lambda 函數的請求，是以下參數和 Amazon Cognito 新增至所有請求的[常用參數](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)之組合。

------
#### [ JSON ]

```
{
    "request": {
        "type": "customSMSSenderRequestV1",
        "code": "string",
        "clientMetadata": {
            "string": "string",
             . . .
            },
        "userAttributes": {
            "string": "string",
            . . .
         }
}
```

------

### 自訂 SMS 寄件者請求參數
<a name="custom-sms-sender-request-parameters"></a>

**type**  
請求版本。對於自訂 SMS 寄件者事件，此字串的值一律為 `customSMSSenderRequestV1`。

**code**  
您的函數可以解密並傳送給您使用者的加密代碼。

**clientMetadata**  
您可以做為自訂 SMS 寄件者 Lambda 函數觸發程序的自訂輸入提供的一個或多個鍵值組。若要將此資料傳遞至您的 Lambda 函數，您可以使用 [AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) 和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API 動作中的 ClientMetadata 參數。Amazon Cognito 不包含其傳遞至身分驗證後函數的請求中的 [AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) 和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API 操作的 ClientMetadata 參數中的資料。

**userAttributes**  
代表使用者屬性的一個或多個鍵值組。

### 自訂 SMS 寄件者回應參數
<a name="custom-sms-sender-response-parameters"></a>

Amazon Cognito 不預期會在回應中收到任何其他傳回的資訊。您的函數可使用 API 操作來查詢和修改您的資源，或將事件中繼資料記錄到外部系統。

## 程式碼範例
<a name="custom-sms-sender-code-examples"></a>

下列 Node.js 範例處理您的自訂 SMS 寄件者 Lambda 函數中的 SMS 訊息事件。此範例假設您的函數定義了兩個環境變數。

**`KEY_ID`**  
您要用來加密和解密使用者程式碼的 KMS 金鑰 ID。

**`KEY_ARN`**  
您想要用來加密和解密使用者程式碼的 KMS 金鑰的 Amazon Resource Name (ARN)。

**部署此函數**

1. 在開發人員工作區中安裝最新版本的 NodeJS。

1. 在工作區中建立新的 NodeJS 專案。

1. 使用 初始化您的專案`npm init -y`。

1. 建立 Lambda 函數的指令碼：`touch index.mjs`。

1. 將下列範例的內容貼到 `index.mjs`。

1. 下載專案相依性： AWS Encryption SDK`npm install @aws-crypto/client-node`。

1. 將專案目錄壓縮為檔案：`zip -r my_deployment_package.zip .`。

1. [將 ZIP 檔案部署到您的 函數](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html)。

```
import { KmsKeyringNode, buildClient, CommitmentPolicy } from '@aws-crypto/client-node';

// Configure the encryption SDK client with the KMS key from the environment variables
const { encrypt, decrypt } = buildClient(
    CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
);

const generatorKeyId = process.env.KEY_ID;
const keyIds = [process.env.KEY_ARN];
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

// Example function to simulate sending SMS.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an SMS message to 'phoneNumber' with body 'message'.
const sendSMS = async (phoneNumber, message) => {
    // Log the destination with the phone number masked.
    console.log(`Simulating SMS send to ${phoneNumber.replace(/[^+]/g, '*')}`);
    // Log the message with the code masked.
    console.log(`Message content: ${message.replace(/\b\d{6,8}\b/g, '********')}`);    
    // Simulate API delay
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log('SMS sent successfully');
    return true;
};

export const handler = async (event) => {
    try {
        // Decrypt the secret code using encryption SDK
        let plainTextCode;
        if (event.request.code) {
            const { plaintext, messageHeader } = await decrypt(keyring, Buffer.from(event.request.code, 'base64'));
            plainTextCode = Buffer.from(plaintext).toString('utf-8');
        }

        // Handle different trigger sources
        if (event.triggerSource == 'CustomSMSSender_SignUp') {
            const phoneNumber = event.request.userAttributes.phone_number;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendSMS(phoneNumber, message);
        }
        else if (event.triggerSource == 'CustomSMSSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomSMSSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomSMSSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_AdminCreateUser') {
            // Handle admin create user
        }
        return;
    } catch (error) {
        console.error('Error in custom SMS sender:', error);
        throw error;
    }
};
```

**Topics**
+ [自訂簡訊寄件者 Lambda 觸發程序來源](#trigger-source)
+ [自訂 SMS 寄件者 Lambda 觸發程序參數](#custom-sms-sender-parameters)
+ [程式碼範例](#custom-sms-sender-code-examples)
+ [使用自訂 SMS 寄件者函數評估 SMS 訊息功能](#sms-to-email-example)

## 使用自訂 SMS 寄件者函數評估 SMS 訊息功能
<a name="sms-to-email-example"></a>

自訂 SMS 寄件者 Lambda 函數會接受您的使用者集區將傳送的 SMS 訊息，且該函數會根據您的自訂邏輯傳遞內容。Amazon Cognito 將 [自訂 SMS 寄件者 Lambda 觸發程序參數](#custom-sms-sender-parameters) 傳送到您的函數中。您的函數可以進行您想要使用此資訊做的事。例如，您可以將代碼傳送至 Amazon Simple Notification Service (Amazon SNS) 主題。Amazon SNS 主題訂閱者可以是 SMS 訊息、HTTPS 端點或電子郵件地址。

若要使用自訂 SMS 寄件者 Lambda 函數來測試 Amazon Cognito SMS 簡訊的測試環境，請參閱 [GitHub 上的 aws-samples 程式庫](https://github.com/aws-samples)中的 [amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email)。儲存庫包含可建立新的使用者集區的 AWS CloudFormation 範本，或使用您已擁有的使用者集區。這些範本會建立 Lambda 函數和 Amazon SNS 主題。由範本指派為自訂 SMS 寄件者觸發程序的 Lambda 函數，會將您的 SMS 訊息重新導向至 Amazon SNS 主題的訂閱者。

當您將此解決方案部署到使用者集區時，對於 Amazon Cognito 通常透過 SMS 簡訊傳送的所有訊息，Lambda 函數會改為傳送到一個中央電子郵件地址。使用此解決方案可以自訂和預覽 SMS 訊息，並測試導致 Amazon Cognito 傳送 SMS 訊息的使用者集區事件。完成測試後，請復原 CloudFormation 堆疊，或從使用者集區中移除自訂 SMS 寄件者函數分配。

**重要**  
請勿使用 [amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email) 中的範本建置生產環境。解決方案中的自訂 SMS 寄件者 Lambda 函數會*模擬* SMS 訊息，但 Lambda 函數會將它們全部傳送到一個中央電子郵件地址。您必須先完成在 [Amazon Cognito 使用者集區的簡訊設定](user-pool-sms-settings.md) 顯示的需求，才能在實際產品的 Amazon Cognito 使用者集區中傳送 SMS 訊息。