Skip to main content

JsonWebToken 中文网

JSON Web Tokens 的实现。

¥An implementation of JSON Web Tokens.

这是针对 draft-ietf-oauth-json-web-token-08 开发的。它使用 node-jws

¥This was developed against draft-ietf-oauth-json-web-token-08. It makes use of node-jws

安装

¥Install

$ npm install jsonwebtoken

迁移说明

¥Migration notes

用法

¥Usage

jwt.sign(payload, secretOrPrivateKey, [options, callback])

(异步)如果提供了回调,则使用 err 或 JWT 调用回调。

¥(Asynchronous) If a callback is supplied, the callback is called with the err or the JWT.

(同步)返回 JsonWebToken 作为字符串

¥(Synchronous) Returns the JsonWebToken as string

payload 可以是表示有效 JSON 的对象字面量、缓冲区或字符串。

¥payload could be an object literal, buffer or string representing valid JSON.

请注意,仅当有效负载是对象字面量时才会设置 exp 或任何其他声明。不会检查缓冲区或字符串有效负载的 JSON 有效性。

¥Please note that exp or any other claim is only set if the payload is an object literal. Buffer or string payloads are not checked for JSON validity.

如果 payload 不是缓冲区或字符串,它将使用 JSON.stringify 强制转换为字符串。

¥If payload is not a buffer or a string, it will be coerced into a string using JSON.stringify.

secretOrPrivateKey 是一个字符串(utf-8 编码)、缓冲区、对象或 KeyObject,其中包含 HMAC 算法的密钥或 RSA 和 ECDSA 的 PEM 编码私钥。如果私钥带有密码,则可以使用对象 { key, passphrase }(基于 加密文档),在这种情况下请确保传递 algorithm 选项。使用 RSA 算法签名时,最小模数长度为 2048,除非将 allowInsecureKeySizes 选项设置为 true。小于此大小的私钥将被拒绝并出现错误。

¥secretOrPrivateKey is a string (utf-8 encoded), buffer, object, or KeyObject containing either the secret for HMAC algorithms or the PEM encoded private key for RSA and ECDSA. In case of a private key with passphrase an object { key, passphrase } can be used (based on crypto documentation), in this case be sure you pass the algorithm option. When signing with RSA algorithms the minimum modulus length is 2048 except when the allowInsecureKeySizes option is set to true. Private keys below this size will be rejected with an error.

options

  • algorithm(默认值:HS256)

    ¥algorithm (default: HS256)

  • expiresIn:以秒为单位表示或描述时间跨度 vercel/ms 的字符串。

    ¥expiresIn: expressed in seconds or a string describing a time span vercel/ms.

    例如:60, "2 days", "10h", "7d".数值被解释为秒数。如果你使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位("120" 等于 "120ms")。

    ¥Eg: 60, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").

  • notBefore:以秒为单位表示或描述时间跨度 vercel/ms 的字符串。

    ¥notBefore: expressed in seconds or a string describing a time span vercel/ms.

    例如:60, "2 days", "10h", "7d".数值被解释为秒数。如果你使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位("120" 等于 "120ms")。

    ¥Eg: 60, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").

  • audience

  • issuer

  • jwtid

  • subject

  • noTimestamp

  • header

  • keyid

  • mutatePayload:如果为 true,则签名函数将直接修改有效负载对象。如果你需要在将声明应用于有效负载之后但在将其编码为令牌之前对其进行原始引用,这将非常有用。

    ¥mutatePayload: if true, the sign function will modify the payload object directly. This is useful if you need a raw reference to the payload after claims have been applied to it but before it has been encoded into a token.

  • allowInsecureKeySizes:如果为 true,则允许模数低于 2048 的私钥用于 RSA

    ¥allowInsecureKeySizes: if true allows private keys with a modulus below 2048 to be used for RSA

  • allowInvalidAsymmetricKeyTypes:如果为 true,则允许与指定算法不匹配的非对称密钥。此选项仅用于向后兼容,应避免使用。

    ¥allowInvalidAsymmetricKeyTypes: if true, allows asymmetric keys which do not match the specified algorithm. This option is intended only for backwards compatability and should be avoided.

expiresInnotBeforeaudiencesubjectissuer 没有默认值。这些声明也可以分别在有效负载中直接使用 expnbfaudsubiss 提供,但不能同时包含在两个位置。

¥There are no default values for expiresIn, notBefore, audience, subject, issuer. These claims can also be provided in the payload directly with exp, nbf, aud, sub and iss respectively, but you can't include in both places.

请记住 expnbfiat 是 NumericDate,请参阅相关的 令牌过期(exp 声明)

¥Remember that exp, nbf and iat are NumericDate, see related Token Expiration (exp claim)

可以通过 options.header 对象自定义标头。

¥The header can be customized via the options.header object.

除非指定 noTimestamp,否则生成的 jwts 将默认包含 iat(颁发于)声明。如果 iat 插入到有效负载中,它将代替实际时间戳来计算其他内容,例如在 options.expiresIn 中给定时间跨度的 exp

¥Generated jwts will include an iat (issued at) claim by default unless noTimestamp is specified. If iat is inserted in the payload, it will be used instead of the real timestamp for calculating other things like exp given a timespan in options.expiresIn.

使用默认 (HMAC SHA256) 同步签名

¥Synchronous Sign with default (HMAC SHA256)

var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');

使用 RSA SHA256 同步签名

¥Synchronous Sign with RSA SHA256

// sign with RSA SHA256
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });

异步签名

¥Sign asynchronously

jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' }, function(err, token) {
console.log(token);
});

将 jwt 追溯 30 秒

¥Backdate a jwt 30 seconds

var older_token = jwt.sign({ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 }, 'shhhhh');

令牌过期(exp 声明)

¥Token Expiration (exp claim)

JWT 标准为到期日期定义了 exp 声明。到期日期表示为 NumericDate:

¥The standard for JWT defines an exp claim for expiration. The expiration is represented as a NumericDate:

一个 JSON 数值,表示从 1970-01-01T00:00:00Z UTC 到指定 UTC 日期/时间的秒数,忽略闰秒。这相当于 IEEE Std 1003.1, 2013 版 [POSIX.1] 定义 "自纪元以来的秒数",其中每天恰好由 86400 秒组成,除了可以表示非整数值之外。有关日期/时间(一般情况下)和 UTC 的详细信息,请参阅 RFC 3339 [RFC3339]。

¥A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.

这意味着 exp 字段应包含自纪元以来的秒数。

¥This means that the exp field should contain the number of seconds since the epoch.

签署有效期为 1 小时的令牌:

¥Signing a token with 1 hour of expiration:

jwt.sign({
exp: Math.floor(Date.now() / 1000) + (60 * 60),
data: 'foobar'
}, 'secret');

使用此库生成此类令牌的另一种方法是:

¥Another way to generate a token like this with this library is:

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

//or even better:

jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '1h' });

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

(异步)如果提供了回调,函数将异步运行。如果签名有效且可选的到期日期、受众或发行者有效,则使用解码的有效负载调用回调。如果没有,它将被调用并出现错误。

¥(Asynchronous) If a callback is supplied, function acts asynchronously. The callback is called with the decoded payload if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will be called with the error.

(同步)如果没有提供回调,函数将同步运行。如果签名有效且可选的到期日期、受众或发行者有效,则返回解码的有效负载。如果没有,它将抛出错误。

¥(Synchronous) If a callback is not supplied, function acts synchronously. Returns the payload decoded if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will throw the error.

警告:当令牌来自不受信任的来源(例如用户输入或外部请求)时,返回的解码后的有效负载应被视为与任何其他用户输入一样;请确保清理并仅使用预期的属性

¥Warning: When the token comes from an untrusted source (e.g. user input or external requests), the returned decoded payload should be treated like any other user input; please make sure to sanitize and only work with properties that are expected

token 是 JsonWebToken 字符串

¥token is the JsonWebToken string

secretOrPublicKey 是一个字符串(utf-8 编码)、缓冲区或 KeyObject,其中包含 HMAC 算法的密钥或 RSA 和 ECDSA 的 PEM 编码公钥。如果 jwt.verify 被异步调用,secretOrPublicKey 可以是一个应该获取密钥或公钥的函数。请参阅下面的详细示例

¥secretOrPublicKey is a string (utf-8 encoded), buffer, or KeyObject containing either the secret for HMAC algorithms, or the PEM encoded public key for RSA and ECDSA. If jwt.verify is called asynchronous, secretOrPublicKey can be a function that should fetch the secret or public key. See below for a detailed example

此评论 中所述,还有其他库需要 base64 编码的密钥(使用 base64 编码的随机字节),如果是这种情况,你可以传递 Buffer.from(secret, 'base64'),通过这样做,密钥将使用 base64 解码,令牌验证将使用原始随机字节。

¥As mentioned in this comment, there are other libraries that expect base64 encoded secrets (random bytes encoded using base64), if that is your case you can pass Buffer.from(secret, 'base64'), by doing this the secret will be decoded using base64 and the token verification will use the original random bytes.

options

  • algorithms:带有允许算法名称的字符串列表。例如,["HS256", "HS384"]

    ¥algorithms: List of strings with the names of the allowed algorithms. For instance, ["HS256", "HS384"].

    如果未指定,将根据提供的密钥类型使用默认值

    ¥If not specified a defaults will be used based on the type of key provided

    • secret - ['HS256', 'HS384', 'HS512']
    • rsa - ['RS256', 'RS384', 'RS512']
    • ec - ['ES256', 'ES384', 'ES512']
    • default - ['RS256', 'RS384', 'RS512']
  • audience:如果你想检查受众 (aud),请在此处提供一个值。可以根据字符串、正则表达式或字符串和/或正则表达式列表检查受众。

    ¥audience: if you want to check audience (aud), provide a value here. The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions.

    例如:"urn:foo", /urn:f[o]{2}/, [/urn:f[o]{2}/, "urn:bar"]

    ¥Eg: "urn:foo", /urn:f[o]{2}/, [/urn:f[o]{2}/, "urn:bar"]

  • complete:返回一个带有解码后的 { payload, header, signature } 的对象,而不是仅返回有效负载的通常内容。

    ¥complete: return an object with the decoded { payload, header, signature } instead of only the usual content of the payload.

  • issuer(可选):iss 字段的有效值的字符串或字符串数​​组。

    ¥issuer (optional): string or array of strings of valid values for the iss field.

  • jwtid(可选):如果你想检查 JWT ID (jti),请在此处提供字符串值。

    ¥jwtid (optional): if you want to check JWT ID (jti), provide a string value here.

  • ignoreExpiration:如果 true 不验证令牌的到期日期。

    ¥ignoreExpiration: if true do not validate the expiration of the token.

  • ignoreNotBefore...

  • subject:如果你要检查主题 (sub),请在此处提供一个值

    ¥subject: if you want to check subject (sub), provide a value here

  • clockTolerance:检查 nbfexp 声明时要容忍的秒数,以处理不同服务器之间的微小时钟差异

    ¥clockTolerance: number of seconds to tolerate when checking the nbf and exp claims, to deal with small clock differences among different servers

  • maxAge:令牌仍然有效的最大允许年龄。它以秒为单位或描述时间跨度 vercel/ms 的字符串表示。

    ¥maxAge: the maximum allowed age for tokens to still be valid. It is expressed in seconds or a string describing a time span vercel/ms.

    例如:1000, "2 days", "10h", "7d".数值被解释为秒数。如果你使用字符串,请确保提供时间单位(天、小时等),否则默认使用毫秒单位("120" 等于 "120ms")。

    ¥Eg: 1000, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").

  • clockTimestamp:应用于所有必要比较的当前时间(以秒为单位)。

    ¥clockTimestamp: the time in seconds that should be used as the current time for all necessary comparisons.

  • nonce:如果你想检查 nonce 声明,请在此处提供字符串值。它在 Open ID 上用于 ID 令牌。(Open ID 实现说明)

    ¥nonce: if you want to check nonce claim, provide a string value here. It is used on Open ID for the ID Tokens. (Open ID implementation notes)

  • allowInvalidAsymmetricKeyTypes:如果为 true,则允许与指定算法不匹配的非对称密钥。此选项仅用于向后兼容,应避免使用。

    ¥allowInvalidAsymmetricKeyTypes: if true, allows asymmetric keys which do not match the specified algorithm. This option is intended only for backwards compatability and should be avoided.

// verify a token symmetric - synchronous
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo) // bar

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

// invalid token - synchronous
try {
var decoded = jwt.verify(token, 'wrong-secret');
} catch(err) {
// err
}

// invalid token
jwt.verify(token, 'wrong-secret', function(err, decoded) {
// err
// decoded undefined
});

// verify a token asymmetric
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, function(err, decoded) {
console.log(decoded.foo) // bar
});

// verify audience
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
// if audience mismatch, err == invalid audience
});

// verify issuer
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(err, decoded) {
// if issuer mismatch, err == invalid issuer
});

// verify jwt id
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) {
// if jwt id mismatch, err == invalid jwt id
});

// verify subject
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) {
// if subject mismatch, err == invalid subject
});

// alg mismatch
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
// if token alg != RS256, err == invalid signature
});

// Verify using getKey callback
// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
});
function getKey(header, callback){
client.getSigningKey(header.kid, function(err, key) {
var signingKey = key.publicKey || key.rsaPublicKey;
callback(null, signingKey);
});
}

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

Need to peek into a JWT without verifying it? (Click to expand)

jwt.decode(token [, options])

(同步)返回解码的有效负载,而不验证签名是否有效。

¥(Synchronous) Returns the decoded payload without verifying if the signature is valid.

警告:这不会验证签名是否有效。你不应该将其用于不受信任的消息。你很可能想改用 jwt.verify

¥Warning: This will not verify whether the signature is valid. You should not use this for untrusted messages. You most likely want to use jwt.verify instead.

警告:当令牌来自不受信任的来源(例如用户输入或外部请求)时,返回的解码后的有效负载应被视为与任何其他用户输入一样;请确保清理并仅使用预期的属性

¥Warning: When the token comes from an untrusted source (e.g. user input or external request), the returned decoded payload should be treated like any other user input; please make sure to sanitize and only work with properties that are expected

token 是 JsonWebToken 字符串

¥token is the JsonWebToken string

options

  • json:即使标头不包含 "typ":"JWT",也强制对有效负载执行 JSON.parse。

    ¥json: force JSON.parse on the payload even if the header doesn't contain "typ":"JWT".

  • complete:返回一个带有解码后的有效负载和标头的对象。

    ¥complete: return an object with the decoded payload and header.

示例

¥Example

// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);

// get the decoded payload and header
var decoded = jwt.decode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload)

错误和代码

¥Errors & Codes

验证期间可能抛出错误。Error 是验证回调的第一个参数。

¥Possible thrown errors during verification. Error is the first argument of the verification callback.

TokenExpiredError

如果令牌已过期,则抛出错误。

¥Thrown error if the token is expired.

错误对象:

¥Error object:

  • 名称:'TokenExpiredError'

    ¥name: 'TokenExpiredError'

  • 消息:'jwt 已过期'

    ¥message: 'jwt expired'

  • expiredAt:[ExpDate]

jwt.verify(token, 'shhhhh', function(err, decoded) {
if (err) {
/*
err = {
name: 'TokenExpiredError',
message: 'jwt expired',
expiredAt: 1408621000
}
*/
}
});

JsonWebTokenError

错误对象:

¥Error object:

  • 名称:'JsonWebTokenError'

    ¥name: 'JsonWebTokenError'

  • 消息:

    ¥message:

    • '令牌无效' - 无法解析标头或有效负载

      ¥'invalid token' - the header or payload could not be parsed

    • 'jwt 格式错误' - 令牌没有三个组件(由 . 分隔)

      ¥'jwt malformed' - the token does not have three components (delimited by a .)

    • '需要 jwt 签名'

      ¥'jwt signature is required'

    • '签名无效'

      ¥'invalid signature'

    • 'jwt 受众无效。预期:[OPTIONS AUDIENCE]'

      ¥'jwt audience invalid. expected: [OPTIONS AUDIENCE]'

    • 'jwt 发行者无效。预期:[OPTIONS ISSUER]'

      ¥'jwt issuer invalid. expected: [OPTIONS ISSUER]'

    • 'jwt id 无效。预期:[OPTIONS JWT ID]'

      ¥'jwt id invalid. expected: [OPTIONS JWT ID]'

    • 'jwt 主题无效。预期:[OPTIONS SUBJECT]'

      ¥'jwt subject invalid. expected: [OPTIONS SUBJECT]'

jwt.verify(token, 'shhhhh', function(err, decoded) {
if (err) {
/*
err = {
name: 'JsonWebTokenError',
message: 'jwt malformed'
}
*/
}
});

NotBeforeError

如果当前时间早于 nbf 声明,则抛出错误。

¥Thrown if current time is before the nbf claim.

错误对象:

¥Error object:

  • 名称:'NotBeforeError'

    ¥name: 'NotBeforeError'

  • 消息:'jwt 未激活'

    ¥message: 'jwt not active'

  • 日期:2018-10-04T16:10:44.000Z

    ¥date: 2018-10-04T16:10:44.000Z

jwt.verify(token, 'shhhhh', function(err, decoded) {
if (err) {
/*
err = {
name: 'NotBeforeError',
message: 'jwt not active',
date: 2018-10-04T16:10:44.000Z
}
*/
}
});

支持的算法

¥Algorithms supported

支持的算法数组。目前支持以下算法。

¥Array of supported algorithms. The following algorithms are currently supported.

alg 参数值数字签名或 MAC 算法
HS256使用 SHA-256 哈希算法的 HMAC
HS384使用 SHA-384 哈希算法的 HMAC
HS512使用 SHA-512 哈希算法的 HMAC
RS256RSASSA-PKCS1-v1_5 使用 SHA-256 哈希算法
RS384RSASSA-PKCS1-v1_5 使用 SHA-384 哈希算法
RS512RSASSA-PKCS1-v1_5 使用 SHA-512 哈希算法
PS256RSASSA-PSS 使用 SHA-256 哈希算法(仅限节点 ^6.12.0 或 >=8.0.0)
PS384RSASSA-PSS 使用 SHA-384 哈希算法(仅限节点 ^6.12.0 或 >=8.0.0)
PS512RSASSA-PSS 使用 SHA-512 哈希算法(仅限节点 ^6.12.0 或 >=8.0.0)
ES256使用 P-256 曲线和 SHA-256 哈希算法的 ECDSA
ES384使用 P-384 曲线和 SHA-384 哈希算法的 ECDSA
ES512使用 P-521 曲线和 SHA-512 哈希算法的 ECDSA
none不包含数字签名或 MAC 值

刷新 JWT

¥Refreshing JWTs

首先,我们建议你仔细考虑自动刷新 JWT 是否会在你的系统中引入任何漏洞。

¥First of all, we recommend you to think carefully if auto-refreshing a JWT will not introduce any vulnerability in your system.

我们不愿意将其作为库的一部分,但是,你可以查看 此示例 以了解如何实现这一点。除了该示例之外,还有 问题拉取请求 可以了解有关此主题的更多知识。

¥We are not comfortable including this as part of the library, however, you can take a look at this example to show how this could be accomplished. Apart from that example there are an issue and a pull request to get more knowledge about this topic.

TODO

  • 未检查 X.509 证书链

    ¥X.509 certificate chain is not checked

问题报告

¥Issue Reporting

如果你发现了错误或有功能请求,请在此存储库问题部分报告。请不要在公共 GitHub 问题跟踪器上报告安全漏洞。负责任的披露计划 详细说明了披露安全问题的程序。

¥If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.

作者

¥Author

Auth0

许可证

¥License

该项目根据 MIT 许可证获得许可。有关更多信息,请参阅 LICENSE 文件。

¥This project is licensed under the MIT license. See the LICENSE file for more info.