Firebase Authentication - 追加

「Firebase のユーザー認証システムで、Web クライアント認証を実装してみます」 の追加記事です.
今回は、要求が多いであろう SNS 認証をやってみます。


フェデレーション ID プロバイダ

プラットフォーマ (GoogleやApple) や SNS (Facebook/Twitter/GitHub) 等は、フェデレーション ID プロバイダとしてユーザ情報を他のアプリでも利用できるようにしてくれています。

Firebase Authentication を使うと、それらの認証システムを簡単にアプリに統合することができます。 フェデレーション ID を直接実装しようとすると、 OAuth とかいろいろと面倒なことを覚えたりする必要があるかと思いますが、Firebaseなら少しの努力で可能になります。

仕組みとしては、パスワード等によるユーザ認証の代わりになります。 通常のログインだと、ユーザ名とパスワードを自分で管理する DB の情報と突き合わせて正しいユーザか判断します。 ソーシャルログインの場合、サイトが信用するプロバイダ側のユーザ認証を使って、ログインしてもらいます。 プロバイダ側が正しいユーザだと判断してくれたら、アプリでもそれを信用するという感じです。

使用するソーシャルログインの UI の表示や ID プロバイダとの情報のやり取り (OAuth) を Firebase がやってくれます。 アプリとしては普通にユーザが認証された時とほぼ同じ様に処理することができます。

ただし、認証データの入力時に連携するサービスを使うための入り口だけ作ってあげる必要があります。 今回の記事はその部分の追加になります。

Firebase の準備

まず、事前準備として Firebase コンソールで、連携するサービスを指定します。

Firebase -> Authentication -> Sign-in method で使用するサービスを有効にします。

Googleログインの場合は自動的に構成されますが、それ以外では、サービスプロバイダ側にもこのアプリを登録して、その情報を Firebase に設定する必要があります。

GitHub に Firebase を登録

例として、GitHub のユーザ認証を使ってログインできる様に構成をしてみます。

アプリ登録の管理者として GitHub アカウントが必要です。 GitHub では、フェデレーションするアプリは管理者のアカウントに紐づきます。 基本的に管理者と権限を委譲された人しか設定の修正はできないので、設定前に GitHub に管理者でログインしているか確認しておいてください。

管理者アカウントの Settings -> Developer settings -> OAuth Apps の上の方にある [ New OAuth App ] から登録をします。

GitHub - Register a new OAuth application

Authorization callback URL の項目に入力する情報は、Firebase コンソール側に載っているものをコピペします。 Firebase でサービス追加する時のダイアログの一番下に出てくる認証コールバックURLと表示されているものです。

GitHub では、アプリを登録した後に、シークレットを生成します。

シークレットは、生成画面を閉じると二度と確認できません。からなず、コピーをとる様にしてください。 (コピーし忘れたら新しいものを生成して、そちらを使う様になります)

生成された、クライアントID とシークレットを Firebase コンソールに登録します。

正しく設定されると、Firebase コンソールで、そのプロバイダが有効になると思います。

ログイン画面の修正

次に Web アプリ側の変更です。

ソースコードは、以下にあります。

Github - vue-firebase-auth

まず、UI を準備します。 SignIn.vue を修正して、ログイン用のボタンを作ります。

    </form>
      <div id="or">--- OR ---</div>
      <div id="other">
        <img class="loginGoogle" src="../assets/btn_google_signin_dark_normal_web.png" @click="onLoginGoogle"/>
        <img class="loginGithub" src="../assets/btn_github_signin.png" @click="onLoginGithub"/>
      </div>
    <div class="message">{{ message }}</div>

両方とも普通に <img> で画像を表示してクリックされたら、適当なメソッドが実行される様にします。

サンプルソースで、 Google ではサインイン用のボタン配置をするための画像が公開されていますが、 GitHub は見当たらなかったので適当に拾ってきています。 (ご自分のアプリで使う場合は、ラインセスを再確認してください)

では、実際のログイン部分の実装です。

    onLoginGoogle: function() {
      console.log("onLoginGoogle");
      var provider = new firebase.auth.GoogleAuthProvider();
      let auth = firebase.auth();
      auth.useDeviceLanguage();
      auth.signInWithPopup(provider)
        .then((result) => {
          console.log("signin with google success", result);
          if (!alert('ログインしました')) {
            this.$router.push('/');
          }
        }).catch((err) => {
          // エラー時の処理
          console.log(err);
          this.message = firebaseErrors[err.code] || err.message;
        });
    },

通常ログインと比べて見ればわかりますが、ほとんど同じです。

違うところは、firebase.auth.GoogleAuthProvider()で対応するサービス用の認証プロバイダを生成しています。

それを、auth.signInWithPopup() で使うだけです。

Popup にするとプロバイダの認証画面が別ウィンドウで開きます。 同じ機能で、signInWithRedirect() もありますので、別ウィンドウを開きたくなければ、そちらを使ってください。

ログインが成功した場合、エラーの場合とも、その先は通常のログインと同じです。

GitHub の方も同様に追加します。 Provider が、GithubAuthProvider になるだけです。

    onLoginGithub: function() {
      console.log("onLoginGithub");
      var provider = new firebase.auth.GithubAuthProvider();
      let auth = firebase.auth();
      auth.useDeviceLanguage();
      auth.signInWithPopup(provider)
        .then((result) => {
          console.log("signin with github success", result);
          if (!alert('ログインしました')) {
            this.$router.push('/');
          }
        }).catch((err) => {
          // エラー時の処理
          console.log(err);
          this.message = firebaseErrors[err.code] || err.message;
        });
    },

実際にボタンを押すと、下の様に別ウィンドウで、それぞれのユーザ認証や設定画面が表示されます。 ソースコードの方をみてお分かりだと思いますが、ウィンドウの中身とかは、アプリ側では一切実装する必要はありません。



まとめ

Firebase Authentication では、フレームワーク側がほぼ全部の実装を提供してくれるので、ソーシャルサービスによるログイン認証も簡単に追加できます。

また、対応するサービスを増やしていっても、開発や管理コストはあまり変わらないのも良いところです。

Firebase ではユーザ情報も一括して管理できるので、この辺はクラウドサービスの強みかなと思います。

ユーザ認証周りは、技術的には結構複雑です。 フレームワーク等を使わないで自分で1から作ったりしたら相当コストがかかると思います。

また、二段階認証とか、ユーザの取り消しとか、 ユーザの管理画面をアプリ側で実装してみるとか、ログ確認とか、ネタはまだまだありますので、そのうち。