njwt, node.js JWT支持,由Stormpath维护

分享于 

12分钟阅读

GitHub

  繁體 雙語
Node.js JWT support - create, verify, ninjafy
  • 源代码名称:njwt
  • 源代码网址:http://www.github.com/jwtk/njwt
  • njwt源代码文档
  • njwt源代码下载
  • Git URL:
    git://www.github.com/jwtk/njwt.git
    Git Clone代码到本地:
    git clone http://www.github.com/jwtk/njwt
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/jwtk/njwt
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    nJwt - Node.js的JWTs

    nin jot/ˈnɪn.dʒɑt/

    NPM VersionNPM DownloadsBuild StatusCoverage Status

    nJwt是用于 node.js 开发人员的最干净的JSON网络令牌( JWT ) 库。 nJwt消除了JWTs的所有复杂性,并提供了简单直观的API,允许你在应用程序中安全地生成和使用 JWTs,而不用读取 rfc7519代码。

    创建安全,签名的JWTs

    他们是一组关于用户的断言和他们能做什么。 JWTs的最常用用例是声明访问令牌的"作用域",这是令牌( 用户)的持有者允许的事件列表。

    JWTs应该签名,否则你无法验证它们是否是由你创建的。 库期望你给我们一个高度随机的签名密钥来签名令牌。 默认情况下,我们使用 HS256 算法,签名密钥的字节长度应该为 MATCH,以确保密码安全。

    库将接受签名密钥的字符串,但建议你使用缓冲区。 如果需要将密钥传输到其他系统,使用缓冲区可以很容易地执行其他操作,比如将签名密钥转换为Base64URL编码。

    尽管声明完全取决于你,但我们建议设置"主题"和"观众"字段。

    JWTs通常包含 iatnbfexp 声明,声明令牌发出的时间。激活日期以及什么时候过期。 我们的库将为你创建这些( nbf除外),默认过期时间为 1小时。 nbf 是可选的。

    以下是一个简单示例,演示如何为签名密钥创建安全字节字符串,然后使用提供的声明签名 JWT:

    var nJwt =require('njwt');var secureRandom =require('secure-random');var signingKey =secureRandom(256, {type:'Buffer'}); // Create a highly random byte array of 256 bytesvar claims = {
     iss:"http://myapp.com/", // The URL of your service sub:"users/user1234", // The UID of the user in your system scope:"self, admins"}var jwt =nJwt.create(claims,signingKey);

    创建JWT之后,你可以通过将它的日志记录到控制台来查看它的内部结构。 这是我们的令牌内部表示形式,这不是你将发送给最终用户的内容:

    console.log(jwt);
    {
     "header": {
     "typ": "JWT",
     "alg": "HS256" },
     "body": {
     "jti": "c84280e6-0021-4e69-ad76-7a3fdd3d4ede",
     "iat": 1434660338,
     "exp": 1434663938,
     "nbf": 1434663938,
     "iss": "http://myapp.com/",
     "sub": "users/user1234",
     "scope": ["self","admins"]
     }
    }

    我们的库为你添加了 jti 字段,这是一个随机标识,它对于每个令牌都是唯一的。 如果你想创建一个已经颁发给用户的令牌数据库,则可以使用这里方法。

    当你准备向最终用户提供令牌时,你需要对它的进行 compact。 这将使它成为一个 Base64 URL编码字符串,使它的在不应用任何意外格式的浏览器中传递安全。

    var token =jwt.compact();console.log(token);
    
    eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJmb28iOiJiYXIiLCJpYXQiOjE0MzQ0Nzk4ODN9.HQyx15jWm1upqsrKSf89X_iP0sg7N46a9pqBVGPMYdiqZeuU_ZZOdU-zizHJoIHMIJxtEWzpSMaVubJW0AJsTqjqQf6GoJ4cmFAfmfUFXmMC4Xv5oc4UqvGizpoLjfZedd834PcwbS-WskZcL4pVNmBIGRtDXkoU1j2X1P5M_sNJ9lYZ5vITyqe4MYJovQzNdQziUNhcMI5wkXncV7XzGInBeQsPquASWVG4gb3Y--k1P3xWA4Df3rKeEQBbInDKXczvDpfIlTojx4Ch8OM8vXWWNxW-mIQrV31wRrS9XtNoig7irx8N0MzokiYKrQ8WP_ezPicHvVPIHhz-InOw
    
    
    
    

    这是客户端应用程序将保留的JWT,用于身份验证。

    你的服务器应用程序还需要保持签名密钥,当客户端尝试使用这里令牌时,你需要使用相同的签名密钥。

    缓冲区需要转换为字符串,以便它可以在数据库中保持,你可以如下所示:

    
    var base64SigningKey = signingKey.toString('base64');
    
    
    
    

    如果要使用多个签名密钥,通常需要创建标识密钥的随机,并将该,存储在数据库中。 创建JWTs时,将头的kid 字段设置为该标识。 验证JWTs时,这个 kid 字段将告诉你应该使用哪个签名密钥进行验证。

    验证签名的JWTs

    最终用户将使用他们的JWT通过你的服务来验证自己。 当它们呈现JWT时,你要检查令牌以确保它是有效的。 在调用 verify 方法时,此库执行以下检查:

    • 它由你创建( 通过验证签名,使用密钥签名密钥)
    • 它还没有被修改( 比如。 某些声明是恶意添加
    • 它还没有过期
    • 它是活动

    若要验证以前颁发的令牌,请使用 verify 方法。 你必须给予它与用来创建令牌的签名密钥相同的签名密钥:

    nJwt.verify(token,signingKey,function(err,verifiedJwt){
     if(err){
     console.log(err); // Token has expired, has been tampered with, etc }else{
     console.log(verifiedJwt); // Will contain the header and body }
    });

    如果验证失败,你可以查看 err.message 以了解问题。 如果JWT的头和正文被解析成( 不可验证的),它们将被提供为 err.parsedHeadererr.parsedBody的对象。

    还可以同步使用验证,在这种情况下,将引发错误:

    try{
     verifiedJwt =nJwt.verify(token,signingKey);
    }catch(e){
     console.log(e);
    }

    更改算法

    如果要从缺省 HS256 更改算法,则可以通过将它的作为第三个参数传递给 create 或者 verify 方法来实现:

    var jwt =nJwt.create(claims,signingKey,'HS512');
    nJwt.verify(token,signingKey, 'HS512');

    请参阅下面的表格以获得支持的算法列表。 如果使用RSA密钥对,则 public 密钥将是签名密钥参数。

    自定义令牌

    当我们为你选择了安全。合理的默认值时,你可能需要更改。

    声明

    在创建JWT之后,如果需要提供自定义声明,只需将它们提供给 create 方法或者手动添加到索赔主体。 这两个示例创建相同的声明主体:

    var claims = {
     scope:'admins'}var jwt =nJwt.create(claims,secret);jwt.body.scope='admins';jwt.setClaim('otherClaim', 'value');

    你可以手动修改头对象,或者使用 setHeader() 方法:

    var jwt =nJwt.create({}, keyMap.kid_a);jwt.headers.myClaim='foo';jwt.setHeader('kid', 'kid_a');

    使用密钥解析器

    如果应用程序使用多个签名密钥,nJwt提供一个方便的小特性,允许你解析应该使用哪个签名密钥来验证令牌。

    为此,首先需要使用 nJwt.createVerifier() 手动创建验证程序实例,然后向 withKeyResolver() 方法提供密钥解析功能:

    var keyMap = {
     kid_a:'<secure signing key>',
     kid_b:'<secure signing key>'};functionmyKeyResolver(kid, cb) {
     var key = keyMap[kid];
     if (key) {
     returncb(null, key);
     }
     cb(newError('Unknown kid'));
    }var tokenA =nJwt.create({}, keyMap.kid_a).setHeader('kid', 'kid_a').compact();var tokenB =nJwt.create({}, 'foo').setHeader('kid', 'bar').compact();var verifier =nJwt.createVerifier().withKeyResolver(myKeyResolver);// synchronouslytry {
     // This will pass and print the resultvar parsedJwt =verifier.verify(tokenA);
     console.log(parsedJwt);
    } catch(e) {
     console.log(e);
    }// asynchronouslyverifier.verify(tokenB, function(err, verifiedJwt) {
     if (err) {
     returnconsole.log(err); // This error with"'Error while resolving signing key for kid"bar"'" }
     console.log(verifiedJwt);
    });
    到期声明

    为修改 exp 声明提供了一种便捷方法。 可以通过将 Date 对象或者毫秒值传递给 setExpiration 方法来修改 exp 声明:

    var jwt =nJwt.create(claims,secret);jwt.setExpiration(newDate('2015-07-01')); // A specific datejwt.setExpiration(newDate().getTime() + (60*60*1000)); // One hour from nowjwt.setExpiration(); // Remove the exp claim
    NotBefore声明

    为修改 nbf 声明提供了一种便捷方法。 可以通过将 Date 对象或者毫秒值传递给 setNotBefore 方法来修改 nbf 声明:

    var jwt =nJwt.create(claims,secret);jwt.setNotbefore(newDate('2015-07-01')); // token is active from this datejwt.setNotbefore(newDate().getTime() + (60*60*1000)); // One hour from nowjwt.setNotbefore(); // Remove the exp claim

    支持算法

    "alg value算法
    HS256HMAC使用 SHA-256 哈希算法
    HS384HMAC使用 SHA-384 哈希算法
    HS512HMAC使用 SHA-512 哈希算法
    RS256使用 SHA-256 哈希算法的RSASSA
    RS384使用 SHA-384 哈希算法的RSASSA
    RS512使用 SHA-512 哈希算法的RSASSA
    ES256使用 P-256 曲线和 SHA-256 哈希算法的ECDSA
    ES384使用 P-384 曲线和 SHA-384 哈希算法的ECDSA
    ES512使用 P-521 曲线和 SHA-512 哈希算法的ECDSA
    未包括数字签名或者MAC值

    不支持的功能

    这里库还不支持以下功能:

    • 加密 JWT ( aka JWE )

    SUP  MAIN  JWT  Storm  Stormpath  
    相关文章