0
0

More than 3 years have passed since last update.

passportモジュールでfacebook認証

Last updated at Posted at 2019-12-03

passportとは

passportはNode.jsで利用できる認証ミドルウェア(モジュール)です。
passportを利用することで、アプリに簡単にOAuth認証を組み込むことができます。

OAuth認証に関して、こちらの記事がすごく分かりやすいので読んでみてください。
一番分かりやすい OAuth の説明

passportの凄いところは、FacebookやTwitter、Googleなど、多くのアカウント認証を利用できる点です。

今回は、ExpressというNode.jsのフレームワークがグローバルインストールされている前提で進んでいきます。
参考:Expressフレームワークのインストールと簡単な使い方

passportを利用して、Facebook認証をしてみる

Facebook Developersでアプリを作成

まずは、Facebook認証を利用するために、https://developers.facebook.com/ からアプリケーションの作成を行なってください。
スクリーンショット 2019-12-02 17.52.37.png
作成ができたら、アプリの設定ページで以下のように、アプリIDとapp secretが作成されています。
スクリーンショット 2019-12-02 17.53.49.png
このアプリIDとapp secretは、後で利用することになります。

passportで使うモジュールのインストール

続いて、passportモジュールのインストールを始めます。
以下のコマンドを入力してください。

console
$ express --view=pug passport-demo
$ cd passport-demo
$ npm install
$ npm init -y
$ npm install passport
$ npm install passport-facebook
$ npm install express-session

・1行目でプロジェクトを行うpassport-demoディレクトリを作成しています。このディレクトリの名前はなんでも大丈夫です。
・2行目は、1行目で作成したpassport-demoディレクトリに移動しています。
・3行目は依存モジュールのインストールを行なっています。
・4行目は、初期化処理を行い、package.jsonを生成しています。
npm initを行うと普通はどういうパッケージにするか質問がされるのですが、-yオプションを作ることで、すべてyesの回答となり、その質問を省略することができます。
・5、6行目でpassportモジュールとpassport-facebookモジュールをインストールしています。
・7行目は、Expressでセッションを利用できるようにするためのモジュールです。認証した結果をサーバーがセッション情報として保存してくれます。

念の為、この段階で以下のコマンドを実行し、expressがうまく起動できているか確認します。

console
$ PORT=8000 npm start

http://localhost:8000/ にアクセスしてみてください。
Express
Welcome to Express
という画面が表示されたら、問題ありません。

必要なディレクトリ・ファイルを作る

今回は以下のようなファイル構造にします。

// *は新しく作成するファイル
passport-demo
|- package.json
|- package-lock.json
|- app.js
|- /routes
  |- index.js
  |- login.js *
  |- logout.js *
|- /bin
  |- www
|- /views
  |- login.pug *
  |- index.pug
  |- layout.pug
|- /public
|- /node_modules

app.jspassportモジュールの設定などを書き込むファイルです。
localhost:8000/にアクセスしたときの処理を書き込みます。
login.jslogout.jsは、/login/logoutにアクセスしたときの処理を書き込みます。
wwwはサーバーの起動などを担当します。
login.pug/loginにアクセスした時のログイン画面を表示します。
index.pug/にアクセスした時の画面を表示します。
layout.puglogin.pugindex.pugの基本となる表示を担当します。

続いて、以上のような認証の際に必要なファイルやディレクトリの作成、その記述を行なっていきます。すでに存在しているファイルの作成は不要なので、以下のファイルだけを作成します。

console
$ touch routes/login.js
$ touch routes/logout.js
$ touch views/login.pug

ファイルに処理の記述を行う。

続いては、処理の記述を行なっていきます。
まずは、今あるapp.jsの記述を削除して、app.jsに以下の処理を記述してください。

app.js
var createError = require('http-errors');
//expressモジュールの読み込み
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

//passportモジュールの読み込み
var passport = require('passport');
//passport-facebookモジュールの読み込み
var Strategy = require('passport-facebook').Strategy;

//先ほど作成したアプリIDを変数に代入
var FACEBOOK_APP_ID = '44923726XXXXXX';
//先ほど作成したapp secretを変数に代入
var FACEBOOK_APP_SECRET = '170dde4751f2ee9d44140b8826457b63';

//passportモジュールによるシリアライズの設定
passport.serializeUser(function(user, done) {
  done(null, user);
});
//passportモジュールによるデシリアライズの設定
passport.deserializeUser(function(obj, done) {
  done(null, obj);
});

////passport-facebookモジュールのStarategy設定
passport.use(new Strategy({
  clientID: FACEBOOK_APP_ID,
  clientSecret: FACEBOOK_APP_SECRET,
  //facebook認証をするためのページの設定(固定)
  callbackURL: "http://localhost:8000/auth/facebook/callback",
  //プロフィールのどの情報を受け取ることができるかの設定
  profileFields: ['id', 'displayName']
},
  function (accessToken, refreshToken, profile, done) {
    //認証後にdone関数を返すために、process.nextTick関数を利用している
    process.nextTick(function () {
      return done(null, profile);
    });
  }
));

//index.jsの処理を利用するために変数に代入
var indexRouter = require('./routes/index');
//users.jsの処理を利用するための処理を変数に代入
var usersRouter = require('./routes/users');
//login.jsの処理を利用するための処理を変数に代入
var loginRouter = require('./routes/login');
//logout.jsの処理を利用するための処理を変数に代入
var logoutRouter = require('./routes/logout');

//expressモジュールを利用するためにapp変数に代入
var app = express();

//アプリケーションで利用するミドルウェアの設定
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

// viewsディレクトリの設定
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

//passportのの初期化
app.use(passport.initialize());
//ログイン後のセッション管理の設定
app.use(passport.session());

//localhost:8000/にアクセスした時にindexRouterの処理がなされる設定
app.use('/', indexRouter);
//localhost:8000/usersにアクセスした時にusersRouterの処理がなされる設定
app.use('/users', usersRouter);

//localhost:8000/auth/facebookにGETアクセスした時に認証リクエストを行う設定
app.get('/auth/facebook',
  passport.authenticate('facebook')
);
//localhost:8000/auth/facebook/callbackにGETアクセスした時に処理が行われる設定
app.get('/auth/facebook/callback',
 //処理が失敗した時のリダイレクト先の設定
  passport.authenticate('facebook', {failureRedirect: '/login' }),
  function(req, res) {
    //処理が成功した時のリダイレクト先の設定
    res.redirect('/');
  });

//localhost:8000/loginにアクセスした時にloginRouter処理がなされる設定
app.get('/login', loginRouter);

//localhost:8000/logoutにアクセスした時にlogoutRouter処理がなされる設定
app.get('/logout', logoutRouter);


//404エラーの処理設定
app.use(function(req, res, next) {
  next(createError(404));
});

// エラー処理の設定
app.use(function(err, req, res, next) {
  // ローカル環境のみ表示されるエラーの設定
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // エラーページを表示する設定
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

var FACEBOOK_APP_ID = '4492xxxxxxxx';
var FACEBOOK_APP_SECRET = '170dde4751f2exxxxxxxxxx';
は、先ほど作成した、アプリIDとapp secretをそれぞれ代入します。

続いて、login.jsとlogout.js、そしてindex.jsに記述していきます。

login.js
'use strict';
//expressの読み込み
var express = require('express');
//expressでルーターを使う設定
var router = express.Router();

//localhost:8000/loginにアクセスした際に、login.pugがレンダリングされる処理
router.get('/login', function(req, res) {
  res.render('login');
});

//モジュールのエキスポート
module.exports = router;
logout.js
'use strict';
//expressの読み込み
var express = require('express');
//expressでルーターを使う設定
var router = express.Router();

//localhost:8000/logoutにアクセスした際に、ログアウトされ、
//localhost:8000/にリダイレクトされる処理
router.get('/logout', function(req, res) {
  req.logout();
  res.redirect('/');
});

//モジュールのエキスポート
module.exports = router;
index.js
'use strict';
var express = require('express');
var router = express.Router();

//localhost:8000/にアクセスした際に、index.pugがレンダリングされ、
//index.pug内でtitleとuserが使えるようになる処理
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express', user: req.user });
});

module.exports = router;

これでモジュールの処理設定が完了しました。
続いて画面の設定です。
上の処理に合わせて、画面設定をしていきます。

index.pug
extends layout

block content
  h1= title
  p Welcome to #{title}
  if user
    p Hello, #{user.displayName}
    a(href="/logout") Logout
  else
    a(href="/login") Login

#{title}にはindex.jsで渡した、'Express'という文字が入り、
{user.displayName}userには、req.userが入ります。
req.userは、app.jsのStarategy設定でdisplayNameをプロフィールから受け取れるようにしたので、displayNameが利用できます。

login.pug
extends layout

block content
  a(href="/auth/facebook") Login with Facebook

ログインするためのa(href="/auth/facebook")を追加しました。

ログインとログアウトをしてみる

これで処理か完成しました。コンソールにて以下のコマンドを入力し、

console
PORT=8000 npm start

以下のURLにアクセスしてみてください。
http://localhost:8000/

アクセスできたら、以下の画面が表示されると思います。
スクリーンショット 2019-12-03 16.53.34.png

ここでLoginをクリックします。
スクリーンショット 2019-12-03 16.53.41.png

すると、/loginに移動するので、Login with Facebookをクリックします。
スクリーンショット 2019-12-03 16.54.07.png

すると、ログイン画面に出るので、
続いて、自分のFacebookアカウントでログインボタンをクリックし、ログインします。
スクリーンショット 2019-12-03 16.54.16.png
ログインすると、以上のように、Hello 自分の名前と表示されます。
続いて、Logoutをクリックし、ログアウトできるかの確認も行います。

スクリーンショット 2019-12-03 16.54.26.png

無事、最初のログイン画面に移動できたら、ログアウトの完了です。
お疲れ様でした。

おまけ

認証された人しか見れないようにするには、app.jsに以下のように書き込みます。

app.js
//認証者を確かめる関数
function authenticatedUser(req, res, next) {
//認証されている人は次の処理が実行される。
  if (req.isAuthenticated()) { return next(); }
//認証されてない人は`/login`にリダイレクトされる。
  res.redirect('/login');
}

/usersを認証者だけが見えるように設定。

app.js
app.use('/users', authenticatedUser, usersRouter);
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0