定義驗證挑戰 Lambda 觸發程序 - Amazon Cognito

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

定義驗證挑戰 Lambda 觸發程序

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

挑戰 Lambda 觸發程序
定義驗證挑戰

Amazon Cognito 會叫用此觸發程序來啟動自訂身分驗證流程

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

您可以讓 Amazon Cognito 在發出自訂挑戰之前驗證使用者密碼。當您在自訂挑戰流程中執行SRP身分驗證時,將在請求速率配額的身分驗證類別中執行相關聯的任何 Lambda 觸發程序。下列為此程序的概觀:

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

  2. Amazon Cognito 以包含 challengeName: SRP_AchallengeResult: true 初始工作階段,叫用您的定義驗證挑戰 Lambda 觸發程序。

  3. 收到這些輸入後,您的 Lambda 函數會以 challengeName: PASSWORD_VERIFIERissueTokens: falsefailAuthentication: false 回應。

  4. 如果密碼驗證成功,Amazon Cognito 會再次以包含 challengeName: PASSWORD_VERIFIERchallengeResult: true 的新工作階段,叫用您的 Lambda 函數。

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

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

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

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

定義驗證挑戰 Lambda 觸發程序參數

Amazon Cognito 傳遞至此 Lambda 函數的請求,是以下參數和 Amazon Cognito 新增至所有請求的常用參數之組合。

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

定義驗證挑戰請求參數

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

userAttributes

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

userNotFound

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

工作階段

ChallengeResult 元素的陣列。每個都包含下列元素:

challengeName

下列挑戰類型之一:CUSTOM_CHALLENGESRP_APASSWORD_VERIFIERSMS_MFAEMAIL_OTPSOFTWARE_TOKEN_MFADEVICE_SRP_AUTHDEVICE_PASSWORD_VERIFIER、 或 ADMIN_NO_SRP_AUTH

當您定義驗證挑戰函數對已設定多重要素身分驗證的使用者發出PASSWORD_VERIFIER挑戰時,Amazon Cognito 會追蹤 SMS_MFAEMAIL_OTPSOFTWARE_TOKEN_MFA挑戰。這些是多重要素身分驗證碼的提示。在函數中,包含處理來自 SMS_MFAEMAIL_OTPSOFTWARE_TOKEN_MFA挑戰的輸入事件。您不需要在定義驗證MFA挑戰函數中叫用任何挑戰。

重要

當您的函數正在確定使用者是否成功驗證,以及是否該發出權杖時,請務必檢查您定義驗證挑戰函數中的 challengeName,並且驗證是否與期望值相符。

challengeResult

如果使用者順利完成挑戰,則設定為 true,否則設定為 false

challengeMetadata

您的自訂挑戰名稱。唯有在 challengeNameCUSTOM_CHALLENGE 時使用。

clientMetadata

您可以做為 Lambda 函數的自訂輸入提供的一個或多個鍵值組,該函數是您用於定義驗證挑戰觸發程序所指定。若要將此資料傳遞至 Lambda 函數,您可以在 AdminRespondToAuthChallengeRespondToAuthChallengeAPI操作中使用 ClientMetadata 參數。叫用定義驗證挑戰函數的請求不包含在 AdminInitiateAuthInitiateAuthAPI操作中的 ClientMetadata 參數中傳遞的資料。

定義驗證挑戰回應參數

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

challengeName

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

issueTokens

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

failAuthentication

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

定義驗證挑戰範例

此範例會定義一系列用來進行身分驗證的挑戰,且唯有在使用者完成所有挑戰時,才會發出權杖。

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 };