ラベル Firebase Authentication の投稿を表示しています。 すべての投稿を表示
ラベル Firebase Authentication の投稿を表示しています。 すべての投稿を表示

2025/06/06

Firebaseコンソールの不具合

 Firebase Authenticationで多要素認証を実装しようとしていて発見した、Firebaseコンソールの不具合です。


準備

まずはテスト用の電話番号を登録します。SMSを受信できるスマホや携帯電話が2台以上あれば、テスト用の電話番号は不要かもしれません。

テスト用電話番号の登録手順は以下のとおり。この手順を説明した記事は少なそうだったので、念のため記載します。

  1. FirebaseコンソールでAuthenticationを選択。
  2. 画面上部のタブで「ログイン方法」を選択。

  3. 「SMS多要素認証」の「変更」を押下。

  4. ダイアログの「有効にする」をチェックして
  5. 「テスト用の電話番号」を押下するとダイアログが伸びてテスト用の電話番号の設定が現れます。
  6. 適当な電話番号(日本なので"+81aabbbbcccc")と確認コード(10進数6桁)を入力して、
  7. 「保存」を押下。


発生手順

手順の際現にはSMS認証による多要素認証をFirebase Authenticationで実装したアプリが必要です。ない場合はFirebaseのquickstart-jsでも再現できます。

以下にquickstart-jsによる再現手順を示します。

  1. SMS multi-factor authenticationを選択。

  2. 登録してある任意のアカウントのEメールアドレスとパスワードを入力して「SIGN IN」を押してログイン。
  3. 「ENROLL」を押下して第2認証のSMS認証の登録を開始。
  4. SMS認証に追加する電話番号を入力。準備で設定したテスト用の番号で十分です。

  5. reCAPTCHAをチェックしたら「SEND CODE」を押下。ここで"Firebase: Error (auth/requires-recent-login)."が発生したらいったんSIGN OUTし、手順2からログインしなおし。
  6. 届いたSMSに記載されている認証コードと、任意の表示名を入力して「VERIFY CODE」を押下。ここでは表示名は"test SMS 1"としています。
  7. SMS認証の追加が完了し、結果が表示されます。
  8. FirebaseコンソールのAuthenticationで「ユーザー」タブを選択し、SMS認証を追加したユーザの3点リーダを押下してオプションメニューを表示。
  9. オプションメニューから「多要素認証を構成」を選択。
  10. ダイアログの「保存」押下。特に編集しなくても現象は発生します。

  11. アプリquickstart-jsに戻ります。手順10でユーザアカウントを編集しているので、ログアウトしているはずです。ログアウトしていなかったら「SIGN OUT」を押下してログアウトします。
  12. もう一度ログインします。今度は手順3~7で追加した第2認証が必要になっていますので、これも認証します。

現象

アプリquickstart-jsでログインしてみると、第2認証のSMS認証の表示名が「N/A」に変わっています。


複数の電話番号を使えば1人のユーザに対して複数のSMS認証を追加できますが、すべてのSMS認証の表示名が「N/A」に変わってしまいます。

第2認証にワンタイムパスワードを使用している場合、ワンタイムパスワードだけ影響をうけません。SMS認証のみで発生します。


最後に

Firebaseのライブラリでいうと、MultiFactorInfo.displayNameがnullになっているようです。表示名を設定する手段はMultiFactorUser.enroll()しか見つからなかってので、消えてしまった表示名を復活させるには、SMS認証をいったん消して再登録するしかないようです。


一応Firebaseのサポートには報告し、「再現できたから開発チームに報告しておく」と回答をいただきました。そのうち修正されるでしょうが影響を受けるのは開発者のみなので、優先順位は低く対応が遅い可能性があります。Firebase Authenticationで多要素認証を実装・デバッグしていると混乱しかねない現象ですので、ご注意ください。

ちなみにFirebaseのサポートとのやり取りには3週間以上かかっています。


2025/04/21

SMS認証登録のログ「Failed to initialize reCAPTCHA Enterprise config. Triggering the reCAPTCHA v2 verification.」

(2025/04/23)
タイトルに「エラー」と表記していましたが、「ログ」に修正しました。

 現象

Identity Platform/Firebase Authenticationを使用して多要素認証にSMS認証の登録を実装する場合、PhoneAuthProvider.verifyPhoneNumber()で表題のログがブラウザのコンソールに出て失敗することがあります。

Failed to initialize reCAPTCHA Enterprise config. Triggering the reCAPTCHA v2 verification.

実装はGoogleのスニペットどおりですが、web8とweb9で実行結果に違いが出たりします。

対象結果
web8 (namespaced)期待どおり成功
web9 (modular)失敗


調査

Googleのドキュメントにはこのような現象についての記述は見当たりません。

ネットで検索してみると、redditの記事「Firebase Phone Auth reCAPTCHA Error」が見つかりました。他の記事はこの記事の別言語版と、リンク切れのみでしたので、実質たった1つです。

この記事ではReact Nativeで発生しているようですが、私が発生を確認したのはweb9 + Angularの組み合わせです。またこの記事は多要素認証ではなく電話認証のようです。しかし発生している現象はほぼ同じの様子です。この記事でも解決はしていません。


解決

手がかりが全くないので、思い当たるところを勘で変更して動作を確認するという地味な作業を繰り返し、解決方法にたどり着けました。

失敗していた実装は以下のような感じです。MultiFactorUserインスタンスをあらかじめ取得しておき、それを使いまわしていました。


class MfaComponent {
    multiFactorUser: MultiFactorUser;
    ...
    constructor(...) {
        ...
        this.multiFactorUser = multiFactor(ログインユーザのUser);
        ...
    }

    sendSms() {
        this.multiFactorUser.getSesstion()		←ここが原因
        .then((multifactorsession) => {
            const options = {
                phoneNumber: 電話番号,
                session: multifactorsesstion,
            };
            const provider = new PhoneAuthProvider(auth);
            provider.verifyPhoneNumber(options, recaptcha).then((verificationid) => {
                ...
            });


MultiFactorUserインスタンスを必要な時に取得するように変更することで、成功するようになりました。


class MfaComponent {
    ...
    constructor(...) {
        ...
    }

    sendSms() {
        multiFactor(ログインユーザのUser).getSesstion()		←修正
        .then((multifactorsession) => {
            const options = {
                phoneNumber: 電話番号,
                session: multifactorsesstion,
            };
            const provider = new PhoneAuthProvider(auth);
            provider.verifyPhoneNumber(options, recaptcha).then((verificationid) => {
                ...
            });


最後に

無事SMSは送信できるようになったものの、表題のログは出続けています。このログがPhoneAuthProvider.verifyPhoneNumber()が期待動作しなかったことと関係あるのかは不明です。動作には影響してなさそうですが、ちょっと不安です。


2022/05/17

vsReversiアップデート

GCPのデモとして用意していた vsReversiをアップデートしました。


アップデート内容は以下のとおりです。

  • ユーザのログインと新規登録を別に
  • SPA対応
  • デザイン変更

ユーザのログインと新規登録を別に

ユーザ認証にはGCPのIdentity Platform(Firebase Authentication)を使用していますが、これには出来合いのUIとして提供されるもの(Firebase UI)も、単体のAPIも、ログインと新規登録の区別がありません。それらが一緒になったサインインがあるのみです。

しかし日本では、ユーザ登録と登録済みユーザのログインが別になっているのをよく見るので、それらしく分けてみました。やってみて出来なくはないのですが、かえって実装は面倒になってしまった印象です。

またEメールで登録する場合は、OAuth(Google/Facebook/Twitter/etc.)に比べて、追加で実装しなければならないのものが多いので、余計面倒です。具体的には、

  • 入力されたEメールアドレスを確認する
  • 入力されたEメールアドレスが間違っていた場合にユーザ登録を解除
  • ユーザがパスワードを忘れた場合のパスワードリセット
  • ユーザがEメールアドレスの変更を希望した場合の対処 (vsReversiでは割愛)
  • さらにこれらのUIのカスタマイズ (vsReversiでは割愛)

Firebase UIではこれらの一部が対応済みなので、簡単に実装したいならそれを使うのが楽です。ただしUIのデザインは簡素なものなので、カスタマイズしたくなります。


SPA対応

Angularを使って一部のページをSingle Page Applicationに対応させました。ログイン/新規登録後のページがそれです。マテリアルデザインは採用していないので それっぽい見た目にはなっていないのですが、ページ遷移が速くなりました。

今までGAE/Java8メインで作っていたのですが、「GAE/Java8でSPA対応に苦戦」に記載したように、これは複数のURIに1つのページを割り当てることができないので、実装の変更が大掛かりになりました。具体的には...

  • HTMLなどスタティックコンテンツをFirebase Hostingに移行してURI割り当てを解決。
  • ajaxリクエストエンドポイントは過去のGAEの実装を流用。ただしCORS(Cross Origin Resource Sharing)に対応。
  • 管理者用のページはCloud Runで管理者の認証を実装。


GCPの初期からあるサービスだけに、GAEは単体でいろいろ必要なものが用意されていることを実感できました。今回は対応できないものが見つかったので、他にいろいろと物色することになりました。それぞれが別のサービスとして名前を持っているので、利用したサービスの数が増えています。


デザイン変更

SPA対応のついでですが、見た目だけの変更です。


CPUの思考ルーチンなどその他は以前のままで、変りありません。


2022/01/23

Identity PlatformをTypeScript+モジュール化で使ってみたら...

初の動作

タイトルどおりなのですが、Identity Platform(Firebase Authentication)を、TypeScript+モジュール化(v9)で使ってみました。あれこれ四苦八苦してやっとFirebaseUIを表示できるようになって、最初に表示された画面のキャプチャがこれです。


Googleさんが笑いを取ろうとしたのかと思ってしまいました。

ちなみに同様のものをJavaScript(v8)で実装したのが以下のキャプチャ。どちらのキャプチャも実寸大です。



v9でサイズがおかしくなったことについて、すぐに想像がついたのはCSSが読み込まれていないみたいということです。いやそもそも読み込みすらしていませんでした。
とりあえずHTMLからv8の要領でCSSだけ別に読み込んでみると、サイズは解決しました。

奇妙な注意書き

FirebaseUI でウェブアプリに簡単にログイン機能を追加する」には以下の注意書きがあります。

注: FirebaseUI は v9 モジュラー SDK と互換性がありません。v9 互換レイヤー(特に app-compat および auth-compat パッケージ)では、v9 とともに FirebaseUI を使用できますが、その場合、アプリのサイズ削減などの v9 SDK のメリットを得ることはできません。
使ったのはcompatパッケージではないのですが、「アプリのサイズ削減など」の「など」って何を指しているんでしょう。気になります。

日本語化

v8では言語のローカライズ版を読み込むことも可能で、上記のv8のキャプチャは日本語版を読み込んでいます。v9でも以下のようにすればローカライズ版の使用が可能なようですが、コンパイル後のJavaScript実行で以下のエラーが発生しました。
パッケージのインストール : npm install firebaseui-ja
TypeScriptソース : import 'firebaseui-ja';
ブラウザのエラー : Uncaught TypeError: Cannot read properties of undefined (reading 'navigator')
stack overflowの「Navigator undefined on React Typescript Firebase project」にも同様の現象が報告されていますが、この記事はローカライズ版ではないようですね。
どなたか回避方法をご存じの方おられましたら、コメントいただけると幸いです。

2021/12/08

GCPのデモアプリ : vsReversi


 GCPのデモとして、vsReversiを作ってみました。ネット対戦リバーシ(オセロ)です。

  • 対戦相手を選択できる。
  • 適当にマッチングして対戦もできる。
  • 相手がいないときは対コンピュータ戦もできる。

使用しているGCPのサービスは以下のとおりです。
  • App Engine : Webサーバ
  • Firestore : データベース
  • Identity Platform (Firebase Authentication) : ユーザ認証
  • Cloud Tasks : 対コンピュータ戦の思考ルーチン
対コンピュータ戦の思考ルーチンはJavaで書いていますが、実質数秒以下で1手を打ちます。そのためCloud Tasksを使用する意味はないのですが、GCPのデモとして無理矢理使っています。でないとただのGAEのデモなりそうなので。
デモにコストをかけられるほど裕福ではないので、GAEを中心に無料枠の範囲内で運用できるように、GAEの最大インスタンス数を制限しています。そのため利用が集中すると、応答が悪かったり、エラーになる可能性があります。最大インスタンス数の制限を外せば大勢が同時にアクセスしてもレスポンス低下の起きにくいGAE/Firestoreの特徴を活かせるのですが、残念なことになっています。GAE/Firestoreのいいところを全くアピールできていない、デモとしてはダメアプリです。

それでも、見つけた方は楽しんでいただければと思います。