初心者のプログラミング日記

プログラミング初心者の日記

プログラミングに関することを書いていきます。

Express+Google OAuth 2.0を使ってログインする

まず、必要なモジュールをインストールします。
これで下準備は完了です。

yarn add passport
yarn add passport-google-oauth
yarn add express-session

Google OAuth 2.0を有効にする

まず、以下URLにアクセスします。
https://console.developers.google.com/

プロジェクトの作成

そしたら以下の画像の順番にクリックしてプロジェクトを作成します。
f:id:nasubiFX:20210108233014p:plain
あとはプロジェクト名と場所を入力して作成ボタンを押せばプロジェクトが作成されます。場所の所は特になければデフォルトのなしのままで大丈夫です。

OAuth 同意画面を作成

まず上記の画像の①の▼をクリックして今作成したプロジェクトを選択して開きます。
そしたら上記の画像の「OAuth 同意画面」の所をクリックして開きます。
まず、User Typeを内部か外部にするかですが今回は外部にして誰でも使用できるようにしますが、おのおの変えてください。
選んだら作成をクリックして次の画面に進みます。そしたら以下の画像のような画面が出てくるので入力してください。
f:id:nasubiFX:20210108235709p:plain
入力が終わったら保存して次へをクリックして次に画面に進みます。
今回のログインにはidとdisplayNameを使うので「スコープを追加または削除」をクリックしてスコープを追加します。右側に出てくるので真ん中を選びます。そして更新を押すと「非機密のスコープ」の所に今選んだAPIが表示されます。
f:id:nasubiFX:20210109002925p:plain
終わったら保存して次へをクリックして次に画面に進みます。テストユーザーはどちらでも構いません。追加する場合はメールアドレスを入れてください。
最後にこれまで入力した一覧が出てくるので、間違っていたら1番上のアプリ名の右の「アプリの編集」で変更してください。

認証情報の作成

以下の画像の順番で「認証情報」、「+ 認証情報を作成」、「OAuth クライアント ID の作成」をクリックします。
f:id:nasubiFX:20210109003322p:plain

そしたら以下の画面が出てくるので入力していきます。
f:id:nasubiFX:20210109004051p:plain
今回はウェブアプリケーションを選択します。
承認済みの JavaScript 生成元にはトップページのURLを入れとけば大丈夫だとおもいます(多分)。
承認済みのリダイレクト URIGoogle側で認証が完了した場合に呼ばれるURLです。好きなように設定してください。入力が終わったら作成します。
そしたら画面に「クライアント ID」と「クライアント シークレット」が出てくるのでコピーしておきます。忘れた場合でも「認証情報」から「OAuth 2.0 クライアント ID」に今作成したOAuth 2.0 クライアントがあるのでクリックすると「クライアント ID」と「クライアント シークレット」を確認できます。
これでgoogle側の設定は終わりなのでexpressに移ります。

ルーティング

すべてapp.jsに書いていきます。

//app.js(抜粋)
const passport = require('passport');
const session = require('express-session');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy

//セッションに保存
passport.serializeUser(function (user, done) {
  done(null, { id: user.id, name: user.name });
});

//セッションから保存されたデータを呼び出し
passport.deserializeUser(function (user, done) {
  done(null, { id: user.id, name: user.name });
});

const clientID = '' //コピーしたクライアント ID
const clientSecret = '' //コピーしたクライアント シークレット
const callbackURL = '' //設定した承認済みのリダイレクト URI
passport.use(new GoogleStrategy({
  clientID, clientSecret, callbackURL
}, function (accessToken, refreshToken, profile, done) { //profileにスコープで設定したアカウント情報が入っている
  process.nextTick(function () {
    return done(null, { id:profile.id,name:profile.displayName });
  })
}
))

app.use( //絶対にpassport.initialize(),passport.session()よりも先に行う。そうしないとエラーになります
  session({
    secret: '', //自由に設定 例:require('crypto').randomBytes(8).toString('hex')で生成したランダムな文字列
    resave: false,
    saveUninitialized: false
  })
);
app.use(passport.initialize());
app.use(passport.session());

app.get('/auth/google', passport.authenticate('google', {
  scope: ['https://www.googleapis.com/auth/userinfo.profile'] //スコープ
}));

app.get('/auth/google/callback',
  passport.authenticate('google', {
    failureRedirect: '/enter', //失敗したときの遷移先
    session: true //セッションを使うためtrue
  }),
  function (req, res) { //成功したときの処理
    res.redirect('/')
  }
)

ほぼ書き方は固定なの好きなようにカスタマイズしてください。
セッションにuserで保存してあるので「req.user」で取り出せます。
scopについては公式のドキュメントを見てください。
https://developers.google.com/identity/protocols/oauth2/scopes#oauth2

/enterでは以下のようにルーティングしています。

//enter.pug
<a href="/auth/google">Sign In with Google</a>

このままではログインしているかわからないのでトップページを少し変更します

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  if(req.user){
    res.render('index',{user_name:req.user.name});
  }else{
    res.render('index',{user_name:null});
  }
});

module.exports = router;

これでログインしている時は「user_name」に名前が入るので、あとはテンプレートファイルで表示してあげるだけです。

ログインしている時のみ表示

まず、

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

module.exports = 

このような関数を用意します。
あとはこれを ログインしている時のみ表示したいルーティングに組み込むだけです

var express = require('express');
var router = express.Router();
const authentication=require('./authentication.js')

/* GET user page. */
router.get('/', authentication,function(req, res, next) {
   //処理
});

module.exports = router;

参考記事
https://qiita.com/tinymouse/items/ab79a14173ebc7b75274#%E3%81%A9%E3%81%AE%E3%83%9A%E3%83%BC%E3%82%B8%E3%81%A7%E3%82%82%E8%AA%8D%E8%A8%BC%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B
https://dackdive.hateblo.jp/entry/2017/08/28/100000
https://blog.spacemarket.com/code/passport_social_login/
http://www.passportjs.org/docs/google/