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]: Auth persistence not working as expected on Flutter web in Safari. #13536

Open
1 task done
vincekruger opened this issue Oct 22, 2024 · 2 comments
Open
1 task done
Labels
Needs Attention This issue needs maintainer attention. platform: web Issues / PRs which are specifically for web. plugin: auth type: bug Something isn't working

Comments

@vincekruger
Copy link

Is there an existing issue for this?

  • I have searched the existing issues.

Which plugins are affected?

Auth

Which platforms are affected?

No response

Description

I am posting this issue as it may be related to how Firebase Auth interacts with Safari’s session or local storage mechanisms, which appear to behave differently from other browsers. Testing with a simple Flutter web app using Firebase Auth (Phone Number Auth), I have encountered an issue specific to Safari regarding user session persistence. While the app correctly maintains the user’s session across page refreshes in Chrome and Firefox, Safari signs the user out upon refresh.

I have also tested this behavior using both a static local development port and a Firebase Hosting deployment, to rule out any local environment-related issues. The problem persists in both environments, which suggests it is not related to local hosting or configuration.

Observed behaviour

  • In Chrome and Firefox, the user session is preserved after refreshing the page. The user remains signed in.
  • In Safari, the session does not persist after a refresh. The user is signed out and prompted to log in again.
Simple Test App
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';

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

  FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
  FirebaseAuth.instance.setPersistence(Persistence.INDEXED_DB);
  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> {
  late User user;
  String mobileNumber = "xxxxxx";

  @override
  void initState() {
    super.initState();

    FirebaseAuth.instance.authStateChanges().listen((User? user) {
      if (user == null) {
        print('User is currently signed out!');
      } else {
        print('User is signed in!');
        user = user;
      }
    });
  }

  @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: <Widget>[
            StreamBuilder(
                stream: FirebaseAuth.instance.authStateChanges(),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return CircularProgressIndicator();
                  }
                  if (snapshot.hasError) {
                    return Text('Error: ${snapshot.error}');
                  }
                  if (snapshot.hasData) {
                    return Text('User: ${snapshot.data}');
                  }
                  return Text('No user');
                }),
          ],
        ),
      ),
      floatingActionButton: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          FloatingActionButton(
            onPressed: () async {
              ConfirmationResult confirmationResult = await FirebaseAuth
                  .instance
                  .signInWithPhoneNumber(mobileNumber);

              await _showMyDialog(confirmationResult);
            },
            child: const Icon(Icons.login),
          ),
          const SizedBox(height: 10),
          FloatingActionButton(
            onPressed: () {
              if (FirebaseAuth.instance.currentUser != null) {
                user = FirebaseAuth.instance.currentUser!;
              }
            },
            tooltip: 'Check auth',
            child: const Icon(Icons.refresh),
          ),
        ],
      ),
    );
  }

  Future<void> _showMyDialog(ConfirmationResult confirmationResult) async {
    TextEditingController controller = TextEditingController();
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // user must tap button!
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('AlertDialog Title'),
          content: TextField(
            controller: controller,
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('Check'),
              onPressed: () async {
                UserCredential userCredential =
                    await confirmationResult.confirm(controller.text);
                print(userCredential);
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }
}
Flutter Doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on macOS 15.0.1 24A348 darwin-arm64, locale en-ES)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 16.0)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.2)
[✓] VS Code (version 1.94.2)
[✓] Connected device (5 available)
[✓] Network resources

• No issues found!

Reproducing the issue

  1. launch app provided.
  2. Sign in with a test user on all browsers in at least two tabs each
  3. Refresh the pages in Safari, Chrome, and Firefox.
  4. Compare the behaviour between browsers.

Firebase Core version

3.6.0

Flutter Version

stable, 3.24.3, on macOS 15.0.1 24A348

Relevant Log Output

No response

Flutter dependencies

Expand Flutter dependencies snippet
Dart SDK 3.5.3
Flutter SDK 3.24.3
flutter_auth_test 1.0.0+1

dependencies:
- cupertino_icons 1.0.8
- firebase_app_check 0.3.1+4 [firebase_app_check_platform_interface firebase_app_check_web firebase_core firebase_core_platform_interface flutter]
- firebase_auth 5.3.1 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 3.6.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine]

dev dependencies:
- flutter_lints 4.0.0 [lints]
- flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math leak_tracker_flutter_testing async boolean_selector characters collection leak_tracker leak_tracker_testing material_color_utilities meta source_span stream_channel string_scanner term_glyph vm_service]

transitive dependencies:
- _flutterfire_internals 1.3.44 [collection firebase_core firebase_core_platform_interface flutter meta]
- async 2.11.0 [collection meta]
- boolean_selector 2.1.1 [source_span string_scanner]
- characters 1.3.0
- clock 1.1.1
- collection 1.18.0
- fake_async 1.3.1 [clock collection]
- firebase_app_check_platform_interface 0.1.0+38 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface]
- firebase_app_check_web 0.2.0 [_flutterfire_internals firebase_app_check_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins web]
- firebase_auth_platform_interface 7.4.7 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 5.13.2 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser meta web]
- firebase_core_platform_interface 5.3.0 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 2.18.1 [firebase_core_platform_interface flutter flutter_web_plugins meta web]
- flutter_web_plugins 0.0.0 [flutter characters collection material_color_utilities meta vector_math]
- http_parser 4.0.2 [collection source_span string_scanner typed_data]
- leak_tracker 10.0.5 [clock collection meta path vm_service]
- leak_tracker_flutter_testing 3.0.5 [flutter leak_tracker leak_tracker_testing matcher meta]
- leak_tracker_testing 3.0.1 [leak_tracker matcher meta]
- lints 4.0.0
- matcher 0.12.16+1 [async meta stack_trace term_glyph test_api]
- material_color_utilities 0.11.1 [collection]
- meta 1.15.0
- path 1.9.0
- plugin_platform_interface 2.1.8 [meta]
- sky_engine 0.0.99
- source_span 1.10.0 [collection path term_glyph]
- stack_trace 1.11.1 [path]
- stream_channel 2.1.2 [async]
- string_scanner 1.2.0 [source_span]
- term_glyph 1.2.1
- test_api 0.7.2 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph]
- typed_data 1.4.0 [collection]
- vector_math 2.1.4
- vm_service 14.2.5
- web 1.1.0

Additional context and comments

  • I tested this behavior in multiple tabs simultaneously in Chrome and Safari. In both tabs on Chrome, the session is maintained, but in Safari, it fails consistently.
  • I have checked existing issues related to persistence, but this specific scenario seems to differ from those reports.
@vincekruger vincekruger added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Oct 22, 2024
@SelaseKay SelaseKay added plugin: auth platform: web Issues / PRs which are specifically for web. labels Oct 23, 2024
@SelaseKay
Copy link
Contributor

Hi @vincekruger, I'm unable to reproduce this issue on Safari version 18.0. What version of Safari did you experience this on?

@SelaseKay SelaseKay added the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Oct 24, 2024
@vincekruger
Copy link
Author

I'm running version 18.0.1 (20619.1.26.31.7)

@google-oss-bot google-oss-bot removed the blocked: customer-response Waiting for customer response, e.g. more information was requested. label Oct 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Attention This issue needs maintainer attention. platform: web Issues / PRs which are specifically for web. plugin: auth type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants