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] FirebaseAuthException not thrown when first logged in with Facebook followed by Google #4612

Closed
nelsyeung opened this issue Jan 10, 2021 · 2 comments · Fixed by #5148
Assignees
Labels
plugin: auth type: documentation Improvements or additions to documentation

Comments

@nelsyeung
Copy link

Bug report

A FirebaseAuthException is not thrown when first logged in with Facebook, followed by Google, while both accounts have the same email address. The Google login would then replaces the already existing Facebook account (i.e., in the Firebase console, the account will only show Google as the provider.).

However, when first logged in with Google, followed by Facebook, the correct FirebaseAuthException is thrown with account-exists-with-different-credential, and hence can be linked correct (i.e., in the Firebase console, the account will show both Google and Facebook as the provider).

Steps to reproduce

The Facebook and Google sign in methods:

  Future<void> signInWithFacebook() async {
    final accessToken = await _facebookAuth.login(
      permissions: facebookPermissions,
    );
    final credential = FacebookAuthProvider.credential(accessToken.token);

     await _firebaseAuth.signInWithCredential(credential);
  }

  Future<void> signInWithGoogle() async {
    final auth = await (await _googleSignIn.signIn()).authentication;
    final credential = GoogleAuthProvider.credential(
      accessToken: auth.accessToken,
      idToken: auth.idToken,
    );

     await _firebaseAuth.signInWithCredential(credential);
  }
    try {
      switch (authMethod) {
        case AuthMethod.facebook:
          await _authService.signInWithFacebook();
          break;
        case AuthMethod.google:
          await _authService.signInWithGoogle();
          break;
      }
    } on FirebaseAuthException catch (e) {
      // Place a breakpoint here
      if (e.code == 'account-exists-with-different-credential') {
        // ...
      }
    }

I currently have two buttons which call the above try-catch statements.

Execute the Facebook sign in first, followed by Google sign in, the above breakpoint will not be reached.

Execute the Google sign in first, followed by Facebook sign in, the above breakpoint will be reached and enters the if statement.

Expected behavior

A FirebaseAuthException is thrown with e.code account-exists-with-different-credential no matter the order.


Additional context

  • I have enabled "One account per email address". As shown by logged in with Google first followed by Facebook works.
  • I have enabled Email, Facebook and Google sign in providers.
  • The userCredential.additionalUserInfo.isNewUser is false during the Google sign in after Facebook, thus it doesn't actually completely overwrite the user. The user still has the same "User UID".
  • I have not tested it with any other providers, so it could simply be to do with Google's credential.

Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.5, on macOS 11.1 20C69 darwin-x64, locale en-GB)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 12.3)
[!] Android Studio (not installed)
[✓] VS Code (version 1.52.1)
[✓] Connected device (1 available)

! Doctor found issues in 1 category.

Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand
Dart SDK 2.10.4
Flutter SDK 1.22.5
eatchie 1.0.0+1

dependencies:
- animations 1.1.2 [flutter]
- cloud_firestore 0.14.4 [flutter meta quiver firebase_core firebase_core_platform_interface cloud_firestore_platform_interface cloud_firestore_web]
- firebase_analytics 6.3.0 [meta flutter firebase_core firebase_analytics_web firebase_analytics_platform_interface]
- firebase_auth 0.18.4 [meta firebase_core firebase_core_platform_interface firebase_auth_platform_interface firebase_auth_web flutter]
- firebase_core 0.5.3 [firebase_core_platform_interface flutter quiver meta firebase_core_web]
- flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine]
- flutter_facebook_auth 1.0.2+2 [flutter]
- flutter_form_builder 4.2.0 [flutter flutter_localizations date_range_picker datetime_picker_formfield dropdown_search flutter_colorpicker flutter_chips_input flutter_datetime_picker flutter_touch_spin flutter_typeahead intl rating_bar signature validators]
- flutter_localizations 0.0.0 [flutter intl characters collection meta path typed_data vector_math]
- flutter_secure_storage 3.3.5 [meta flutter]
- freezed 0.12.6 [analyzer build build_config meta source_gen freezed_annotation]
- google_sign_in 4.5.6 [google_sign_in_platform_interface flutter meta google_sign_in_web]
- googleapis 0.56.1 [_discoveryapis_commons http]
- googleapis_auth 0.2.12 [crypto http]
- http 0.12.2 [http_parser path pedantic]
- intl 0.16.1 [path]
- json_annotation 3.1.1
- provider 4.3.2+2 [flutter nested collection]
- sliding_up_panel 1.0.2 [flutter]

dev dependencies:
- build_runner 1.10.9 [args async build build_config build_daemon build_resolvers build_runner_core code_builder collection crypto dart_style glob graphs http_multi_server io js logging meta mime path pedantic pool pub_semver pubspec_parse shelf shelf_web_socket stack_trace stream_transform timing watcher web_socket_channel yaml]
- flutter_driver 0.0.0 [file json_rpc_2 meta path web_socket_channel vm_service_client webdriver flutter flutter_test fuchsia_remote_debug_protocol archive args async boolean_selector characters charcode clock collection convert crypto fake_async matcher platform process pub_semver source_span stack_trace stream_channel string_scanner sync_http term_glyph test_api typed_data vector_math]
- flutter_launcher_icons 0.8.1 [image args yaml path]
- flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data]
- json_serializable 3.5.1 [analyzer build build_config json_annotation meta path source_gen]
- mockito 4.1.3 [analyzer build code_builder collection dart_style matcher meta source_gen test_api]
- pedantic 1.10.0-nullsafety.2
- test 1.16.0-nullsafety.5 [analyzer async boolean_selector coverage http http_multi_server io js node_preamble package_config path pedantic pool shelf shelf_packages_handler shelf_static shelf_web_socket source_span stack_trace stream_channel typed_data web_socket_channel webkit_inspection_protocol yaml test_api test_core]

transitive dependencies:
- _discoveryapis_commons 0.2.0 [http]
- _fe_analyzer_shared 12.0.0 [meta]
- analyzer 0.40.6 [_fe_analyzer_shared args cli_util collection convert crypto glob meta package_config path pub_semver source_span watcher yaml]
- archive 2.0.13 [crypto args path]
- args 1.6.0
- async 2.5.0-nullsafety.1 [collection]
- basic_utils 2.7.0-rc.4 [http logging json_annotation pointycastle convert crypto]
- boolean_selector 2.1.0-nullsafety.1 [source_span string_scanner]
- build 1.5.2 [analyzer async convert crypto logging meta path glob]
- build_config 0.4.5 [checked_yaml json_annotation meta path pubspec_parse yaml]
- build_daemon 2.1.4 [built_collection built_value http_multi_server logging pedantic path pool shelf shelf_web_socket stream_transform watcher web_socket_channel]
- build_resolvers 1.4.4 [analyzer build crypto graphs logging meta path package_config pool pub_semver]
- build_runner_core 6.1.4 [async build build_config build_resolvers collection convert crypto glob graphs json_annotation logging meta path package_config pedantic pool timing watcher yaml]
- built_collection 4.3.2 [collection quiver]
- built_value 7.1.0 [built_collection collection fixnum quiver]
- characters 1.1.0-nullsafety.3
- charcode 1.2.0-nullsafety.1
- checked_yaml 1.0.4 [json_annotation source_span yaml]
- cli_util 0.2.0 [path]
- clock 1.1.0-nullsafety.1
- cloud_firestore_platform_interface 2.2.1 [flutter meta collection firebase_core plugin_platform_interface]
- cloud_firestore_web 0.2.1+2 [flutter flutter_web_plugins http_parser meta firebase_core firebase_core_web cloud_firestore_platform_interface js]
- code_builder 3.5.0 [built_collection built_value collection matcher meta]
- collection 1.15.0-nullsafety.3
- convert 2.1.1 [charcode typed_data]
- coverage 0.14.2 [args logging package_config path source_maps stack_trace vm_service]
- crypto 2.1.5 [collection convert typed_data]
- dart_style 1.3.10 [analyzer args path source_span]
- date_range_picker 1.0.6 [flutter]
- datetime_picker_formfield 1.0.0 [flutter intl]
- dropdown_search 0.4.8 [flutter]
- fake_async 1.2.0-nullsafety.1 [clock collection]
- file 6.0.0-nullsafety.2 [meta path]
- firebase 7.3.3 [http http_parser js]
- firebase_analytics_platform_interface 1.0.3 [flutter meta]
- firebase_analytics_web 0.1.1 [flutter flutter_web_plugins firebase firebase_analytics_platform_interface meta]
- firebase_auth_platform_interface 2.1.4 [flutter meta firebase_core plugin_platform_interface]
- firebase_auth_web 0.3.2+2 [flutter flutter_web_plugins meta http_parser intl firebase_core firebase_core_web firebase_auth_platform_interface js]
- firebase_core_platform_interface 2.1.0 [flutter meta plugin_platform_interface quiver]
- firebase_core_web 0.2.1+1 [firebase_core_platform_interface flutter flutter_web_plugins meta js]
- fixnum 0.10.11
- flutter_chips_input 1.9.5 [flutter]
- flutter_colorpicker 0.3.5 [flutter]
- flutter_datetime_picker 1.4.0 [flutter]
- flutter_keyboard_visibility 4.0.2 [meta flutter_keyboard_visibility_platform_interface flutter_keyboard_visibility_web flutter]
- flutter_keyboard_visibility_platform_interface 1.0.1 [flutter meta plugin_platform_interface]
- flutter_keyboard_visibility_web 1.0.1 [flutter_keyboard_visibility_platform_interface flutter_web_plugins flutter]
- flutter_touch_spin 1.0.1 [flutter intl]
- flutter_typeahead 1.9.1 [flutter flutter_keyboard_visibility]
- flutter_web_plugins 0.0.0 [flutter characters collection meta typed_data vector_math]
- freezed_annotation 0.12.0 [collection json_annotation meta]
- fuchsia_remote_debug_protocol 0.0.0 [json_rpc_2 process web_socket_channel flutter_test flutter_driver archive args async boolean_selector charcode clock collection convert crypto fake_async file matcher meta path platform pub_semver source_span stack_trace stream_channel string_scanner sync_http term_glyph test_api typed_data vector_math vm_service_client webdriver]
- glob 1.2.0 [async collection node_io path pedantic string_scanner]
- google_sign_in_platform_interface 1.1.2 [flutter meta quiver]
- google_sign_in_web 0.9.2 [google_sign_in_platform_interface flutter flutter_web_plugins meta js]
- graphs 0.2.0
- http_multi_server 2.2.0 [async]
- http_parser 3.1.4 [charcode collection source_span string_scanner typed_data]
- image 2.1.19 [archive xml meta]
- io 0.3.4 [charcode meta path string_scanner]
- js 0.6.3-nullsafety.2
- json_rpc_2 2.2.2 [stack_trace stream_channel]
- logging 0.11.4
- matcher 0.12.10-nullsafety.1 [stack_trace]
- meta 1.3.0-nullsafety.3
- mime 0.9.7
- nested 0.0.4 [flutter]
- node_interop 1.2.1 [js]
- node_io 1.1.1 [node_interop path]
- node_preamble 1.4.12
- package_config 1.9.3 [path charcode]
- path 1.8.0-nullsafety.1
- petitparser 3.1.0 [meta]
- platform 3.0.0-nullsafety.2
- plugin_platform_interface 1.0.3 [meta]
- pointycastle 2.0.0
- pool 1.5.0-nullsafety.2 [async stack_trace]
- process 4.0.0-nullsafety.2 [file path platform]
- pub_semver 1.4.4 [collection]
- pubspec_parse 0.1.7 [checked_yaml json_annotation pub_semver yaml]
- quiver 2.1.5 [matcher meta]
- random_string 2.1.0
- rating_bar 0.2.0 [flutter]
- shelf 0.7.9 [async collection http_parser path stack_trace stream_channel]
- shelf_packages_handler 2.0.0 [path shelf shelf_static]
- shelf_static 0.2.8 [convert http_parser mime path shelf]
- shelf_web_socket 0.2.3 [shelf web_socket_channel stream_channel]
- signature 3.2.0 [flutter image]
- sky_engine 0.0.99
- source_gen 0.9.9 [analyzer async build dart_style glob meta path pedantic source_span]
- source_map_stack_trace 2.1.0-nullsafety.3 [path stack_trace source_maps]
- source_maps 0.10.10-nullsafety.2 [source_span]
- source_span 1.8.0-nullsafety.2 [charcode collection path term_glyph]
- stack_trace 1.10.0-nullsafety.1 [path]
- stream_channel 2.1.0-nullsafety.1 [async]
- stream_transform 1.2.0
- string_scanner 1.1.0-nullsafety.1 [charcode source_span]
- sync_http 0.2.0
- term_glyph 1.2.0-nullsafety.1
- test_api 0.2.19-nullsafety.2 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher]
- test_core 0.3.12-nullsafety.5 [analyzer async args boolean_selector collection coverage glob io meta package_config path pedantic pool source_map_stack_trace source_maps source_span stack_trace stream_channel vm_service yaml matcher test_api]
- timing 0.1.1+3 [json_annotation]
- typed_data 1.3.0-nullsafety.3 [collection]
- validators 2.0.1 [vin_decoder]
- vector_math 2.1.0-nullsafety.3
- vin_decoder 0.1.3 [meta basic_utils http random_string]
- vm_service 5.5.0 [meta]
- vm_service_client 0.2.6+2 [async collection json_rpc_2 pub_semver source_span stack_trace stream_channel web_socket_channel]
- watcher 0.9.7+15 [async path pedantic]
- web_socket_channel 1.1.0 [async crypto stream_channel]
- webdriver 2.1.2 [archive matcher path stack_trace sync_http]
- webkit_inspection_protocol 0.7.4 [logging]
- xml 4.5.1 [collection convert meta petitparser]
- yaml 2.2.1 [charcode collection string_scanner source_span]

@nelsyeung nelsyeung added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Jan 10, 2021
@markusaksli-nc
Copy link
Contributor

markusaksli-nc commented Jan 12, 2021

I was able to reproduce this on the latest master 1.26.0-2.0.pre.296 with

firebase_core: ^0.6.0
firebase_auth: ^0.19.0+1
google_sign_in: ^4.5.9
flutter_facebook_auth: ^2.0.0+1
flutter doctor -v
[√] Flutter (Channel master, 1.26.0-2.0.pre.296, on Microsoft Windows [Version 10.0.19041.685], locale et-EE)
    • Flutter version 1.26.0-2.0.pre.296 at C:\Development\flutter_master
    • Framework revision 737496e8db (3 hours ago), 2021-01-12 02:54:03 -0500
    • Engine revision 10cee6abcb
    • Dart version 2.12.0 (build 2.12.0-214.0.dev)

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at C:\Users\marku\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\201.6953283\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.7.7)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
    • Visual Studio Community 2019 version 16.7.30621.155
    • Windows 10 SDK version 10.0.18362.0

[√] Android Studio (version 4.1.0)
    • Android Studio at C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\201.6953283
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] Connected device (4 available)
    • SM G950F (mobile) • ce12171c51cc001c03 • android-arm64  • Android 9 (API 28)
    • Windows (desktop) • windows            • windows-x64    • Microsoft Windows [Version 10.0.19041.685]
    • Chrome (web)      • chrome             • web-javascript • Google Chrome 87.0.4280.141
    • Edge (web)        • edge               • web-javascript • Microsoft Edge 87.0.664.66

• No issues found!
Minimal reproducible code sample
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter/foundation.dart' show kIsWeb;

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(AuthExampleApp());
}

final FirebaseAuth _auth = FirebaseAuth.instance;

/// The entry point of the application.
///
/// Returns a [MaterialApp].
class AuthExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Firebase Example App',
        theme: ThemeData.dark(),
        home: SignInPage());
  }
}

/// Entrypoint example for various sign-in flows with Firebase.
class SignInPage extends StatefulWidget {
  /// The page title.
  final String title = 'Sign In & Out';

  @override
  State<StatefulWidget> createState() => _SignInPageState();
}

class _SignInPageState extends State<SignInPage> {
  User user;

  @override
  void initState() {
    _auth.userChanges().listen((event) => setState(() => user = event));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          Builder(builder: (BuildContext context) {
            return FlatButton(
              child: const Text('Sign out'),
              textColor: Theme.of(context).buttonColor,
              onPressed: () async {
                final User user = await _auth.currentUser;
                if (user == null) {
                  Scaffold.of(context).showSnackBar(const SnackBar(
                    content: Text('No one has signed in.'),
                  ));
                  return;
                }
                _signOut();
                final String uid = user.uid;
                Scaffold.of(context).showSnackBar(SnackBar(
                  content: Text(uid + ' has successfully signed out.'),
                ));
              },
            );
          })
        ],
      ),
      body: Builder(builder: (BuildContext context) {
        return ListView(
          padding: EdgeInsets.all(8),
          scrollDirection: Axis.vertical,
          children: <Widget>[
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Text(
                  user == null
                      ? 'Not signed in'
                      : 'Email: ${user.email}\n\nName: ${user.displayName}\n\nCreated: ${user.metadata.creationTime.toString()}\n\nID: ${user.uid}\n\nPhone number: ${user.phoneNumber}\n\n\nProviders: ${user.providerData.fold('', (previousValue, element) => previousValue += '\n${element.providerId} ${element.email}')}',
                ),
              ),
            ),
            _OtherProvidersSignInSection(),
          ],
        );
      }),
    );
  }

  // Example code for sign out.
  void _signOut() async {
    await _auth.signOut();
  }
}

class _OtherProvidersSignInSection extends StatefulWidget {
  _OtherProvidersSignInSection();

  @override
  State<StatefulWidget> createState() => _OtherProvidersSignInSectionState();
}

class _OtherProvidersSignInSectionState extends State<_OtherProvidersSignInSection> {
  int _selection = 0;
  String _provider = 'GitHub';

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
          padding: EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              Container(
                child: const Text('Social Authentication', style: TextStyle(fontWeight: FontWeight.bold)),
                alignment: Alignment.center,
              ),
              ElevatedButton(
                child: const Text("Sign in with Facebook"),
                onPressed: _signInWithFacebook,
              ),
              ElevatedButton(
                child: const Text("Sign in with Google"),
                onPressed: _signInWithGoogle,
              ),
              ElevatedButton(
                child: const Text("Link with Facebook"),
                onPressed: () async {
                  if (_auth.currentUser == null) {
                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text("No user signed in"),
                    ));
                    return;
                  }
                  try {
                    final result = await FacebookAuth.instance.login();
                    final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.token);
                    await _auth.currentUser.linkWithCredential(facebookAuthCredential);

                  Scaffold.of(context).showSnackBar(SnackBar(
                  content: Text("Linked with Facebook"),
                  ));
                  } catch (e) {
                  print(e);
                  Scaffold.of(context).showSnackBar(SnackBar(
                  content: Text("Failed to sign in with Facebook: ${e}"),
                  ));
                  }
                },
              ),
              ElevatedButton(
                child: const Text("Link with Google"),
                onPressed: () async {
                  if (_auth.currentUser == null) {
                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text("No user signed in"),
                    ));
                    return;
                  }
                  try {
                    final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();
                    final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
                    final GoogleAuthCredential googleAuthCredential = GoogleAuthProvider.credential(
                      accessToken: googleAuth.accessToken,
                      idToken: googleAuth.idToken,
                    );

                    await _auth.currentUser.linkWithCredential(googleAuthCredential);
                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text("Linked with Google"),
                    ));
                  } catch (e) {
                    print(e);

                    Scaffold.of(context).showSnackBar(SnackBar(
                      content: Text("Failed to sign in with Google: ${e}"),
                    ));
                  }
                },
              ),
            ],
          )),
    );
  }

// Example code of how to sign in with Facebook.
  void _signInWithFacebook() async {
    try {
      final result = await FacebookAuth.instance.login();
      final FacebookAuthCredential facebookAuthCredential = FacebookAuthProvider.credential(result.token);
      final User user = (await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential)).user;

      Scaffold.of(context).showSnackBar(SnackBar(
        content: Text("Sign In ${user.uid} with Facebook"),
      ));
    } catch (e) {
      print(e);
      Scaffold.of(context).showSnackBar(SnackBar(
        content: Text("Failed to sign in with Facebook: ${e}"),
      ));
    }
  }

  //Example code of how to sign in with Google.
  void _signInWithGoogle() async {
    try {
      UserCredential userCredential;

      if (kIsWeb) {
        GoogleAuthProvider googleProvider = GoogleAuthProvider();
        userCredential = await _auth.signInWithPopup(googleProvider);
      } else {
        final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();
        final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
        final GoogleAuthCredential googleAuthCredential = GoogleAuthProvider.credential(
          accessToken: googleAuth.accessToken,
          idToken: googleAuth.idToken,
        );
        userCredential = await _auth.signInWithCredential(googleAuthCredential);
      }

      final user = userCredential.user;
      Scaffold.of(context).showSnackBar(SnackBar(
        content: Text("Sign In ${user.uid} with Google"),
      ));
    } catch (e) {
      print(e);

      Scaffold.of(context).showSnackBar(SnackBar(
        content: Text("Failed to sign in with Google: ${e}"),
      ));
    }
  }
}

To be clear here, the issue is that when the account is created with Facebook sign-in, Google sign-in will override the provider. When done the other way around (or after Google sign-in has overridden the provider), it will throw the existing user message as expected.

After linking both providers, sign-in works just fine.

@markusaksli-nc markusaksli-nc added plugin: auth and removed Needs Attention This issue needs maintainer attention. labels Jan 12, 2021
@russellwheatley russellwheatley self-assigned this Jan 14, 2021
@russellwheatley
Copy link
Member

russellwheatley commented Feb 19, 2021

I'm afraid this is expected behaviour. For further information, please check this thread or more specifically, this comment.

In a nutshell; the Facebook provider isn't deemed trustworthy and as such, emailVerified is false. Google provider is trustworthy (who'd have known), thus emailVerified is true.

Apparently, you can work your way around this by setting emailVerified to true via the Firebase admin sdk. Once it is "verified", it will retain the provider, at least that is my understanding of the feedback on that thread.

This could probably be documented better, I've raised a low priority ticket to rectify, but we also accept PRs should you wish to see this documented sooner.

Internal ticket: INVERTASE/FF-33

@russellwheatley russellwheatley added type: documentation Improvements or additions to documentation and removed type: bug Something isn't working labels Feb 19, 2021
@firebase firebase locked and limited conversation to collaborators Apr 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
plugin: auth type: documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants