使用 Identity-Aware Proxy 驗證使用者身分

1. 簡介

驗證網頁應用程式的使用者通常是必要的,而且通常需要在應用程式中進行特殊程式設計。就 Google Cloud Platform 應用程式而言,您可以將這些責任交給 Identity-Aware Proxy 服務。若只需要限制特定使用者的存取權,則無須對應用程式進行任何變更。如果應用程式需要知道使用者的身分 (例如為了將使用者偏好保留於伺服器端),則 Identity-Aware Proxy 可運用最少的應用程式程式碼提供這項資訊。

什麼是 Identity-Aware Proxy?

Identity-Aware Proxy (IAP) 是一項 Google Cloud Platform 服務,可攔截傳送至應用程式的網頁要求、透過 Google Identity 服務驗證提出要求的使用者,並且只有在要求來自您授權的使用者時才會通過。此外,這項功能還能修改要求標頭,加入已驗證使用者相關資訊。

本程式碼研究室將引導您建立自己的應用程式、限制存取應用程式,以及透過 IAP 取得使用者身分。

建構目標

在本程式碼研究室中,您會使用 Google App Engine 建構極少量的網頁應用程式,接著探索各種使用 Identity-Aware Proxy 限制應用程式存取權的方式,並向應用程式提供使用者身分資訊。您的應用程式將會:

  • 顯示歡迎頁面
  • 存取 IAP 提供的使用者身分資訊
  • 採用加密編譯驗證,防止使用者身分資訊遭到假冒

課程內容

  • 如何使用 Python 3.7 編寫及部署簡單的 App Engine 應用程式
  • 如何啟用和停用 IAP 以限制應用程式存取權
  • 如何透過 IAP 取得使用者身分資訊並提供給應用程式
  • 如何以加密編譯的方式驗證 IAP 提供的資訊,防範假冒行為

軟硬體需求

  • 使用新型網路瀏覽器,例如 Chrome
  • 具備 Python 程式設計語言的基本知識

本程式碼研究室著重於 Google App Engine 和 IAP。我們不會對與本主題無關的概念和程式碼多做介紹,但會事先準備好這些程式碼區塊,屆時您只要複製及貼上即可。

2. 開始設定

您將在 Cloud Shell 指令列環境中操作。首先,開啟該環境並擷取程式碼範例。

啟動控制台和 Cloud Shell

按一下研究室頁面左上方的「Open Google Console」按鈕。您必須使用該按鈕下方顯示的使用者名稱與密碼登入。

系統會在 Cloud Shell 中為您建立和開啟的專案執行本程式碼研究室中的所有指令。按一下控制台頁面標頭右側的「啟用 Cloud Shell」圖示,開啟 Cloud Shell。您可以在頁面的下半部輸入並執行指令。指令可以在您的電腦上執行,但您必須先安裝及設定必要的開發軟體。Cloud Shell 已有您需要的所有軟體工具。

下載程式碼

點選 Cloud Shell 中的指令列區域,即可使用指令。從 GitHub 擷取程式碼,然後變更為程式碼資料夾:

git clone https://github.com/googlecodelabs/user-authentication-with-iap.git
cd user-authentication-with-iap

這個資料夾包含本程式碼研究室每個步驟的子資料夾。您必須切換至正確的資料夾才能執行每個步驟。

3. 步驟 1 - 部署應用程式並使用 IAP 保護應用程式

這是以 Python 3.7 編寫的 App Engine Standard 應用程式,這個應用程式只會顯示「Hello, World」歡迎頁面。我們會部署並測試應用程式,然後使用 IAP 限制相關存取權。

查看應用程式程式碼

從主要專案資料夾變更為包含這個步驟程式碼的 1-HelloWorld 子資料夾。

cd 1-HelloWorld

應用程式程式碼位於 main.py 檔案中。會使用 Flask 網路架構,使用範本內容回應網路要求。這個範本檔案位於 templates/index.html,在這個步驟中,只有純 HTML 檔案。第二個範本檔案包含 templates/privacy.html 中的基本隱私權政策範例。

還有兩個檔案:requirements.txt 會列出應用程式使用的所有非預設 Python 程式庫,app.yaml 則會告知 Google Cloud Platform 是否為 Python 3.7 App Engine 應用程式。

您可以使用 cat 指令在殼層中列出每個檔案,如下所示:

cat main.py

或者,您也可以按一下 Cloud Shell 視窗右上角的鉛筆圖示,開啟 Cloud Shell 程式碼編輯器,然後檢查程式碼。

在這個步驟中,您不需要變更任何檔案。

部署至 App Engine

現在,將應用程式部署至 Python 3.7 適用的 App Engine 標準環境

gcloud app deploy

系統可能會要求您選擇要部署的區域。如果附近顯示「支援標準」字樣,請選取附近商家。當系統詢問是否要繼續進行時,請輸入 Y 表示「是」。

部署應該會在幾分鐘內完成,屆時您將會看到可透過 gcloud app browse 查看應用程式的訊息。輸入該指令。如果瀏覽器沒有開啟新分頁,請按一下顯示的連結以在新分頁中開啟,或視需要將分頁複製到手動開啟的新分頁。由於是首次執行該應用程式,啟動雲端執行個體時需要幾秒鐘時間才會顯示,接著您應該會看到以下視窗。

1c1c0b166c6023e.png

您可以在任何連線至網際網路的電腦上開啟同一個網址,查看該網頁。存取權尚未受到限制。

透過 IAP 限制存取權

在 Cloud 控制台視窗中,依序點選頁面左上方的「選單」圖示 >「安全性」,然後點選「Identity-Aware Proxy」。

由於這是您第一次為這項專案啟用驗證選項,因此系統會顯示訊息,請您先設定 OAuth 同意畫面,才能使用 IAP。

按一下「設定同意畫面」按鈕。系統隨即會開啟新分頁,讓您設定同意畫面。

在所需欄位中填入適當的值:

應用程式名稱

應用程式內購範例

支援服務電子郵件地址

您的電子郵件地址。系統可能已為你填入內容

已授權網域

應用程式網址的主機名稱部分,例如iap-example-999999.appspot.com。您可以在先前開啟的 Hello World 網頁的網址列中查看這項資訊。請勿加入該網址的開頭 https:// 或結尾為 /填入這個值後,您必須按下 Enter 鍵。

應用程式首頁連結

您用來瀏覽應用程式的網址

應用程式隱私權政策連結

應用程式中的隱私權頁面連結,就是在結尾加上 /privacy 的首頁連結

按一下「儲存」。系統會提示您建立憑證。您不需要為本程式碼研究室建立憑證,只要關閉這個瀏覽器分頁即可。

返回 Identity-Aware Proxy 頁面並重新整理。現在,您應該會看到可保護的資源清單。在「App Engine 應用程式」資料列中,按一下「IAP」欄中的切換鈕以啟用 IAP。

您會看見將受 IAP 保護的網域名稱。按一下「開啟」。

現在,請開啟瀏覽器分頁,然後前往應用程式的網址。系統會顯示「使用 Google 帳戶登入」畫面,您必須登入才能存取應用程式。

請使用 Google 或 G Suite 帳戶登入。畫面會顯示「拒絕存取」。

您已成功使用 IAP 保護應用程式,但尚未指示 IAP 哪些帳戶有存取權。

返回控制台的「Identity-Aware Proxy」頁面,勾選 App Engine 應用程式旁邊的核取方塊,然後查看頁面右側的側欄。

您必須將允許存取的電子郵件地址 (或 Google 群組地址或 G Suite 網域名稱) 新增為成員。按一下新增成員。輸入您的電子郵件地址,然後選擇要指派給該地址的 Cloud IAP/IAP 保護網頁應用程式使用者角色。您可以使用同樣的方式輸入更多地址或 G Suite 網域。

按一下「儲存」。系統隨即會在視窗底部顯示「已更新政策」訊息。

返回應用程式,然後重新載入頁面。您現在應會看見網頁應用程式,因為您已經透過授權的使用者登入。不過,您仍然可能看到「您沒有存取權」因為 IAP 可能不會重新檢查您的授權。在這種情況下,請執行下列步驟:

  • 開啟網路瀏覽器並前往首頁網址,並在網址結尾加上 /_gcp_iap/clear_login_cookie,例如:https://iap-example-999999.appspot.com/_gcp_iap/clear_login_cookie
  • 您會看到新的「使用 Google 帳戶登入」畫面,當中顯示您的帳戶。請不要點選該帳戶,而是點選「使用其他帳戶」,然後重新輸入憑證。
  • 這些步驟會使 IAP 重新確認存取權限,您現在應該可以看到應用程式的主畫面。

如果您可以使用其他瀏覽器,或是在瀏覽器中使用無痕模式,並且擁有其他有效的 Gmail 或 G Suite 帳戶,您就可以使用該瀏覽器前往您的應用程式頁面,然後使用其他帳戶登入。由於該帳戶尚未獲得授權,因此會顯示「您沒有存取權」畫面,而不是應用程式頁面。

4. 步驟 2:存取使用者身分資訊

應用程式受到 IAP 保護後,就能使用 IAP 在網頁要求標頭中提供的身分資訊。在這個步驟中,應用程式將取得已登入使用者的電子郵件地址,以及 Google Identity 服務指派給該使用者的永久專屬使用者 ID。系統會在歡迎頁面向使用者顯示這項資料。

此為步驟 2,最後一個步驟則是在 iap-codelab/1-HelloWorld 資料夾中開啟 Cloud Shell。變更為用來執行這個步驟的資料夾:

cd ~/iap-codelab/2-HelloUser

部署至 App Engine

由於部署作業需要幾分鐘才能完成,請先將應用程式部署至 Python 3.7 適用的 App Engine 標準環境:

gcloud app deploy

當系統詢問您是否要繼續時,請輸入 Y 表示「是」。部署應該會在幾分鐘內完成。等待過程中,您可以按照下方說明檢查應用程式檔案。

部署作業準備就緒時,您會收到訊息,您可以使用 gcloud app browse 查看應用程式。輸入該指令。如果瀏覽器未開啟新分頁,請將顯示的連結複製到新分頁正常開啟。您應該會看到類似以下頁面:

5b5fb03111258cec.png

系統可能需要幾分鐘,才能將先前的應用程式版本替換為新版本。請視需要重新整理頁面,以查看類似上述內容的頁面。

檢查應用程式檔案

這個資料夾包含您在步驟 1 中看到的同一組檔案,但系統變更了 main.pytemplates/index.html 這兩個檔案,該程式已改為檢索 IAP 在要求標頭中提供的使用者資訊,且範本現在也會顯示該項資料。

main.py 中有兩行可取得 IAP 提供的身分識別資料:

user_email = request.headers.get('X-Goog-Authenticated-User-Email')
user_id = request.headers.get('X-Goog-Authenticated-User-ID')

X-Goog-Authenticated-User- 標頭是由 IAP 提供且名稱不區分大小寫,因此,您可以視需要全部大寫或全部大寫。render_template 語句現在包含這些值,因此可以顯示:

page = render_template('index.html', email=user_email, id=user_id)

index.html 範本能以雙大括號括住名稱,即可顯示這些值:

Hello, {{ email }}! Your persistent ID is {{ id }}.

如您所見,提供的資料前方會加上 accounts.google.com:顯示資訊來源。應用程式可視需要移除包括半形冒號在內的所有內容,以取得原始值。

停用 IAP

如果停用或以某種方式 (例如透過同一個雲端專案中執行的其他應用程式) 略過 IAP,會對應用程式有什麼影響?停用 IAP 以查看後續影響。

在 Cloud 控制台視窗中,依序點選頁面左上方的「選單」圖示 >「安全性」,然後點選「Identity-Aware Proxy」。按一下 App Engine 應用程式旁邊的 IAP 切換鈕,即可關閉 IAP。

系統會提醒您,停用 IAP 後所有使用者都可以存取該應用程式。

重新整理應用程式網頁您應該會看到相同的頁面,但沒有顯示任何使用者資訊:

17c850de95fea839.png

應用程式目前未受到保護,因此使用者可以發送看似透過 IAP 傳送的網頁要求。舉例來說,透過 Cloud Shell 執行下列 curl 指令即可 (請將 <your-url-here> 替換成應用程式的正確網址):

curl -X GET <your-url-here> -H "X-Goog-Authenticated-User-Email: totally fake email"

網頁會顯示在指令列中,如下所示:

<!doctype html>
<html>
<head>
  <title>IAP Hello User</title>
</head>
<body>
  <h1>Hello World</h1>

  <p>
    Hello, totally fake email! Your persistent ID is None.
  </p>

  <p>
    This is step 2 of the <em>User Authentication with IAP</em>
    codelab.
 </p>

</body>
</html>

應用程式無法知道 IAP 是否遭到停用或略過。如果可能有潛在風險,步驟 3 會顯示解決方案。

5. 步驟 3:使用加密編譯驗證

如果 IAP 可能遭到停用或略過,您的應用程式可確認收到的身分資訊是否有效。這會使用 IAP 新增的第三個網路要求標頭,稱為 X-Goog-IAP-JWT-Assertion。該標頭的值是以加密編譯方式簽署的物件,也包含使用者身分資料。應用程式可驗證數位簽章,並使用該物件中提供的資料確保這個簽章是出自 IAP,未經修改。

數位簽章驗證需要幾個額外的步驟,例如檢索最新的 Google 公開金鑰。您可以根據使用者可能停用或略過 IAP 的可能性,以及應用程式的敏感度,決定應用程式是否需要這些額外步驟。

此為步驟 3,最後一個步驟則是在 iap-codelab/2-HelloUser 資料夾中開啟 Cloud Shell。變更為用來執行這個步驟的資料夾:

cd ~/iap-codelab/3-HelloVerifiedUser

部署至 App Engine

將應用程式部署至 Python 3.7 適用的 App Engine 標準環境:

gcloud app deploy

當系統詢問您是否要繼續時,請輸入 Y 表示「是」。部署應該會在幾分鐘內完成。等待過程中,您可以按照下方說明檢查應用程式檔案。

部署作業準備就緒時,您會收到訊息,您可以使用 gcloud app browse 查看應用程式。輸入該指令。如果瀏覽器未開啟新分頁,請將顯示的連結複製到新分頁正常開啟。

提醒您,您已經在步驟 2 中停用 IAP,因此系統並未將 IAP 資料提供給應用程式。您應該會看到類似以下頁面:

8ef2abcc23d96958.png

如同之前的情況,系統可能需要幾分鐘才能將最新版本上線,屆時才能看到新版頁面。

IAP 已停用,因此沒有提供使用者資訊。現在重新啟用 IAP。

在 Cloud 控制台視窗中,依序點選頁面左上方的「選單」圖示 >「安全性」,然後點選「Identity-Aware Proxy」。按一下 App Engine 應用程式旁邊的 IAP 切換鈕,即可再次啟用 IAP。

重新整理頁面。頁面應如下所示:

(3a4d93c11f228852.png)

請注意,透過已驗證方法提供的電子郵件地址不含 accounts.google.com: 前置字元。

如果停用或略過 IAP,經過驗證的資料會遺失或失效,原因是不具備有效簽章,除非是由 Google 私密金鑰持有者所建立的資料。

檢查應用程式檔案

這個資料夾內含與步驟 2 中相同的一組檔案,其中兩個檔案有所不同,一個是新的檔案。新檔案是 auth.py,提供的 user() 方法可擷取及驗證經加密簽署的身分資訊。已變更的檔案包括 main.pytemplates/index.html,現在會使用該方法的結果。系統也會顯示步驟 2 中的未經驗證標頭,方便您進行比較。

新功能主要位於 user() 函式中:

def user():
    assertion = request.headers.get('X-Goog-IAP-JWT-Assertion')
    if assertion is None:
        return None, None

    info = jwt.decode(
        assertion,
        keys(),
        algorithms=['ES256'],
        audience=audience()
    )

    return info['email'], info['sub']

assertion 是指定要求標頭中提供的加密簽署資料。該程式碼會使用程式庫驗證並解碼該資料。驗證作業採用 Google 提供的公開金鑰檢查相關簽署資料,並瞭解資料目標對象 (基本上是指受到保護的 Google Cloud 專案)。輔助函式 keys()audience() 會收集並傳回這些值。

已簽署的物件含有我們需要的兩項資料:已驗證的電子郵件地址,以及專屬 ID 值 (由 sub 針對訂閱者、標準欄位提供)。

這樣步驟 3 就完成了。

6. 摘要

您部署了 App Engine 網頁應用程式。在步驟 1 中,您已限制應用程式存取權,只允許您選擇的使用者存取。在步驟 2 中,您擷取並顯示受 IAP 允許存取您應用程式的使用者身分,並且看到瞭如果停用或規避 IAP 停用或略過 IAP 之後可能遭到假冒的資訊。在步驟 3 中,您驗證了使用者身分的加密簽署斷言,因此無法遭人假冒。

7. 清除

您在本程式碼研究室中只使用 App Engine 執行個體。每次部署應用程式時,系統都會建立新版本,直到刪除為止。離開研究室即可刪除專案和當中的所有資源。