2016-10-03 57 views
7

我有一個基於Koa的Node.js後端,用於我的個人/業餘愛好應用程序。處理JWT過期和智威湯遜負載更新

我用JWT令牌實現了會話處理。客戶端(AngularJS)在成功登錄後獲取令牌並將令牌存儲在某處(目前在sessionStorage中,但對於此問題而言,這應該不重要)。

我有兩個問題:

  1. 當我需要更新其JWT表示,比方說,用戶打開2FA於是我問他提供他的電話號碼,我想用戶記錄在用戶記錄中設置此電話號碼。目前,在成功驗證電話號碼後,我打電話給後臺更新用戶記錄,並使用更新後的用戶記錄創建了新的JWT令牌(我從JWT令牌中排除了敏感信息,例如哈希密碼,但我想包括客戶端使用的電話號碼)。當某些憑證更改並使用此新令牌更新現有客戶端令牌時,是否可以創建新令牌?我是否永遠不會創建另一個令牌,只有在成功驗證後才創建一個令牌?我如何更新令牌中的有效載荷?

  2. 我應該如何處理過期的JWT令牌?在我看來,我有3個(可能的)場景:

    2.1。智威湯遜設置爲短暫的生活,比如15分鐘。如果後端服務器回覆401 Unauthenticated'Invalid token'(我猜這是koa-jwt的默認行爲),那麼我會自動註銷我的客戶端並要求重新驗證。但我也建立了一個互補的中間件,它是後端鏈中的最後一個,用重新刷新的到期來重新創建令牌,並且客戶端也會用已刷新的令牌替換現有的令牌。因此,如果用戶處於活動狀態並在每個受保護的API調用中使用該應用程序,那麼在成功的情況下,將創建一個新的令牌來替換舊的令牌。

    2.2。 JWT設置時間長,例如1周,如果到期,我會選擇從客戶端重新進行身份驗證。

    2.3。複製https://tools.ietf.org/html/rfc6749#section-1.5。在成功驗證後創建JWT令牌時,我們發送access_token以及refresh_token。當access_token過期並且服務器以HTTP 401'無效令牌'響應(默認爲koa-jwt)時,客戶端將refresh_token發送到支持者以要求新的access_token(以及可選的新的refresh_token)。在這種情況下,我不完全瞭解refresh_token如何通過舊的access_token驗證以提供新的令牌?或者爲什麼我們需要有一個refresh_token?

關於上層主題(JWT更新和JWT到期)的任何通用建議將會有所幫助。

+0

爲什麼不只是使用cookie? – Kebman

回答

3

我想在回答第一個問題之前回答第二個問題。

基本上你提到的第三個選項是更新你的訪問令牌的最好方法。訪問令牌應該是短暫的(~5分鐘),刷新令牌的壽命更長。當您的訪問令牌過期時,將您的刷新令牌發送到後端並獲取新的訪問令牌。所以,你的反應應該是這樣的:

{ 
"token_type":"bearer", 
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s", 
"expires_in":10, 
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b" 
} 

這樣的想法是單獨的應用程序到授權服務器(生成訪問令牌/刷新令牌)&資源服務器(驗證訪問令牌和訪問的資源)。您可以維護模式以根據授權服務器中的訪問令牌驗證刷新令牌。請參考這個鏈接中提到的模式部分,這可能會給你一些想法。 Oauth2。您可以根據需要修改架構。對於每個請求調用,您不需要將刷新令牌與訪問令牌一起發送。刷新令牌只能發送到授權服務器以生成新的訪問令牌。如何生成刷新令牌?如果我使用Java,我會使用UUID.randomUUID()來生成一個唯一的刷新令牌。

現在回答你第一個問題,如果你要根據你更新的用戶記錄,以更新您的智威湯遜的有效載荷,然後就可以使用相同的刷新令牌來產生與更新的有效載荷新的訪問令牌。邏輯保持不變,因爲如果用戶記錄中存在電話號碼,它將被添加到有效內容中,否則它將在有效內容中爲空。

使用刷新標記的主要優點是訪問令牌可以在任何時間使用刷新令牌

5

從底部開始,我會忽略刷新令牌被更新,因爲我不認爲他們會幫助你在這裏。它們通常針對客戶端應用程序可以提供比用戶瀏覽器更安全的存儲的其他場景 - 考慮原生移動應用程序或服務器端Web應用程序。

刷新令牌很長壽。這意味着當客戶端得到一個從服務器,此令牌必須安全地存儲,以保持它從正在使用的潛在攻擊者,這個原因,它是不是安全將它們存儲在瀏覽器中。

(重點是我的;源refresh tokens

這意味着選項2.3是基本相同2.2,這是個不錯的選擇。擁有長會話持續時間的Web應用程序並不罕見。如果您的應用程序不是非常敏感,則可以使用長時間會話來改善用戶體驗。例如,Django會話cookie的年齡默認爲兩週。請參閱SESSION_COOKIE_AGE

剩餘選項(2.1),通常稱爲滑動會話。會話超時很短,但只要用戶在該時間間隔內繼續使用應用程序,會話就會自動更新。這可能是最常用的方法,或者至少是我最常用的方法,所以我很偏向。我唯一需要注意的是,滑動會話通常使用存儲在客戶端的不透明會話標識符作爲cookie,然後與存儲在服務器上的實際會話數據一起實現。

你的做法有點不同,因爲你有一個無狀態的JWT令牌(包含實際用戶數據)存儲在瀏覽器本地存儲。就像你說的,爲了更新令牌,你必須生成一個新的令牌,因爲你必須生成一個新的簽名。

該簽名用於驗證JWT的發件人是誰說它是並確保郵件未被更改。

(重點是我的;源JSON web tokens

說了這麼多,我會考慮以下幾點:

  1. 問問自己,如果你真的需要JWT的或者定期的會話標識符存儲爲餅乾(HTTP Only)將簡化您的邏輯。
  2. 例如,如果需要JWT,則您有另一個API也會接受這些令牌作爲認證,那麼我會考慮選項2.1或2.2作爲不建議基於瀏覽器的應用程序的刷新令牌。

話雖如此,你還應該考慮JWT的並不是很大,但如果你決定自動更新,他們仍然是一個開銷。您可以通過選擇20分鐘的會話持續時間來緩解這一點,並且僅在會話過去一半後才執行自動更新。

的另一點是,在你的應用程序將公開訪問令牌攻擊者作爲注入腳本像XSS漏洞將能夠從localStorage/sessionStorage閱讀,這樣可以有利於HTTP唯一的會話cookie存儲的另一點。