Diary

@ssig33

09 Mar 2018 Fri 17:31

Firebase がデフォルトで対応してない OAuth2 Provider に Firebase でログイン できたら便利だなと思ったのでやってみる。今回僕が扱いたい「Firebase がデフォルトで対応してない OAuth2 Provider」というのは今働いている会社であるところのユビレジです。

カスタム認証というのが提供されていて、そういうことをしたい時これを利用すればよいのだと思われる。ところが、これは基本的にはサーバーサイドで Firebase とやり取りして認証用トークンを作成する必要がある。

今回いじりたいのは自社サービスなので、そっちをいじってもいいのだろうと思う。ただまあめんどうなのでクライアントサイドと Cloud Functions だけで問題を解決したい。

というわけで CloudFunctions 側に以下のようなものを実装した。ここにある oauth2 というのは simple-oauth2 というライブラリのアレです、アレ。 redirect_uri はとりあえず http://localhost:5000/callback を指定している。

exports.auth = functions.https.onRequest((req, res) => {
  const authorizationUri = oauth2.authorizationCode.authorizeURL({ redirect_uri: redirect_uri });
  res.redirect(authorizationUri);
});

exports.callback = functions.https.onRequest((req, res) => {
  const tokenConfig = {
    code: req.query.code,
    redirect_uri: redirect_uri
  };
  // ユビレジの accessToken を取得
  oauth2.authorizationCode.getToken(tokenConfig).then((result)=>{
    const accessToken = oauth2.accessToken.create(result);
    const account_id = String(accessToken.token.account_id);
    // カスタムトークンを生成
    admin.auth().createCustomToken(account_id).then((customToken)=>{
      // ユビレジの accessToken を firestore に保存しておく
      const db = admin.firestore()
      const ref = db.collection('credentials').doc(account_id)
      ref.set(accessToken.token).then(()=>{
        ref.update(accessToken.token).then(()=>{
          res.redirect(`/?customToken=${customToken}`);
        });
      });
    });
  });
});

ルーティングは以下のように

  • / は index.html を普通に返す
  • /auth で ↑ の auth
  • /callback で ↑ の callback

を使う。

で index.html 側では location.search を見て customeToken があれば

firebase.auth().signInWithCustomToken

で認証してやっていく。たぶんこれでセキュリティ上の問題もない、よね?

これで Firebase Hosting と Firebase Cloud Functions だけで Firebase がデフォルトで対応していない OAuth2 Provider にログインが出来た。

サーバサイドで accessToken などを Cloud Firestore に入れているので、認証後はそこから accessToken をとってきてユビレジ API にアクセスできる。

というつもりだったのだが、ここまで作って気付いたことがあり、なんとユビレジ API は CORS 対応してないので、 Cloud Functions でプロキシしてあげないといまのままだと動かない、、、

というわけなので CORS 対応 Pull Request を作ろうと思う。