フロントエンドデベロッパーのメモ

スキル: HTML/Jade/Jinja2, CSS/SCSS, JavaScript(ES6), Angular, React,Next, Redux, Node, Express, Python, Flask, Postgres, Redis, MongoDB, Kafka, Knex, SQLAlchemy, React Native, EXPO, GraphQL/Apollo, REST, AWS, Heroku, Docker, CircleCI, SCRUM, XP, Vim, TDD

Node.js, Express.js, Passportを試してみた。

認証認可の開発と言ったらOAuth使ってたけど、今回はPassportを使ってログイン部分のみを作ってみました。 Passportは認証リクエストを手軽に作成できるミドルウェアFacebook, Twitter, Googleアカウントなどのアカウントでログインすることも多いかもしれないけど、それぞれの認証のための必要事項が異なります。それをシンプルなコードで作成できるのがPassport。

まずは、APIサーバーファイルを作ってポート3000を割り当てます。

yarn add -D express

-DはdevDepenveciesにだけインストールするためのオプション。

const express = require("express");
const app = express();

ホーム画面。

app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});

app.listen(3000, () => console.log("listening..."));
yarn add -D passport passport-local passport-session


const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy,
path = require("path");

ログイン画面の作成

app.get("/login", (req, res) => {
res.sendFile(path.join(__dirname + "/login.html"));
});

passport.authenticateが成功した場合のみ、コールバックが起動してホーム画面へリダイレクさせます。

app.post("/login", passport.authenticate("local"), function(req, res) {
res.redirect("/");
});

認証リクエストはpassport.authenticateを発火させるだけ。 認証に失敗するとデフォルトでは、401 Unauthorizedステータスが返ってきます。

app.post("/login",
passport.authenticate("local", {
failureRedirect: "/login"
 }),
function(req, res) {
res.redirect("/");
 }
);

認証失敗した場合のリダイレクト先を指定したいことが多いと思いますけど、その場合はauthenticateメソッドに2つ目の引数を指定。

環境設定 Passportの認証を使うために必要な設定 基本的に2つ、オプションでもう1つ設定する必要あり。 1. Authentication Strategy 2. Application middleware 3. Sessions(optional) 1. Authentication Strategy Strategyは認証リクエストをするために使われる用語。ユーザーネーム、パスワード、OAuthを使った認証など使用できる情報は自由度が高いです。

Strategyとその設定内容はpassport.use()内に記述します。 ユーザーネームとパスワードによる認証認可にはLocalStrategyをインスタンスとして使用します。 LocalStrategyはpassport-localモジュールをインストールして使用します。ユーザーネームとパスワードでの認証システムを作成するのが一番一般的ですから、このようなモジュールを作成したんでしょうね。

passport.use(new LocalStrategy());

今回はユーザーネームだけが入力されたどうかを確認します。

passport.use(
  new LocalStrategy(function(username, password, done) {
    if (!username) {
      return done(null, false, { message: "Incorrect username." });
     }
    return done(null, username);
  })
);

リクエストが認証されると、ユーザー情報を引数として検証するためのコールバック関数に渡されます。今回の場合は、ユーザーネームとパスワード。 ユーザー情報が有効であれば、検証コールバック関数はdoneをユーザー情報と共に起動。

done(null, username);

失敗した場合は、ユーザー情報の代わりにfalseを第2引数に渡します。

done(null, false);
passport.use(
 new LocalStrategy(

 { usernameField: "username", passwordField: "password" },
function(username, password, done) {


    if (!username) {
     return done(null, false, { message: "Incorrect username." });
     }
    return done(null, username);
  })
);

ログインフォーム

<form action="/login" method="post">
 <div>
 <label>Username:</label>
 <input type="text" name="username" id="username" />
 </div>
 <div>
 <label>Password:</label>
 <input type="password" name="password" id="password" />
 </div>
 <div>
 <input type="submit" value="Log In" />
 </div>
</form>
  1. Middleware Expressベースでの開発には、passport.initialize()がミドルウェアとして必要になります。 Express4.xからConnectミドルウェアとapp.configure()は塩ゆできなくなったので、同様の機能をもつモジュールが必要です。
const session = require("express-session"),
bodyParser = require("body-parser");
 

app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());

ファイル全体

const express = require("express");
const passport = require("passport"),
LocalStrategy = require("passport-local").Strategy,
bodyParser = require("body-parser");
path = require("path");

const app = express();

app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(passport.initialize());
passport.use(
new LocalStrategy(
 { usernameField: "username", passwordField: "password" },
function(username, password, done) {
if (!username) {
return done(null, false, { message: "Incorrect username." });
 }
return done(null, username);
 }
 )
);
passport.serializeUser(function(user, done) {
done(null, user);
});

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

app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
app.get("/login", (req, res) => {
res.sendFile(path.join(__dirname + "/login.html"));
});

app.post(
"/login",
passport.authenticate("local", {
successRedirect: "/",
failureRedirect: "/login"
 }),
function(req, res) {
res.redirect("/");
 }
);

app.listen(3000, () => console.log("listening..."));