電話認証

電話認証を使用すると、ユーザーはスマートフォンを認証システムとして使用して Firebase にログインできます。提供された電話番号を使用して、一意のコードを含む SMS メッセージがユーザーに送信されます。コードが認可されると、ユーザーは Firebase にログインできるようになります。

エンドユーザーが認証のために提供する電話番号は Google に送信され、Google はそれを Google サービス全体(Firebase だけに限定されません)でスパムや不正行為の防止対策を強化するために保存します。デベロッパーは Firebase Authentication の電話番号ログイン サービス認証を使用する前に、エンドユーザーから必ず適切な同意を得る必要があります。

一部の国では、Firebase 電話認証はサポートされていません。詳しくは、こちらのよくある質問をご覧ください。

設定

電話認証を開始する前に、次の手順を行ってください。

  1. Firebase コンソールで、ログイン方法として電話番号を有効にします。
  2. Android: アプリの SHA-1 ハッシュを Firebase コンソールにまだ設定していない場合は、それを行います。アプリの SHA-1 ハッシュを見つける方法についてはクライアントの認証をご覧ください。
  3. iOS: Xcode でプロジェクトのプッシュ通知を有効にし、APNs 認証キーが Firebase Cloud Messaging(FCM)で構成されていることを確認します。また、リモート通知用にバックグラウンド モードを有効にする必要があります。この手順の詳細については、Firebase iOS 電話認証のドキュメントをご覧ください。
  4. ウェブ: Firebase コンソールの [OAuth リダイレクト ドメイン] で、アプリケーション ドメインが追加されていることを確認します。

:電話番号ログインは、実際のデバイスとウェブでのみ使用できます。デバイス エミュレータで認証フローをテストする場合は、テストをご覧ください。

使用方法

Flutter 用の Firebase Authentication SDK には、電話番号を使用してユーザー ログインを行う方法が 2 つ用意されています。ネイティブ(Android、iOS など)プラットフォームとウェブでは、電話番号を検証する機能が異なるため、プラットフォームごとにメソッドが用意されています。

  • ネイティブ プラットフォーム: verifyPhoneNumber
  • ウェブ プラットフォーム: signInWithPhoneNumber

ネイティブ: verifyPhoneNumber

ネイティブ プラットフォームの場合、最初にユーザーの電話番号を確認する必要があります。確認後、ユーザーはログインするか、アカウントをリンクできます(PhoneAuthCredential を使用)。

まず、ユーザーに電話番号の入力を求めます。入力された場合は、verifyPhoneNumber() メソッドを呼び出します。

await FirebaseAuth.instance.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) {},
  verificationFailed: (FirebaseAuthException e) {},
  codeSent: (String verificationId, int? resendToken) {},
  codeAutoRetrievalTimeout: (String verificationId) {},
);

処理する必要があるコールバックは 4 つあります。処理されるコールバックにより、アプリ UI の更新方法が決まります。

  1. verificationCompleted: Android デバイスでの SMS コードの自動処理。
  2. verificationFailed: 無効な電話番号、SMS の割り当て超過などのエラーイベントを処理します。
  3. codeSent: コードが Firebase からデバイスに送信されたときに処理され、ユーザーにコードの入力を求めます。
  4. codeAutoRetrievalTimeout: SMS コードの自動処理が失敗した場合のタイムアウトを処理します。

verificationCompleted

このハンドラは、SMS コードの自動解決をサポートしている Android デバイスでのみ呼び出されます。

SMS コードがデバイスに配信されると、Android は SMS コードを自動的に検証します。ユーザーがコードを手動で入力する必要はありません。このイベントが発生すると、PhoneAuthCredential が自動的に提供されます。これは、ユーザーの電話番号でのログインまたは電話番号のリンクで使用されます。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) async {
    // ANDROID ONLY!

    // Sign the user in (or link) with the auto-generated credential
    await auth.signInWithCredential(credential);
  },
);

verificationFailed

電話番号が間違っている場合や、プロジェクトの SMS 割り当てを超過した場合など、Firebase からエラーが返された場合、このハンドラに FirebaseAuthException が送信されます。この場合、エラーコードに応じて、ユーザーになんらかの問題が発生したことを示すプロンプトを表示します。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationFailed: (FirebaseAuthException e) {
    if (e.code == 'invalid-phone-number') {
      print('The provided phone number is not valid.');
    }

    // Handle other errors
  },
);

codeSent

Firebase がデバイスに SMS コードを送信すると、このハンドラがトリガーされ、verificationIdresendToken が渡されます(resendToken は Android デバイスでのみサポートされます。iOS デバイスは常に null 値を返します)。

トリガーされたら、ユーザーに SMS コードの入力を求めるようにアプリの UI を更新します。SMS コードが入力されたら、確認 ID と SMS コードを組み合わせて、新しい PhoneAuthCredential を作成できます。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  codeSent: (String verificationId, int? resendToken) async {
    // Update the UI - wait for the user to enter the SMS code
    String smsCode = 'xxxx';

    // Create a PhoneAuthCredential with the code
    PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: verificationId, smsCode: smsCode);

    // Sign the user in (or link) with the credential
    await auth.signInWithCredential(credential);
  },
);

デフォルトでは、SMS メッセージが最近送信されている場合、Firebase がメッセージを再送信することはありません。ただし、forceResendingToken 引数に再送信トークンを指定して verifyPhoneNumber メソッドを呼び出すと、この動作をオーバーライドできます。成功すると、SMS メッセージが再送信されます。

codeAutoRetrievalTimeout

SMS コードの自動解決をサポートしている Android デバイスの場合、デバイスが所定の期間内に SMS メッセージを自動的に解決しないと、このハンドラが呼び出されます。この期間が過ぎると、デバイスは受信メッセージの解決を行いません。

デフォルトでは、デバイスは 30 秒間待機します。この期間は、timeout 引数を使用してカスタマイズできます。

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  timeout: const Duration(seconds: 60),
  codeAutoRetrievalTimeout: (String verificationId) {
    // Auto-resolution timed out...
  },
);

ウェブ: signInWithPhoneNumber

ウェブ プラットフォームの場合、提供された電話番号に SMS コードを送信します。ユーザーは、このコードを入力することで、スマートフォンにアクセスできることが確認され、ログインできるようになります。セキュリティの強化とスパム防止のため、ユーザーは Google reCAPTCHA ウィジェットを完了して、人間であることを証明するように求められます。確認が完了すると、SMS コードが送信されます。

Flutter 用 Firebase Authentication SDK はデフォルトの reCAPTCHA ウィジェットを使用しますが、必要に応じて表示や構成を制御することもできます。まず、電話番号を指定して signInWithPhoneNumber メソッドを呼び出します。

FirebaseAuth auth = FirebaseAuth.instance;

// Wait for the user to complete the reCAPTCHA & for an SMS code to be sent.
ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456');

このメソッドを呼び出すと、最初に reCAPTCHA ウィジェットがトリガーされて表示されます。ユーザーがこのテストを完了しないと、SMS コードは送信されません。完了したら、解決された ConfirmationResult レスポンスの confirm メソッドに SMS コードを渡して、ユーザーをログインさせることができます。

UserCredential userCredential = await confirmationResult.confirm('123456');

他のログインフローと同様に、ログインに成功すると、アプリケーション全体でサブスクライブした認証状態リスナーがトリガーされます。

reCAPTCHA 構成

reCAPTCHA ウィジェットは、ウェブ アプリケーションにセキュリティを提供するフルマネージド フローです。

signInWithPhoneNumber の 2 番目の引数には、ウィジェットの管理に使用できるオプションの RecaptchaVerifier インスタンスを指定できます。デフォルトでは、ログインフローがトリガーされると、ウィジェットは非表示のウィジェットとしてレンダリングされます。非表示のウィジェットは、アプリケーションの上にフルページ モーダルとして表示されます。

インライン ウィジェットを表示することもできますが、ユーザーはこのウィジェットを明示的に確認する必要があります。

インライン ウィジェットを追加するには、RecaptchaVerifier インスタンスの container 引数に DOM 要素 ID を指定します。要素が存在し、かつ空にする必要があります。そうでないとエラーがスローされます。container 引数が指定されていない場合、ウィジェットは非表示としてレンダリングされます。

ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456', RecaptchaVerifier(
  container: 'recaptcha',
  size: RecaptchaVerifierSize.compact,
  theme: RecaptchaVerifierTheme.dark,
));

必要に応じてサイズとテーマを変更できます。変更するには、前述のように size 引数と theme 引数をカスタマイズします。

また、ユーザーが reCAPTCHA が完了したかどうか、reCAPTCHA が期限切れになったかどうか、エラーがスローされたかどうか、などのイベントをリッスンすることもできます。

RecaptchaVerifier(
  onSuccess: () => print('reCAPTCHA Completed!'),
  onError: (FirebaseAuthException error) => print(error),
  onExpired: () => print('reCAPTCHA Expired!'),
);

テスト

Firebase では、電話番号をローカルでテストできます。

  1. Firebase コンソールで [電話番号] 認証プロバイダを選択し、[テスト用の電話番号] プルダウンをクリックします。
  2. 新しい電話番号(例: +44 7444 555666)とテストコード(例: 123456)を入力します。

verifyPhoneNumber メソッドまたは signInWithPhoneNumber メソッドにテスト用の電話番号を渡した場合、SMS は送信されません。代わりに、テストコードを PhoneAuthProvider に直接渡すことも、signInWithPhoneNumber の確認結果ハンドラを使用して指定することもできます。