web-dev-qa-db-ja.com

JWTでjtiクレームを使用する方法

JWT仕様には、リプレイ攻撃を防ぐためのノンスとして使用できるjtiクレームが記載されています。

Jti(JWT ID)クレームは、JWTの一意の識別子を提供します。識別子の値は、同じ値が誤って異なるデータオブジェクトに割り当てられる可能性が無視できるほど小さいことを保証する方法で割り当てられなければなりません。アプリケーションが複数の発行者を使用する場合、異なる発行者によって生成された値の間でも衝突を防ぐ必要があります。 jtiクレームは、JWTがリプレイされるのを防ぐために使用できます。 jti値は、大文字と小文字が区別される文字列です。この主張の使用は任意です。

私の質問は、これをどのように実装するのですか?以前に使用したjtisを保存し、リクエストごとに新しいJWTを発行する必要がありますか?もしそうなら、これはJWTの目的に反しませんか?単にランダムに生成されたセッションIDをデータベースに保存するのではなく、JWTを使用するのはなぜですか?

私のREST APIにはmongoデータベースがあり、redisインスタンスを追加することに反対していません。JWTよりも優れた認証オプションはありますか?主にクライアントにパスワードを保存したくないだけです。ただし、このJWTの内容をより深く理解するにつれて、カスタムトークンの実装または別の標準が私のニーズにより適していると感じ始めています。トークンの取り消しとトークンのローテーションをサポートするベースの認証?

アドバイスをお願いします。

48
nw.

実際、発行されたすべてのJWT IDを保存すると、JWTを使用するステートレスな性質が損なわれます。ただし、JWT IDの目的は、以前に発行されたJWTを取り消せるようにすることです。これは、ホワイトリストではなくブラックリストに登録することで最も簡単に実現できます。 「exp」クレームを含めた場合(そうすべきです)、最終的にブラックリストに登録されたJWTが自然に期限切れになるため、クリーンアップできます。もちろん、他の失効オプションを一緒に実装できます(たとえば、「iat」と「aud」の組み合わせに基づいて1つのクライアントのすべてのトークンを失効させます)。

40
Gert Hengeveld

Express-jwtパッケージを使用できます

GitHub または [〜#〜] npm [〜#〜] のexpress-jwtを参照してください。

Express-jwtは、失効したトークンをここで説明するように処理します: https://github.com/auth0/express-jwt#revoked-tokens

var jwt = require('express-jwt');
var data = require('./data');
var utilities = require('./utilities');

var isRevokedCallback = function(req, payload, done){
  var issuer = payload.iss;
  var tokenId = payload.jti;

  data.getRevokedToken(issuer, tokenId, function(err, token){
    if (err) { return done(err); }
    return done(null, !!token);
  });
};

app.get('/protected',
  jwt({secret: shhhhhhared-secret,
    isRevoked: isRevokedCallback}),
  function(req, res) {
    if (!req.user.admin) return res.send(401);
    res.send(200);
  });

パート4も読むことができます。オーバーヘッドを追加しないようにするにはどうすればよいですか?from this oauth0 blog post .

9
Yves M.