1. ホーム
  2. node.js

[解決済み] node-jwt-simpleを使ったパスポートローカル

2023-04-14 05:14:03

質問

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

私は node-jwt-simple を見てみると パスポート.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?
}

そうでない場合、どのようにトークンを返せばよいのでしょうか?

どのように解決するのですか?

解決しました!

まず最初に、正しいストラテジーを実装する必要があります。私の場合は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トークンの作成を追加する必要があるのは、ここです。このように。

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

passport-localの例から。(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経由でなければなりません)、上記の最初のコード片は提供されたユーザー名に基づいてユーザーを見つけようとし、パスワードが一致するかチェックします(もちろん、あなたのニーズに合わせて変更する必要があります)。

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

これが誰かの助けになることを願っています。もし私が何か間違えたり、忘れたりしたことがあれば教えてください。