JavaScript
Firebase

Firebase Authで新規ユーザを作らせたくない!

問題意識

Twitter連携などのOAuthでユーザ登録をできるようにしたり、メールアドレス/パスワードでユーザ登録をさせたりするようにすると、本当に誰でも自分のプロジェクトに新規ユーザ登録できてしまう。ECサイトとかSNSとかではこれは望ましい動作だろうが、サークルや研究室のサイト構築などではこれは望ましい動作ではない。ホワイトリスト形式でユーザを登録させる方法はあるだろうか?

世の中の見解

見解1: 登録/認証は好きにさせて、認可ではじけば?

Is there a way to restrict registrations in firebase - Stack Overflow

How do I restrict signup to a product in Firebase - Stack Overflow

Restrict Google Auth to specific users - Google グループ

ひとこと: 認可の設定に穴があったらどうする?未来の実装にもコストがのしかかる。リスク高め。

見解2: 独自認証プロバイダを作って移譲させればできるよ

Restrict google auth with firebase for some emails : javascript - reddit

ひとこと: めんどくさいし、他のプロバイダ経由で登録されたらバイパスされる。

見解3: custom claims っていう機能使えばできるんじゃないかな多分

これは見解1 をスマートにした感じ。このスレッドは結構突っ込んでいるのでしっかり読む価値あり

Disable new user signups · Issue #99 · firebase/firebaseui-web

ひとこと: 結局見解1 と一緒かな

私の試した方法

Functions の機能で、ユーザが新規登録された瞬間にそのユーザを disable にする。上記の見解3 のスレッドの中で紹介されていたけどみんなからスルーされていた方法。

exports.noMoreUser = functions.auth.user().onCreate(record =>
  admin.auth().updateUser(record.uid, { disabled: true })
    .then(r => console.log(`Disabled New user ${r.uid}`))
    .catch(error => console.log("Error Disabling New User", error))
);

本当に登録したければ、管理者に言って disable を解除してもらう。管理者は定期的に disable となっているユーザを削除する、という運用でよさそう。

ただ、問題がある。登録と同時に自動的にログインするという仕様なのだが、その時のトークンで色々操作できてしまう。トークンは 1時間でリフレッシュされるので、1時間は好き放題されてしまう可能性があることを示唆している。

強制的にトークンを無効化する revokeRefreshTokens を呼び出すということも考えられるが、既存のトークンはアクティブになる可能性があるとドキュメントで指摘があったし、verifyIdToken の第二引数を true にしなければいけないという、コードベースでの対策が必要となりうるのが頭が痛いところ。

そもそも、少し試してみたところ、Functions がトリガされるのが非同期なので、この方法も見解3も穴があるといわざるを得ない。登録と同時にユーザを削除するという方針も同様に穴がある。

結局

厳密に運用したいなら、現状ではたぶん見解1のように認可の段階で 実行できる IDをホワイトリストにするしかない。緩くていいなら、見解3 や私の方法でいいかも。