examlab .net 用最有效率的方法,考取最有價值的認證
Vol. I
本篇導覽 約 32 分鐘

Amazon Cognito:User Pools 與 Identity Pools

6,400 字 · 約 32 分鐘閱讀 ·

掌握 DVA-C02 考試所需的 Amazon Cognito 知識:使用者池與身份池的差異、JWT 令牌(ID/存取/刷新)、OAuth 2.0 流程、Hosted UI、Lambda 觸發器、SAML/OIDC/社群聯合認證、API Gateway Cognito Authorizer、AppSync 授權、AssumeRoleWithWebIdentity、進階安全功能,以及最常出現的使用者池與身份池混淆陷阱,附考試陷阱解析與白話文類比。

立即做 20 題練習 → 免費 · 不用註冊 · DVA-C02

Amazon Cognito 是 AWS 為面向終端使用者的應用程式所設計的身份服務,適用於行動 App、單頁網頁應用程式(SPA)以及企業對消費者(B2C)入口網站。它解決了開發者經常混淆的兩個截然不同的問題:(1) 讓使用者登入你的應用程式(這個使用者是不是 alice@example.com?她能證明嗎?),以及 (2) 將 AWS 憑證發給應用程式,讓應用程式可以直接呼叫 AWS API(這位已登入的使用者能從瀏覽器直接寫入某個 Amazon S3 前綴嗎?)。第一個問題由 Amazon Cognito 使用者池解決,第二個問題由 Amazon Cognito 身份池解決。混淆這兩者,是 DVA-C02 安全性領域中考試頻率最高的陷阱。

在 DVA-C02 考試的 Task 2.1(「為應用程式和 AWS 服務實作驗證與授權」)中,你需要在無伺服器架構中正確設計 Amazon Cognito:準確選擇使用者池或身份池、選擇正確的 OAuth 2.0 流程、在 Amazon API Gateway 上接上 Cognito Authorizer、解碼 JWT 令牌、在註冊和登入時觸發 Lambda 函式、與 SAML 2.0 和社群身份提供者進行聯合認證,以及透過 AssumeRoleWithWebIdentity 將令牌兌換為臨時 AWS 憑證。本指南涵蓋所有關鍵知識點,揭示最高頻率的陷阱,並用白話文類比幫助你在考試當天記住這些概念。

Amazon Cognito 是什麼?

Amazon Cognito 是一項受管 AWS 服務,為 Web 和行動應用程式提供驗證、授權與使用者管理功能。它是區域性服務(每個 Amazon Cognito 使用者池和身份池都存在於單一 AWS 區域),並可自動擴展至數百萬名使用者。Amazon Cognito 有兩個獨立的核心元件,雖然同屬一個品牌,但解決的是不同的問題:

  • Amazon Cognito 使用者池 — 完全受管的使用者目錄。負責處理註冊、登入、密碼重設、MFA、帳號復原,並發行符合 OpenID Connect(OIDC)規範的 JWT 令牌(ID 令牌、存取令牌、刷新令牌)。可以將使用者池想成「你的應用程式的登入資料庫,由 AWS 管理」。
  • Amazon Cognito 身份池 — 聯合身份代理器。接收一個身份證明令牌(來自 Amazon Cognito 使用者池、Facebook、Google、Apple、SAML、OIDC,甚至是未驗證的訪客),然後透過 AWS STS AssumeRoleWithWebIdentity 換回臨時 AWS 憑證。可以將身份池想成「核對入場章後發放 AWS 鑰匙的保鑣」。

你可以單獨使用 Amazon Cognito 使用者池(最常見——只需要應用程式的登入功能),單獨使用身份池(較少見——僅在直接從非 Cognito 的 IdP 聯合到 AWS 時使用),或兩者搭配使用(適用於需要從客戶端直接呼叫 AWS API 的行動應用程式)。

  • 使用者池(User pool):Amazon Cognito 的使用者目錄,負責驗證使用者身份並發行 JWT 令牌。
  • 身份池(Identity pool):Amazon Cognito 的聯合身份代理器,將令牌兌換為臨時 AWS 憑證。
  • ID 令牌(ID token):包含使用者身份聲明(sub、email、cognito:groups)的 OIDC JWT。用於證明使用者是誰
  • 存取令牌(Access token):包含 OAuth 2.0 範圍和 cognito:groups 的 JWT。用於授權 API 呼叫。
  • 刷新令牌(Refresh token):長效不透明令牌,用於在不重新驗證的情況下取得新的 ID 令牌和存取令牌。
  • Hosted UI:由 Amazon Cognito 使用者池提供的 AWS 代管登入和註冊頁面。
  • App client(應用程式客戶端):使用者池內代表某一應用程式(行動、SPA、伺服器)的設定項目,包含 OAuth 設定。
  • 聯合認證(Federation):接受來自外部身份提供者(SAML 2.0、OIDC、Google、Facebook、Apple、Amazon)的身份。
  • 參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html

Amazon Cognito 對 DVA-C02 的重要性

DVA-C02 第 2 領域(安全性)佔考試比重 26%,而 Amazon Cognito 是其中兩個最重要的主題之一(另一個是 IAM 角色與政策)。考試反覆測試四個決策:使用者池還是身份池、ID 令牌還是存取令牌、哪種 OAuth 2.0 流程符合特定客戶端類型、以及 API Gateway Cognito Authorizer 還是 Lambda Authorizer。掌握這四個決策,Amazon Cognito 在考試當天就不再是陷阱。

白話文解釋 Amazon Cognito

Amazon Cognito 融合了兩個容易混淆的概念。以下類比能幫助你清楚區分它們。

類比一:便利超商的兩道驗證關卡

想像一間大型連鎖便利超商的倉儲會員中心。門口的第一位服務人員負責核對你的會員資格和身份證,這就是 Amazon Cognito 使用者池。通過驗證後,她在你的手上蓋了一個入場章,並給你一張印有 QR Code 的會員貼紙(也就是 JWT 令牌:ID 令牌加上存取令牌加上刷新令牌)。這張貼紙代表「此人已通過驗證,屬於黃金會員等級」。

進入倉儲後,站在高級會員專區入口的第二位服務人員就是 Amazon Cognito 身份池。第二位服務人員不會重新核對你的身份證,只是掃描你貼紙上的 QR Code,確認是真的,然後發給你一張限時專區通行卡(也就是 AssumeRoleWithWebIdentity 返回的臨時 AWS 憑證)。通行卡只能開啟特定區域的門(對應 IAM 角色權限),而且會自動失效,就算遺失也不怕被永久濫用。

把這兩位服務人員搞混,正是 DVA-C02 的陷阱所在:使用者池負責驗證身份並蓋章(JWT);身份池負責用那個章換取 AWS 鑰匙。你不會「直接登入」身份池——你永遠是帶著某個章(來自 Amazon Cognito 使用者池、Google、Facebook、SAML)到場,身份池再決定你的章值得換哪種通行卡。

類比二:護照局與租車櫃台

你的護照局就是 Amazon Cognito 使用者池。它核查你的身份(戶口名簿、生物特徵、MFA),核發給你一本護照(簽名的 JWT ID 令牌)和一張旅遊許可證(帶有範圍的存取令牌)。護照局不提供租車服務,它只負責建立身份。

機場的租車櫃台就是 Amazon Cognito 身份池。它不會重新核查你的戶口名簿,只看你的護照、確認它來自受信任的國家(受信任的身份提供者),依你的會籍等級判斷你能租哪個等級的車(角色映射:白金會員對應白金角色,一般會員對應標準角色,未登入訪客對應公開角色),然後發給你一把臨時車鑰匙(臨時 AWS 憑證),幾小時後自動失效。

陷阱在這裡:護照本身開不了車,車鑰匙本身也進不了護照局。使用者池的 JWT 負責驗證你的應用程式;身份池的憑證負責授權直接呼叫 AWS API。兩者是依序執行的,不能互換。

類比三:飯店 Check-in 與禮賓服務

最後,想像一間大型飯店。入住櫃台(Amazon Cognito 使用者池)核查你的訂房資訊——電子郵件確認、簡訊 MFA、身份證件,甚至還有一個自訂的入住前 Lambda 觸發器來檢查你的賓客紀錄(pre-signuppre-authentication Lambda 觸發器)。他們列印給你一張附有「黃金樓層」標籤的房間門卡(帶有 cognito:groups 聲明的 ID 令牌)。

需要使用飯店的外部合作夥伴服務——高爾夫球場預約時段、合作餐廳訂位?你走向禮賓部(Amazon Cognito 身份池)。禮賓人員查看你的黃金樓層門卡(你的使用者池 JWT),將「黃金樓層」對應到合作夥伴的 VIP 等級(角色映射),然後發給你一張只在接下來一小時內有效的臨時合作夥伴兌換券(臨時 AWS 憑證)。如果你帶來的是其他合作夥伴的卡——比如你的 Facebook 登入——禮賓人員一樣能發券,因為禮賓部信任多個發卡單位(聯合身份提供者),不僅限於飯店前台。

考試當天,看到「Amazon Cognito 使用者池」就在腦中想像門口驗證身份、蓋章的服務人員;看到「Amazon Cognito 身份池」就想像核對入場章、發放臨時通行卡的第二道關卡。只憑這個區分,就能解開 80% 的陷阱題。參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html

Amazon Cognito 使用者池 — 註冊、登入與 JWT 發行

Amazon Cognito 使用者池是區域性的使用者目錄。一個使用者池可以支援你 AWS 帳號中的一個或多個應用程式。每個應用程式在使用者池中以一個 **App client(應用程式客戶端)**代表,每個 App client 有自己的 OAuth 2.0 設定、回呼 URL 清單以及身份提供者清單。

使用者池能為你做什麼

  • 儲存使用者記錄(使用者名稱、電子郵件、電話號碼,以及任何你自訂的屬性,例如 custom:tenant_id)。
  • 處理註冊——電子郵件和(或)電話驗證、自訂屬性填寫、選擇性 MFA 啟用。
  • 處理登入——SRP 密碼流程、admin-auth 流程、user-password 流程、自訂驗證挑戰流程,以及聯合認證。
  • 處理帳號復原——忘記密碼、忘記使用者名稱。
  • 在成功驗證後發行三種 JWT 令牌:ID 令牌、存取令牌、刷新令牌。
  • 提供 Hosted UI——由 AWS 代管的登入、註冊和密碼重設頁面,讓你不需要自己建置這些畫面。

密碼政策與 MFA

每個 Amazon Cognito 使用者池都有一套密碼政策,可在建立時設定(之後也能更新)。你可以設定最短密碼長度(6 到 99 個字元),以及必要的字元類型(大寫、小寫、數字、符號)。同時也可以設定管理員建立帳號時所發放的臨時密碼的有效期限

多因素驗證(MFA)可在使用者池層級設為關閉可選必要。支援的驗證因素包括:

  • 簡訊文字訊息 — 發送至使用者電話號碼的一次性驗證碼(電話號碼必須已驗證)。
  • 基於時間的一次性密碼(TOTP) — Google Authenticator、Authy、1Password 等。
  • 電子郵件 MFA — 發送至已驗證電子郵件的一次性驗證碼(較新功能)。

若 MFA 設為必要,每次登入都必須提供第二因素。若設為可選,使用者可以自行選擇是否啟用 MFA。

三種 JWT 令牌 — ID、存取、刷新

使用者成功登入後,Amazon Cognito 使用者池會返回三種令牌。了解每種令牌的用途,是 DVA-C02 考試的直接考點。

  • ID 令牌 — 由使用者池簽署的 JWT,包含身份聲明:sub(使用者唯一識別碼)、emailphone_numbercognito:usernamecognito:groups,以及任何自訂屬性。ID 令牌供你的應用程式辨識使用者身份。預設有效期:1 小時(可設定為 5 分鐘至 24 小時)。
  • 存取令牌 — 由使用者池簽署的 JWT,包含 OAuth 2.0 範圍(例如 openidemailprofileaws.cognito.signin.user.admin,或自訂資源伺服器範圍)以及 cognito:groups。存取令牌供你保護的 API進行呼叫授權。預設有效期:1 小時(可設定為 5 分鐘至 24 小時)。
  • 刷新令牌 — 不透明令牌(不是可以解析的 JWT)。用於在不要求使用者重新登入的情況下申請新的 ID 令牌和存取令牌。預設有效期:30 天(可設定為 1 小時至 10 年)。

令牌撤銷

刷新令牌可以透過 RevokeToken API 撤銷。一旦撤銷,該刷新令牌就無法再發行新的 ID 令牌和存取令牌。撤銷刷新令牌同時也會使從它發行的、用於 aws.cognito.signin.user.admin 範圍的存取令牌失效,但已發行的 JWT 存取令牌在第三方 API 中仍在其自然有效期內繼續有效——因為這些 API 只在本地驗證簽章和 exp 聲明,不會每次請求都呼叫 Amazon Cognito。這正是存取令牌應設為較短有效期的原因——撤銷不會追溯性地使飛行中的 JWT 失效,只有時間到期才能做到。

Hosted UI、自訂網域與 OAuth 2.0 流程

Hosted UI 是 Amazon Cognito 為你代管的登入和註冊網頁體驗。你透過啟用 App client 並設定網域前綴和允許的回呼 URL 清單來設定它;從你的應用程式將使用者的瀏覽器重導向到 Hosted UI 網址,使用者登入後,Amazon Cognito 會帶著驗證碼或令牌(在 URL 片段或查詢字串中)重導回你的應用程式。

三種 Cognito 網域選項

  • Amazon Cognito 前綴網域 — 免費,格式為 https://<your-prefix>.auth.<region>.amazoncognito.com。設定快速;網域明顯帶有 AWS 品牌標識。
  • 自訂網域 — 使用你自己的網域(https://auth.example.com)。需要在 us-east-1 中建立 ACM 憑證(供代理 Hosted UI 的 Amazon CloudFront 使用),並設定指向 Cognito CloudFront 發佈的 DNS 記錄。適用於希望登入頁面融入自家品牌的情境。
  • Managed login(較新版本) — 更新版的 Hosted UI,支援更豐富的品牌設定和多語言資源。

Cognito 支援的 OAuth 2.0 流程

Amazon Cognito 使用者池 App client 支援 OAuth 2.0 和 OIDC。DVA-C02 考試要求你能將客戶端類型對應到正確的流程。

  • 授權碼授予(code — 應用程式在重導向 URL 中收到一個短效的 code,然後其後端將驗證碼 POST 到 Cognito 的 /oauth2/token 端點(附帶 App client secret),換取 ID 令牌、存取令牌和刷新令牌。推薦用於伺服器渲染的 Web 應用程式和行動應用程式(公開客戶端使用 PKCE)。這是最安全的流程,因為令牌不會出現在瀏覽器 URL 中。
  • 隱式授予(token — 應用程式直接在 URL 片段中收到令牌。屬於舊版 OAuth 2.0 流程;因令牌可能透過瀏覽器歷史記錄或 referrer 標頭洩漏而被視為安全性較低。歷史上用於單頁應用程式,但現已不建議使用——應優先選擇帶有 PKCE 的授權碼流程。
  • 客戶端憑證授予(client_credentials — 機器對機器(M2M)流程。呼叫方直接提供 App client ID 和 secret,換取僅包含存取令牌的回應(沒有使用者——此流程不涉及終端使用者)。用於後端對後端的 API 存取,適合不存在終端使用者的後端服務呼叫受保護資源的情境。需要在使用者池中設定包含自訂範圍的資源伺服器

DVA-C02 直接測試 OAuth 流程選擇。依客戶端類型對應流程:有終端使用者的 Web/行動端 → 授權碼(公開客戶端使用 PKCE)。無終端使用者的伺服器對伺服器 → 客戶端憑證隱式授予屬於舊版,不應選擇——除非題目明確說明是針對舊版 SPA,否則現代 SPA 也應使用授權碼 + PKCE。參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html

OAuth 範圍與資源伺服器

除了內建的 OIDC 範圍(openidemailprofilephone),你還可以在使用者池中定義資源伺服器,並宣告自訂範圍,例如 api.example.com/orders.readapi.example.com/orders.write。你的 App client 設定了它可以申請的範圍;存取令牌 JWT 的 scope 聲明列出已授予的範圍。你的 API(在 Amazon API Gateway 或自有伺服器後面)會在處理請求前先驗證 scope 聲明。

Cognito Lambda 觸發器 — 自訂使用者流程

Amazon Cognito 使用者池讓你在特定生命週期節點注入 Lambda 函式。觸發器是同步的:你的 Lambda 接收觸發器事件,返回修改後的事件物件,Amazon Cognito 再根據你的回應繼續(或中止)流程。這是 Amazon Cognito 的主要擴充機制,也是 DVA-C02 的常見考點。

你應該熟記的主要觸發器:

  • Pre sign-up(註冊前) — 在新使用者寫入目錄之前觸發。使用情境:根據允許清單驗證電子郵件網域、自動確認受信任的使用者(略過電子郵件驗證)、拒絕一次性電子郵件服務。
  • Post confirmation(確認後) — 在使用者確認其電子郵件或電話後觸發。使用情境:在 Amazon DynamoDB 中新增使用者的預設記錄、透過 Amazon SES 觸發歡迎信、將他們加入郵件清單。
  • Pre authentication(驗證前) — 在處理登入之前觸發。使用情境:地理 IP 允許清單、拒絕已知遭洩露帳號登入、實作超出 Cognito 標準保護範圍的帳號鎖定邏輯。
  • Post authentication(驗證後) — 在成功登入後觸發。使用情境:將登入事件記錄到 Amazon CloudWatch、更新「最後登入」時間戳記、刷新 Amazon DynamoDB 中的使用者快取工作階段。
  • Custom message(自訂訊息) — 在 Amazon Cognito 即將發送簡訊或電子郵件時觸發(驗證碼、忘記密碼碼、管理員建立帳號的邀請函)。使用情境:自訂主旨和內容、依使用者語言進行本地化。
  • Pre token generation(令牌生成前) — 在 ID 令牌和存取令牌簽署之前觸發。使用情境:將自訂聲明(例如租戶 ID、角色、功能旗標)加入 ID 令牌,讓下游 API 無需額外資料庫查詢即可進行授權。
  • User migration(使用者遷移) — 當使用者登入但尚未存在於 Amazon Cognito 使用者池中時觸發。使用情境:在使用者首次登入時從舊版驗證系統遷移(Cognito 呼叫你的 Lambda,你的 Lambda 查詢舊系統,返回屬性,Cognito 建立記錄)。這是分階段遷移而不需大量匯入使用者的強大模式。
  • Define auth challenge(定義驗證挑戰)/ Create auth challenge(建立驗證挑戰)/ Verify auth challenge response(驗證挑戰回應) — 三個組合觸發器,透過讓你編寫挑戰-回應狀態機,實現自訂驗證流程(無密碼簡訊 OTP、魔法連結、CAPTCHA、Passkey)。

考試中,如果情境說「自動批准來自公司電子郵件網域的使用者,不需要電子郵件驗證」,答案是使用 pre sign-up Lambda 觸發器,並設定 autoConfirmUser: true。如果情境說「將使用者的租戶 ID 加入 JWT,讓 API 能直接進行授權」,答案是 pre token generation Lambda 觸發器。參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html

聯合身份提供者 — SAML、OIDC 與社群登入

Amazon Cognito 使用者池可以設定為與外部身份提供者進行聯合認證。除了(或配合)使用者池內的本地使用者名稱/密碼帳號,使用者也可以點擊「以 Google 登入」或「以公司 IdP 登入」,返回一個 Amazon Cognito 再包裝成自己 JWT 令牌的已驗證身份。

支援的聯合身份提供者

  • SAML 2.0 — Microsoft Entra ID、Active Directory Federation Services、Okta、Ping Identity,或任何 SAML IdP。你上傳 IdP 的 metadata XML(或 URL),並設定從 SAML assertion 到使用者池屬性的屬性映射。
  • OIDC — 任何符合 OpenID Connect 規範的 IdP。你提供 issuer URL、client id、client secret 以及屬性映射。
  • 社群身份提供者 — 針對 Google、Facebook、Login with Amazon 和 Sign in with Apple 的預建整合。你在社群提供者處註冊你的應用程式,貼上 app id 和 app secret,Amazon Cognito 負責處理 OAuth 流程。

聯合認證的實際流程

  1. 使用者在你的應用程式上點擊「以 Google 登入」。
  2. 瀏覽器重導向到 Amazon Cognito 的 /oauth2/authorize 端點,查詢字串中帶有身份提供者名稱。
  3. Amazon Cognito 重導向到 Google。
  4. 使用者在 Google 登入;Google 帶著 Google 令牌重導回 Amazon Cognito。
  5. Amazon Cognito 驗證 Google 令牌,在使用者池中建立或更新對應的使用者(依你的設定映射屬性),然後帶著驗證碼(授權碼流程)重導回你的應用程式。
  6. 你的應用程式用驗證碼換取 Amazon Cognito JWT 令牌。

從你的應用程式角度來看,結果與原生使用者池登入完全相同:你會得到 Cognito 發行的 ID 令牌、存取令牌和刷新令牌。ID 令牌內的 identities 聲明會告訴你使用者是從哪個外部 IdP 來的。

從使用者池遷移至社群 IdP

DVA-C02 常見情境:原本使用本地使用者名稱/密碼的使用者池,擴充為也支援「以 Google 登入」的相同使用者。有兩個重要模式:

  • 透過 identities 屬性進行帳號連結 — 當聯合使用者登入且其電子郵件與現有使用者池記錄相符時,Amazon Cognito 可以設定為連結這兩個帳號(讓使用者有一個同時包含本地和聯合登入路徑的統一身份)。
  • 使用者遷移 Lambda 觸發器 — 用於完全放棄舊版驗證系統:使用者第一次以舊密碼登入時,遷移觸發器根據舊系統驗證密碼,擷取其屬性,Amazon Cognito 隨即動態建立使用者池記錄。

DVA-C02 Cognito 考題中最高頻的陷阱:題目描述一個行動應用程式需要從裝置直接將使用者生成的照片上傳到 Amazon S3,並提供選項「設定 Amazon Cognito 使用者池」或「設定 Amazon Cognito 身份池」。正確答案是兩者都要——使用者池驗證使用者(發行 JWT),身份池將 JWT 兌換為行動 SDK 用來簽署 S3 PutObject 請求的臨時 AWS 憑證。如果題目只允許選一個,注意動詞:「登入 / 驗證身份 / 發行 JWT」→ 使用者池;「取得 AWS 憑證 / 從客戶端呼叫 AWS API / AssumeRoleWithWebIdentity」→ 身份池。參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html

進階安全功能(Advanced Security Features,ASF)

Amazon Cognito 使用者池提供一個付費進階方案,稱為進階安全功能(ASF),新增了基於風險的自適應驗證以及遭洩露憑證的偵測功能。在 DVA-C02 考試中,這屬於認知層次的內容——你應該能辨識這些功能名稱以及何時應啟用它們。

  • 自適應驗證 — Amazon Cognito 根據裝置、位置和行為模式,為每次登入嘗試評定風險分數(低、中、高)。你可以為每個風險等級設定對應動作:允許、要求 MFA、封鎖、通知使用者。典型情境:封鎖來自異常國家的登入、對中風險要求 MFA、記錄所有高風險嘗試。
  • 遭洩露憑證偵測 — Amazon Cognito 將使用者名稱和密碼與公開洩漏憑證對照資料庫進行比對。你可以設定使用者池,封鎖使用已出現在該資料庫中的憑證進行註冊或登入,或要求變更密碼。
  • 基於風險的事件記錄 — 每次登入嘗試都會被評分並記錄以供稽核,可在 Amazon Cognito 主控台中查看,也會傳送到 Amazon CloudWatch。

ASF 適用於整個使用者池,以每月活躍使用者(MAU)計費,費用疊加在 Amazon Cognito 使用者池的基本定價之上。

ASF 預設不啟用,並依每月活躍使用者收費,疊加在標準 Amazon Cognito 使用者池定價之上。當 DVA-C02 考題詢問「基於風險的自適應驗證」或「偵測使用者池中使用遭洩露密碼」時,答案是 Amazon Cognito 使用者池中的進階安全功能。參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pool-managing-security.html

Amazon Cognito 身份池 — 臨時 AWS 憑證

Amazon Cognito 身份池(此 AWS 服務過去稱為「Cognito Federated Identities」)是獨立於 Amazon Cognito 使用者池的另一種資源。它只做一件事:接收一個證明身份的令牌,將該身份映射到 IAM 角色,代表呼叫方呼叫 AWS STS AssumeRoleWithWebIdentity,並返回短期 AWS 憑證(存取金鑰 ID、私密存取金鑰、工作階段令牌、到期時間)。

為什麼需要身份池

行動和瀏覽器應用程式通常希望直接呼叫 AWS API——上傳到 Amazon S3、讀取 Amazon DynamoDB、發布到 Amazon SNS——而不需要經過你自己的伺服器層。行動和 Web 客戶端中的 AWS SDK 需要 AWS 憑證才能簽署請求。你不能在行動應用程式中內嵌長期 IAM 使用者存取金鑰(這是極度危險的反模式;任何反組譯應用程式的人都能取得永久 AWS 金鑰)。取而代之,應用程式透過 Amazon Cognito(或 Google、Facebook、SAML 等)登入,然後在身份池將所得令牌兌換為預設有效期一小時的短期憑證

已驗證身份與未驗證身份

每個 Amazon Cognito 身份池都支援兩種身份類型:

  • 已驗證身份 — 呼叫方帶著來自受信任身份提供者的有效令牌(Amazon Cognito 使用者池、Google、Facebook、Apple、Amazon、SAML IdP 或任何 OIDC IdP)。身份池將此身份映射到已驗證 IAM 角色
  • 未驗證(訪客)身份 — 呼叫方未提供令牌。若身份池設定為允許未驗證身份,呼叫方將映射到未驗證 IAM 角色。典型使用情境:公開的唯讀 Amazon S3 圖庫,任何人(無論是否登入)都可以從瀏覽器瀏覽。

兩個角色都是標準 IAM 角色,附有允許身份池代入它們的信任政策。差異只在每個角色所攜帶的權限——未驗證角色通常權限極為有限(唯讀、特定前綴)。

角色映射 — 基本模式與規則式映射

Amazon Cognito 身份池讓你根據身份的屬性指派不同的已驗證角色。存在兩種映射模式:

  • 預設角色解析 — 所有已驗證身份獲得同一個已驗證角色。簡單,對大多數應用程式已足夠。
  • 規則式角色映射 — 檢查傳入令牌的聲明(例如 Cognito 使用者池 ID 令牌的 cognito:groups 或 SAML assertion 屬性),從多個角色中擇一。典型模式:cognito:groups contains "Admin" → 具有廣泛權限的管理員角色;否則 → 具有唯讀權限的標準角色。

此外,以令牌聲明進行角色存取讓令牌本身可以指名要代入的角色(透過 cognito:preferred_role 聲明),只要它在允許清單中即可。

AssumeRoleWithWebIdentity 的底層運作

當你的應用程式對身份池呼叫 GetCredentialsForIdentity(直接呼叫或透過 AWS SDK 的 CognitoIdentityCredentials 提供者),身份池內部會以映射的 IAM 角色 ARN 和 OIDC 令牌呼叫 AWS STS AssumeRoleWithWebIdentity。AWS STS 根據 IdP 的公鑰驗證令牌簽章,確認角色的信任政策允許此 Web 身份,並返回臨時憑證。身份池再將這些憑證傳回你的應用程式。預設工作階段有效期為 1 小時;某些流程下,角色的 MaxSessionDuration 可延長至最多 12 小時

  1. 透過 IdP(使用者池、Google、Facebook、SAML、OIDC、Apple、Amazon)驗證 → 取得 OIDC/SAML 令牌。
  2. 帶著令牌對身份池呼叫 GetId → 收到 Cognito identity id。
  3. 用 identity id 和令牌呼叫 GetCredentialsForIdentity
  4. 身份池內部呼叫 AWS STS AssumeRoleWithWebIdentity
  5. 你的應用程式收到短期 AWS 憑證(存取金鑰、私密金鑰、工作階段令牌、到期時間)。 參考資料:https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html

使用者池 vs 身份池 — 經典陷阱完整解析

這個區分在每次 DVA-C02 考試中都會被測試。請牢記下表。

面向 Amazon Cognito 使用者池 Amazon Cognito 身份池
主要功能 驗證使用者;管理使用者目錄 將身份令牌兌換為臨時 AWS 憑證
返回內容 JWT 令牌(ID、存取、刷新) 透過 AssumeRoleWithWebIdentity 換取的臨時 AWS 憑證
信任方 你的應用程式程式碼;Amazon API Gateway;AWS AppSync 透過 IAM 角色信任政策的 AWS 服務
整合對象 Hosted UI、OAuth 2.0、SAML、OIDC、社群 IdP 使用者池、Google、Facebook、Apple、Amazon、SAML、OIDC、未驗證身份
輸出的使用方 應用程式的工作階段;API 授權器 AWS SDK 用於從客戶端直接呼叫 AWS API
可比喻為 「登入資料庫 + OIDC IdP」 「令牌換 IAM 角色的保鑣」
從瀏覽器/行動端直接呼叫 AWS API 的必要條件?

最清晰的心智測試:如果應用程式呼叫的是我自己的 API(在 Amazon API Gateway 後面),我只需要使用者池——API Gateway Cognito Authorizer 會驗證 JWT。如果應用程式從客戶端直接呼叫 AWS API(從瀏覽器上傳到 Amazon S3、從行動端讀取 Amazon DynamoDB),我需要身份池——它是唯一能發行 AWS 憑證的元件。如果兩者都需要,我就同時使用,依序串聯。

Amazon Cognito 與 Amazon API Gateway — Cognito Authorizer

Amazon API Gateway 有一個原生的授權器類型,稱為 Cognito User Pool Authorizer。你將一個 REST API 方法或 HTTP API 路由與特定的 Amazon Cognito 使用者池綁定,API Gateway 就會在每次請求轉發給後端之前自動驗證 JWT。

Cognito Authorizer 的運作方式

  • 客戶端將 JWT(通常是 REST API 的 ID 令牌,或 HTTP API 檢查範圍時的存取令牌)放在 Authorization 標頭(或你設定的自訂標頭)中。
  • Amazon API Gateway 取得使用者池的 JSON Web Key Set(JWKS),快取公鑰,並在本地驗證 JWT 的簽章——每次請求不需要呼叫 Amazon Cognito,使授權器速度極快。
  • API Gateway 驗證令牌的 iss 是否符合使用者池 URL、token_use 聲明是否符合授權器設定(idaccess)、client_id/aud 聲明是否符合允許的 App client,以及 exp 是否未過期。
  • 若驗證通過,API Gateway 轉發請求,並將令牌聲明放入整合上下文($context.authorizer.claims.sub$context.authorizer.claims.email$context.authorizer.claims['cognito:groups'])。
  • 若驗證失敗,API Gateway 立即返回 401。

基於範圍的授權(HTTP API)

Amazon API Gateway HTTP API(較新的 API Gateway 類型)支援 OAuth 2.0 範圍檢查:你宣告每個路由需要哪些範圍,若存取令牌的 scope 聲明不包含所需範圍,授權器就拒絕請求。這是 API 保護的標準 OAuth 模式,與客戶端憑證授予的 M2M 呼叫(此時只有存取令牌,沒有 ID 令牌)完全吻合。

Cognito Authorizer vs Lambda Authorizer

Amazon API Gateway 支援兩種授權器類型。DVA-C02 考試要求你知道何時選擇哪種。

  • Cognito User Pool Authorizer — 當你的令牌來自 Amazon Cognito 使用者池時使用。零程式碼、完全受管、速度快(本地 JWT 驗證)。應作為預設選擇。
  • Lambda Authorizer(前身為自訂授權器) — 當驗證來自非 Cognito IdP(Auth0、Firebase、自製 JWT 發行者)、你需要檢查 Cognito 無法提供的自訂聲明,或授權邏輯依賴外部查詢(資料庫、第三方 API)時使用。有兩個子類型:token authorizer(傳遞原始令牌)和 request authorizer(傳遞完整請求上下文——標頭、路徑、來源 IP)。

兩種授權器都支援返回 IAM 風格政策文件(允許/拒絕特定 API Gateway 方法)的政策回應。Lambda Authorizer 的結果可以依身份進行快取(預設 TTL 300 秒),以減少 Lambda 呼叫次數。

如果情境說「用 Amazon Cognito 使用者池保護我的 API Gateway 端點」,答案是 Cognito User Pool Authorizer——不是 Lambda Authorizer。只有在(a)IdP 不是 Amazon Cognito,或(b)你需要內建授權器無法表達的自訂授權邏輯時,才改用 Lambda Authorizer。參考資料:https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html

Amazon Cognito 與 AWS AppSync

AWS AppSync 是受管的 GraphQL 服務。它支援五種授權模式,其中 Amazon Cognito 使用者池是最常見的:

  • Amazon Cognito 使用者池 — 在 Authorization 標頭中傳遞 JWT;AWS AppSync 驗證它並將聲明公開給 resolver。你可以使用 @aws_auth 指令,在特定欄位上強制要求 cognito:groups 成員資格。
  • AWS IAM — 使用 AWS 憑證以 SigV4 簽署請求(客戶端應用程式的憑證通常從 Amazon Cognito 身份池取得)。
  • API 金鑰 — 僅用於開發或真正的公開端點;不適合生產環境的使用者資料。
  • OpenID Connect(OIDC) — 任何 OIDC IdP,不一定要是 Amazon Cognito。
  • Lambda authorizer — 與 Amazon API Gateway Lambda authorizer 相同的模式。

典型的行動應用程式設定,使用 Cognito 使用者池作為已驗證操作的主要授權模式,使用者池的 JWT 直接從登入流向 GraphQL 查詢。

整合全局 — 兩種典型架構

架構一:受 API Gateway 保護的無伺服器 Web 應用程式

單頁應用程式(React、Vue、Svelte)呼叫 Amazon API Gateway 後端,路由到 AWS Lambda。

  1. 使用者透過 Amazon Cognito Hosted UI 登入(帶 PKCE 的授權碼流程,自訂網域 auth.example.com)。
  2. Hosted UI 帶著授權碼重導回來;SPA 用授權碼換取 ID 令牌、存取令牌和刷新令牌。
  3. SPA 儲存令牌(存取令牌和刷新令牌存放在記憶體或安全儲存中;生產環境不要將長效令牌存放在 localStorage)並在每次 API 呼叫的 Authorization 標頭中附上 ID 令牌
  4. Amazon API Gateway 的 Cognito User Pool Authorizer 使用使用者池的 JWKS 在本地驗證 JWT。成功後,帶著聲明將請求轉發給 AWS Lambda。
  5. AWS Lambda 讀取 event.requestContext.authorizer.claims.sub 以識別呼叫的使用者,並套用業務層授權邏輯。

不需要身份池——應用程式不會從客戶端直接呼叫 AWS API。

架構二:行動應用程式直接上傳照片到 Amazon S3

行動應用程式(iOS/Android)希望使用者直接上傳照片到 Amazon S3,不經過伺服器。

  1. 使用者在應用程式內透過 Amazon Cognito 使用者池登入(SDK 原生流程或 Hosted UI)。
  2. 應用程式收到 ID 令牌(JWT)。
  3. 應用程式透過 GetId + GetCredentialsForIdentity 將 ID 令牌傳給 Amazon Cognito 身份池
  4. 身份池呼叫 AWS STS AssumeRoleWithWebIdentity,並返回臨時 AWS 憑證(存取金鑰、私密金鑰、工作階段令牌),綁定到一個具有 s3:PutObject 權限、路徑為 arn:aws:s3:::photo-bucket/${cognito-identity.amazonaws.com:sub}/* 的 IAM 角色。
  5. 應用程式的 Amazon S3 AWS SDK 使用這些憑證直接上傳到 bucket。${cognito-identity.amazonaws.com:sub} IAM 政策變數將每個使用者的前綴限定為其自己的 identity id——這是經典的多租戶隔離模式。

這裡同時需要使用者池和身份池,兩者依序協作。

Amazon Cognito 關鍵數字與必記事實

  • 使用者池發行 JWT;身份池透過 AssumeRoleWithWebIdentity 發行 AWS 憑證。
  • ID 令牌存取令牌:預設 1 小時,可設定為 5 分鐘至 24 小時。
  • 刷新令牌:預設 30 天,可設定為 1 小時至 10 年。
  • 來自身份池的臨時 AWS 憑證:預設 1 小時;角色 MaxSessionDuration 最長可達 12 小時。
  • OAuth 2.0 流程:授權碼(最適合 Web/行動端)、隱式授予(舊版)、客戶端憑證(伺服器對伺服器)。
  • MFA:SMS、TOTP、電子郵件。選項:關閉 / 可選 / 必要。
  • 聯合認證:SAML 2.0、OIDC、Google、Facebook、Apple、Amazon。
  • API Gateway Cognito Authorizer 使用 JWKS 在本地驗證 JWT——每次請求不呼叫 Cognito API。
  • 進階安全功能(ASF):自適應驗證 + 遭洩露憑證偵測;依 MAU 付費。
  • 令牌撤銷RevokeToken 使刷新令牌失效;已發行的 JWT 在 exp 到期前仍然有效。
  • 參考資料:https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html

常見考試陷阱 — DVA-C02 中的 Amazon Cognito

陷阱一:使用者池與身份池的混淆

最常被考的 Cognito 陷阱。任何說到「登入 / 驗證身份 / 管理使用者帳號 / MFA / 密碼重設」的情境,都要選使用者池。任何說到「行動/Web 應用程式需要直接呼叫 AWS API / 從瀏覽器上傳到 Amazon S3 / 透過社群登入取得 AWS 憑證」的情境,都要選身份池(通常搭配使用者池)。「臨時 AWS 憑證」加上「客戶端」幾乎一定指向身份池。

陷阱二:ID 令牌 vs 存取令牌用於 API 授權

兩者都是 JWT。Amazon API Gateway REST API Cognito Authorizer 歷史上預設檢查 ID 令牌,但可以設定為存取令牌。HTTP API JWT Authorizer 預設使用存取令牌(OAuth 正確選擇),並支援範圍驗證。當情境提到 OAuth 範圍時,正確的令牌是存取令牌。當情境只需要知道使用者是誰時,使用 ID 令牌即可。

陷阱三:OAuth 2.0 流程選擇

「伺服器對伺服器 / M2M / 後端服務呼叫 API」= 客戶端憑證授予,只返回存取令牌。「SPA / 行動端 / 任何有終端使用者的應用程式」= 帶 PKCE 的授權碼授予(不要選隱式授予)。如果題目明確描述一個沒有後端且不支援 PKCE 的舊版瀏覽器應用程式,隱式授予是歷史上的答案——但現代最佳實踐是到處使用授權碼 + PKCE。

陷阱四:API Gateway 上的 Cognito Authorizer vs Lambda Authorizer

如果 IdP 是 Amazon Cognito 使用者池,預設答案是 Cognito User Pool Authorizer。只有在情境提到非 Cognito IdP(Auth0、Firebase、自訂 JWT 發行者)、需要自訂授權邏輯(跨租戶檢查、外部資料庫查詢),或使用非 JWT 令牌(根據外部目錄驗證的 API 金鑰)時,Lambda Authorizer 才是正確答案。

陷阱五:「訪客存取」代表未驗證的身份池身份

如果考試情境說「允許任何人,包括未驗證的使用者,透過我的行動應用程式讀取這個 Amazon S3 bucket」,那要使用的是 Amazon Cognito 身份池的未驗證身份功能——不是使用 Principal: "*" 的 bucket 政策,也不是嵌入應用程式的 IAM 使用者。在身份池上啟用「允許未驗證身份」,並嚴格限制未驗證 IAM 角色的權限範圍。

陷阱六:Amazon Cognito 是區域性服務,AWS IAM 是全域性服務

Amazon Cognito 使用者池和身份池是區域性 AWS 資源。如果你需要使用者在多個區域登入並具備災難復原能力,你必須自行規劃區域複製(或使用全域資料庫層搭配區域特定的使用者池策略)。相比之下,AWS IAM 是全域的,不需要考慮區域規劃。

陷阱七:Lambda 觸發器 vs 自訂驗證流程

「在 JWT 中新增自訂聲明」= pre token generation Lambda 觸發器。「在首次登入時從舊版系統懶遷移使用者」= user migration Lambda 觸發器。「實作無密碼簡訊 OTP 登入、魔法連結或 Passkey」= 自訂驗證挑戰三件組(define / create / verify auth challenge),而不是單一觸發器。

練習題情境連結 — DVA-C02 Task 2.1 Cognito 情境

  • 「行動應用程式需要為每個已登入使用者直接上傳檔案到 Amazon S3。」→ Amazon Cognito 使用者池(登入)+ Amazon Cognito 身份池(臨時 AWS 憑證),搭配以 ${cognito-identity.amazonaws.com:sub} 限定 S3 前綴的 IAM 角色。
  • 「保護 Amazon API Gateway REST API,只允許我們 Web 應用程式的已登入使用者呼叫。」→ Amazon Cognito 使用者池 + API Gateway 上的 Cognito User Pool Authorizer
  • 「後端微服務需要呼叫內部 API Gateway 端點,沒有人類使用者。」→ OAuth 2.0 客戶端憑證授予,在使用者池中設定資源伺服器和自訂範圍;API Gateway HTTP API JWT Authorizer 驗證存取令牌的 scope 聲明。
  • 「客戶應能以 Google 或 Facebook 登入,且每人只有一筆使用者記錄。」→ 將 Google 和 Facebook 設定為聯合身份提供者的使用者池,搭配以電子郵件進行帳號連結
  • 「自動確認電子郵件以 @corp.example.com 結尾的使用者,拒絕其他人。」→ Pre sign-up Lambda 觸發器,檢查電子郵件網域,對受信任網域設定 autoConfirmUser: true,對其他人拋出例外。
  • 「將使用者的租戶 ID 注入 JWT,讓下游 API 無需資料庫查詢即可授權。」→ Pre token generation Lambda 觸發器。
  • 「封鎖來自已知遭洩露憑證的 IP 地址的登入。」→ 在使用者池上啟用進階安全功能,並設定自適應驗證 + 遭洩露憑證偵測。
  • 「從舊版 MySQL 驗證資料表懶遷移使用者,在首次登入時無需強制密碼重設。」→ User migration Lambda 觸發器。

FAQ — Amazon Cognito 高頻問題

Q1:什麼時候應該用 Amazon Cognito 使用者池,什麼時候用身份池?

當你需要讓使用者登入、管理帳號、發行 JWT 令牌,或透過 Amazon API Gateway 的 Cognito Authorizer 保護你自己的 API 時,使用 Amazon Cognito 使用者池。只有當客戶端應用程式(行動端或瀏覽器)需要直接呼叫 AWS API,因此需要臨時 AWS 憑證時,才使用 Amazon Cognito 身份池。大多數應用程式兩者搭配使用——使用者池負責驗證,身份池透過 AssumeRoleWithWebIdentity 將 JWT 轉換為 AWS 憑證。如果你的應用程式只與你自己的 API 通訊(不直接呼叫 AWS 服務),你大概不需要身份池。

Q2:ID 令牌、存取令牌和刷新令牌有什麼差別?

ID 令牌是包含身份聲明(subemailcognito:groups、自訂屬性)的 OIDC JWT;用它來在應用程式中識別使用者是誰存取令牌是包含範圍和 cognito:groups 的 OAuth 2.0 JWT;用它來授權 API 呼叫——尤其是使用 OAuth 資源伺服器範圍時。刷新令牌是不透明的長效令牌,用於在不要求使用者重新登入的情況下申請新的 ID 令牌和存取令牌。預設有效期:1 小時 / 1 小時 / 30 天,均可設定。

Q3:我的應用程式應該使用哪種 OAuth 2.0 流程?

伺服器渲染的 Web 應用程式和原生行動應用程式應使用授權碼授予(公開客戶端使用 PKCE,因為無法安全儲存客戶端 secret)。在 2026 年,單頁應用程式也應使用授權碼 + PKCE——隱式授予屬於舊版,應避免使用。客戶端憑證授予是後端對後端服務呼叫(沒有人類使用者)的正確流程;它只返回存取令牌,並需要在使用者池中設定包含自訂範圍的資源伺服器。不要將客戶端憑證與授權碼混淆——客戶端憑證沒有重導向,也沒有終端使用者。

Q4:如何用 Amazon Cognito 保護 Amazon API Gateway 端點?

建立 Amazon Cognito 使用者池和 App client。在 API Gateway 的方法(REST)或路由(HTTP API)上,附加一個指向該使用者池的 Cognito User Pool Authorizer。客戶端在 Authorization 標頭中傳送 JWT;API Gateway 使用使用者池的 JWKS 在本地驗證簽章(每次請求不需呼叫 Cognito),檢查 issaud/client_idtoken_useexp,並將聲明轉發給你的整合。對於 HTTP API,還需為每個路由設定所需的 OAuth 範圍,以檢查存取令牌的 scope 聲明。只有在 IdP 不是 Cognito 或你需要自訂邏輯時,才改用 Lambda Authorizer。

Q5:如何在使用者池發行的 JWT 中新增自訂聲明?

實作一個 pre token generation Lambda 觸發器。觸發器接收預設聲明,可以在 claimsToAddOrOverride 中新增或覆寫聲明,然後返回修改後的事件。Amazon Cognito 再對最終令牌進行簽署。典型的自訂聲明包括:租戶 ID、功能旗標、內部使用者 ID、角色——任何下游 API 需要用於授權而不想每次請求都進行額外資料庫查詢的資訊。

Q6:刷新令牌被撤銷後會發生什麼?

對刷新令牌呼叫 RevokeToken 會阻止該刷新令牌生成新的 ID 令牌和存取令牌。但是,已從該刷新令牌發行的 JWT 存取令牌,在其 exp 聲明到期之前仍然有效,因為第三方 API 是在本地根據使用者池的公鑰驗證 JWT 的——它們不會在每次請求時呼叫 Amazon Cognito。因此,如果撤銷傳播很重要,請將存取令牌有效期設為較短(5 至 60 分鐘)。aws.cognito.signin.user.admin 範圍是特例:即使在令牌的自然有效期內,Cognito 也會在撤銷後拒絕其使用。

Q7:如何將使用者從舊版驗證系統遷移到 Amazon Cognito?

User migration Lambda 觸發器是主要模式。當使用者以在 Amazon Cognito 使用者池中不存在的使用者名稱登入時,觸發器就會以提交的使用者名稱和密碼觸發;你的 Lambda 根據舊系統驗證,成功時返回使用者屬性,Amazon Cognito 透明地建立使用者池記錄。這讓使用者能在登入時逐步遷移,不需要密碼重設或大量匯入。若要大量匯入,Cognito 也支援基於 CSV 的使用者匯入(使用 AdminCreateUser 的變體),但這需要使用者在首次登入時重設密碼。

Q8:Amazon Cognito 如何與 AWS AppSync 整合?

AWS AppSync 支援以 Amazon Cognito 使用者池作為五種授權模式之一。客戶端在 Authorization 標頭中包含 JWT;AppSync 驗證它並將聲明公開給你的 resolver(直接 Amazon DynamoDB resolver、Lambda resolver 等)。你可以使用 @aws_auth schema 指令,將特定 GraphQL 欄位或 mutation 限制為特定的 cognito:groups。對於細粒度的逐筆記錄授權,可結合使用者池 JWT 模式與 VTL resolver 邏輯,在呼叫使用者的 sub 和記錄屬性(如 ownerId)之間進行比對。若要直接呼叫 AWS API,AppSync 也支援 AWS IAM 授權——通常搭配發行 IAM 憑證的 Amazon Cognito 身份池使用。

延伸閱讀

官方資料來源

更多 DVA-C02 主題