firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.62k stars 1.47k forks source link

`fetchSignInMethodsForEmail` returning `nil` when email has providers associated. #11810

Closed russellwheatley closed 11 months ago

russellwheatley commented 1 year ago

Description

Running fetchSignInMethodsForEmail returns nil even when there are providers associated with the email account.

Firebase documentation: https://firebase.google.com/docs/reference/ios/firebaseauth/api/reference/Classes/FIRAuth#-fetchsigninmethodsforemail:completion:

I expect an array with the associated providers for the given email address.

Reproducing the issue

Setup the following API in your app with relevant Firebase setup:

[[FIRAuth auth] fetchSignInMethodsForEmail:@"EMAIL ADDRESS WITH PROVIDER ASSOCIATED"
                        completion:^(NSArray<NSString *> *_Nullable providers,
                                     NSError *_Nullable error) {
                          if (error != nil) {
                            NSLog(@"error");
                          } else {
                            if (providers == nil) {
                              NSLog(@"providers is nil");
                            } else {
                              NSLog(@"providers: %@", providers);
                            }
                          }
                        }];

Replace the "EMAIL ADDRESS WITH PROVIDER ASSOCIATED" with an email address that has providers associated in your Firebase console.

Firebase SDK Version

10.15

Xcode Version

14.3.1

Installation Method

CocoaPods

Firebase Product(s)

Authentication

Targeted Platforms

iOS

Relevant Log Output

There are no relevant logs outputted with `-FIRDebugEnabled` from app boot up or when executing the API.

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet
```json Replace this line with the contents of your Package.resolved. ```

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
```yml PODS: - AppAuth (1.6.2): - AppAuth/Core (= 1.6.2) - AppAuth/ExternalUserAgent (= 1.6.2) - AppAuth/Core (1.6.2) - AppAuth/ExternalUserAgent (1.6.2): - AppAuth/Core - Firebase/Auth (10.15.0): - Firebase/CoreOnly - FirebaseAuth (~> 10.15.0) - Firebase/CoreOnly (10.15.0): - FirebaseCore (= 10.15.0) - Firebase/Messaging (10.15.0): - Firebase/CoreOnly - FirebaseMessaging (~> 10.15.0) - firebase_auth (4.9.0): - Firebase/Auth (= 10.15.0) - firebase_core - Flutter - firebase_core (2.15.1): - Firebase/CoreOnly (= 10.15.0) - Flutter - firebase_messaging (14.6.7): - Firebase/Messaging (= 10.15.0) - firebase_core - Flutter - FirebaseAppCheckInterop (10.15.0) - FirebaseAuth (10.15.0): - FirebaseAppCheckInterop (~> 10.0) - FirebaseCore (~> 10.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - GoogleUtilities/Environment (~> 7.8) - GTMSessionFetcher/Core (< 4.0, >= 2.1) - RecaptchaInterop (~> 100.0) - FirebaseCore (10.15.0): - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Logger (~> 7.8) - FirebaseCoreInternal (10.15.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - FirebaseInstallations (10.15.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) - FirebaseMessaging (10.15.0): - FirebaseCore (~> 10.0) - FirebaseInstallations (~> 10.0) - GoogleDataTransport (~> 9.2) - GoogleUtilities/AppDelegateSwizzler (~> 7.8) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Reachability (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - nanopb (< 2.30910.0, >= 2.30908.0) - Flutter (1.0.0) - google_sign_in_ios (0.0.1): - Flutter - GoogleSignIn (~> 6.2) - GoogleDataTransport (9.2.5): - GoogleUtilities/Environment (~> 7.7) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) - GoogleSignIn (6.2.4): - AppAuth (~> 1.5) - GTMAppAuth (~> 1.3) - GTMSessionFetcher/Core (< 3.0, >= 1.1) - GoogleUtilities/AppDelegateSwizzler (7.11.5): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - GoogleUtilities/Environment (7.11.5): - PromisesObjC (< 3.0, >= 1.2) - GoogleUtilities/Logger (7.11.5): - GoogleUtilities/Environment - GoogleUtilities/Network (7.11.5): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - "GoogleUtilities/NSData+zlib (7.11.5)" - GoogleUtilities/Reachability (7.11.5): - GoogleUtilities/Logger - GoogleUtilities/UserDefaults (7.11.5): - GoogleUtilities/Logger - GTMAppAuth (1.3.1): - AppAuth/Core (~> 1.6) - GTMSessionFetcher/Core (< 3.0, >= 1.5) - GTMSessionFetcher/Core (2.3.0) - nanopb (2.30909.0): - nanopb/decode (= 2.30909.0) - nanopb/encode (= 2.30909.0) - nanopb/decode (2.30909.0) - nanopb/encode (2.30909.0) - PromisesObjC (2.3.1) - RecaptchaInterop (100.0.0) DEPENDENCIES: - firebase_auth (from `.symlinks/plugins/firebase_auth/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - Flutter (from `Flutter`) - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`) SPEC REPOS: trunk: - AppAuth - Firebase - FirebaseAppCheckInterop - FirebaseAuth - FirebaseCore - FirebaseCoreInternal - FirebaseInstallations - FirebaseMessaging - GoogleDataTransport - GoogleSignIn - GoogleUtilities - GTMAppAuth - GTMSessionFetcher - nanopb - PromisesObjC - RecaptchaInterop EXTERNAL SOURCES: firebase_auth: :path: ".symlinks/plugins/firebase_auth/ios" firebase_core: :path: ".symlinks/plugins/firebase_core/ios" firebase_messaging: :path: ".symlinks/plugins/firebase_messaging/ios" Flutter: :path: Flutter google_sign_in_ios: :path: ".symlinks/plugins/google_sign_in_ios/ios" SPEC CHECKSUMS: AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570 Firebase: 66043bd4579e5b73811f96829c694c7af8d67435 firebase_auth: 978da643e4c50d0850762c77cd92a534bccfdb04 firebase_core: e617553c3f3cad53131d5679e3ca86fb336100d9 firebase_messaging: 7e286d6a66bc283b1a3dbf5444b8561e1cd05807 FirebaseAppCheckInterop: a8c555b1c2db1d9445e6c3a08a848167ddb7eb51 FirebaseAuth: a55ec5f7f8a5b1c2dd750235c1bb419bfb642445 FirebaseCore: 2cec518b43635f96afe7ac3a9c513e47558abd2e FirebaseCoreInternal: 2f4bee5ed00301b5e56da0849268797a2dd31fb4 FirebaseInstallations: cae95cab0f965ce05b805189de1d4c70b11c76fb FirebaseMessaging: 0c0ae1eb722ef0c07f7801e5ded8dccd1357d6d4 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 google_sign_in_ios: 1256ff9d941db546373826966720b0c24804bcdd GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2 GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084 GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4 RecaptchaInterop: 7d1a4a01a6b2cb1610a47ef3f85f0c411434cb21 PODFILE CHECKSUM: 329a5fe659b48e1f9eb6aa93d909bbbadd8d6bbb COCOAPODS: 1.12.1 ```
russellwheatley commented 1 year ago

As an FYI; this API appears to work on our emulators but not when using Firebase server.

paulb777 commented 1 year ago

Hmm, I've just confirmed that the corresponding sample at https://github.com/firebase/firebase-ios-sdk/blob/master/FirebaseAuth/Tests/Sample/Sample/MainViewController%2BUser.m#L113 works for me, so not sure what is going on. We may need a full repro.

Screenshot 2023-09-15 at 8 41 09 AM

anisabboud commented 1 year ago

Related: https://github.com/firebase/firebaseui-web/issues/1040 (same issue on the web; seems to affect new projects).

Has something changed with the backend https://identitytoolkit.googleapis.com/v1/accounts:createAuthUri recently?

russellwheatley commented 1 year ago

We have another issue related to this problem. This user reports that the issue can be replicated by enabling "Create multiple accounts for each identity provider".

However, I was able to replicate across web, android & ios without it enabled. It appears to be a Firebase server issue so not sure if this is in the right repository, and apologies for flagging here.

I've created a quick web script to demonstrate.

It requires:

  1. inserting script into a html file with a button element with the ID "button-id". The html file also needs to import firebase-app and firebase-auth.
  2. Updating firebase config with your Firebase project.
  3. Adding email and password.

As a sanity check, I've also included sign-in.

import { initializeApp } from 'firebase/app';

import {
  getAuth,
  fetchSignInMethodsForEmail,
  signInWithEmailAndPassword,
  onAuthStateChanged,
} from 'firebase/auth';

var config = {
    //INSERT FIREBASE CONFIG
};

var app = initializeApp(config);

const auth = getAuth(app);

const email = 'INSERT EMAIL ADDRESS';
const password = 'INSERT PASSWORD';

onAuthStateChanged(auth, async (user) => {
  if (user) {
    console.log('user', user);
    // ...
  } else {
    console.log('Signing in.....');
    let userCred = await signInWithEmailAndPassword(
      auth,
      email,
      password
    );
    console.log('userCred', userCred);
  }
});

const button = document.getElementById('button-id');

// Attach an event listener to the button
button.addEventListener('click', async () => {
  fetchSignInMethodsForEmail(auth, email)
    .then((signInMethods) => {
    // This produces an empty array
      console.log('signInMethods', signInMethods);
    })
    .catch((error) => {
      console.log('error', error);
    });
});
paulb777 commented 1 year ago

thanks for the invsestigation @russellwheatley. Backend issue tracked internally at b/301111687

felkru commented 1 year ago

I have the same issue with the javascript web sdk, except that the promise resolves to [] instead of giving me the correct signinmethods. I need to use the feature to decide whether I should link a currently signed in, anonymous account with a new email link sign in method or if I should just sign in the existing account and throw away the old account. Would be very glad if this were to be fixed.

tolotrasamuel commented 1 year ago

@paulb777 Hello, can we downgrade to a specific version to make it work ? It blocks our authentication logic

paulb777 commented 1 year ago

@tolotrasamuel The issue is on the server side so changing the SDK will not help.

sgb-io commented 1 year ago

@paulb777 Hey, has there been any movement on this issue? It seems that implementing proper email/password auth flows has been broken for new projects for the past couple of weeks

paulb777 commented 1 year ago

@sgb-io There is ongoing progress. Hopefully, we can share something soon.

paulb777 commented 1 year ago

See https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection for context and a possible workaround

russellwheatley commented 1 year ago

I can confirm once I disabled email enumeration protection via this API call:

curl -X PATCH -d "{'email_privacy_config':{'enable_improved_email_privacy':"false"}}" \
    -H 'Authorization: Bearer ACCESS_TOKEN' \
    -H 'Content-Type: application/json' -H 'X-Goog-User-Project: PROJECT_ID' \
    "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=email_privacy_config"

The provider list returned. I would say that the project I am testing against was created before the date specified this feature would be default enabled - September 15, 2023.

I am going to put a note in the Firebase Flutter documentation here: https://firebase.google.com/docs/auth/flutter/email-link-auth#differentiating_emailpassword_from_email_link

regarding this protection and put the PR up for review.

nohe427 commented 11 months ago

Documentation updated and switch is now available in the Firebase Console

nohe427 commented 11 months ago

I believe we can close this issue @morganchen12

paulb777 commented 11 months ago

API deprecation is in progress at #12081