masalibの日記

システム開発、運用と猫の写真ブログです

React Firebase入門 Twitter認証

「クソみたいなサイトでログインIDパスワードなんて覚えてられるか!!」と思っているのは

私です

という事でTwitterでもログインできるようにしたいと思います

この記事はReact Firebase入門シリーズです 1-1-1・ Firebase初期設定とFirebaseAuthのSignUp
1-1-2・ 「react-hook-form」を入れてみた
1-1-3・ AuthのSignUpの通信エラー対応
1-2 ・ FirebaseAuthのログイン処理
1-3 ・ FirebaseAuthのログイン認証とログアウト処理
1-4 ・ FirebaseAuthのパスワード初期化処理
1-5 ・ FirebaseAuthのメールアドレスの有効化
1-6 ・ FirebaseAuthのメールアドレスとパスワード変更
1-7 ・ FirebaseAuthの表示名変更
1-8 ・ FirebaseAuthの拡張項目追加
1-9-1 ・ FirebaseAuthのTwitter認証 今ここ
2-1・ FirebaseStorageのファイルアップ:基礎
2-2・ FirebaseStorageのファイルアップ前に画像の切り抜き
2-3・ FirebaseStorageのファイルアップの移動 3-1・FirestoreのCRUD
3-2・Firestoreのデータ取得補足
3-3・Firestoreのページネーション処理
3-4・Firestoreのコレクション(テーブル)のJOIN
よかったら他の記事も見てください。

やりたい事

  • Twitterでログイン認証する

事前作業

TwitterとFirebase側に設定が必要です。

事前作業1:Twitterでアプリを作成

Twitterデベロッパー登録を行う必要があります。

qiita.com

この記事を参考にしておこないました。

一番めんどくさいのは

APIを使うための理由が 英語 でかかないといけないのです。 しかも200文字以上・・・めんどくさい。がんばって文字数をかせぎました

日本
WEBアプリを作成しています。 このアカウントはそのアプリでログイン認証にTwitterを使うために 必要でした。 BotなどからのTweetはおこないません。 Tweet検索などはおこないません

英語
We are creating a web app. This account is to use Twitter for login credentials in that app. I needed it. No tweeting from bots etc. will be done. No Tweet search will be done.
登録が終わってメールが届くのでログインすると アプリの設定画面があります

メニュー「Projects & Apps」→「自分のプロジェクト」→「Keys and tokens」→「View keys」とたどります。 そちらでキーが表示されますので保存します

事前作業2:Firebaseコンソール上の設定

現在はメールしか認証方法をせってしていないので FirebaseのWebコンソールへログインしたら、メニュー「Authentication」→「Sign-in method」→「Twitter」→「編集」とたどります。

そちらに事前作業1で取得したAPIキーと秘密鍵(シークレットキー)を入力します。

下に表示されている

https://プロジェクト名.firebaseapp.com/__/auth/handler」

コールバックURLをコピーする

事前作業3:Twitterの設定画面でコールバックURLの設定

メニュー「Projects & Apps」→「自分のプロジェクト」→「Settings」→「Authentication settings Edit」とたどります。

そちらにあるコールバックURLを登録する

プログラムについて

修正箇所が多いので全部みたい人はブランチのリンクから参照してください

https://github.com/masalib/Learn-Firebase/blob/Firebase_Twitter_link/src/firebase.js
https://github.com/masalib/Learn-Firebase/blob/Firebase_Twitter_link/src/components/Login.js
https://github.com/masalib/Learn-Firebase/blob/Firebase_Twitter_link/src/components/Signup.js

Firebaseの初期設定のプログラム修正箇所

/src/firebase.js

var storage_obj = firebase.storage();
+ export const Twitter = new firebase.auth.TwitterAuthProvider();
export default firebase;

ツイッターのプロバイダーを設定するのみです。GoogleGithubが追加になった場合はこの部分を修正します

Singupのプログラム修正箇所

ツイッターでログインするためのボタンを追加した

<Button
    fullWidth
    variant="contained"
    size="large"
    color="primary"
    className={classes.loginBtn}
    onClick={handleTwitterSignup}
>
<TwitterIcon />Twitterでアカウント作成
</Button>

ボタンを押したときに起動する関数を追加しました

  async function handleTwitterSignup (event) {  
    console.log("handleTwitterSignup")
    try {
      firebase
        .auth()
        .signInWithPopup(Twitter)
        .then((result) => {
          console.log(result);
          setSuccessMessage("アカウントの作成に成功しました。ダッシュボードにリダレクトします")
          setTimeout(function(){
              console.log("リダレクト処理")
              history.push("/dashboard")
          },2000);
        });
    } catch (error) {
      switch (error.code) {
        case "auth/network-request-failed":
            setError("通信がエラーになったのか、またはタイムアウトになりました。通信環境がいい所で再度やり直してください。");
            break;
        case "auth/credential-already-in-use": 
            setError("他のユーザーでTwitter認証しているため、認証ができませんでした。");
            break;
        case "auth/requires-recent-login": 
            setError("別の端末でログインしているか、セッションが切れたので再度、ログインしてください。(ログインページにリダイレクトします)");
            setTimeout(function(){
                console.log("リダレクト処理")
                history.push("/login")
            },3000);
            break;
        default:  //想定外
            setError("失敗しました。通信環境がいい所で再度やり直してください。");
      }
    }
  }

この関数で注目するのは以下の部分です

firebase
  .auth()
  .signInWithPopup(Twitter)
  .then((result) => {
    console.log(result);
    setSuccessMessage("アカウントの作成に成功しました。ダッシュボードにリダレクトします")
    setTimeout(function(){
        console.log("リダレクト処理")
        history.push("/dashboard")
    },2000);
  });

これだけでツイッターで連携をしてくれるのです。 作った事がある人ならこれにびっくりする。ツイッターの連携はめっちゃややこしいのです

ozuma.o.oo7.jp より引用

これを見たときに Firebase最高!!! と思った

エラーハンドリングはちょっと微妙で 「auth/credential-already-in-use(サイトに既存のユーザーがいるエラー)」を仕込んだのですが うまく動いてくれず、存在する場合はログイン処理になるみたいです。

Loginのプログラム修正箇所

SingUPとあまり変わらないです。ボタンを配置して関数を用意するだけ。 唯一違うのはエラーハンドリングで「auth/credential-already-in-use」がないぐらいです。

ツイッターでログインするためのボタンを追加した

<Button
    fullWidth
    variant="contained"
    size="large"
    color="primary"
    className={classes.loginBtn}
    onClick={handleTwitterLogin}
>
<TwitterIcon />TwitterでLoginする
</Button>

ボタンを押したときに起動する関数を追加しました

  async function handleTwitterLogin(event) {  
    console.log("handleTwitterLogin")
    try {
      firebase
        .auth()
        .signInWithPopup(Twitter)
        .then((result) => {
          console.log(result);
          setSuccessMessage("アカウントの作成に成功しました。ダッシュボードにリダレクトします")
          setTimeout(function(){
              console.log("リダレクト処理")
              history.push("/dashboard")
          },2000);
        });
    } catch (error) {
      switch (error.code) {
        case "auth/network-request-failed":
            setError("通信がエラーになったのか、またはタイムアウトになりました。通信環境がいい所で再度やり直してください。");
            break;
        case "auth/credential-already-in-use": 
            setError("他のユーザーでTwitter認証しているため、認証ができませんでした。");
            break;
        case "auth/requires-recent-login": 
            setError("別の端末でログインしているか、セッションが切れたので再度、ログインしてください。(ログインページにリダイレクトします)");
            setTimeout(function(){
                console.log("リダレクト処理")
                history.push("/login")
            },3000);
            break;
        default:  //想定外
            setError("失敗しました。通信環境がいい所で再度やり直してください。");
      }
    }
  }

結果

  1. ツイッターのログインのボタンを押す
    f:id:masalib:20201210200336p:plain
  2. ツイッターの連携画面が表示される
    f:id:masalib:20201210200346p:plain
  3. IDとパスワードを入力する

結果として以下がかえってきます

additionalUserInfo: tg {providerId: "twitter.com", isNewUser: false, profile: {…}, username: "masalib"}
credential: Lg {a: null, accessToken: "81032211-cM1Th2bgkav8fMR6DhIrYLdyxk1PTEr7yrJtQd5j3", secret: "qLggwQhmxrGwS7gaurk1yunYyj61v80PDO7tRNRTIL2xw", providerId: "twitter.com", signInMethod: "twitter.com"}
operationType: "signIn"
user: Jm {G: Array(0), l: "AIzaSyBewJgxhZbiBy42KXp5Y-BkrBP3ZokadIU", m: "[DEFAULT]", o: "learn-firebase-masalib.firebaseapp.com", a: Ji, …}
__proto__: Object

またcurrentUserにプロバイダーの部分に twitter.comがあります。

またFirebaseのコンソールでもユーザーが追加されている事が確認できます
f:id:masalib:20201210200617p:plain

できていない事

  • 1度ログインするとツイッターの認証画面が省略されてしまいます。複数のアカウントがある人むけに クリアしないといけないんですが。。。よくわからず
  • メールアドレスでユーザー作成した人もツイッターログインできるようにする
  • ツイッター連携を解除する

感想

  • ツイッターのログインとか簡単にできると思っていたら、そもそもAPIキーを作成する所に苦戦した。英語で200文字。。。無理ゲー
  • ツイッターのログインを作った事がある人ならこのsourceは感動すると思う