38
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FirebaseUIによるログイン + Firestoreへのユーザ情報の書き込み

Last updated at Posted at 2018-09-25

概要

FirebaseUIによるユーザ登録と、登録されたユーザ情報をFirestoreに書き込むという流れについてのメモです。

FirebaseUI

FirebaseUIについてですが、

FirebaseUI は Firebase Authentication SDK の上に構築されるライブラリで、アプリで使用するドロップイン UI フローを提供します。

とあるように、FirebaseUIを使用すれば、複数のプロバイダ(メールアドレス、Facebook、Twitterなどなど)によるユーザ登録、ログイン、ログイン後のページ遷移などのログインフローをほぼFirebaseUIに任せることができます。

方法

以下、方法を記していきますが、Firebaseプロジェクトの作成や、初期設定等の必要最低限のことは済んでいることが前提です。
Firebase を JavaScript プロジェクトに追加する  |  Firebase

ログイン方法の設定

今回は利用者が多そうなFacebookログインを使いたいと思います。

Facebook for Developersの設定

Facebookログイン機能を使うためには、「Facebook for Developers」で設定を行う必要があります。
Facebook for Developers | 人と人がより身近になる世界を実現する

Facebook for Developersの「新しいアプリを作成」からアプリを作成し、
設定 > ベーシック
から画像のような、

  • アプリID
  • app secret

の二つをメモしておきます(Firebase Authenticationの設定で使用します)。
facebook_config.png

次に、Firebaseコンソールに戻り、下の画像のような、OAuthリダイレクトURI(黒く塗りつぶした部分)をコピーします。
firebase_facebook.jpg

再びFacebook for Developersに戻り、
Facebookログイン > 設定
から「有効なOAuthリダイレクトURI」に、先ほどコピーしたURIを貼り付けます。
facebook_login.png

Firebase Authenticationの設定

Firebaseコンソールの「Authentication」から「ログイン方法」タブに切り替え、ログインプロバイダを選択します。「Facebook」を選択し、右側にある「有効にする」を切り替えて有効にします。
そして、先ほどのfacebook for developerの管理画面に記述されていた「アプリID」と「app secret」を、Firebase Authenticationの、

  • アプリケーションID
  • アプリシークレット

にペーストします。
firebase_facebook.jpg

FirebaseUIによるログイン処理

FirebaseUIをインストールします。

npm install firebaseui --save

以下がFirebaseUIによるログイン処理のコード全体です。
今回はReactで書いていますすが、おそらくもっとReactらしい記述方法があると思います...

import firebase from 'firebase/app';
import firebaseui from 'firebaseui';
import 'firebaseui/dist/firebaseui.css';
import React from 'react';

export default class LoginPage extends React.Component {
  componentDidMount() {
    let ui = firebaseui.auth.AuthUI.getInstance();
    if (!ui) {
      ui = new firebaseui.auth.AuthUI(firebase.auth());
    }
    const uiConfig = {
      callbacks: {
        signInSuccessWithAuthResult: (authResult, redirectUrl) => {
          return true;
        },
        uiShown: () => {
          document.getElementById('loader').style.display = 'none';
        },
      },
      signInFlow: 'popup',
      signInSuccessUrl: 'mypage',
      signInOptions: [
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
      ],
      tosUrl: 'terms',
      privacyPolicyUrl: 'policy',
    };
    ui.start('#firebaseui-auth-container', uiConfig);
  }

  render() {
    return (
      <div>
        <div id="firebaseui-auth-container" />
        <div id="loader">Now Loading...</div>
      </div>
    );
  }
}

まず、FirebaseUI のログインフローを開始するには、

const ui = new firebaseui.auth.AuthUI(firebase.auth());

として、基盤となる Auth インスタンスを渡して FirebaseUI インスタンスを初期化する必要があります。
ちなみに今回、

let ui = firebaseui.auth.AuthUI.getInstance();
if (!ui) {
  ui = new firebaseui.auth.AuthUI(firebase.auth());
}

としているのは、SPAでサイトを構築した場合にError: An AuthUI instance already existsとなるのを防ぐ為です。

次に、uiConfigにFirebaseUIの設定(サポートするプロバイダ、UI のカスタマイズ、成功時のコールバックなど)を指定していきます。

signInSuccessWithAuthResultは、ユーザのサインイン成功時に自動的にリダイレクトを続行するか否かを記述します。

uiShownでは、FirebaseUIのUIが描画されたときの処理を記述しています。ここでは、UIが表示されるまでは<div id="loader">Now Loading...</div>を表示させて、UIが表示されたら消す、という内容です。

signInFlowでは、サインインフローをポップアップにするか、リダイレクトにするかなどが記述できます。

signInSuccessUrlは、サインイン処理完了後のリダイレクト先を記述します。
例えば、サインイン完了後に/mypageに遷移したいのであれば上記コードのように記述します。

signInOptionsでは、サインイン処理の為にユーザに提供したいプロバイダーを記述します。
今回はログインプロバイダーをFacebookに指定したので、上記コードのようになっています。
ちなみにTwitterを使いたいのであれば、

firebase.auth.TwitterAuthProvider.PROVIDER_ID

のように記述します。

tosUrlでは、利用規約のページを記述します。signInSuccessUrlと同じ要領です。

privacyPolicyUrlでは、プライバシーポリシーのページを記述します。こちらもsignInSuccessUrlと同じ要領です。
ちなみにtosUrlprivacyPolicyUrlの記述は必須になります。
uiConfigの設定項目の詳細は下記リンク先から確認できます。
Configuration

最後に、

 ui.start('#firebaseui-auth-container', uiConfig);

としてUIをレンダリングします。

以上で画像のような、ユーザ登録、ログイン、ログイン後のページ遷移などをイイ感じにやってくれるUIが出来上がります。
firebaseUI.png

Cloud FunctionsによるFirestoreへのユーザ情報の書き込み

FirebaseUIによるユーザ登録、ログイン処理が実装できたので、次は登録されたユーザ情報をFirestoreに書き込む方法です。
これはCloud Functions経由で行います。
Cloud Functionsの設定方法は、下記リンク先が分かりやすいと思います。
はじめに: 最初の関数を作成してデプロイする  |  Firebase

とりあえずコード全体です。

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);

exports.registerUsers = functions.auth.user().onCreate((user) => {
  const { uid } = user;
  const db = admin.firestore();
  const displayName = user.displayName || 'Anonymous';
  const email = user.email || '';
  const photoURL = user.photoURL || '/assets/img/default_profile.svg';

  return db.collection('users').doc(uid).set({
    user_name: displayName,
    photo_url: photoURL,
    email,
    create_on: new Date(),
  })
    .then(() => {
      console.log('Success'); // eslint-disable-line no-console
    })
    .catch((err) => {
      console.log(err); // eslint-disable-line no-console
    });
});

functions.auth.user().onCreate() イベント ハンドラを使用して、Firebase ユーザーが作成されたときにトリガーされる関数を作成できます。
そして、ユーザ属性にアクセスしてFirestoreに登録するユーザ情報として必要そうなものを取得します。今回の例ではdisplayName, email, photoURLを取得しました。
下記リンク先にアクセス可能なユーザ属性一覧が載っています。
Interface: UserRecord  |  Firebase

後は、set()メソッドを使用してFirestoreにユーザ情報を書き込みます。

以上で、FirebaseUIによるユーザ登録/ログイン処理と同時に、Firestoreにユーザ情報を書き込むことができます。

所感

FirebaseUIを使えば、面倒くさいユーザ登録やログイン処理をとても簡単に実現することができました。
加えて、Cloud Functionsともうまく連携すれば今回のようにできることの幅が広がりそうです。
また、FirebaseUIは日本語にも対応可能みたいなのでやってみたいと思います。

Firebase、とても便利です。

補足

仮に、Facebookログイン以外にもTwitterログインを使う場合、ほとんどはFacebookログインと同じような方法で実装することができます。
しかし、Cloud Functionsでユーザ情報を取得しようとしたときに、emailが取得できないことがあります。

const email = user.email || ''; // Twitterの場合、emailが取得できない

そのようなときは、Twitter Developersの管理画面から画像のように「Request email address from users」にチェックを入れれば、emailが取得できるようになると思います。
twitter_email.JPG

38
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?