🐛

[Amplify][GoRouter]Flutterを3.27にバージョンアップしたらソーシャルログイン後に意図しない画面遷移が起こる

2024/12/30に公開

Flutterのバージョンを3.24から3.27にバージョンアップした際にハマったのところです。

利用していたライブラリ

environment:
  sdk: ^3.6.0

dependencies:
  amplify_auth_cognito: ^2.4.2
  amplify_flutter: ^2.4.1
  go_router: ^12.1.3

事象

Flutterで3.27に上げたタイミングでAmplifyのソーシャルログイン機能がAndroidでうまく動かなくなっていました。

これまで(3.24)

GoRouterで定義した/login(ログイン画面)からWebViewでGoogleログインやApple IDログインを完了させると /login-complete(ログイン完了画面)に遷移する

3.27アップデート後

GoRouterで定義した/login(ログイン画面)からWebViewでGoogleログインやApple IDログインを完了させると /(ホーム画面)に遷移する

原因

Flutter3.27で入ったDeep links flagのデフォルト値がfalseからtrueに変更していたことが原因でした。
https://docs.flutter.dev/release/breaking-changes/deep-links-flag-change

これまで、Amplifyで設定したログイン後の callbackUrls に ディープリンクを設定していましたが、Deep links flagがfalseだったため機能していませんでした。
しかし、3.27バージョンアップ時にDeep links flagがtrueになったことでログイン成功時に設定していたパスに自動で遷移してしまうようになっていました。

ampliy/auth/resource.ts
import { defineAuth, secret } from "@aws-amplify/backend";

export const auth = defineAuth({
  loginWith: {
    email: true,
    externalProviders: {
      google: {
        clientId: secret("GOOGLE_CLIENT_ID"),
        clientSecret: secret("GOOGLE_CLIENT_SECRET"),
      },
      // ログイン成功時に `/` に遷移するように設定している
      callbackUrls: ["myapp://"],
      logoutUrls: ["myapp://"],
    },
  },
});
android/app/src/main/AndroidManifest.xml
<application>
  ...
  <activity
        android:name=".MainActivity" android:exported="true">
        <intent-filter>
            ...
            <!-- 上記のresource.tsで設定したURI scheme -->
            <data android:scheme="myapp" />
        </intent-filter>
  </activity>
  ...
</application>

解決法

公式のMigration guideに従ってDeep links flagをfalseにするか、AmplifyのcallbackUrlsを正しい遷移先に設定することで解決できました。

android/app/src/main/AndroidManifest.xml
 <manifest>
     <application
         <activity>
+            <!-- ログイン成功後に画面遷移させないようにする -->
+            <meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
         </activity>
     </application>
 </manifest>

Androidのみこの設定が必要(3.27でもiOSでは/に画面遷移しない)ですが、プラットフォームごとにフラグの値が異なると今後混乱する可能性があるので、iOSもfalseにします。

ios/Runner/info.plist
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
 "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
    ...
+	<key>FlutterDeepLinkingEnabled</key>
+ 	<false/>
 </dict>
 </plist>

callbackUrlsを正しい値に変更する

ampliy/auth/resource.ts
import { defineAuth, secret } from "@aws-amplify/backend";

export const auth = defineAuth({
  loginWith: {
    email: true,
    externalProviders: {
      google: {
        clientId: secret("GOOGLE_CLIENT_ID"),
        clientSecret: secret("GOOGLE_CLIENT_SECRET"),
      },
-      callbackUrls: ["myapp://"],
+      callbackUrls: ["myapp://login-complete"],
      logoutUrls: ["myapp://"],
    },
  },
});

学び

定期的なバージョンアップ大事

Flutterのマイナーバージョンのアップデートを定期的に実施していたおかげで、3.24から3.27への移行時には変更点の確認範囲を限定することができました。
3.27のBreaking changesは6つのみだったため、問題の原因をすぐに特定できましたが、もし以前のバージョンから一気に3.27にアップデートしていた場合、原因の特定にかなりの時間と労力を要していたと思います。
定期的にFlutterのバージョンアップをやっておいて良かったなと思います。

プラットフォーム毎にしっかり動作確認した方がいい

Androidではログイン時にうまく動作しない問題が発生しましたが、iOSではこれまで通り正常に動作しました。
Flutter公式のChange Logsを確認したところ、プラットフォームごとの差分はないように見えたものの、利用しているライブラリなどによって予期しないバグが発生する可能性があるため、動作確認は各プラットフォームでしっかり行った方がいいという学びがありました。

Discussion