iT邦幫忙

2025 iThome 鐵人賽

DAY 15
0
Vue.js

打造銷售系統30天修練 - 全集中・Vue之呼吸系列 第 15

Day 15:[Authの呼吸・壹之型] SSO整合 - Google OAuth登入實作(上)

  • 分享至 

  • xImage
  •  

在 Day 14,我們成功地將各個元件組合成一個精美的登入表單。但一個沒有實際驗證功能的登入頁。今天,我們將踏入使用者驗證的領域,修煉「Authの呼吸・壹之型:SSO整合」。

在正式動手前,讓我們先回答兩個基本但至關重要的問題:什麼是 SSO?以及,我們為什麼要選擇 Google 作為我們的 SSO ?

什麼是 SSO (Single Sign-On)?

SSO,全名為「單一登入」(Single Sign-On),是一種允許使用者使用「單一一組」登入憑證(例如:Google 帳號、Facebook 帳號),來登入多個不同應用程式或網站的驗證機制。

你可以把它想像成一張「萬能鑰匙」。過去,你每到一個地方(網站),就需要一把專屬的鑰匙(一組新的帳號密碼)。時間久了,你的鑰匙圈變得又大又重,還常常找不到對應的鑰匙。而 SSO 就是一張萬能鑰匙,你只需要保管好這一張,就可以輕鬆打開所有支援它的門。

使用者而言,好處顯而易見:

  • 極致便利:不用再為每個網站記憶不同的帳號密碼。
  • 快速登入:通常只需點擊一下,即可完成登入,省去填寫表單的麻煩。

開發者與企業而言,導入 SSO 也有莫大誘因:

  • 降低註冊門檻:使用者註冊意願更高,有助於提升轉換率。
  • 提升安全性:將密碼管理等複雜且高風險的工作,委託給像 Google 這樣的大型專業公司處理。
  • 簡化使用者資料管理:在使用者同意下,可以從 SSO 供應商那裡獲取基本的用户資料(如姓名、Email),無需再讓使用者手動填寫。

我們為什麼選擇 Google SSO?

在眾多 SSO 供應商中(如 Facebook, Line...),我們選擇 Google 作為第一個整合的對象,這背後有一個非常明確且關鍵的理由:我們公司本身就是採用 Google Workspace,每位員工在入職時都會配發一組公司專屬的 Google Email (@your-company.com)。

這使得 Google SSO 從一個「選項」變成了「標準答案」。基於這個前提,整合 Google 登入能帶來以下核心優勢:

  1. 無縫的內部驗證:由於系統的使用者(業務人員)都擁有公司配發的 Google 帳號,我們可以確保只有公司員工才能登入此 POS 系統,完美符合內部工具的權限控管需求。
  2. 簡化帳號生命週期管理:當有新員工入職或員工離職時,IT 部門只需要管理他們的 Google Workspace 帳號即可。一旦員工的 Google 帳號被停用,他將自動失去登入 POS 系統的權限,大幅簡化了權限的維護工作。
  3. 統一的專業身份:員工使用他們的工作用 Email 登入,而非個人 Gmail,確保了公私分明,也讓系統後台的使用者紀錄更清晰、更專業。
  4. 開發者友善:承上,Google 提供了非常完整且清晰的開發者文件與函式庫(例如我們即將使用的 Google Identity Services),讓我們可以快速地將這套內部驗證機制整合進來。

理解了這個選擇背後的商業與管理邏輯後,接下來,讓我們深入了解實現這一切的技術核心——OAuth 2.0 授權流程。

OAuth 2.0 授權碼流程 (Authorization Code Flow) 詳解

OAuth 2.0 是一個關於「授權」的開放標準。它允許使用者授權一個第三方應用程式(例如我們的銷售系統)去存取他們在另一個服務(例如 Google)上的特定資源,而無需將使用者名稱和密碼直接提供給該第三方應用程式。

我們將採用其中最常見且安全的流程:「授權碼流程 (Authorization Code Flow)」。這個流程有點像這樣:

授權碼流程圖

  1. 授權請求:使用者在我們的 POS 系統點擊「使用 Google 登入」,應用程式向 Google 的授權伺服器發出授權請求。
  2. 使用者同意授權:使用者在 Google 的登入與授權頁面輸入帳號密碼,並同意授權應用程式存取其基本資料。
  3. 通知應用程式:授權伺服器確認授權後,通知應用程式授權已完成。
  4. 發送 Access Token:授權伺服器直接將 Access Token 回傳給應用程式。
  5. 驗證與使用 Token:應用程式攜帶 Access Token,向 Google 的資源伺服器請求受保護的使用者資料。
  6. 取得受保護資源:資源伺服器驗證 Token 後,將使用者資料(如姓名、Email)回傳給應用程式,登入流程完成。。

在這個流程中,我們的前端(Vue App)主要負責 1 到 3 步,也就是引導使用者完成授權並取得「授權碼」。而 4 到 6 步 則是後端的職責。

參考內容:30 天與九頭蛇先生做好朋友 系列 第 3 篇 - OAuth 2.0 授權流程

前置作業一:取得 Google Client ID

在開始寫程式碼之前,我們必須先向 Google 註冊我們的應用程式,以取得一組專屬的「用戶端 ID (Client ID)」。

  1. 前往 Google Cloud Console:登入您的 Google 帳號,並進入 Google Cloud Console
  2. 建立新專案:如果您還沒有專案,請點擊頂端的專案選單,並選擇「新增專案」。
  3. 啟用 API:通常在建立 OAuth 憑證時會自動啟用,但請確保您的專案已啟用 Google Identity Services API
  4. 設定 OAuth 同意畫面
    • 在左側導覽列找到「API 和服務」>「OAuth 同意畫面」。
    • 選擇「外部」使用者類型,然後點擊「建立」。
    • 填寫必要的應用程式資訊,例如應用程式名稱、使用者支援電子郵件等。
    • 在「已授權的網域」部分,新增您應用程式的網域(在開發階段,可以暫時跳過)。
  5. 建立 OAuth 2.0 用戶端 ID
    • 在左側導覽列找到「API 和服務」>「憑證」。
    • 點擊「+ 建立憑證」,選擇「OAuth 2.0 用戶端 ID」。
    • 應用程式類型選擇「網頁應用程式」。
    • 設定「已授權的 JavaScript 來源」:這是您應用程式的來源網址。對於本地開發,請填入 http://localhost:5173 (或您 Vite 專案的實際 Port)。
    • 設定「已授權的重新導向 URI」:這是 Google 完成授權後要將使用者導回的網址。同樣,請填入 http://localhost:5173
    • 點擊「建立」,您就會看到一組用戶端 ID (Client ID)。請妥善保管它!

前置作業二:專案設定

有了 Client ID 後,我們需要在專案中進行兩項設定。

1. 引入 Google Identity Services Script

我們需要在 index.html<head> 區塊中,加入 Google 的官方 JavaScript 函式庫。

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <!-- Google Identity Services -->
    <script src="https://accounts.google.com/gsi/client" async defer></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

async defer 屬性可以確保這個腳本的載入和執行不會阻塞頁面的渲染。

2. 設定環境變數

為了不將敏感的 Client ID 直接寫在程式碼中,我們使用 Vite 提供的環境變數功能。

在專案根目錄下建立一個 .env 檔案,並將您的 Client ID 填入:

# /.env

VITE_GOOGLE_CLIENT_ID="YOUR_GOOGLE_CLIENT_ID.apps.googleusercontent.com"

重要:這邊Vite 要求客戶端可見的環境變數必須以 VITE_ 開頭。

總結

至此,所有的前置作業都已完成!我們已經理解了 OAuth 的流程,並取得了必要的憑證。在下篇,Day 16:[Authの呼吸・貳之型] SSO整合 - Google OAuth登入實作(下),用程式碼實現這一切。


上一篇
Day 14:[Componentの呼吸・柒之型] Form組合 - 基礎登入表單實作
系列文
打造銷售系統30天修練 - 全集中・Vue之呼吸15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言