WebAuthn:網頁上使用指紋、安全金鑰來認證

現在安全性越來越講究了,很多網站都開放使用二步驟驗證,甚至可以使用實體的安全金鑰(YubiKey、Ledger Nano、Google Titan 等);而手機端許多也支援指紋認證,不需要一直輸入密碼就能安全登入。這篇文章會來討論這些東西大概是怎麼做的。

哪些地方可以用?

先把 WebAuthn 當作一種驗證方式,它可以用來驗證實體的安全金鑰(USB、藍牙、NFC 等)、指紋、臉部辨識......等等,不需要密碼就可以拿來驗證;至於 WebAuthn 有沒有要取代密碼,其實都可以。例如 Google 就把安全金鑰當作二步驟驗證的方式,你輸入正確的帳號密碼後,還需要插入實體安全金鑰才可以成功登入;而 GitHub 則可以在你進行重要操作時(刪除 Repo 等等),讓你用實體安全金鑰取代輸入密碼。

哪些網站支援實體金鑰?可以到 USB Dongle Authentication 網站查詢。

至於 WebAuthn 是不是可以用來取代密碼、多個裝置怎麼做指紋、怎樣才是最正確的實行方法,我們到後面的文章再來解釋,這邊還是先了解一下 WebAuthn 是什麼東西。

目前 Windows 電腦可以用 Windows Hello 登入(不管是裝置上的 PIN 碼,還是你的鍵盤有相容的指紋辨識裝置)、Android 和 iOS 手機的指紋辨識等等,透過公私鑰的方式取代了密碼登入。

WebAuthn、FIDO 是什麼

你可能也聽過 FIDO,更聽過 Android 手機通過 FIDO2 規範等等,簡單做一下名詞解釋。

FIDO Alliance 是一個聯盟、一個組織,包含 Amazon、Apple、Google、MasterCard、Microsoft、NTT DoCoMo、NXP、PayPal、Samsung、Yubico 等大公司都有參加,在官網可以看到。那他們的宗旨就是,大部分資安問題都是因為密碼外洩,如果沒有密碼就解決了──所以他們會訂一些規範。而 FIDO2 就是目前最新的規範,包含 WebAuthn、CTAP 兩個部分。

如何實作 WebAuthn

這邊大概會分三個角色:Relying Party(也就是 Server)、Browser 和 Authenticator。

一切都是從 Browser 開始的。首先使用者從瀏覽器向伺服器發出註冊請求,伺服器會把可以接受的認證方式(可以接受哪種 Authenticator,例如是不是一定要用外接安全晶片)告訴瀏覽器。

瀏覽器收到回應後,就會開始跟 Authenticator 互動(例如要求你觸碰安全晶片、要求按下指紋等等),並透過瀏覽器的 navigator.credentials API 開始建立公私鑰。接著,瀏覽器整理一組資料,包含伺服器的 originchallenge、伺服器剛剛產生的使用者 id 等資訊,還有最重要的公鑰,傳送給可信賴的 Relying Party,也就是我們的伺服器。

等伺服器確認過這把公鑰沒問題,而且是剛剛來向我請求註冊的那個 Client 沒錯,就會把這組公鑰和 Authenticator 資訊存下來,以供後續登入驗證。

登入的時候也是大同小異:首先由 Browser 發出登入請求。伺服器收到後,會把之前存下來的使用者資訊拿出來比對,並把之前註冊的的 Authenticator 資訊傳給瀏覽器。

瀏覽器收到回應後,會開始跟 Authenticator 互動,如果沒有問題的話,瀏覽器會透過私鑰把剛剛收到的資訊簽名(signature),再回傳給 Server。

最後,伺服器會透過註冊時儲存的公鑰,來驗證這個簽名有沒有問題,沒問題的話就會讓使用者順利登入。否則,就會回傳 401 等無法登入的回應。

公私鑰加密的部分太難了嗎?
非對稱加密?到底是什麼鎖可以有兩把鑰匙,用簡單數學解釋給你聽

為什麼無法登入要回傳 401?
常見與不常見的 HTTP Status Code