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/からアプリケーションの作成を行なってください。
作成ができたら、アプリの設定ページで以下のように、アプリIDとapp secretが作成されています。
このアプリIDとapp secretは、後で利用することになります。
passportで使うモジュールのインストール
続いて、passportモジュールのインストールを始めます。
以下のコマンドを入力してください。
$ 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がうまく起動できているか確認します。
$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.js
はpassport
モジュールの設定などを書き込むファイルです。
・localhost:8000/
にアクセスしたときの処理を書き込みます。
・login.js
とlogout.js
は、/login
と/logout
にアクセスしたときの処理を書き込みます。
・www
はサーバーの起動などを担当します。
・login.pug
は/login
にアクセスした時のログイン画面を表示します。
・index.pug
は/
にアクセスした時の画面を表示します。
・layout.pug
はlogin.pug
とindex.pug
の基本となる表示を担当します。
続いて、以上のような認証の際に必要なファイルやディレクトリの作成、その記述を行なっていきます。すでに存在しているファイルの作成は不要なので、以下のファイルだけを作成します。
$touch routes/login.js
$touch routes/logout.js
$touch views/login.pug
ファイルに処理の記述を行う。
続いては、処理の記述を行なっていきます。
まずは、今あるapp.jsの記述を削除して、app.jsに以下の処理を記述してください。
varcreateError=require('http-errors');//expressモジュールの読み込みvarexpress=require('express');varpath=require('path');varcookieParser=require('cookie-parser');varlogger=require('morgan');//passportモジュールの読み込みvarpassport=require('passport');//passport-facebookモジュールの読み込みvarStrategy=require('passport-facebook').Strategy;//先ほど作成したアプリIDを変数に代入varFACEBOOK_APP_ID='44923726XXXXXX';//先ほど作成したapp secretを変数に代入varFACEBOOK_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(newStrategy({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(){returndone(null,profile);});}));//index.jsの処理を利用するために変数に代入varindexRouter=require('./routes/index');//users.jsの処理を利用するための処理を変数に代入varusersRouter=require('./routes/users');//login.jsの処理を利用するための処理を変数に代入varloginRouter=require('./routes/login');//logout.jsの処理を利用するための処理を変数に代入varlogoutRouter=require('./routes/logout');//expressモジュールを利用するためにapp変数に代入varapp=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';
は、先ほど作成した、アプリIDとapp secretをそれぞれ代入します。
var FACEBOOK_APP_SECRET = '170dde4751f2exxxxxxxxxx';
続いて、login.jsとlogout.js、そしてindex.jsに記述していきます。
'use strict';//expressの読み込みvarexpress=require('express');//expressでルーターを使う設定varrouter=express.Router();//localhost:8000/loginにアクセスした際に、login.pugがレンダリングされる処理router.get('/login',function(req,res){res.render('login');});//モジュールのエキスポートmodule.exports=router;
'use strict';//expressの読み込みvarexpress=require('express');//expressでルーターを使う設定varrouter=express.Router();//localhost:8000/logoutにアクセスした際に、ログアウトされ、//localhost:8000/にリダイレクトされる処理router.get('/logout',function(req,res){req.logout();res.redirect('/');});//モジュールのエキスポートmodule.exports=router;
'use strict';varexpress=require('express');varrouter=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;
これでモジュールの処理設定が完了しました。
続いて画面の設定です。
上の処理に合わせて、画面設定をしていきます。
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
が利用できます。
extends layout
block content
a(href="/auth/facebook") Login with Facebook
ログインするための
a(href="/auth/facebook")
を追加しました。
ログインとログアウトをしてみる
これで処理か完成しました。コンソールにて以下のコマンドを入力し、
PORT=8000 npm start
以下のURLにアクセスしてみてください。
http://localhost:8000/
すると、/login
に移動するので、Login with Facebook
をクリックします。
すると、ログイン画面に出るので、
続いて、自分のFacebookアカウントでログインボタンをクリックし、ログインします。
ログインすると、以上のように、Hello 自分の名前
と表示されます。
続いて、Logout
をクリックし、ログアウトできるかの確認も行います。
無事、最初のログイン画面に移動できたら、ログアウトの完了です。
お疲れ様でした。
おまけ
認証された人しか見れないようにするには、app.jsに以下のように書き込みます。
//認証者を確かめる関数functionauthenticatedUser(req,res,next){//認証されている人は次の処理が実行される。if(req.isAuthenticated()){returnnext();}//認証されてない人は`/login`にリダイレクトされる。res.redirect('/login');}
/users
を認証者だけが見えるように設定。
app.use('/users',authenticatedUser,usersRouter);