# Authentication ### 登入驗證 </br> *YoMin Su* --- ## 基礎環節 > 認識一下這是什麼東西 ---- ### 什麼是 Authentication? ---- 在進行需要確認權限的請求時,身份識別、取得權限的過程,可以分成建立、驗證、銷毀三種階段。 ---- ### 為何需要 Authentication? ---- 就如同前面提到的,在使用某些功能時,若不先驗證你是誰,你能做什麼,就可能導致你可以使用到不應該開放給你的功能,這在系統設計上是非常嚴重的問題。 ---- ### 目前有哪些可以實作的技術? ---- - Session - Json Web Token - AD / LDAP - SSO(OAuth) (Authorization) --- ## Session > 老歸老,但是好用 ---- <!-- .slide: data-background="White" --> ### How it works? ```sequence title: Session 工作流程 使用者->前端: 輸入帳號&密碼 前端->後端: 送出驗證的資料 後端->前端: 驗證成功,前端Cookie儲存SessionID 使用者->前端: 瀏覽某功能 前端->後端: 帶著資料跟SessionID過去 後端->前端: 操作成功 ``` ---- ### 普通的細節 1. 當後端收到請求後,會去驗證使用者的有效性(查DB) 2. 比對相符後,就會將這筆資料儲存在後端的儲存區中(File, DB, RAM) 3. 並對應生成一組帶有時效限制的SessionID 4. 在回傳請求的回覆中,會加入一組Header,Key為Set-Cookie,Value則是SessionID 5. 在下一次的請求發生時,瀏覽器會自動帶入儲存的Cookie,進行驗證 ---- ### 細節的細節 1. 當請求送入後端後,若是需要驗證身份的路由,通常會將驗證功能放在中介層(Middleware),若檢查未通過,會直接回傳錯誤資訊與4XX狀態碼 2. Set-Cookie Header 並非只存Key跟Value,還會連帶存入其他細節,如Expires, HttpOnly, Path, Secure, SameSite...等等設定 > [MDN Set-Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) ---- ### 實作的細節 每種程式語言的實作都有各自的方法,甚至,也可能因為使用的套件不同,而有不同的方案,這裡主要分享在JS/TS上開發Express後端時,常使用的 express-session 的作法,細節可參考連結文章 > [深入 Session 與 Cookie:Express、PHP 與 Rails 的實作 ](https://blog.huli.tw/2019/08/09/session-and-cookie-part3/) ---- ### 可能會遇到的問題 1. Cookie安全性 (CSRF) 2. 橫向擴展時,Session資料的同步 > [CSRF 攻擊原理](https://medium.com/@Tommmmm/csrf-%E6%94%BB%E6%93%8A%E5%8E%9F%E7%90%86-d0f2a51810ca) --- ## Json Web Token > 驗證好方便 ---- <!-- .slide: data-background="White" --> ## How it works? ```sequence title: JWT 工作流程 使用者->前端: 輸入帳號&密碼 前端->後端: 送出驗證的資料 後端->前端: 驗證成功,前端從回傳中取得Token並儲存 使用者->前端: 瀏覽某功能 前端->後端: 帶著資料跟Authorization Header過去 後端->前端: 操作成功 ``` ---- ### 普通的細節 1. JWT可以分為三個部分,先透過Base64編碼再以「 . 」連接在一起,有各自的用途: - Header: 存放Token的種類跟Signature的雜湊算法 - Payload: 存放要攜帶的資訊(用戶資料...等) - Signature: 前兩者的簽章,會加入自定義的密鑰,用於驗證資料是否有效 ---- ### 普通的細節II 2. 後端不負責儲存使用者的資料,這些東西都將放在Payload裡面 3. 前端接收到Token後需要自己儲存好,在下一次請求時帶著一起送出 > [[筆記] 透過 JWT 實作驗證機制](https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8) ---- ### 細節的細節 1. 當請求送入後端後,跟Session的處理會採用相似的方法,在Middleware中進行驗證,若Signature的部分與後端當下雜湊出來的結果不符,則回傳錯誤資訊與狀態碼 2. 正常的狀況下,JWT是個無法註銷的令牌,由於簽發後,必要的資訊都已傳送給前端,因此只要拿著這個令牌,在有效期限內送出請求,後端都需要回覆給前端正常的執行結果 ---- ### JavaScript 中的 JWT 在「jwt.io」中,有提供詳細的列表說明各種程式語言中,哪些套件是可以提供JWT功能的,除此之外,還有細節提及支援哪些算法與簽名。 > [JWT.io](https://jwt.io/libraries?language=JavaScript) ---- ### 後端開發上的選擇 在後端開發上,多數人則選擇使用 [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) 套件,其實作的部分就足夠開發者進行簽發與驗證了 當然,實際上也有 [express-jwt](https://www.npmjs.com/package/express-jwt) 可以使用,不過,這部分可以自己實際嘗試過後再做決定 ---- ### 可能會遇到的問題 1. 如何安全的儲存Token 2. 如何註銷尚未過期的Token > [JSON Web Token(JWT) 儲存在前端那邊比較好?](https://www.kvzhuang.net/2019/04/json-web-tokenjwt.html) --- ## Session ## vs ## Json Web Token ---- [更好的選擇?用 JWT 取代 Session 的風險](https://blog.kenwsc.com/posts/2023/jwt-vs-session/) --- ## AD / LDAP > 這個另一個大坑 ---- <!-- .slide: data-background="White" --> ### How it works? ```sequence title: AD/LDAP 工作流程 使用者->前端: 輸入帳號&密碼 前端->後端: 送出驗證的資料 後端->AD/LDAP主機: 驗證使用者資訊 AD/LDAP主機->後端: 使用者有效 後端->前端: 驗證成功,前端Cookie儲存SessionID note right of 後端: 以Passport.js為例 使用者->前端: 瀏覽某功能 前端->後端: 帶著資料跟SessionID過去 後端->前端: 操作成功 ``` ---- ### 為什麼這樣用? 因為當你有多個服務,且想要共用同一組帳號以方便使用者操作時,就會有這樣的需求出現! ---- ### 可以選擇的套件 1. [ldap-authentication](https://www.npmjs.com/package/ldap-authentication) 2. [Passport.js](https://www.passportjs.org/) 若是只要基本的AD/LDAP驗證,透過上者就可以做到,但若也需要後續的管理(像是生成Session),透過下者會更方便一點 ---- ### 可能會遇到的問題 通常驗證用的主機跟後端不會是同一台設備,在跨機器通訊時,有經過WAN,則會有AD/LDAP加密通訊相關的問題要處理,明碼總是危險的! --- ## SSO(OAuth) > 以XXX登入,太多種了吧 ---- <!-- .slide: data-background="White" --> ### How it works? ```sequence title: SSO(OAuth) 工作流程 使用者->前端: 點選「以XXX登入」 前端->>SSO前端: 跳轉至XXX提供的登入系統 使用者->SSO前端: 輸入帳號密碼 SSO前端->SSO後端: 送出驗證的資料 SSO後端->SSO前端: 驗證成功 SSO前端->使用者: 詢問是否授權給應用程式 使用者->SSO前端: 同意授權 SSO前端->SSO後端: 使用者同意授權 SSO前端->>前端: 帶著Token跳轉回原本的系統 前端->後端: 給予Token以取得使用者資料 後端->SSO後端: 索取使用者資訊 後端->前端: 前端Cookie儲存SessionID ``` ---- ### 為什麼寫著Authorization? 因為登入的步驟並非是在我們的系統執行的,是由其他系統進行,再將能索取所需資訊的Token傳給後端,這部分就屬於給予授權,而非驗證身份了 > [驗證(Authentication)與授權(Authorization)的區別](https://matthung0807.blogspot.com/2018/03/authenticationauthorization.html) ---- ### 補充資訊:OAuth 2.0 > [[筆記] 認識 OAuth 2.0:一次了解各角色、各類型流程的差異](https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E8%AA%8D%E8%AD%98-oauth-2-0-%E4%B8%80%E6%AC%A1%E4%BA%86%E8%A7%A3%E5%90%84%E8%A7%92%E8%89%B2-%E5%90%84%E9%A1%9E%E5%9E%8B%E6%B5%81%E7%A8%8B%E7%9A%84%E5%B7%AE%E7%95%B0-c42da83a6015)
{"metaMigratedAt":"2023-06-17T22:20:17.100Z","metaMigratedFrom":"YAML","title":"Authentication","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"allottedMinutes\":25}","description":"YoMin Su","contributors":"[{\"id\":\"86b6dc70-72ec-4014-84f0-bfb2a06c3dc4\",\"add\":5101,\"del\":276}]"}
    169 views