Node.js＋Express＋Passport を使ってみた

# Passport とは
Passport は Node.js のための認証ミドルウェアです。認証リクエストをおこなうための必要最低限の機能をもつように設計されています。 
公式 [Passport - Node.jsのための、シンプルで使いどころを選ばない認証モジュール](http://knimon-software.github.io/www.passportjs.org/)

# Passport を使ってみた
Passport をインストールして、ユーザＩＤ＆パスワード認証するところまで、使ってみました。

* node 0.10.24
* express 4.13.4
* passport 0.3.2

## ワークスペースを作る
まず、Node.js＋Express のワークスペースを作ります。

参考 [Node.js、Express.js入門 - ぺーぺーSEのブログ](http://tanakakns.hatenablog.com/entry/20150302/1425285635)

## インストールする

```
$ npm install --save passport
```

参照 [Passport | はじめに](http://knimon-software.github.io/www.passportjs.org/guide/)

以下をソースコードに追加します。

```js:app.js
var passport = require('passport');
app.use(passport.initialize());
```

参照 [Passport | 設定](http://knimon-software.github.io/www.passportjs.org/guide/configure/) ミドルウェアの設定

## ユーザＩＤ＆パスワード認証するための準備

Passport を使って認証確認する処理を書きます。

まず、認証ストラテジをインストールします。

```
$ npm install --save passport-local
```

以下をソースコードに追加します。

```js:app.js
var LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(function(username, password, done){
    // ここで username と password を確認して結果を返す
}));
```

結果を返すところは、

```js:
    if (なんらかのエラー) {
        return done(エラー内容);
    }
    else if (失敗) {
        return done(null, false);
    }
    else if (成功) {
        return done(null, username);
    }
```

この辺は [Passport | 設定](http://knimon-software.github.io/www.passportjs.org/guide/configure/) 検証用コールバックに関する設定

## ログイン画面を用意する

ログイン画面、例えば login.html を用意します。

```html:login.html
<form action="/login" method="post">
    <div>
        <label>ユーザーID：</label>
        <input type="text" name="username"/>
    </div>
    <div>
        <label>パスワード：</label>
        <input type="password" name="password"/>
    </div>
    <div>
        <input type="submit" value="ログイン"/>
    </div>
</form>    
```

この例では /login に POST します。

/login に GET するとこの画面を表示するようにしておきましょう。

```js:app.js
app.get('/login', function(req, res){
    res.sendFile(__dirname + '/◇◇/login.html');
});
```

## ログイン情報を受取って認証処理に渡す

/login に POST されたら、その情報を受取って認証処理に渡すようにします。

```
$ npm install --save body-parser
```

```js:app.js
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/login',
    passport.authenticate('local'),
    function(req, res){
        // 認証成功するとここが実行される
    }
);
```

```passport.authenticate()``` には、```post()``` で受け取った username と password が渡されます。上記で準備した認証確認する処理が実行され、その結果が返ってきます。

この辺までは [Passport | ユーザーID & パスワード](http://knimon-software.github.io/www.passportjs.org/guide/username-password/)

認証すると通常はページ遷移します。

```js:app.js
app.post('/login',
    passport.authenticate('local'),
    function(req, res){
        res.redirect('/◇◇');
```

遷移先はオプション指定することができます。

```js:app.js
app.post('/login',
    passport.authenticate('local', {
        failureRedirect: '/◆◆',  // 失敗したときの遷移先
        successRedirect: '/◇◇',  // 成功したときの遷移先
    }),
```

認証成功したときは URL 遷移せずに処理することが多いでしょうか。

```js:app.js
app.post('/login',
    passport.authenticate('local', {
        failureRedirect: '/◆◆',  // 失敗したときの遷移先
    }),
    function(req, res){
        ◇◇  // 成功したときの処理
```

## セッションを無効にして使う

Passport は認証成功したとき認証情報をセッションに保存します。API サーバとして実行するときは、リクエストごとに認証処理する必要があります。このときはセッションを無効にして使用します。

```js:app.js
app.post('/login',
    passport.authenticate('local', {
        session: false,
```

この辺までは [Passport | 認証](http://knimon-software.github.io/www.passportjs.org/guide/authenticate/)

## セッションを有効にして使う

Passport は認証成功したとき認証情報をセッションに保存します。Express でセッションを使えるようにしておきましょう。

```
$ npm install --save express-session
```

```js:app.js
var session = require('express-session');
app.use(session({
    secret: '○○',
}));
app.use(passport.session());

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

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

この辺は [Passport | 設定](http://knimon-software.github.io/www.passportjs.org/guide/configure/) セッション管理に関する設定

## どのページでも認証確認する

これまでのコードでは、ログイン画面以外のページでは認証確認されません。どのページでも認証確認されるようにしましょう。

まず、ページのリクエストを貰ったとき認証済か確認する関数を用意します。

```js:app.js
function isAuthenticated(req, res, next){
    if (req.isAuthenticated()) {  // 認証済
        return next();
    }
    else {  // 認証されていない
        res.redirect('/login');  // ログイン画面に遷移
    }
}
```

ページごとに確認処理を入れるようにします。例えば、

```js:app.js
app.get('/◆◆', isAuthenticated, function(req, res){
    ◇◇  // 認証済のとき実行される
```

参考 [express - Documentation for "ensureAuthentication" "isAuthenticated" passport's functions? - Stack Overflow](http://stackoverflow.com/questions/14188834/documentation-for-ensureauthentication-isauthenticated-passports-functions)

# おわりに

とりあえず Node.js＋Express＋Passport を使って、ユーザＩＤ＆パスワード認証できるようになりました。
Passport は、Facebook や Twitter と連携した認証もできます。
また、ログアウトの処理も用意しないといけません。
これらについては、改めて。