建造 | 依賴性 |
---|---|
JSON Web 令牌的實作。
這是針對draft-ietf-oauth-json-web-token-08
開發的。它利用node-jws
$ npm 安裝 jsonwebtoken
從 v8 到 v9
從 v7 到 v8
(非同步)如果提供回調,則使用err
或 JWT 呼叫回調。
(同步)以字串形式傳回 JsonWebToken
payload
可以是物件文字、緩衝區或表示有效 JSON 的字串。
請注意,僅當有效負載是物件文字時才會設定
exp
或任何其他聲明。不會檢查緩衝區或字串有效負載的 JSON 有效性。
如果
payload
不是緩衝區或字串,則會使用JSON.stringify
將其強制轉換為字串。
secretOrPrivateKey
是一個字串(utf-8 編碼)、緩衝區、物件或 KeyObject,其中包含 HMAC 演算法的秘密或 RSA 和 ECDSA 的 PEM 編碼私密金鑰。如果私鑰帶有密碼短語,則可以使用物件{ key, passphrase }
(基於加密文件),在這種情況下,請確保傳遞algorithm
選項。使用 RSA 演算法簽署時,最小模數長度為 2048,除非allowInsecureKeySizes 選項設為 true。低於此大小的私鑰將被拒絕並出現錯誤。
options
:
algorithm
(預設: HS256
)
expiresIn
:以秒或描述時間跨度 vercel/ms 的字串表示。
例如:
60
、"2 days"
、"10h"
、"7d"
。數值被解釋為秒數。如果您使用字串,請確保提供時間單位(天、小時等),否則預設使用毫秒單位("120"
等於"120ms"
)。
notBefore
:以秒或描述時間跨度 vercel/ms 的字串表示。
例如:
60
、"2 days"
、"10h"
、"7d"
。數值被解釋為秒數。如果您使用字串,請確保提供時間單位(天、小時等),否則預設使用毫秒單位("120"
等於"120ms"
)。
audience
issuer
jwtid
subject
noTimestamp
header
keyid
mutatePayload
:如果為 true,sign 函數將直接修改有效負載物件。如果您在應用聲明之後但在將其編碼到令牌之前需要對有效負載進行原始引用,那麼這非常有用。
allowInsecureKeySizes
:如果 true 允許模數低於 2048 的私鑰用於 RSA
allowInvalidAsymmetricKeyTypes
:如果為 true,則允許與指定演算法不符的非對稱金鑰。此選項僅用於向後相容,應避免使用。
expiresIn
、notBefore
、audience
、subject
、issuer
沒有預設值。 這些聲明也可以分別透過exp
、nbf
、aud
、sub
和iss
直接在有效負載中提供,但不能同時包含在這兩個地方。
請記住exp
、 nbf
和iat
是NumericDate ,請參閱相關的令牌到期時間(exp 宣告)
可以透過options.header
物件自訂標頭。
除非指定noTimestamp
,否則產生的 jwts 將預設包含iat
(發佈於)宣告。如果將iat
插入有效負載中,則將使用它將代替真實時間戳來計算其他內容,例如在options.expiresIn
中給定時間跨度的exp
。
預設同步簽章 (HMAC SHA256)
var jwt = require('jsonwebtoken');var token = jwt.sign({ foo: 'bar' }, 'shhhhh');
使用 RSA SHA256 同步簽名
// 使用 RSA SHA256 進行簽章var privateKey = fs.readFileSync('private.key');var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });
非同步簽名
jwt.sign({ foo: 'bar' }, privateKey, { 演算法: 'RS256' }, function(err, token) { console.log(令牌);});
jwt 回溯 30 秒
var old_token = jwt.sign({ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 }, 'shhhhh');
JWT 標準定義了過期exp
。過期時間用NumericDate表示:
一個 JSON 數值,表示從 1970-01-01T00:00:00Z UTC 到指定 UTC 日期/時間的秒數,忽略閏秒。 這相當於 IEEE Std 1003.1,2013 版 [POSIX.1] 定義“自紀元以來的秒數”,其中每天精確計算 86400 秒,但可以表示非整數值。 有關一般日期/時間(特別是 UTC)的詳細信息,請參閱 RFC 3339 [RFC3339]。
這意味著exp
字段應包含自紀元以來的秒數。
簽署具有 1 小時有效期限的令牌:
jwt. 符號({ exp: Math.floor(Date.now() / 1000) + (60 * 60), 數據:'foobar'},'秘密');
使用此庫產生此類令牌的另一種方法是:
jwt. 符號({ data: 'foobar'}, 'secret', { expiresIn: 60 * 60 });//甚至更好:jwt.sign({ 數據: 'foobar'}, '秘密', { expiresIn: '1h' });
(非同步)如果提供回調,函數將非同步運行。如果簽名有效且可選的過期時間、受眾或發行者有效,則使用解碼後的有效負載呼叫回呼。如果沒有,呼叫時會出現錯誤。
(同步)如果未提供回調,函數將同步運行。如果簽名有效且可選的過期時間、受眾或發行者有效,則傳回解碼的有效負載。如果沒有,它將拋出錯誤。
警告:當令牌來自不受信任的來源(例如使用者輸入或外部請求)時,返回的解碼負載應像任何其他使用者輸入一樣對待;請確保進行消毒並僅使用預期的房產
token
是 JsonWebToken 字串
secretOrPublicKey
是一個字串(utf-8 編碼)、緩衝區或 KeyObject,其中包含 HMAC 演算法的秘密或 RSA 和 ECDSA 的 PEM 編碼公鑰。如果jwt.verify
被非同步調用, secretOrPublicKey
可以是應該取得秘密或公鑰的函數。請參閱下面的詳細範例
如同本篇評論中所提到的,還有其他函式庫需要 base64 編碼的秘密(使用 base64 編碼的隨機位元組),如果是你的情況,你可以傳遞Buffer.from(secret, 'base64')
,透過這樣做,秘密將被解碼使用base64並且令牌驗證將使用原始隨機位元組。
options
algorithms
:包含允許的演算法名稱的字串清單。例如, ["HS256", "HS384"]
。
如果未指定,將根據提供的密鑰類型使用預設值
秘密 - ['HS256'、'HS384'、'HS512']
rsa - ['RS256','RS384','RS512']
ec-['ES256'、'ES384'、'ES512']
預設 - ['RS256'、'RS384'、'RS512']
audience
:如果您想檢查受眾 ( aud
),請在此處提供一個值。可以對照字串、正規表示式或字串和/或正規表示式的清單來檢查受眾。
例如:
"urn:foo"
,/urn:f[o]{2}/
,[/urn:f[o]{2}/, "urn:bar"]
complete
:返回一個帶有解碼後的{ payload, header, signature }
的對象,而不是僅返回有效負載的通常內容。
issuer
(可選): iss
欄位有效值的字串或字串陣列。
jwtid
(可選):如果您想檢查 JWT ID ( jti
),請在此處提供字串值。
ignoreExpiration
:如果true
則不驗證令牌的過期時間。
ignoreNotBefore
...
subject
:如果您想檢查主題 ( sub
),請在此處提供一個值
clockTolerance
:檢查nbf
和exp
聲明時容忍的秒數,以處理不同伺服器之間的微小時鐘差異
maxAge
:令牌仍然有效的最大允許年齡。它以秒或描述時間跨度 vercel/ms 的字串表示。
例如:
1000
、"2 days"
、"10h"
、"7d"
。數值被解釋為秒數。如果您使用字串,請確保提供時間單位(天、小時等),否則預設使用毫秒單位("120"
等於"120ms"
)。
clockTimestamp
:套用所有必要比較的目前時間的時間(以秒為單位)。
nonce
:如果您想檢查nonce
聲明,請在此處提供字串值。它在 Open ID 上用於 ID 令牌。 (開放ID實施說明)
allowInvalidAsymmetricKeyTypes
:如果為 true,則允許與指定演算法不符的非對稱金鑰。此選項僅用於向後相容,應避免使用。
// 驗證令牌對稱- 同步var解碼= jwt.verify(token, 'shhhhh');console.log(decoded.foo) // bar//驗證令牌對稱jwt.verify(token, 'shhhhh', function (err) ,解碼){ console.log(decoded.foo) // bar});// 無效令牌 - synchronoustry { var解碼 = jwt.verify(token, '錯誤的秘密');} catch(err) { // err}// 無效 tokenjwt.verify(token, '錯誤的秘密', function(err, 已解碼) { // 錯誤 // 解碼 undefined});// 驗證令牌非對稱var cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, function(err,已解碼) { console.log(decoded.foo) // bar});// 驗證受眾 var cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, { Audience: 'urn:foo' }, function(err,已解碼) { // 如果受眾不匹配,則 err == 無效受眾});// 驗證頒發者var cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, { Audience: 'urn:foo', Issuer: 'urn:issuer' }, function(err,已解碼) { // 如果頒發者不匹配,err == 無效頒發者});// 驗證 jwt idvar cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, { Audience: 'urn:foo', Issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err,已解碼) { // 如果 jwt id 不匹配,則 err == 無效 jwt id});// 驗證主題var cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, { Audience: 'urn:foo', Issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err,已解碼) { // 如果主題不匹配,則 err == 無效主題});// alg 不符合var cert = fs.readFileSync('public.pem'); // 取得公鑰jwt.verify(token, cert, {演算法: ['RS256'] }, function (err, payload) { // if token alg != RS256, err == invalid Signature});// 使用 getKey 回呼驗證 // 範例使用 https://github.com/auth0/node-jwks-rsa 作為取得金鑰的方式。 jwksClient = require('jwks-rsa');var client = jwksClient({ jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'});函數 getKey(標頭, 回呼){ client.getSigningKey(header.kid, function(err, key) {varsigningKey = key.publicKey || key.rsaPublicKey;callback(null,signingKey); });}jwt.verify(token, getKey, 選項, 函數(err, 解碼) { console.log(decoded.foo) // bar});
(同步)返回解碼後的有效負載,而不驗證簽名是否有效。
警告:這不會驗證簽名是否有效。您不應該將其用於不受信任的訊息。您很可能會想使用
jwt.verify
代替。
警告:當令牌來自不受信任的來源(例如使用者輸入或外部請求)時,返回的解碼負載應像任何其他使用者輸入一樣對待;請確保進行消毒並僅使用預期的房產
token
是 JsonWebToken 字串
options
:
json
:即使標頭不包含"typ":"JWT"
也對有效負載強制 JSON.parse 。
complete
:傳回一個有解碼後的有效負載和標頭的物件。
例子
// 取得解碼後的有效負載,忽略簽名,不需要SecretOrPrivateKeyvar解碼= jwt.decode(token);// 取得解碼後的有效負載和標頭var解碼= jwt.decode(token, {complete: true}) ;console.log(decoded. header);console.log(decoded.payload)
驗證過程中可能拋出錯誤。 Error 是驗證回呼的第一個參數。
如果令牌過期,則會拋出錯誤。
錯誤對象:
名稱:'TokenExpiredError'
訊息:“jwt 已過期”
過期時間:[過期日期]
jwt.verify(token, 'shhhhh', 函數(err, 解碼) { if (err) {/* err = { name: 'TokenExpiredError', message: 'jwt 過期', expiredAt: 1408621000 } */ }});
錯誤對象:
名稱:'JsonWebTokenError'
訊息:
“無效令牌” - 無法解析標頭或有效負載
“jwt 格式錯誤” - 令牌不具有三個組成部分(由.
分隔)
'需要jwt簽名'
“簽名無效”
'jwt 觀眾無效。預期:[選項觀眾]'
'jwt 發行者無效。預期:[選項發行者]'
'jwt ID 無效。預期:[選項 JWT ID]'
'jwt 主題無效。預期:[選項主題]'
jwt.verify(token, 'shhhhh', 函數(err, 解碼) { if (err) {/* err = { name: 'JsonWebTokenError', message: 'jwt 格式錯誤' } */ }});
如果當前時間早於 nbf 聲明,則拋出該異常。
錯誤對象:
名稱:'NotBeforeError'
訊息:“jwt 未啟動”
日期:2018-10-04T16:10:44.000Z
jwt.verify(token, 'shhhhh', 函數(err, 解碼) { if (err) {/* err = { name: 'NotBeforeError', message: 'jwt 未啟動', date: 2018-10-04T16:10:44.000Z } */ }});
支援的演算法數組。目前支援以下演算法。
alg 參數值 | 數位簽章或MAC演算法 |
---|---|
HS256 | 使用 SHA-256 哈希演算法的 HMAC |
HS384 | 使用 SHA-384 雜湊演算法的 HMAC |
HS512 | 使用 SHA-512 哈希演算法的 HMAC |
RS256 | RSASSA-PKCS1-v1_5 使用 SHA-256 雜湊演算法 |
RS384 | RSASSA-PKCS1-v1_5 使用 SHA-384 雜湊演算法 |
RS512 | RSASSA-PKCS1-v1_5 使用 SHA-512 雜湊演算法 |
PS256 | RSASSA-PSS 使用 SHA-256 雜湊演算法(僅限節點 ^6.12.0 OR >=8.0.0) |
PS384 | RSASSA-PSS 使用 SHA-384 雜湊演算法(僅限節點 ^6.12.0 OR >=8.0.0) |
PS512 | RSASSA-PSS 使用 SHA-512 雜湊演算法(僅限節點 ^6.12.0 OR >=8.0.0) |
ES256 | 使用 P-256 曲線和 SHA-256 雜湊演算法的 ECDSA |
ES384 | 使用 P-384 曲線和 SHA-384 雜湊演算法的 ECDSA |
ES512 | 使用 P-521 曲線和 SHA-512 雜湊演算法的 ECDSA |
沒有任何 | 不包含數位簽章或 MAC 值 |
首先,我們建議您仔細考慮自動刷新 JWT 是否不會在您的系統中引入任何漏洞。
我們不願意將其作為庫的一部分,但是,您可以查看此範例以展示如何實現這一點。除了該範例之外,還有一個問題和拉取請求以獲取有關該主題的更多知識。
X.509 憑證鏈未檢查
如果您發現錯誤或有功能請求,請在此儲存庫問題部分報告。請不要在公共 GitHub 問題追蹤器上報告安全漏洞。負責任的揭露計劃詳細說明了揭露安全問題的程序。
授權0
該專案已獲得 MIT 許可。有關詳細信息,請參閱許可證文件。