什麼是身份驗證?登入、工作階段與 OAuth 簡單解說
身份驗證是 App 確認用戶身份的方式,通常透過檢查用戶知道的東西(密碼)、擁有的東西(發送到手機或電郵的驗證碼),或來自可信第三方服務的身份(例如「使用 Google 登入」)。用戶通過驗證後,App 會以工作階段或權杖記住他們,讓他們不必在每個頁面都重新登入。至於已知用戶可以做什麼,則屬於另一個步驟,稱為授權。
用 AI 做 App 時,為何重要
要求 AI 生成工具加入登入功能,是人們最常提出的要求之一,也是最容易出現細微錯誤的功能。登入頁面很容易生成,困難的地方在於周邊的一切:
- 密碼是否安全儲存?
- 每個私人頁面及每個 API 端點,是否真的核對了是誰在提出請求?
- 登入了的客戶,能否透過更改網址中的一個數字,看到別的客戶的資料?
- 用戶忘記密碼時會發生什麼事?
一個 App 可能看起來十分安全,卻在以上每一點都失敗。了解各個運作部件,有助你提出正確的問題,並測試正確的地方。
日常比喻
想像一下入住酒店。
在前台,你出示身份證明文件,這就是身份驗證:證明你是誰。接待員隨後給你一張門卡,這張卡就是你的工作階段:在整個住宿期間,你不必再出示證件,只需用卡感應便可。
這張卡能開啟你的房間、健身室,以及通往你樓層的升降機,但開不了其他住客的房間,也進不了員工辦公室。這就是授權:你的身份獲准存取什麼。如果你遺失了卡,酒店可以在前台把它停用(撤銷工作階段)。退房後,卡便失效(登出或到期)。
「使用 Google 登入」就像酒店接受一位可信夥伴的信件,信中說「這位是誰」,而不是自己核對你的身份證件。
主要登入方式
| 方式 | 運作原理 | 優點 | 缺點 |
|---|---|---|---|
| 電郵加密碼 | 用戶設定密碼;App 儲存其雜湊值 | 熟悉,不依賴外部服務 | 你必須安全地儲存雜湊值,並處理重設密碼 |
| 魔術連結/一次性驗證碼 | App 以電郵發送連結或驗證碼,讓用戶登入 | 沒有可能外洩或遺忘的密碼 | 依賴電郵送達;登入較慢 |
| 社交登入(OAuth / OpenID Connect) | 用戶以 Google、Apple、GitHub 等帳戶登入 | 對用戶來說很快;你不必儲存密碼 | 每個供應商都要另外設定;沒有該等帳戶的用戶無法使用 |
| 代管式身份驗證供應商 | Clerk、Auth0 或 Supabase Auth 等服務處理註冊、登入與重設 | 你需要處理的安全工作較少 | 規模擴大後需付月費;多一項依賴 |
| 多重驗證(MFA / 2FA) | 第一步之後再加一重核對,例如驗證器應用程式的驗證碼 | 更難被入侵 | 操作稍微麻煩 |
密碼應如何儲存
安全的 App 從不儲存你的實際密碼,而是儲存一個雜湊值(hash):把密碼經單向函數轉換成一串固定字串的結果。登入時,App 會把你輸入的內容雜湊,再與已儲存的雜湊值比較。
有兩個細節令這做法安全:
- 鹽值(salt):在雜湊前為每個密碼加入的隨機值,令兩個密碼相同的人得到不同的雜湊值,預先算好的查找表因此無用。
- 專為密碼而設、運算較慢的演算法:例如 Argon2、bcrypt 或 scrypt。MD5 或 SHA-256 這類通用雜湊本身速度太快,攻擊者可以嘗試數十億次猜測。
雜湊與加密不同。加密的資料可以用金鑰解密;密碼雜湊則設計成完全不可逆。
工作階段與權杖
登入後,App 需要在每個請求中認出你。常見的做法有兩種。
| 工作階段(Cookie) | 權杖(例如 JWT) | |
|---|---|---|
| 瀏覽器持有什麼 | Cookie 中的隨機工作階段 ID | 已簽署的權杖,內含用戶資料及到期時間 |
| 登入狀態存放在哪裡 | 伺服器上,位於資料庫或儲存區 | 存在權杖本身之中 |
| 在所有裝置上強制登出 | 容易:在伺服器刪除工作階段 | 較難:權杖在到期前一直有效,除非你維護封鎖清單 |
| 典型用途 | 傳統網頁 App | API、手機 App、服務之間的通訊 |
對於 Cookie,有三項設定尤其重要:HttpOnly(頁面上的 JavaScript 不能讀取該 Cookie)、Secure(只透過 HTTPS 傳送)及 SameSite(限制來自其他網站的請求時傳送它)。把權杖存放在瀏覽器的 localStorage 雖然很常見,但會令任何在頁面上運行的腳本都能讀取它。
OAuth 與「使用 Google 登入」
OAuth 2.0 是委派授權的標準,讓 App 在另一服務中獲得你帳戶的有限權限,例如讀取你的 Google 日曆,而全程無需看到你的 Google 密碼。你會被引導到 Google,批准特定權限(稱為範圍(scopes)),然後 Google 只把這些權限的權杖交給該 App。
OAuth 本身的設計目的是授予存取權,而非確認你是誰。OpenID Connect(OIDC)則是建基於 OAuth 2.0 之上的一層,加入了身份資訊,「使用 Google 登入」或「使用 Apple 登入」便是用它。要設定時,你需要在供應商處註冊你的 App,取得用戶端 ID(client ID)及用戶端密鑰(client secret);密鑰必須留在你的伺服器上。
實例:為客戶入口網站加入登入
假設你要建立一個入口網站,讓一間設計公司的客戶查看其項目及發票。
- 身份驗證:客戶以電郵及魔術連結登入,因此無需管理密碼。公司員工則以 Google Workspace 帳戶登入。
- 角色:每位用戶都有一個角色,即
client(客戶)或staff(員工)。 - 授權規則:
| 操作 | 客戶 | 員工 |
|---|---|---|
| 查看本公司的項目 | 可以 | 可以 |
| 查看其他公司的項目 | 不可以 | 可以 |
| 為項目上載檔案 | 只限自己的項目 | 可以 |
| 將發票標示為已付 | 不可以 | 可以 |
- 在哪裡執行:在伺服器上,針對每個請求執行。伺服器會找出已登入的用戶,然後只返回
project.company_id與該用戶所屬公司相符的項目。單單隱藏「標示已付」按鈕並不足夠,端點本身也必須拒絕請求。
重要詞彙
| 詞彙 | 意思 |
|---|---|
| 身份驗證(AuthN) | 確認某人是誰。 |
| 授權(AuthZ) | 決定某人可以做什麼。 |
| 工作階段(Session) | App 在多次請求之間記住你已登入的狀態。 |
| Cookie | 瀏覽器每次向網站發送請求時都會送回的一小段資料。 |
| JWT | JSON Web Token:已簽署的精簡權杖,載有用戶 ID、到期時間等聲明(claims)。 |
| 角色/權限 | 例如 admin(管理員)或 member(成員)等標籤,用來決定存取權。 |
| MFA / 2FA | 要求第二重證明,例如驗證器應用程式的驗證碼。 |
| SSO | 單一登入(Single sign-on):一次登入(通常是公司帳戶),即可使用多個應用程式。 |
| 401 與 403 | 「你是誰?」(未通過驗證)與「你不可以這樣做」(未獲授權)。 |
常見錯誤與誤解
- 只在頁面上檢查權限。 如果瀏覽器隱藏了按鈕,但 API 沒有核對,任何人都可以直接呼叫該 API。
- 信任網址中的 ID。
/invoices/1042必須確認發票 1042 屬於已登入的用戶。 - 自行創造加密方案。 請使用廣泛使用的程式庫或供應商,不要讓 AI 發明雜湊方案。
- 重設密碼機制薄弱。 重設連結應只能使用一次、很快過期,並且不應透露某電郵是否有帳戶。
- 把你的 App 登入與生成工具的登入混為一談。 App 的用戶與你在建構工具上的帳戶是兩回事。
- 登入沒有速率限制。 沒有它,攻擊者便可以不斷嘗試密碼。
可以要求你的 AI 生成工具做的事
- 「使用[某個廣泛使用的程式庫或供應商]加入註冊及登入。不要自行撰寫密碼雜湊。」
- 「以 bcrypt 或 Argon2 雜湊儲存密碼。」
- 「為工作階段使用 HttpOnly、Secure 的 Cookie。」
- 「加入角色:admin 與 member。列出每個端點,以及可以呼叫它的角色。」
- 「在伺服器上強制執行:用戶只能讀取及編輯自己的紀錄。然後向我展示你如何核對。」
- 「加入密碼重設功能,連結只能使用一次,並在一小時後過期。」
- 「限制登入嘗試的次數。」
之後請親自測試:以兩個帳戶登入,嘗試在一個帳戶登入時讀取另一個帳戶的資料。我們的加入登入指南及AI 生成 App 安全清單可以提供更多資訊。
Mythex 中的身份驗證
Mythex 沒有為你 App 的用戶提供內建的身份驗證產品。你需要自行選擇方案,例如把電郵及密碼儲存在專案的資料庫中,或使用供應商的 SDK,然後要求代理程式加入。供應商金鑰應放在專案機密中,而不是放在聊天內。這與你如何登入 Mythex 本身是分開的。說明文件中的為 App 加入登入食譜提供了可改寫的起始提示,而什麼是 API則解釋了這些伺服器端檢查應放在哪裡。
常見問題
身份驗證與授權有什麼分別?
身份驗證確認你是誰,例如核對你的密碼。授權則決定你獲確認身份後可以做什麼,例如能否查看管理頁面,或編輯別人的預約。App 兩者都需要。
什麼是 OAuth?
OAuth 2.0 是一項標準,讓 App 在另一服務中獲得你帳戶的有限權限,而無需看到你的密碼。「使用 Google 登入」採用 OpenID Connect,它是建基於 OAuth 2.0 之上的身份層,讓 App 從 Google 得知你是誰。
我的 App 應否儲存密碼?
絕不應以可讀的形式儲存。如果你採用電郵加密碼登入,密碼必須以加鹽雜湊(salted hash)儲存,並使用專為密碼設計、運算較慢的演算法,例如 Argon2 或 bcrypt。許多 App 會改用代管式身份驗證供應商、社交登入或電郵魔術連結,以避開這個問題。
應使用工作階段還是權杖?
兩者都可行。工作階段把登入狀態儲存在伺服器,並在 Cookie 中給瀏覽器一個隨機 ID,容易撤銷。權杖(例如 JWT)本身載有已簽署的資料,適合 API 及手機用戶端,但在到期前較難取消。對一般網頁 App 來說,以 Cookie 為基礎的工作階段是穩妥的預設選擇。