Express(passport-google-oauth2)で認証

passportのストラテジ(google-oauth2)を動かしてみます。

Overview

passportでのpassport-localストラテジでの認証を先日動かしてみたので、googleの認証を試してみたいと思います。

Input

Proccess

passport-oauth2のインストール

npm i passport-google-oauth2 --save

googleに登録

クライアントIDとsecretkeyが割り当てられます。 Auth後のリダイレクト先を設定する項目があるのですが、今回はストラテジの引数で指定しているのでこちらでは設定せずでもよいのかなと思ったのですが、これを合わせておかないとエラーが発生します。

入力画面設置

先日のローカルの画面にGoogle用の認証ボタンを追加してみます。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    </head>
    <body>
        <h1>認証テスト</h1>
        <form action="login" method="POST">
            <input type="text" name="username">
            <input type="password" name="password">
            <button type="submit">ログイン</button>
        </form>
        <form action="auth/facebook" method="POST">
            <button type="submit">facebook</button>
        </form>
        <form action="auth/twitter" method="POST">
            <button type="submit">twitter</button>
        </form>
        <form action="auth/google" method="POST">
            <button type="submit">google</button>
        </form>
    </body>
</html>

認証リクエストのルーティング,認証処理

google-oauth2ストラテジを使用するので、postでgoogle向けのURLで受け取ったらそのまま委譲する形になります。 で、Gooogle認証後のコールバックはgoogle側に設定した際のパスに合わせて作成しておきます。 ※今回はGoogleのコールバック(戻り先URL)の設定は「"http://localhost:3090/auth/google/callback"」としました。

// ログイン 【Google】認証
app.post('/auth/google', passport.authenticate('google'));
// ログイン 【Google】処理 成功なら/へだめならloginへ
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
    function (req, res) {
        // ログイン成功
        res.redirect('/');
    }
);

UserスキーマにgoogleId追加するためにmongooseのスキーマに追加

var mongoose = require('mongoose');

// スキーマ設定
var User = mongoose.Schema({
    username: String,
    password: String,
    facebookId: String, // これは前々回追加
    twitterId: String, // これは前回追加
    googleId: String, // ★これは今回追加
    date: {type: Date, default: new Date()},
});

module.exports = mongoose.model('User', User, 'users');

googleストラテジの追加(ここでクライアントIDとSECRETが必要)

var GOOGLE_CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
var GOOGLE_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxx';
passport.use(new GoogleStrategy({
    clientID:     GOOGLE_CLIENT_ID,
    clientSecret: GOOGLE_CLIENT_SECRET,
    callbackURL: "http://localhost:3090/auth/google/callback",
    passReqToCallback   : true
}, function (token, tokenSecret, profile, done) {
    User.findOneAndUpdate({
        googleId: profile.id
    }, {
        $set: {
            googleId: profile.id
        }
    }, {
        upsert: true
    }, (err, user) => {
        if (err) throw (err);
        return done(err, user);
    });
})); // passport.use

認証リクエストのルーティング

app.post('/auth/google', passport.authenticate('google', { scope:
      [ 'https://www.googleapis.com/auth/userinfo.email'] }));
// ログイン 【GO】処理 成功なら/へだめならloginへ
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
    function (req, res) {
        // ログイン成功
        res.redirect('/');
    }
);

スコープの設定が必要。 スコープ設定しないと怒られる。。

gonotscope

※サンプルにあったスコープはGoogleのサイトでは掲載されておらず。。
でもGooglePlayGroundで試したらそれは存在するみたいでした。 https://developers.google.com/oauthplayground/

goplayground

ここでスコープの確認ができます。 https://developers.google.com/identity/protocols/OAuth2UserAgent?hl=ja#identify-access-scopes
で、ここでスコープの一覧が参照できます。
https://developers.google.com/identity/protocols/googlescopes?hl=ja

goscopelist

Output

goresult1

goreuslt2

goresult3

goresult4