Flutter 🇯🇵
Published in

Flutter 🇯🇵

Flutter・Firebase で Android アプリの Sign in with Apple 対応をする🎯🔥🤖🍎

[2022年8月26日追記] firebase_auth 3.7.0 から簡単になりました

コード的には以下だけで済むようになりました:

import 'package:firebase_auth/firebase_auth.dart';

Future<UserCredential> signInWithApple() async {
final appleProvider = AppleAuthProvider();
if (kIsWeb) {
await _auth.signInWithPopup(appleProvider);
} else {
await _auth.signInWithAuthProvider(appleProvider);
}
}
https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/

Android上でのApple認証の現状

https://firebase.flutter.dev/docs/auth/social#apple の記載では https://github.com/FirebaseExtended/flutterfire/issues/2691 を理由に未対応になっています。

https://firebase.flutter.dev/docs/auth/social#apple

大まかな流れ

以下が大まかな流れです。

  1. Apple認可サーバーからリダイレクトされるWeb APIをCloud Functionsで用意しておく
  2. Androidアプリ上でApple認証を要求されたら、その用意したリダイレクトURL・ハッシュ化したnonce・stateなどのパラメーター付きでApple認証サイトをChromeカスタムタブにて開く
  3. ユーザーがログインに成功したら、用意したWeb APIにリダイレクトされる
  4. Web APIではインテントURLスキームを用いてAndroidアプリにリダイレクトしながらApple認可サーバーから受け取った認証情報(identityToken・authorizationCode・stateなど)を渡す
  5. 認証情報を受け取ったアプリは state が渡した値と同一であることを検証
  6. identityToken・authorizationCode・nonce(ハッシュ化前)から組み立てた認証情報をFirebase Authentication SDKに渡してログイン(内部的にJWT検証が行われる)

Apple認可サーバーからリダイレクトされるWeb APIをCloud Functionsで用意

次のようなCloud Functionsを組んでデプロイします。

インテントURLスキームを受け取れるようにしておく

上の以下の値でアプリが開かれたときに処理がされるようにします。

  • intent://callback
  • scheme=signinwithapple
https://github.com/aboutyou/dart_packages/blob/a9f49f69c8f7ccc1d0dffc488f5f94b3d3bf9533/packages/sign_in_with_apple/android/src/main/kotlin/com/aboutyou/dart_packages/sign_in_with_apple/SignInWithApplePlugin.kt#L143-L176

Service IDの作成

さらに、Service ID周りの設定が必要です。まず、Configure Sign in with Apple for the web の手順に従って、Service IDを設定して対象のアプリと紐づけておきます。

Service IDに、Apple認可サーバーから上で用意したWeb APIへのリダイレクト許可設定

仮に、デプロイしたURLが https://us-central1-mono-firebase.cloudfunctions.net/siwa だとすると、作成したService ID のWebsite URLs に次のように指定して保存します。

Service IDのFirebase Authenticationへの紐付け

さらに、Firebase AuthenticationのApple認証の設定で、Service IDを紐づけて保存します。Firebase SDKのログインメソッド実行時などにJWT検証がされますが、これが不合致だとそこでエラーが発生します。

Flutterアプリでログインボタンを押された時の処理

Flutterアプリでログインボタンを押された時の処理は、各種パッケージを活用しながら次のように記述します。sign_in_with_appleパッケージの内部処理によって、AndroidではwebAuthenticationOptions・nonce・stateに指定した値のパラメーター付きでApple認証サイトをChromeカスタムタブにて開かれます。

  • nonce : リプレイアタック対策
  • state : CSRF対策
  1. Apple認可サーバーでのログイン操作
  2. リダイレクトWeb APIに渡ってきた認証情報をIntent経由でアプリに渡す
  3. Activityが起動されて、渡された認証情報をFlutter側にMethod Channelで渡す

appleCredentialを用いてFirebase Authenticationにログイン

stateは自分で検証し、nonceはハッシュ化前の値を認証情報に含めてFirebase Authentication SDKにJWT検証時に使ってもらえるようにします。

サンプルリポジトリ

Firebase・Flutterプロジェクトが含まれるリポジトリはこちらです。

  • Service ID (clientId)
  • redirectUri (リダイレクトWeb APIのURL)
  • applicationId
  • Firebase接続ファイル

--

--

Flutterに関する日本語記事を書いていきます🇯🇵

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store