JWT Token 沒有提供 Remember Token 的功能
若要在 JWT Token 提供 Remember Token 的功能,可以將儲存在 Cookie 的 JWT Token 時間效期拉很長,當 Cookie 存在就可以正常的去做驗證登入功能
使用 JWT Token Refresh Token 機制
JWT Token 會產生一個有效期的 Token,而 Token 中會包含以下欄位
欄位 | 說明 |
---|---|
iat | Token 產生時間 |
exp | Token 最後可用時間,在此時間內 token 都可以重新 refresh 取得 |
nbf | Token 有效時間,超過此時間 Token 會失效 |
/* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGgua2VqeXVuLmNvbS9hcGkvdjEvdXNlci9hdXRoL2xvZ2luIiwiaWF0IjoxNjIxMzIyMDg2LCJleHAiOjE2MjE0MDg0ODYsIm5iZiI6MTYyMTMyMjA4NiwianRpIjoiSzRzbzNmeWJsMjBjUnFjeCIsInN1YiI6InVzZXItc2V1azU4ODN6bXY1YXV1In0.EeB6mb-XWU9Yhq9UroKeI6SNiiC6taa7Jo5FF8jzrhc
*/
{
"iss": "https://auth.kejyun.com/api/v1/user/auth/login",
"iat": 1621322086,
"exp": 1621408486,
"nbf": 1621322086,
"jti": "K4so3fybl20cRqcx",
"sub": "user-seuk5883zmv5auu"
}
exp
欄位時間會大於或等於 nbf
時間,當時間超過 nbf
時間時此 Token 會無法使用,但若 nbf
時間在 exp
時間內,可以重新使用 refresh 的方式再取得有效的 Token,直到時間超過 exp
為止
此 Token 會透過 JWT 金鑰去驗證資料是否有被串改過,所以可以保護 Token 的安全性,所以可以將 JWT Token 的過期時間 nbf
設定為比較短,而 JWT Token 可用時間 exp
設定長一點,當 Token 過期可以重新得去
Refresh Token 就可以持續不斷延長 Token 可用時間
步驟 | 流程 | 用途 |
---|---|---|
1 | 傳入帳號密碼驗證 | 驗證帳號密碼是否正確,資料庫是否有此帳號 |
2 | 記錄使用者 user_id 到 JWT Token Cookie | 告訴前端此使用者的身份是誰,之後會透過這個含有 user_id 的 JWT Token cookie 做驗證 |
3 | 透過含有 user_id 的 JWT Token Cookie 做其他驗證請求 | 使用金鑰驗證 Token 是否合法沒有被串改,驗證合法則撈取 JWT Token Cookie 中的 user_id 撈取使用者資料 |
4 | 呼叫 Refresh Token API 取得新的 JWT Token 儲存至 Cookie | 若 JWT Token 失效,但 exp 還在效期內,重新 Refresh 取得新的 Refresh JWT Token |
5 | 使用新的 JWT Refresh Token 做驗證請求 | 透過新的 Refresh Token 重新驗證取得登入使用者資料 |
JWT Token 效期過長安全性問題
當將 JWT Token 效期設定比較長,可以達到記住登入使用者帳號,讓使用者保持隨時是登入的狀態,但若時間設定過長(e.g. 3 年、5 年)則 Token 安全性會有問題,若此 Token 被劫取走,在這個這麼長的有效期限內,此 Token 都會是有效的可以合法的存取 API
JWT Token 加入 remember_token
在使用者資料表加入一個 remember_token
的欄位,當作幫使用者做重新產生 JWT Token 驗證的動作,所以登入流程會變成
步驟 | 流程 | 用途 |
---|---|---|
1 | 傳入帳號密碼驗證 | 驗證帳號密碼是否正確,資料庫是否有此帳號 |
2 | 產生新的 remember_token 記錄到使用者資料表的 remember_token 欄位 |
做為之後驗證重新登入用 |
3 | 記錄使用者 user_id 及 remember_token 到 JWT Token Cookie | 告訴前端此使用者的身份是誰,之後會透過這個含有 user_id 的 JWT Token cookie 做驗證 |
4 | 透過含有 user_id 及 remember_token 的 JWT Token Cookie 做其他驗證請求 | 使用金鑰驗證 Token 是否合法沒有被串改,驗證合法則撈取 JWT Token Cookie 中的 user_id 撈取使用者資料 |
5 | 呼叫 Refresh Token API 取得新的 JWT Token 儲存至 Cookie | 若 JWT Token 失效,但 exp 還在效期內,重新 Refresh 取得新的 Refresh JWT Token |
6 | 使用新的 JWT Refresh Token 做驗證請求 | 透過新的 Refresh Token 重新驗證取得登入使用者資料 |
7 | 透過 remember_token 及 user_id 的 Cookie 做重新取得新 JWT Token | 撈取 JWT Cookie 中的 remember_token 及 user_id,與資料庫做比對,確認是否 token 合法可以正常重新產生 |
8 | 使用新產生的 JWT Token 做驗證請求 | 透過新產生的 JWT Token 重新驗證取得登入使用者資料 |
/* eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGgua2VqeXVuLmNvbS9hcGkvdjEvdXNlci9hdXRoL2xvZ2luIiwiaWF0IjoxNjIxMzIyMDg2LCJleHAiOjE2MjE0MDg0ODYsIm5iZiI6MTYyMTMyMjA4NiwianRpIjoiSzRzbzNmeWJsMjBjUnFjeCIsInN1YiI6InVzZXItc2V1azU4ODN6bXY1YXV1IiwicmVtZW1iZXJfdG9rZW4iOiJyYW5kb20tcmVtZW1iZXItdG9rZW4ifQ.GoW1zQ70ncIox--G1zrurNhEmTTpqWV_2d-2gWWWsow */
{
"iss": "https://auth.kejyun.com/api/v1/user/auth/login",
"iat": 1621322086,
"exp": 1621408486,
"nbf": 1621322086,
"jti": "K4so3fybl20cRqcx",
"sub": "user-seuk5883zmv5auu",
"remember_token" : "random-remember-token"
}
當 JWT Token 效期時間很短時(例如 300 分鐘),在 JWT Token 過期時,也可以透過 Cookie 中的 remember_token 去重新驗證並產生新的 JWT Token 回傳給使用者,讓使用者可以持續使用合法的 JWT Token 不斷做存取
remember_token 安全性
因為只要 JWT Token Cookie 過期時間設定的夠長,只要一直有 remember_token
,則使用者就可以一直無限期的一直不斷的維持登入狀態,這樣可能會有安全性的問題,所以在使用者自己觸發登出時,記得更新儲存在資料庫的 remember_token,讓其他有此 remember_token 的使用者無法繼續登入
參考資料
- security - What is the best way to implement “remember me” for a website? - Stack Overflow
- API Authentication Workflow with JWT and Refresh Tokens - DEV Community
- Remember Me and Forgot Password functionality in JWT Auth · Issue #261 · tymondesigns/jwt-auth · GitHub
- JWT Authentication
Donate KJ 贊助作者喝咖啡
如果這篇文章對你有幫助的話,可以透過下面支付方式贊助作者喝咖啡,如果有什麼建議或想說的話可以贊助並留言給我
If this article has been helpful to you, you can support the author by treating them to a coffee through the payment options below. If you have any suggestions or comments, feel free to sponsor and leave a message for me!
方式 Method | 贊助 Donate |
PayPal | https://paypal.me/kejyun |
綠界 ECPay | https://p.ecpay.com.tw/AC218F1 |
歐付寶 OPay | https://payment.opay.tw/Broadcaster/Donate/BD2BD896029F2155041C8C8FAED3A6F8 |