iT邦幫忙

2025 iThome 鐵人賽

DAY 12
1
Build on AWS

從一個網站的誕生,看懂 AWS 架構與自動化的全流程!系列 第 12

Day 12 API 安全守門員:API Gateway x Cognito 權杖驗證

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250926/20172743KWULDvyV2E.png

一、前言

在無伺服器架構中,API Gateway 是前端與後端的主要橋樑,但若缺乏嚴格的身份驗證與授權,API 容易被濫用或惡意存取,透過與 Cognito 整合,能以權杖(JWT Token)為核心,確保只有合法使用者能調用 API,兼顧安全與便利。

此 Lab 著重在 API 存取控制,讓前端呼叫後端服務時不再依靠靜態金鑰或弱密碼,而是以 Cognito 產生的權杖進行驗證,這能有效避免未授權存取,並成為後續 API 保護與 RBAC(角色型存取控制)的基礎。

白話來說,通常便於用戶,很多網站都會開發API的功能(像是快速做網頁內的任何操作),通常是用找到指定的API網址 + 使用被授權的角色/金鑰,就能快速取用該功能,而並非每次操作都要透過UI圖像介面。

而本次的實驗就是為了這個金鑰可以更安全,所以跟Cognito一起搭配,讓你的API不會被濫用。

二、需要使用到的服務

  • Amazon API Gateway:作為 API 入口,整合 Cognito 進行權杖驗證。
  • Amazon Cognito User Pools:管理使用者登入,並簽發 JWT Token(ID Token / Access Token)。
  • AWS Lambda:提供 API 背後邏輯,僅允許持有合法 Token 的請求進入。
  • CloudWatch Logs:監控 API 呼叫與權杖驗證失敗的紀錄。

三、架構/概念圖

https://ithelp.ithome.com.tw/upload/images/20250926/20172743cMnT5RAqj0.png

四、技術重點

(1) JWT Token 驗證:API Gateway 會自動驗證傳入的 JWT Token,包括其簽名、發行者(Issuer)和有效期限。
(2) Access Token vs. ID Token:建議使用 Access Token 作為 API 認證的依據,而非 ID Token。ID Token 主要是用來驗證使用者身分,而 Access Token 則是用來授權存取後端服務。
(3) Token 過期時間:設定合理的 Token 過期時間(一般建議 1 小時),避免長時間有效的 Token 遭竊取濫用。
(4 )擴展性:除了基本的驗證,你還可以結合 WAF(Web Application Firewall)進一步防禦惡意流量,或使用 Lambda Authorizer 實現更細緻的 RBAC(角色存取控制)。
(5)由於Day11中已啟用MFA,而MFA的驗證碼有時效限制,建議直接寫一個自動化腳本執行獲取AccessToken,並執行API。

♦可用JWT專用的Decoder工具來解碼:https://www.jwt.io/
https://ithelp.ithome.com.tw/upload/images/20250926/20172743CSNPRoUhp6.png

  • AccessToken:類似於「通行證」,通常較常使用這個,內部有比較多「權限」相關的資訊。
  • IdToken:類似於「身分證」,多為「使用者」相關的資訊。

五、Lab流程

1️⃣ 前置作業

  1. 確認已存在一個 Cognito User Pool 並可進行登入。

2️⃣ 主要配置

1. 創建一個Lambda函數(驗證User Token用)

  1. 進入「Lambda」服務頁面。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743Bgjm8jA3Q3.png

  2. 點選「創建函數」。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743jouS733oU1.png

  3. 輸入函數名稱、選用指定的代碼編輯器、執行角色,並按下建立。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743olOViqhgGb.png

  4. 退出推薦的模板。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743vOxIKSgLtV.png

  5. 撰寫Lambda內容+部署。

    • 程式碼範例

      export const handler = async (event) => {
          const response = {
            statusCode: 200,
            body: JSON.stringify('Hello, your token is valid! Then you can use the API to create some functions now. :3'),
          };
          return response;
        };
      

    https://ithelp.ithome.com.tw/upload/images/20250926/20172743noc0YNogO1.png

2. 在Cognito創建一個沒有secret的APP Client

  1. 創建一個新的APP Client。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743NpvFnD752q.png

  2. 選用非「傳統 Web 應用程式」及「Machine-to-machine應用程式」的應用程式用戶端及輸入APP名稱,並創建。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743ghjCLyAKdJ.png

    💡有「用戶端秘密(Client secret)」的APP Client無法使用session交換到Cognito的AccessToken或是IdToken,這是後面會執行的動作。

    • 為什麼不能選用這兩種「應用程式用戶端類型」?可參考文檔[2]中的規範。
      https://ithelp.ithome.com.tw/upload/images/20250926/20172743MHoOUI9ts9.png
  3. 創建完成畫面。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743NkEUMBgdTJ.png

3. 調整Cognito APP Client權限

  1. 編輯現在的應用程式用戶端(APP Client)。
    https://ithelp.ithome.com.tw/upload/images/20250926/201727431z5P5PCzOA.png

  2. 新增「ALLOW_USER_PASSWORD_AUTH」權限。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743U8TTGzJOMT.png
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743wH6yeEkSF1.png

  3. 完成修改。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743oEAZmTtYIM.png

4. 創建一個API Gateway(HTTP API 或 REST API)

  1. 進入「API Gateway」服務頁面。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743u61FpycZmv.png

  2. 點選「建立API」。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743gSLCZD4YyC.png

  3. 選用「HTTP API」。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743LYhvsf8DVS.png

  4. 創建API名稱及整合後端要使用的Lambda函數。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743JIDBa9eZSI.png

    • Lambda的函數 ARN在哪裡?
      https://ithelp.ithome.com.tw/upload/images/20250926/20172743vwheryMUrO.png
  5. 選用HTTP獲取方式及路徑。
    https://ithelp.ithome.com.tw/upload/images/20250926/201727431HNnAyCjjo.png

  6. 定義名稱(使用預設即可)。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743akvGjOAtiJ.png

  7. 確認創建。
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743yqILmWhjVX.png

  8. 確認路由路徑有整合Lambda。(表示經過API gateway後,會執行什麼動作)
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743dYjPDMfrVH.png

3. 設定API Gateway觸發驗證

  1. 創建一個新的授權方。
    https://ithelp.ithome.com.tw/upload/images/20250926/201727433F3884bAQe.png

  2. 創建授權方。

    • 範例路徑,路徑可參考文檔[1]
      https://cognito-idp.<Region>.amazonaws.com/<userpoolID>
      
      

    https://ithelp.ithome.com.tw/upload/images/20250926/20172743vGuprODjbs.png

    • Cognito「userpoolID」在哪裡?
      https://ithelp.ithome.com.tw/upload/images/20250926/201727432NxhpMTKpy.png

    • 對象(用戶端ID)在哪?
      https://ithelp.ithome.com.tw/upload/images/20250926/20172743VCClbqvhga.png

  3. 授權成功畫面。(表示要通過授權方驗證才能通過API Gateway)
    https://ithelp.ithome.com.tw/upload/images/20250926/20172743gZ10gXOXPK.png

3️⃣ 測試驗證

1. 透過SDK,成功登入並取得 JWT Token(AccessToken或是IdToken)

  1. 透過終端機(terminal)向Cognito取得 session

    • 第一段

      aws cognito-idp initiate-auth \
        --auth-flow USER_PASSWORD_AUTH \
        --client-id <Cognito_APP_CLIENT_ID> \
        --auth-parameters USERNAME=<username>,PASSWORD=<password>
      

    https://ithelp.ithome.com.tw/upload/images/20250926/20172743I45DUOzmEh.png

  2. 透過終端機(terminal),用 session向Cognito拿到對應的 IdTokenAccessToken

    • 第二段

      aws cognito-idp respond-to-auth-challenge \
        --client-id <Cognito_APP_CLIENT_ID> \
        --challenge-name SOFTWARE_TOKEN_MFA \
        --session <上一步回傳的Session> \
        --challenge-responses USERNAME=<username>,SOFTWARE_TOKEN_MFA_CODE=<六位數驗證碼>
      

    https://ithelp.ithome.com.tw/upload/images/20250926/20172743cQawbIzsZm.png

2. 使用 Token 測試 API

  1. 透過終端機(terminal),用 curl 測試是否API可以成功獲得授權,取得API Gateway後端運行的服務結果。

    • 第三段(建議使用AccessToken)

      curl -H "Authorization: Bearer <IdToken或AccessToken>" \
        https://<api_id>.execute-api.<region>.amazonaws.com/hello
      

    https://ithelp.ithome.com.tw/upload/images/20250926/20172743oZyHlcHZ4T.png

3. 測試未帶 Token 或帶錯誤 Token,應回傳 401 Unauthorized

https://ithelp.ithome.com.tw/upload/images/20250926/20172743ck0urosVAa.png

【補充】想要查看更多的錯誤狀況,可以在最後帶「-svo /dev/null」

https://ithelp.ithome.com.tw/upload/images/20250926/20172743MwEYIDkBDU.png
https://ithelp.ithome.com.tw/upload/images/20250926/20172743hApr3jcbpy.png

六、結語

本 Lab 將 Cognito 與 API Gateway 整合,實現以 JWT Token 為基礎的 API 安全機制,確保只有通過 Cognito 認證的使用者才能調用 API。這大幅提升 API 的安全性,避免未授權存取,並為後續的角色授權與存取管控打下基礎。


七、參考資料

[1] AWS API gateway - 使用 API Gateway 中的 JWT 授權方來控制對 HTTP API 的存取
https://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/http-api-jwt-authorizer.html

[2] AWS Cognito - 使用應用程式用戶端的應用程式特定設定
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html#user-pool-settings-client-app-client-types

【補充】
JWKS URI 包含有關簽署使用者權杖之私有金鑰的公開資訊。您可以在以下位置找到使用者集區的 JWKS URI(參照:https://docs.aws.amazon.com/zh_tw/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html),範例如下(未來可能會失效):

https://cognito-idp.us-east-1.amazonaws.com/us-east-1_0Kius6YBt/.well-known/jwks.json


上一篇
Day 11 安全機制再升級:Cognito 忘記密碼與 MFA 設定、黑名單禁止註冊
系列文
從一個網站的誕生,看懂 AWS 架構與自動化的全流程!12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言