返回文章列表

Cognito 伺服器端驗證流程詳解

本文探討 Amazon Cognito 的伺服器端驗證流程,涵蓋使用 AWS CLI 和 CloudFormation 建立使用者池、應用程式客戶端,以及管理員 API 操作等關鍵步驟。同時,解析了安全遠端密碼協定(SRP)、Token 用途、`ADMIN_NO_SRP_AUTH` 與

Web 開發 資安

Cognito 作為 AWS 的應用程式安全驗證服務,提供多種驗證流程,其中伺服器端驗證流程適用於後端語言如 Java、Node.js 等。本篇著重於伺服器端驗證的實務操作,包含 AWS CLI 指令運用、CloudFormation 範本佈署,以及關鍵引數設定說明。同時也涵蓋了密碼變更流程、Token 更新機制,以及 Cognito 的核心功能,如使用者註冊、登入、多因素驗證等。最後,文章也釐清了 AliasAttributesUsernameAttributes 的差異,避免設定錯誤導致的異常,並提供相關概念解析,例如 SRP 協定、Token 用途及不同驗證流程的選擇,讓開發者更深入理解 Cognito 的運作機制。

使用 Amazon Cognito 進行應用程式安全驗證 Chapter 4

建立 Cognito 使用者池

在 Amazon Cognito 中,使用者池是用於管理使用者註冊、登入和存取控制的核心元件。以下將介紹如何使用 JSON 檔案和 CloudFormation 範本建立 Cognito 使用者池。

使用 JSON 檔案建立使用者池

首先,我們需要建立一個 JSON 檔案來定義使用者池的屬性。以下是一個範例 JSON 檔案:

{
  "PoolName": "MyFirstUserPool",
  "Policies": {
    "PasswordPolicy": {
      "MinimumLength": 8,
      "RequireUppercase": true,
      "RequireLowercase": true,
      "RequireNumbers": true,
      "RequireSymbols": true
    }
  },
  "AutoVerifiedAttributes": [
    "email"
  ],
  "AliasAttributes": [
    "email"
  ],
  "EmailVerificationMessage": "Your verification code from MyApp is {####}.",
  "EmailVerificationSubject": "Your verification code from MyApp",
  "UserPoolTags": {
    "Team": "Dev"
  },
  "AdminCreateUserConfig": {
    "AllowAdminCreateUserOnly": false,
    "UnusedAccountValidityDays": 7,
    "InviteMessageTemplate": {
      "EmailMessage": "Your username for MyApp is {username} and password is {####}.",
      "EmailSubject": "Your temporary password for MyApp"
    }
  }
}

JSON 檔案內容解密:

  1. PoolName:定義使用者池的名稱。
  2. Policies.PasswordPolicy:定義密碼政策,包括最小長度、是否需要大寫字母、小寫字母、數字和特殊字元。
  3. AutoVerifiedAttributesAliasAttributes:定義自動驗證的屬性,例如電子郵件地址。
  4. EmailVerificationMessageEmailVerificationSubject:定義電子郵件驗證訊息和主題。
  5. UserPoolTags:為使用者池新增標籤,以便進行分類別和管理。
  6. AdminCreateUserConfig:定義管理員建立使用者的設定,包括是否只允許管理員建立使用者、未使用帳戶的有效期等。

建立好 JSON 檔案後,可以使用以下命令建立使用者池:

aws cognito-idp create-user-pool \
--cli-input-json file://resources/create-user-pool-cli-input.json \
--profile admin

命令執行結果解密:

  • 該命令使用 aws cognito-idp create-user-pool 指令建立一個新的使用者池。
  • --cli-input-json 引數指定了包含使用者池設定的 JSON 檔案路徑。
  • --profile admin 指定了使用的 AWS 組態檔。

使用 CloudFormation 範本建立使用者池

除了使用 JSON 檔案外,我們還可以使用 CloudFormation 範本來建立使用者池。以下是一個範例 YAML 檔案:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'My First Cognito User Pool'

Resources:
  MyFirstUserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      Policies:
        PasswordPolicy:
          MinimumLength: 8
          RequireLowercase: true
          RequireNumbers: true
          RequireSymbols: true
          RequireUppercase: true
      AutoVerifiedAttributes:
        - email
      AliasAttributes:
        - email
      EmailVerificationMessage: 'Your verification code from MyApp is {####}.'
      EmailVerificationSubject: 'Your verification code from MyApp'
      AdminCreateUserConfig:
        AllowAdminCreateUserOnly: false
        InviteMessageTemplate:
          EmailMessage: 'Your username for MyApp is {username} and password is {####}.'
          EmailSubject: 'Your temporary password for MyApp'
        UnusedAccountValidityDays: 7
      UserPoolName: 'MyApp User Pool'
      UserPoolTags:
        Team: Dev

Outputs:
  UserPoolId:
    Description: 'Cognito user pool'
    Value: !Ref MyFirstUserPool
    Export:
      Name: MyFirstUserPoolId

CloudFormation 範本內容解密:

  1. AWSTemplateFormatVersionDescription:定義範本的版本和描述。
  2. Resources.MyFirstUserPool:定義一個名為 MyFirstUserPool 的資源,型別為 AWS::Cognito::UserPool
  3. Properties:定義使用者池的屬性,與 JSON 檔案中的屬性相似。
  4. Outputs.UserPoolId:輸出使用者池的 ID,並將其匯出,以便在其他 Stack 中參照。

建立好 CloudFormation 範本後,可以使用以下命令建立 Stack:

aws cloudformation create-stack \
--stack-name my-cognito-stack \
--template-body file://cognito-user-pool-cf-template.yml \
--profile admin

清理資源

完成測試後,可以刪除建立的 Stack 或使用者池,以清理資源。使用以下命令刪除 Stack:

aws cloudformation delete-stack \
--stack-name my-cognito-stack \
--profile admin

或者,直接刪除使用者池:

aws cognito-idp delete-user-pool \
--user-pool-id us-east-1_fYsb1Gyec \
--profile admin

Amazon Cognito 應用安全:第 4 章深入解析

Amazon Cognito 是 AWS 中用於應用程式安全驗證、授權和存取控制的主要服務。本章節將探討 Cognito 的核心功能及其運作原理,並介紹如何使用 AWS CLI 和 CloudFormation 範本來建立和管理 Cognito 使用者池及應用程式客戶端。

Cognito 的核心功能與運作機制

Cognito 提供了一系列強大的功能,包括使用者註冊、登入、管理員建立使用者、多因素驗證(MFA)、使用者資料管理、電子郵件和簡訊驗證、忘記密碼處理等。這些功能使得開發者能夠輕鬆實作應用程式的安全驗證和授權機制。

重點功能說明

  • 使用者註冊與登入:Cognito 支援使用者自行註冊和登入,同時也允許管理員建立使用者帳戶。
  • 多因素驗證(MFA):增強了帳戶的安全性,防止未授權的存取。
  • 自訂屬性:除了預設屬性外,Cognito 還支援建立自訂屬性,以滿足不同的應用需求。
  • 與外部身份提供者整合:Cognito 可以與 Google、Facebook、Twitter 等外部身份提供者整合,簡化使用者登入流程。

使用 AWS CLI 和 CloudFormation 建立 Cognito 使用者池

在建立 Cognito 使用者池時,可以使用 AWS CLI 或 CloudFormation 範本。透過 generate-cli-skeleton 選項,可以產生 JSON 範本檔案,簡化輸入引數的過程,降低錯誤率。

AliasAttributes 與 UsernameAttributes 的區別

在建立使用者池時,需要了解 AliasAttributesUsernameAttributes 的區別。AliasAttributes 定義了可用於登入的別名屬性,如電話號碼、電子郵件或首選使用者名稱。UsernameAttributes 則定義了可作為使用者名稱的屬性,如電話號碼或電子郵件。兩者不可同時設定,否則會導致 InvalidParameterException 錯誤。

建立 Cognito 使用者池客戶端

要使用 Cognito 使用者池,需要建立一個應用程式客戶端。應用程式客戶端是一個具有呼叫 API 許可權的實體,例如註冊、登入和忘記密碼等操作。

使用 AWS CLI 建立使用者池客戶端

aws cognito-idp create-user-pool-client \
--user-pool-id us-east-1_fYsb1Gyec \
--client-name my-user-pool-client \
--explicit-auth-flows ADMIN_NO_SRP_AUTH \
--profile admin

使用 CloudFormation 範本建立使用者池客戶端

Resources:
  MyUserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      ClientName: 'My Cognito User Pool Client'
      ExplicitAuthFlows:
        - ADMIN_NO_SRP_AUTH
      RefreshTokenValidity: 30
      UserPoolId: !ImportValue MyFirstUserPoolId
Outputs:
  ClientId:
    Description: 'Cognito user pool Client'
    Value: !Ref MyUserPoolClient

伺服器端驗證流程

Cognito 支援多種驗證流程,包括伺服器端驗證流程、客戶端驗證流程和自訂驗證流程。伺服器端驗證流程主要用於伺服器端語言,如 Java、Node.js 等。

重點步驟

  1. 建立應用程式客戶端:首先,需要為使用者池建立一個應用程式客戶端,支援使用者名稱和密碼驗證。
  2. 執行管理員特定 API 命令:透過 AWS CLI 執行管理員特定的 API 命令,示範伺服器端驗證流程。

參考資源

使用 Amazon Cognito 進行應用程式安全驗證 - 第四章:伺服器端驗證流程詳解

伺服器端驗證流程(Server-side Authentication Flow)

伺服器端驗證流程主要與管理員 API 搭配使用,以下是具體步驟:

  1. 建立使用者帳號 使用 admin-create-user 命令建立新使用者:
    aws cognito-idp admin-create-user \
    --user-pool-id us-east-1_fYsb1Gyec \
    --username testuser \
    --temporary-password Passw0rd$ \
    --profile admin
    
    建立成功後,使用者狀態預設為 FORCE_CHANGE_PASSWORD,首次登入時需變更密碼。

內容解密:

此步驟使用 AWS CLI 指令建立新使用者,並設定臨時密碼。需替換 user-pool-id 為實際的使用者池 ID。

  1. 以管理員身份啟動驗證流程 使用 admin-initiate-auth 命令啟動驗證流程:
    aws cognito-idp admin-initiate-auth \
    --user-pool-id us-east-1_fYsb1Gyec \
    --client-id 4o1kgtd4sj39nr36ouak5mhblt \
    --auth-flow ADMIN_NO_SRP_AUTH \
    --auth-parameters USERNAME=testuser,PASSWORD=Passw0rd$ \
    --profile admin
    
    此命令需指定 ADMIN_NO_SRP_AUTH 驗證流程,並提供正確的客戶端 ID。

內容解密:

ADMIN_NO_SRP_AUTH 是伺服器端驗證流程的必要選項,用於避免在網路上明文傳輸密碼。需在客戶端建立時組態此選項。

  1. 回應密碼變更挑戰 當使用者首次登入時,Cognito 會要求變更密碼。使用 admin-respond-to-auth-challenge 命令回應此挑戰:
    aws cognito-idp admin-respond-to-auth-challenge \
    --user-pool-id us-east-1_fYsb1Gyec \
    --client-id 5hh4v7nveu22vea74h8stt9238 \
    --challenge-name NEW_PASSWORD_REQUIRED \
    --challenge-responses USERNAME=testuser,NEW_PASSWORD=NewPass0123$ \
    --session <session-id> \
    --profile admin
    
    成功後,Cognito 將傳回三個 Token:Access Token、Refresh Token 和 ID Token。

內容解密:

此步驟需提供新的密碼,並傳遞 Session ID 以完成密碼變更挑戰。

  1. 使用 Refresh Token 更新 Access Token 和 ID Token 當 Access Token 和 ID Token 到期時,可使用 Refresh Token 更新:
    aws cognito-idp admin-initiate-auth \
    --user-pool-id us-east-1_fYsb1Gyec \
    --client-id 5hh4v7nveu22vea74h8stt9238 \
    --auth-flow REFRESH_TOKEN_AUTH \
    --auth-parameters REFRESH_TOKEN=<refresh-token> \
    --profile admin
    

內容解密:

此步驟展示瞭如何使用 Refresh Token 取得新的 Access Token 和 ID Token,以維持使用者登入狀態。

清理資源

  • 刪除使用者池客戶端

    aws cognito-idp delete-user-pool-client \
    --user-pool-id us-east-1_fYsb1Gyec \
    --client-id 5hh4v7nveu22vea74h8stt9238 \
    --profile admin
    
  • 刪除測試使用者

    aws cognito-idp admin-delete-user \
    --user-pool-id us-east-1_fYsb1Gyec \
    --username testuser \
    --profile admin
    

相關概念解析

安全遠端密碼協定(SRP)

SRP 是一種安全協定,允許客戶端在不直接傳輸密碼的情況下向伺服器證明其擁有正確的密碼。目前,SRP 主要支援在 iOS、Android 和 JavaScript 等客戶端 SDK 中。

三種 Token 的用途

  • ID Token:用於後端服務的驗證,例如 API Gateway。
  • Access Token:用於授權更新使用者引數的 Cognito API 操作。
  • Refresh Token:用於取得新的 ID Token 和 Access Token。

ADMIN_NO_SRP_AUTHUSER_PASSWORD_AUTH

兩者都支援在不使用 SRP 的情況下傳輸使用者名稱和密碼,但 USER_PASSWORD_AUTH 更適合於從舊系統遷移使用者。AWS 檔案建議在完成遷移後更新為更安全的驗證流程,如 SRP。