Flutterでwebアプリ開発を始めました。
以前にVue.jsを使ってFirebaseHostingを使ったWebアプリでFirebase&GoogleSignInでの認証を作っていて、「認証に簡単にできるんだ!」と感動した覚えがあったので、今回もサクッと認証機能を入れ込もうと思ったのですが、、、、思いの他はまったので、記録として残します。
最初に結論
- Flutter2.8以降でFirebaseを使ったログイン方法が変わっているようです。(詳しくは理解していない)
- このバージョン以前の実装方法はいろんな記事があり、そのまま実装で大丈夫そう。
- 2.8以降?ではFirebaseAuth.signInWithPopup()を使うとうまくいく。(行った)
補足
- この記事ではFirebaseの設定や、GCPの設定は記載していません。他参考サイトを貼っておきます。
- 環境・パッケージのバージョンは最後に記載しています。
はまったコード
だいたい色んな参考サイトを見てみるとこんな感じで記載されていると思います。
Flutterを使ったAndroidアプリ、iOSアプリならこれで大丈夫な様子。
Future<void> googleSignin() async {
// Google認証の部分
final GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
try {
final GoogleSignInAccount? googleUser = await _google_signin.signIn();
} catch (error) { print(error); }
final GoogleSignInAuthentication? googleAuth =
await googleUser?.authentication;
// 🔥🔥🔥🔥🔥 クレデンシャルの取得 🔥🔥🔥🔥🔥
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleAuth?.idToken,
accessToken: googleAuth?.accessToken,
);
// Firebase 認証 インスタンス生成
final FirebaseAuth _fauth = FirebaseAuth.instance;
// Google認証を通過した後、Firebase側にログイン
try {
final UserCredential result =
await _fauth.signInWithCredential(credential);
user = result.user;
// TODO:ログイン後画面にアカウントを引き継ぐ
// ログイン後の画面遷移
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NextView(),
));
} catch (e) {
print(e);
}
}
このコードで散々試しましたが、、、🔥🔥🔥🔥🔥の部分で以下のエラーが出て、うまくいきませんでした。。。
Error: Assertion failed:
file:///xxxx/flutter_dev/flutter/.pub-cache/hosted/pub.dartlang.org
/firebase_auth_platform_interface-6.2.5/lib/src/providers/google_auth.dart:43
:12
accessToken != null || idToken != null
"At least one of ID token and access token is required"
at Object.throw_ [as throw] (http://localhost:7357/dart_sdk.js:5067:11)
at Object.assertFailed (http://localhost:7357/dart_sdk.js:4992:15)
at Function.credential
(http://localhost:7357/packages/firebase_auth_platform_interface/src/type
s.dart.lib.js:516:59)
at main.xxxx.new.googleSignin
(http://localhost:7357/packages/mappy/main.dart.lib.js:527:57)
at googleSignin.next (<anonymous>)
at http://localhost:7357/dart_sdk.js:40571:33
at _RootZone.runUnary (http://localhost:7357/dart_sdk.js:40441:59)
at _FutureListener.thenAwait.handleValue
(http://localhost:7357/dart_sdk.js:35363:29)
at handleValueCallback (http://localhost:7357/dart_sdk.js:35931:49)
at Function._propagateToListeners
(http://localhost:7357/dart_sdk.js:35969:17)
at _Future.new.[_complete] (http://localhost:7357/dart_sdk.js:35809:25)
at http://localhost:7357/dart_sdk.js:34915:30
at internalCallback (http://localhost:7357/dart_sdk.js:26619:11)
なぜかはよくわかりませんでしたが、googleUser?.authenticationの結果は取得できているものの、
それを使った、GoogleAuthProvider.credential(xx)の結果はnullになっている。。。
うまく動いたコード
ちょーシンプルですが、いかでGoogle認証して、Firebase認証までしてくれます。
Future<void> googleSignin() async {
GoogleAuthProvider authProvider = GoogleAuthProvider();
try {
final UserCredential userCredential =
await _fauth.signInWithPopup(authProvider);
user = userCredential.user;
// TODO:ログイン後画面にアカウントを引き継ぐ
// ログイン後の画面遷移
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NextView(),
));
} catch (e) {
print(e);
}
その他にハマった対策メモ
ローカルテストでGoogle認証を使うには、ポートを指定して起動する必要がある
ポート指定での起動方法
$ flutter run -d chrome --web-hostname localhost --web-port 7357
「GCP -> APIとサービス -> 認証情報」で以下のように設定してあげる。
認証のリダイレクト先にFirebaseの登録が必要
同じく、「GCP -> APIとサービス -> 認証情報」で以下のように設定してあげる。
この部分に下のID部分を登録してあげる。
参考サイト
-
FlutterへFirebase AuthenticationとGoogle Sign-Inで簡単にログイン機能を実装
Firebaseの設定など含めて基本的なことがわかりやすく解説されています。 -
Flutterを使ったGoogleサインイン&Firebase認証
解決につながったサイト
環境
doctor
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.10.3, on Mac OS X 10.14.6 18G103 darwin-x64, locale ja-JP)
[✗] Android toolchain - develop for Android devices
✗ Unable to locate Android SDK.
Install Android Studio from: https://developer.android.com/studio/index.html
On first launch it will assist you in installing the Android SDK components.
(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
If the Android SDK has been installed to a custom location, please use
`flutter config --android-sdk` to update to that location.
[✗] Xcode - develop for iOS and macOS
✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
Download at: https://developer.apple.com/xcode/download/
Or install Xcode via the App Store.
Once installed, run:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
✗ CocoaPods not installed.
CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the
Dart side.
Without CocoaPods, plugins will not work on iOS or macOS.
For more info, see https://flutter.dev/platform-plugins
To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] VS Code (version 1.66.2)
[✓] Connected device (1 available)
[✓] HTTP Host Availability
! Doctor found issues in 3 categories.
パッケージバージョン
$ flutter pub outdated
Showing outdated packages.
[*] indicates versions that are not the latest available.
Package Name Current Upgradable Resolvable Latest
direct dependencies: all up-to-date.
dev_dependencies:
firebase_core *1.15.0 1.16.0 1.16.0 1.16.0
flutter_lints *1.0.4 *1.0.4 *1.0.4 2.0.1
google_maps_flutter *2.1.3 2.1.4 2.1.4 2.1.4
transitive dependencies:
characters *1.2.0 *1.2.0 *1.2.0 1.2.1
collection *1.15.0 *1.15.0 *1.15.0 1.16.0
material_color_utilities *0.1.3 *0.1.3 *0.1.3 0.1.5
vector_math *2.1.1 *2.1.1 *2.1.1 2.1.2
transitive dev_dependencies:
async *2.8.2 *2.8.2 *2.8.2 2.9.0
fake_async *1.2.0 *1.2.0 *1.2.0 1.3.0
google_maps *5.3.0 *5.3.0 *5.3.0 6.1.0
js *0.6.3 *0.6.3 *0.6.3 0.6.4
lints *1.0.1 *1.0.1 *1.0.1 2.0.0
path *1.8.0 *1.8.0 *1.8.0 1.8.1
source_span *1.8.1 *1.8.1 *1.8.1 1.9.0
test_api *0.4.8 *0.4.8 *0.4.8 0.4.9
2 upgradable dependencies are locked (in pubspec.lock) to older versions.
To update these dependencies, use `flutter pub upgrade`.