nodejs+express+passport-gitlab2を使ってOAuth Applicationを作る


はじめに

gitlabはオンプレで独自に構築してます。
認証作るのめんどくさいな。gitlabでいいじゃん。
という事で、OpenIDでの認証+OAuthで認可もできるようにしよう!

と、フロントエンド初心者がハマりつつ実装した記録です。

passport-gitlab2

これです。
https://www.npmjs.com/package/passport-gitlab2

事前準備

gitlab側でつなぐ準備しておきます。
【Admin Area】→【Applications】のところで設定します。

  • アプリケーション名の入力
  • OAuthでのコールバックURLの入力

結果

こうなる。

まずは依存情報の追加。

requiredの追加
var passport = require('passport');
var session = require('express-session');
var GitLabStrategy = require('passport-gitlab2').Strategy;

次に、セッション有効化のための定義記載。

session管理のための設定
app.use(session({
  secret: "secret-key",
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: false,
    secure: true,
    maxage: 1000 * 60 * 30
  }
}));
app.use(passport.initialize());
app.use(passport.session());

次に、認証するURL、コールバックURLの定義を記載。

認証するための設定
app.get('/', passport.authenticate('gitlab'));
app.get('/auth/gitlab/callback',
  passport.authenticate('gitlab', {
    failureRedirect: '/error.html'
  }),
  function (req, res) {
    // Successful authentication, redirect home.
    res.redirect('/home');
  });

そして、gitlabからの認証時の戻りの処理と、deserialize/serialize処理を定義。
done

passport関連の定義
//passport
passport.use(new GitLabStrategy({
  clientID: process.env.GITLAB_APP_ID,
  clientSecret: process.env.GITLAB_APP_SECRET,
  callbackURL: process.env.GITLAB_CALLBACK,
  baseURL: process.env.GITLAB_URL
},
  function (accessToken, refreshToken, profile, done) {
    if (profile) {
      user = profile;
      return done(null, { id: profile.id });
    }
    else {
      return done(null, false);
    }
  }
));
passport.deserializeUser(function (id, done) {
  console.log('Deserialize user called.');
  return done(null, { "id": id });
});
passport.serializeUser(function (user, done) {
  console.log('Serialize user called.');
  return done(null, { id: user.id });
});

後は、各種routeに対して認証が必須のように定義する。

ensureAuthenticatedからパススルーするように変更
function ensureAuthenticated(req, res, next) {
  console.log("ensureAuthenticated");
  if (req.isAuthenticated())
    return next();
  else
    res.redirect('/');
}

router.get('/home', ensureAuthenticated, function (req, res, next) {
  res.send("OK");
})

ハマったところ

User is not define

公式にこう書いてるから、なるほどなるほど。よし、コピペだ!

passport.use(new GitLabStrategy({
    clientID: GITLAB_APP_ID,
    clientSecret: GITLAB_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/gitlab/callback"
  },
  function(accessToken, refreshToken, profile, cb) {
    User.findOrCreate({gitlabId: profile.id}, function (err, user) {
      return cb(err, user);
    });
  }
));

動かしてみると、 User is not defined. と動きません。
https://github.com/auth0/passport-windowsauth/issues/37

無限に認証のリダイレクトループ発生

var session = require('express-session');
・・・
app.use(passport.session());

そもそもsession使わないと、上手く連携できないよって話。

あれ?認証しなくても動いちゃう…

interceptor?的なもんが勝手にやってくれると思ったけど、やってくれない。
自分でちゃんとパス毎に設定してあげないと!
※通常は、routerを拡張するのかなぁー。

ensureAuthenticatedからパススルーするように変更
//認証チェック
function ensureAuthenticated(req, res, next) {
  console.log("ensureAuthenticated");
  if (req.isAuthenticated())
    return next();//認証チェックしてから、次を呼び出すよ。
  else
    res.redirect('/');
}

router.get('/home', ensureAuthenticated, function (req, res, next) {
  res.send("OK");
})

なんか…思った画面と違う

OAuthってあのGoogleのような認証して、「このアクセス許可与えますけど良いですか?」画面が出るはずなんだけど、出ない。
ただのログイン画面が出てくるだけ。さみしい。

でも、まぁ・・・こういうもんだろうと思って放置しました。

そもそもpassport知る必要がある。

http://www.passportjs.org/packages/passport-npm/
これ前提で動く。passport-gitlab2は、このOAuthのService Providerのライブラリなだけ。
なので、そもそもpassportがどう動くのか知る必要がある。