認証ミドルウェア”Passport”

Blog Single

“Passport”とは

何かしらのアプリやページのプログラミングを書く際に、頻繁に立ち向かわなければならないのが認証システムです。意外と面倒臭い割りによく対峙します。
フレームワークによってはあらかじめ認証機能が搭載されていたりもしますが、シンプルさ・軽量さを売りにしているフレームワークには認証機能がデフォルトとしては備わっていないこともあります。
サーバーサイドJavaScriptであるNode.jsの一番メジャーなフレームワークにExpressというものがあります。柔軟性と軽量さがExpressの魅力であり強みです。御察しの通り、認証機能はデフォルトでは備わっていません。
折角軽量なフレームワークなんだし、どうせだったら認証もサクッと終わらせてしまいたい…。
そんな時に役立つのが”Passport”というミドルウェアです。史上最も成功した認証システムと称する人もいるこのPassportの使い方を説明したいと思います。

まずは準備

まず例によって必要なモジュールをインストールする必要があります。
$ npm i passport passport-local express-session
今回はユーザーIDとパスワードを認証に用いたいと考えているので”passport-local”をインストールしましたが、他にもTwitterアカウントで認証する”passport-twitter”、facebookアカウントで認証する”passport-facebook”など、利用したいストラテジーに合わせて色々なものがサポートされています。”express-session”はログイン情報を保持しておくために必要なので持っておきます。
今回はPassportの使い方に焦点を当てるため、express-generatorで自動生成したアプリの土台にユーザー認証システムを追加させていくこととします。なのでexpress-generatorもグローバルでインストールしておきます。
$ npm i -g express-generator
インストールが完了した後で
$ express sample
とコマンドを打つとsampleというアプリケーション・スケルトンが生成されたと思います。このsampleの中のapp.jsというフォルダがあるのを確認できると思いますが、このapp.jsがsampleというアプリケーションの肝になります。今回はこれに手を加えていきます。

app.jsの加工

まずはインストールしたpassportとpassport-localを呼び出します。

var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport'); //追加する
var LocalStrategy = require('passport-local').Strategy; //追加する

更に

var app = express();

//以下追加する
app.use(require('express-session'){
    secret: '*******************' // cookieの暗号化に必要、任意な文字列にしてください
});
app.use(passport.initialize());
app.use(passport.session());

ここではpassportの基本設定と初期化を行なっています。
この下に更に書き加えていきます。

//passport.authenticateを呼び出されるとここが実行される
passport.use(new LocalStrategy(
    {
        usernameField: "username",
        passowrdField: "password" //デフォルトはusernameとpasswordだが変更可能
    },
    function(username, password, done){
    // usernameとpasswordを用いて特定のユーザーがいるかどうか確認する処理
    } if (!user) {
        return done(null, false); //該当するユーザーがいなかった場合
    }
        return done(null, user); //該当するユーザーがいた場合
));

上に書いてあるusernameとpasswordを用いて特定のユーザーがいるかどうか確認する処理はデータベースを参照してもいいですし、とにかく該当するuserがいるかどうか判定できれば大丈夫です。
シリアライズ、デシリアライズも続けて、

passport.serializeUser(function(user, done) {
    done(null, user);
});

passport.deserializeUser(function(user, done) {
    done(null, user);
});

と書けます。
そして、例えば認証成功時にたどり着く’success’というviewと、ログインに関するrouterとユーザー名・パスワードを入力させるフォームを’login’というviewに作っておいて、formタグで入力結果を/loginにpostするように設定していた場合、

app.post('/login',
        passport.authenticate('local', {failureRedirect: '/login'}),
        function(req, res){
            res.render('success');
        }
);

のように書くと認証が成功した時だけsuccessのviewを見ることができ、認証失敗した際はログインフォーム入力画面まで戻されるよう設定することができます。

app.get('/success',
        passport.authenticate('local', {failureRedirect: '/login'}),
        function(req, res){
            res.render('success');
        }
);

このように書くと/successに直接アクセスさせず、必ず認証を挟むよう設定することもできます。

まとめ

Passportの機能にだけ焦点を合わせたのでかなり駆け足での説明になってしまいましたが、一度書いてしまうとPassport側が定めてる書き方のまま書いてしまって大方完成することが実感できると思います。Node.js周りで認証を扱うことになった際はPassportを選択肢の一つにしてみてはいかがでしょうか。

技術書は勿論、本全般が好き。品揃えの良い本屋に行くとテンション上がりすぎて後で具合が悪くなる。

Other Posts: