Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

firebase_auth: App does not automatically login on startup in release build #17047

Open
1 task done
centy opened this issue Feb 4, 2025 · 14 comments
Open
1 task done
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. platform: android Issues / PRs which are specifically for Android. plugin: auth type: bug Something isn't working

Comments

@centy
Copy link

centy commented Feb 4, 2025

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Auth

Which platforms are affected?

Android

Description

We are using login via Google, user is able to login and all seems to work, however when app is closed and reopen, user is not logged in.

  1. FirebaseAuth.instance.authStateChanges() not triggers
  2. FirebaseAuth.instance.currentUser is null
  3. When https://firebase.google.com/docs/auth/flutter/federated-auth#google called again all login silently and works

We follow exactly steps from here -> https://firebase.google.com/docs/auth/flutter/start

What is strange that in debug it works and remember current user, problem is only in release build.

Nothing interesting in logcat related auth or filebase, no errors.

Reproducing the issue

Just follow steps https://firebase.google.com/docs/auth/flutter/start,

Firebase Core version

3.10.1

Flutter Version

3.27.3

Relevant Log Output

Flutter dependencies

dependencies: after_layout: ^1.2.0 applovin_max: ^4.1.2 async: ^2.11.0 auto_size_text: ^3.0.0 bloc: ^9.0.0 cached_network_image: ^3.3.1 carousel_slider_plus: ^7.0.0 collection: ^1.18.0 copy_with_extension: ^5.0.4 crop_your_image: ^1.0.2 cupertino_icons: ^1.0.6 dio: 5.6.0 dots_indicator: ^3.0.0 equatable: ^2.0.7 file: ^7.0.0 firebase_analytics: ^11.1.0 firebase_core: ^3.1.1 firebase_crashlytics: ^4.0.2 firebase_messaging: ^15.0.2 firebase_remote_config: ^5.0.2 flutter: sdk: flutter flutter_bloc: ^9.0.0 flutter_cache_manager: ^3.3.1 flutter_colorpicker: ^1.0.3 flutter_localizations: sdk: flutter flutter_native_splash: ^2.3.5 flutter_shaders: ^0.1.2 flutter_staggered_grid_view: git: https://github.com/centy/flutter_staggered_grid_view.git #go router bug in newer versions with popscope go_router: 12.1.3 hive: 2.2.3 hive_flutter: ^1.1.0 hive_generator: ^2.0.1 http: ^1.1.0 image: ^4.1.3 image_picker: ^1.0.4 in_app_purchase: ^3.2.0 in_app_purchase_android: ^0.3.6+8 in_app_review: ^2.0.8 intl: ^0.19.0 loading_animations: ^2.2.0 material_symbols_icons: ^4.2719.1 mocktail: ^1.0.1 vector_math: ^2.1.0 objectbox: ^4.0.1 objectbox_flutter_libs: any octo_image: ^2.0.0 path: ^1.8.3 path_provider: ^2.1.1 permission_handler: ^11.1.0 rxdart: ^0.28.0 scrollable_positioned_list: ^0.3.8 share_plus: ^10.0.0 synchronized: ^3.1.0+1 theme_tailor_annotation: ^3.0.1 url_launcher: ^6.2.1 uuid: ^4.2.1 webview_flutter: ^4.4.2 bubble_box: ^0.5.3 provider: ^6.1.2 rive: ^0.13.14 fluttertoast: ^8.2.8 flutter_local_notifications: ^18.0.1 timezone: ^0.9.0 connectivity_plus: ^6.0.5 gaimon: ^1.3.2 json_annotation: ^4.9.0 flutter_animate: ^4.5.1 firebase_performance: ^0.10.0+11 in_app_purchase_storekit: ^0.3.20+2 audioplayers: ^6.1.0 duration: ^4.0.3

dependency_overrides:
shared_preferences_android: '2.4.0'

Replace this line with the contents of your `flutter pub deps -- --style=compact`.

Additional context and comments

No response

@centy centy added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Feb 4, 2025
@SelaseKay SelaseKay added plugin: auth platform: android Issues / PRs which are specifically for Android. labels Feb 4, 2025
@SelaseKay
Copy link
Contributor

Hi @centy, I'm unable to reproduce this issue with the firebase_auth example app. Kindly provide a complete minimal example reproducing this issue. Also, you could reference the example app to ensure you're not missing anything in your implementation.

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 4, 2025
@centy
Copy link
Author

centy commented Feb 4, 2025

Is there any way to turn on any verbose logging?

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 4, 2025
@SelaseKay
Copy link
Contributor

Hi @centy, I'm not entirely sure on what you're trying to achieve with the verbose logging. Were you able to test with the firebase_auth example app I linked?

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 4, 2025
@centy
Copy link
Author

centy commented Feb 4, 2025

Hi @centy, I'm not entirely sure on what you're trying to achieve with the verbose logging. Were you able to test with the firebase_auth example app I linked?

I found guilty code:
Look on compute ...

`
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);

unawaited(
  compute(
    (args) async {
      final token = args['token']! as RootIsolateToken;

      BackgroundIsolateBinaryMessenger.ensureInitialized(token);
      await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

      Future.delayed(const Duration(seconds: 200), () {});
    },
    {
      'token': RootIsolateToken.instance,
    },
  ),
);

FirebaseAuth.instance.authStateChanges().listen((user) async {
  /*never called*/
});

`

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 4, 2025
@SelaseKay
Copy link
Contributor

I'll close this now, as it isn't a bug in FlutterFire.

@SelaseKay SelaseKay added the resolution: user This was a user issue, e.g. invalid configuration or code. label Feb 4, 2025
@centy
Copy link
Author

centy commented Feb 4, 2025

@SelaseKay why are you closing it?

I have to initialize Firebase in izolate and login not working then

@SelaseKay
Copy link
Contributor

You don't need to initialize firebase in an isolate. You can do that in your main function. Kindly reference the firebase_auth example app.

@centy
Copy link
Author

centy commented Feb 4, 2025

@SelaseKay Unfortunately I have to because other features of Firebase are not working in isolate

E/flutter ( 9709): [ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
E/flutter ( 9709): #0 MethodChannelFirebase.app (package:firebase_core_platform_interface/src/method_channel/method_channel_firebase.dart:195:5)
E/flutter ( 9709): #1 Firebase.app (package:firebase_core/src/firebase.dart:79:41)
E/flutter ( 9709): #2 FirebasePerformance.instance (package:firebase_performance/src/firebase_performance.dart:21:47)
E/flutter ( 9709): #3 PictureInfoRepository._addNewPictures (package:pixyfy_color_by_number/core/repositories/picture_info_repository.dart:360:39)
E/flutter ( 9709): #4 PictureInfoRepository.fetchPicturesFromServer.. (package:pixyfy_color_by_number/core/repositories/picture_info_repository.dart:83:19)
E/flutter ( 9709):
E/flutter ( 9709): #5 _RemoteRunner._run (dart:isolate:1100:18)
E/flutter ( 9709):

@SelaseKay SelaseKay reopened this Feb 4, 2025
@SelaseKay SelaseKay removed the resolution: user This was a user issue, e.g. invalid configuration or code. label Feb 4, 2025
@SelaseKay
Copy link
Contributor

Could you provide a complete example reproducing this issue?

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 4, 2025
@centy
Copy link
Author

centy commented Feb 4, 2025

void main() {

  await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
  unawaited(
  compute(
    (args) async {
      final token = args['token']! as RootIsolateToken;

      BackgroundIsolateBinaryMessenger.ensureInitialized(token);
      await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

      /* for example

      final trace = FirebasePerformance.instance.newTrace('load_images');
    await trace.start();
    await trace.stop();

      */

      Future.delayed(const Duration(seconds: 200), () {});
    },
    {
      'token': RootIsolateToken.instance,
    },
  ),
);

FirebaseAuth.instance.authStateChanges().listen((user) async {
  /*never called*/
});

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Text('Hello World'),
    );
  }
}

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 4, 2025
@SelaseKay
Copy link
Contributor

I'm still unable to reproduce this issue. I followed these steps

  • Logged in with Google
  • Terminated app
  • Opened the app again
  • Verified that authChanges().listen was triggered with the currentUser.

Additionally, I made a few slight modifications to the sample you shared. Please have a look and see if it helps.

import 'dart:async';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_auth_example/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  FirebaseAuth.instance.authStateChanges().listen((user) async {
    print('Auth state changed: ${user?.uid}');
  });

  unawaited(
    compute(
      (args) async {
        final token = args['token']! as RootIsolateToken;
        BackgroundIsolateBinaryMessenger.ensureInitialized(token);
        
        await Firebase.initializeApp(
          options: DefaultFirebaseOptions.currentPlatform,
        );

        await Future.delayed(const Duration(seconds: 200));
      },
      {
        'token': RootIsolateToken.instance,
      },
    ),
  );

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  bool _isLoading = false;

  Future<void> _signInWithGoogle() async {
    try {
      setState(() {
        _isLoading = true;
      });

      // Start the Google Sign-In process
      final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
      if (googleUser == null) return;

      // Obtain auth details from request
      final GoogleSignInAuthentication googleAuth = await googleUser.authentication;

      // Create credential
      final credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      // Sign in to Firebase with the Google credential
      await _auth.signInWithCredential(credential);
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Sign in failed: ${e.toString()}')),
      );
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  Future<void> _signOut() async {
    try {
      setState(() {
        _isLoading = true;
      });

      await Future.wait([
        _auth.signOut(),
        _googleSignIn.signOut(),
      ]);
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Sign out failed: ${e.toString()}')),
      );
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Show user info if logged in
            StreamBuilder<User?>(
              stream: _auth.authStateChanges(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  final user = snapshot.data!;
                  return Column(
                    children: [
                      CircleAvatar(
                        backgroundImage: user.photoURL != null 
                          ? NetworkImage(user.photoURL!) 
                          : null,
                        radius: 40,
                        child: user.photoURL == null 
                          ? const Icon(Icons.person, size: 40) 
                          : null,
                      ),
                      const SizedBox(height: 16),
                      Text(user.displayName ?? 'User'),
                      Text(user.email ?? ''),
                      const SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: _isLoading ? null : _signOut,
                        child: _isLoading 
                          ? const SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Text('Sign Out'),
                      ),
                    ],
                  );
                }
                return ElevatedButton.icon(
                  onPressed: _isLoading ? null : _signInWithGoogle,
                  icon: _isLoading 
                    ? const SizedBox(
                        width: 20,
                        height: 20,
                        child: CircularProgressIndicator(strokeWidth: 2),
                      )
                    : Image.network(
                        'https://developers.google.com/identity/images/g-logo.png',
                        height: 24,
                      ),
                  label: const Text('Sign in with Google'),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 5, 2025
@centy
Copy link
Author

centy commented Feb 6, 2025

@SelaseKay I made several tests and:

Moving FirebaseAuth.instance.authStateChanges() before second initialization cause that this event triggers once. Unfortunately right after second init will trigger it stops receiving any events for example when user logs out.

It seems that calling Firebase.initializeApp brokes previous calls silently is whole app.

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Feb 6, 2025
@SelaseKay
Copy link
Contributor

Hi @centy, you are right. The second initialization within the isolate seems to interrupt authStateChanges.listen, preventing it from receiving events. we'll investigate this further.

@SelaseKay
Copy link
Contributor

Hi @centy, I've made some changes to the example I shared earlier. Kindly try it out to see if it resolves your issue

import 'dart:async';

import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_auth_example/firebase_options.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  unawaited(
    compute(
      (args) async {

        final token = args['token']! as RootIsolateToken;
        BackgroundIsolateBinaryMessenger.ensureInitialized(token);

        await Firebase.initializeApp(
          options: DefaultFirebaseOptions.currentPlatform,
        );

        await Future.delayed(const Duration(seconds: 200));
      },
      {
        'token': RootIsolateToken.instance,
      },
    ),
  );


    await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );


  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final GoogleSignIn _googleSignIn = GoogleSignIn();
  bool _isLoading = false;

  Future<void> _signInWithGoogle() async {
    try {
      setState(() {
        _isLoading = true;
      });

      final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
      if (googleUser == null) return;

      final GoogleSignInAuthentication googleAuth =
          await googleUser.authentication;

      final credential = GoogleAuthProvider.credential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );

      await _auth.signInWithCredential(credential);
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Sign in failed: ${e.toString()}')),
      );
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  Future<void> _signOut() async {
    try {
      setState(() {
        _isLoading = true;
      });

      await Future.wait([
        _auth.signOut(),
        _googleSignIn.signOut(),
      ]);
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Sign out failed: ${e.toString()}')),
      );
    } finally {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  @override
  void initState() {
    super.initState();
        FirebaseAuth.instance.authStateChanges().listen((user) async {
      print('Auth state changed: ${user?.uid}');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            StreamBuilder<User?>(
              stream: _auth.authStateChanges(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  final user = snapshot.data!;
                  return Column(
                    children: [
                      CircleAvatar(
                        backgroundImage: user.photoURL != null
                            ? NetworkImage(user.photoURL!)
                            : null,
                        radius: 40,
                        child: user.photoURL == null
                            ? const Icon(Icons.person, size: 40)
                            : null,
                      ),
                      const SizedBox(height: 16),
                      Text(user.displayName ?? 'User'),
                      Text(user.email ?? ''),
                      const SizedBox(height: 16),
                      ElevatedButton(
                        onPressed: _isLoading ? null : _signOut,
                        child: _isLoading
                            ? const SizedBox(
                                width: 20,
                                height: 20,
                                child:
                                    CircularProgressIndicator(strokeWidth: 2),
                              )
                            : const Text('Sign Out'),
                      ),
                    ],
                  );
                }
                return ElevatedButton.icon(
                  onPressed: _isLoading ? null : _signInWithGoogle,
                  icon: _isLoading
                      ? const SizedBox(
                          width: 20,
                          height: 20,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        )
                      : Image.network(
                          'https://developers.google.com/identity/images/g-logo.png',
                          height: 24,
                        ),
                  label: const Text('Sign in with Google'),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

@SelaseKay SelaseKay added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Feb 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked: customer-response Waiting for customer response, e.g. more information was requested. platform: android Issues / PRs which are specifically for Android. plugin: auth type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants