

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

# 自訂身分驗證挑戰 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 };
```

------