flutter firebase auth Googleプロバイダを使う
Play Consoleアカウントをお金を払って登録していることが条件
アプリごとに SHA1 フィンガープリントを追加する
https://developers.google.com/android/guides/client-auth?authuser=0
そのためには何でもいいので適当にアプリを作ってflutter build appbundle
それを内部テストでもいいのでリリースを作ってアップロード
サンプル作って動かしたらエラーが発生
サンプル
https://firebase.flutter.dev/docs/auth/social#google
エラー内容
com.google.android.gms.common.api.ApiException: 10
Play Consoleの アップロード鍵の証明書
のところにあるSHA-1 証明書のフィンガープリント
をFirebaseのコンソールに登録しないとダメみたいなので、登録し直し。
気を取り直して、サンプルを動かすとデバッグでコンソールにuser情報が出力されることを確認
import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:firebase_auth/firebase_auth.dart'; Future<UserCredential?> signInWithGoogle() async { // Trigger the authentication flow final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn(); if (googleUser == null) { return null; } // Obtain the auth details from the request final GoogleSignInAuthentication googleAuth = await googleUser.authentication; // Create a new credential final credential = GoogleAuthProvider.credential( accessToken: googleAuth.accessToken, idToken: googleAuth.idToken, ); // Once signed in, return the UserCredential return await FirebaseAuth.instance.signInWithCredential(credential); } Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(MaterialApp( home: Scaffold( body: MyBody(), ), )); } class MyBody extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ElevatedButton( child: Text('SIGN IN'), onPressed: () async { final user = await signInWithGoogle(); print(user); }, ), ); } }
この段階でAuthenticationにレコードができる
sign in, outをいい感じにする
単純にやると下記のようなコードになると思います。
// signInWithGoogleはさっきと変わりなし Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(ProviderScope(child: MyApp())); } final authStateChangesProvider = StreamProvider((ref) { return FirebaseAuth.instance.authStateChanges(); }); class MyApp extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { return MaterialApp(home: AuthWidget()); } } class AuthWidget extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return ref.watch(authStateChangesProvider).when( data: (user) { if (user == null) return SignInScreen(); return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () async { await FirebaseAuth.instance.signOut(); }, child: Text('SIGN OUT'), ), body: WellcomeScreen(), ); }, error: (e, s, d) => Center(child: Text('$e')), loading: (d) => CircularProgressIndicator()); } } class SignInScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ElevatedButton( child: Text('SIGN IN'), onPressed: () async { // googleアカウントを選択するポップアップが起動して選択するとログインできる await signInWithGoogle(); }, ), ); } } class WellcomeScreen extends StatelessWidget { const WellcomeScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Wellcome'), ElevatedButton( onPressed: () async { // この方法だと遷移先でsign outしてもsignInページには移動しない Navigator.push( context, MaterialPageRoute(builder: (context) => AnotherScreen()), ); }, child: Text('to another screen')) ], ), ); } } class AnotherScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ Center(child: Text('AnotherScreen')), ElevatedButton( onPressed: () async { // signOutが実行されてもこのページは表示されたまま await FirebaseAuth.instance.signOut(); // 例えば苦し紛れにこの辺でNavigator.pushなどすると、 // SignInScreenからandroidのbackボタンで // このAnotherScreenに戻ってこれる。 // その時、firestoreなどに接続するようになってると // 権限の問題でエラーが発生したりする。 }, child: Text('SIGN OUT')) ], ); } }
ソースのコメントに書いてありますが、うまくsign outしません
単純にNavigatorを使うと上手くいきます。
class AuthWidget extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return ref.watch(authStateChangesProvider).when( data: (user) { if (user == null) return SignInScreen(); return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () async { await FirebaseAuth.instance.signOut(); }, child: Text('SIGN OUT'), ), // ここにNavigatorを追加するだけで、AnotherScreenまで行った時に // fabでsign outすると、sign inページに遷移する body: Navigator( pages: const [ MaterialPage( key: ValueKey('WellcomeScreen'), child: WellcomeScreen(), ) ], onPopPage: (route, result) => route.didPop(result), ), ); }, error: (e, s, d) => Center(child: Text('$e')), loading: (d) => CircularProgressIndicator()); } }
https://github.com/na8esin/flutter2_open_project/tree/main/lib/src/auth