web-dev-qa-db-ja.com

node-jwt-simpleを使用したpassport-local

認証の成功時にpassport-localを組み合わせてJWTトークンを返すにはどうすればよいですか?

node-jwt-simple を使用し、 passport.js を確認したいのですが、どうすればいいかわかりません。

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function(err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));

Done()を呼び出すときにトークンを返すことは可能ですか?このようなもの...(単なる擬似コード)

if(User.validCredentials(username, password)) {
  var token = jwt.encode({username: username}, tokenSecret);
  done(null, {token : token}); //is this possible?
}

そうでない場合、どうすればトークンを返すことができますか?

87
cgiacomi

私はそれを考え出した!

まず、正しい戦略を実装する必要があります。私の場合、LocalStrategy、および検証ロジックを提供する必要があります。たとえば、passport-localにあるものを使用してみましょう。

_var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function(err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));
_

提供する検証コールバックfunction(username, password, done)は、ユーザーを見つけ、パスワードが一致するかどうかを確認します(質問と私の回答の範囲を超えて)

passport.jsは、いくつかの要素が機能することを期待しています。1つは、戦略でユーザーを返すことです。私はコードのその部分を変更しようとしていましたが、それは間違っていました。コールバックは、検証が失敗した場合はfalseを期待し、成功した場合はobject(検証されたユーザー)を期待します。

さて.... JWTを統合するには?

ログインルートでは、成功した認証または失敗した認証を処理する必要があります。そして、ここにJWTトークン作成を追加する必要があります。そのようです:

(セッションを無効にすることを忘れないでください。そうしないと、シリアライズおよびデシリアライズ機能を実装する必要があります。セッションを永続化していない場合、トークンベースの認証を使用していない場合は必要ありません)

パスポートローカルの例から:(JWTトークンを追加)

_// POST /login
//   This is an alternative implementation that uses a custom callback to
//   achieve the same functionality.
app.post('/login', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err) }
    if (!user) {
      return res.json(401, { error: 'message' });
    }

    //user has authenticated correctly thus we create a JWT token 
    var token = jwt.encode({ username: 'somedata'}, tokenSecret);
    res.json({ token : token });

  })(req, res, next);
});
_

それだけです!/loginとPOSTユーザー名とパスワード(常にSSL経由である必要があります))を呼び出すと、上記の最初のコードスニペットは、指定したユーザー名に基づいてユーザーを見つけようとし、パスワードが一致する(もちろん、ニーズに合わせて変更する必要があります)。

その後、ログインルートが呼び出され、そこでエラーまたは有効なトークンが返されます。

これが誰かを助けることを願っています。そして、私が何か間違いをしたか、何かを忘れてしまった場合、私に知らせてください。

122
cgiacomi

これは素晴らしい解決策です。これを追加したいだけです。

var expressJwt = require('express-jwt');

app.use('/api', expressJwt({secret: secret}));

"express-jwt"を使用してトークンを検証するのが好きです。

btw:この記事は、Angularを使用してクライアントサイドでトークンを処理し、すべてのリクエストでトークンを送り返す方法を学ぶのに最適です。

https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

18
ZeroCR

ここに私が具体的にAPIトークンのみを使用するために取り組んでいる定型文があります(セッションはありません...もちろんそのセッションは悪いことではありません;トークンアプローチを使用しています): https://github.com/roblevintennis/passport-api-tokens

3
Rob