2017-05-04 104 views
2

我有一個有角度前端的nodejs api。該API成功使用JWT和護照來保護其端點。智威湯遜驗證客戶端?

我現在意識到,在令牌過期後,我的前端仍然允許用戶請求我的api端點,而不會提示他們重新輸入他們的詳細日誌以獲取新的令牌。

這是我的後端是如何生成的令牌:

function generateToken(user) { 
    return jwt.sign(user, secret, { 
    expiresIn: 10080 // in seconds 
    }); 
} 

因此,要實現這個邏輯,我想我需要驗證令牌JWT的客戶端。 Q1,這是一個明智的做法。

Q2,我使用的JWT庫似乎需要一個公鑰才能使用它的verify()函數。我似乎沒有公鑰,只有一個祕密,我只是編了一個祕密,所以它不是用一對產生的。我的公鑰來自哪裏,或者有沒有另外一種驗證我的令牌的方式?

這一切似乎應該是顯而易見的,我已經錯過了一些東西,所以道歉,如果這是一個愚蠢的問題,但我似乎無法找到答案?

回答

0

答1:它不認爲是一個很好的方法來驗證客戶端的身份驗證令牌,因爲它涉及祕密密鑰而編碼/解碼,並保持在客戶端密鑰是不安全

創建令牌

jwt.sign({ data: 'foobar' }, 'secret', { expiresIn: 60 * 60 });

驗證令牌

jwt.verify(token, 'secret', function(err, decoded) { console.log(decoded.foo) // bar });

答案2:JWT涉及祕密公鑰,同時對令牌進行編碼和解碼。它必須在服務器端的某個地方聲明或保存在配置文件中。

說明: 解碼指從Base64編碼解碼,還有參與這一過程中沒有密鑰。另一方面,驗證智威湯遜將需要一個祕密密鑰,因爲它會涉及加密簽名操作。

綜上所述,解碼不需要祕密(記得解碼只是解釋的base64)和驗證/簽名確實需要它

0

我想驗證JWT令牌在客戶端是不是好主意。 IMO;

1-每當用戶登錄時生成訪問並刷新令牌並返回給用戶那樣;

{ 
    "accessToken": <<accessToken>> 
    "refreshToken": <<refreshToken>> 
    "expiresAt": <<expiresAt>> 
} 

因此,您的客戶端可以瞭解訪問令牌何時到期,並且可以使用刷新令牌刷新它。

2-加密您放入訪問令牌的數據,因爲有機會訪問沒有密鑰的數據。但是有人需要密鑰來驗證。

0

Q1:客戶端上的令牌驗證是個壞主意。你可以做的是在客戶端上保存一個具有相同過期日期的令牌,然後刷新/刪除令牌。但是我認爲最好是在服務器端有一些日期checkig原因存在簡單規則:不要相信客戶端因爲它總是可以發送惡意代碼。

Q2:智威湯遜不需要任何公鑰。它總是必須有私鑰存儲在服務器端,如果有人知道你的祕密密鑰,你的令牌沒有任何意義。您只能添加一些有效載荷,使其更加複雜。

4

TL; DR

  1. 您必須驗證 JWS在服務器始終簽名。
  2. 客戶端簽名驗證並沒有給出太多,除非你有一個特定的情況下有意義不要這樣做
  3. 不需要驗證JWS令牌的簽名來檢查客戶端中的到期。 (除非你是在加密聲明,也就是使用JWE,在這種情況下你需要做類似的事情,因爲你需要一個密鑰來解密聲明)。
  4. 您不需要驗證JWS的簽名以檢查服務器中的到期日期,但是您應該這樣做,因爲這樣可以確保沒有人更改過期日期(否則驗證將失敗,因爲如果索賠更改,則重新計算的簽名將有所不同)
  5. 要讀取非加密聲明,您只需要解碼它們即可。您可以在客戶端使用jwt-decode

我現在意識到,之後令牌已經過期,我的前端仍允許用戶請求我的API端點[...]

因此,要實現這個邏輯我想我需要驗證JWT令牌客戶端

如果我正確理解您,您正在討論檢查JWS是否已在客戶端過期。 爲了做到這一點,您不需要驗證令牌簽名(儘管您正在使用的庫似乎正在爲您做both things at the same time,但也可以讓您使用ignoreExpiration標誌禁用到期控制)。 (除非您正在加密聲明,也就是使用JWE) RFC 7515 (JWS)沒有提到過期。Message Signature or MAC Validation不控制到期(並且不應該因爲簽名給你真實性和完整性)。 即使RFC 7519 (JWT)也不能控制如果JWT is valid or not已解決的到期索賠。

另外,所有的claims are optional。因此,您可以檢查JWT是否已過期或未驗證簽名,因此既不需要公共密鑰(用於RSA等非對稱加密),也不需要用於對稱加密(如AES)的密鑰(既不需要公鑰也不需要)。 在JWT和JWS令牌中,聲明只是明文base64編碼,因此您只需decode the payload without verifying if the signature is valid並閱讀到期聲明。 如果你正在加密有效載荷(又名使用JWE),那麼你將無法做到這一點。

的說明從jjwt library

JWTs可以是加密簽署(使其成爲一個JWS)或加密(使其成爲一個JWE)。

Here是從auth0一個ligthweigth庫以JWT/JWS的base64encoded聲明令牌解碼。 一個男人甚至問起checking expiration

我不知道你爲什麼認爲你應該做這個控制客戶端,唯一的好處是避免發送客戶端知道會失敗的API請求。並且他們應該失敗,因爲服務器應該驗證令牌未過期,以前的簽名驗證(帶有祕密/私鑰)顯然。

RFC 7519說了解這個要求:

的「EXP」(到期時間)根據權利要求標識過期時間上 或在此之後,JWT 必須不用於處理被接受。

在一個Web應用程序中,您說的令牌的使用是允許無狀態服務器對客戶端請求進行身份驗證。 可選到期聲明的目標是允許服務器對生成的JWS進行一些控制(如果我們使用JWT進行身份驗證,則必須簽署它們,因此我們應該談論JWS)。

沒有到期,令牌將永久生效或直到用於簽名的密鑰更改(這將使驗證過程失敗)。 順便說一下,invalidatingsessions是使用無狀態身份驗證最臭名昭着的缺點之一。

如果我們在用於授權的JWS有效負載(又名聲明)中包含信息(例如用戶擁有哪些角色),則會話失效成爲一個實際問題。

Stop using JWT for sessions

,但更嚴重的是,它也可以指人與管理員的角色令牌,即使你只是吊銷了其管理角色。因爲你也不能無效令牌,有沒有辦法爲你免除他們的管理員權限

到期控制的不解決這個問題,我認爲是更注重以避免會話劫持或CSRF攻擊。

使用CSRF的攻擊者將能夠使用過期的JWS向您的API發出請求,以跳過到期控制。

另一個問題是使用公鑰或密鑰驗證客戶端中的簽名。

關於你的問題

我使用似乎都需要一個公共密鑰使用它來驗證()函數。我似乎沒有公鑰,只有一個祕密,我只是編了一個祕密,所以它不是用一對產生的。

您指出的驗證方法明確指出它接受公鑰或密鑰。

jwt.verify(token, secretOrPublicKey, [options, callback]) 

secretOrPublicKey是RSA和ECDSA

字符串或它可以包含HMAC算法的祕密,或PEM緩衝編碼的公共密鑰我假設你既沒有使用,你使用的是像'shhhh'字符串。

var token = jwt.sign({ data: '¿Donde esta Santiago?'}, 'shhhh'); 

那麼你應該做的

var decoded = jwt.verify(token, 'shhhhh'); 

然而,這裏的問題是:是否真的需要客戶端簽名驗證?

我想不是,至少不是這種類型的應用程序,其中客戶端只是使用JWS發送後續請求到服務器說:「嘿服務器,我是加百列,我在這裏有一個紙張(令牌)這可以保證你的文件是由你簽署的。「 因此,如果客戶端不驗證JWS並且MITM已成功向該客戶端發送了由他自己簽名的JWS(而不是由服務器簽名的JWS),則後續請求將會失敗。 像到期控制一樣,簽名驗證只能防止客戶端發出失敗的請求。

現在,客戶端驗證需要發送公鑰或密鑰。 發送公鑰並不代表安全問題,但它是額外的努力和處理,沒有什麼好處。

發送密鑰(如'shhhh')可能代表安全問題,因爲是用於簽署令牌的相同密鑰。