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

Bug: Auth.auth().currentUser Returns Nil on Some Devices Despite Available User Data. #13231

Open
jesus-mg-ios opened this issue Jul 4, 2024 · 46 comments
Assignees

Comments

@jesus-mg-ios
Copy link

jesus-mg-ios commented Jul 4, 2024

Description

The Auth.auth().currentUser property consistently returns nil on specific devices, even though a logged-in user is expected. In contrast, the getStoredUser(forAccessGroup:) method intermittently returns a user object, suggesting that the user data is accessible. The behavior remains consistent across device lifecycles, where the method either returns a user object or does not, without variation. The whole extension works on a concurrent environment.

Also functions are working authenticated despite Auth.auth().currentUser is nil. State listener does not change the rules, I mean, it does not change Auth.auth().currentUser, and also does not return other than nil on those cases Auth.auth().currentUser is nil.

Reproducing the issue


I'm not sure, but maybe it more reproducible when updates happens. Because what I saw in some cases is:

Auth.auth().currentUser is nil and getStoredUser(forAccessGroup:) is also nil until the user enters on the app, then getStoredUser(forAccessGroup:) returns a value in the extension.

Even sometimes both Auth.auth().currentUser getStoredUser(forAccessGroup:) are nil until the extension restart.

Could be any kind of deadlock trying to get the keychain element?

Firebase SDK Version

10.25

Xcode Version

15.2

Installation Method

Swift Package Manager

Firebase Product(s)

Authentication

Targeted Platforms

iOS, macCatalyst

Relevant Log Output

No response

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

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

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet
Replace this line with the contents of your Podfile.lock!
@jesus-mg-ios
Copy link
Author

@rizafran any update on this? The bug has a high repro on end devices.

@rizafran
Copy link
Contributor

rizafran commented Jul 9, 2024

Thanks for reporting, @jesus-mg-ios. In order to investigate and replicate the issue, could you provide the following info:

  • Model and OS version of the affected devices
  • Sign in method you're using
  • Sample app that reproduces the issue

@jesus-mg-ios
Copy link
Author

Several ones...

  • XR, 14 Pro, 14 Pro Max, SE 3rd, 15 plus ...
  • Signing Method -> Apple Sign In
  • Right now I cannot provide you a sample. Please double check the issue related to this in which there's a crash to give you a hint about what can be happening.

@paulb777
Copy link
Member

paulb777 commented Jul 9, 2024

See this stackoverflow question and answer - https://stackoverflow.com/q/69201789/556617

@jesus-mg-ios
Copy link
Author

I've already implemented a state listener @paulb777, but it didn't resolve the issue. The state listener initially triggers with a nil value, even though the data is available in the keychain, and it never triggers again with the correct user value.

@paulb777
Copy link
Member

Does 11.0.0 (released today) make any difference?

@google-oss-bot
Copy link

Hey @jesus-mg-ios. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@yarodevuci
Copy link

yarodevuci commented Aug 7, 2024

I have the same issue on 11.0.0 .. each time i reset the app auth is nil!
resetting entitlement did not help.

Downgrading to FirebaseCore 10.29.0 (was 11.0.0) solved the issue....

Removing FirebaseAppCheckInterop
Removing FirebaseAuthInterop
Removing FirebaseCoreExtension
Removing FirebaseSharedSwift
Removing RecaptchaInterop

not sure if those files have anything to do with it? those are removed after downgrade from 11

@yarodevuci
Copy link

@jesus-mg-ios have you figured it out ?

@yarodevuci
Copy link

@rizafran
happens on any phones and simulator for me running iOS 17, can't test other OSs

Auth.auth().signIn(withEmail: email, password: xxx completion: { result, error in

Auth.auth().currentUser returns nil after app restart ..

@rizafran
Copy link
Contributor

Hi @yarodevuci, I tried to reproduce the issue using v11.0.0 on iOS 17 simulator, but my currentUser is returning a value every time I restart the app. Is it possible for you to provide a sample app that reproduces the issue?

@yarodevuci
Copy link

yarodevuci commented Aug 12, 2024

Hi @yarodevuci, I tried to reproduce the issue using v11.0.0 on iOS 17 simulator, but my currentUser is returning a value every time I restart the app. Is it possible for you to provide a sample app that reproduces the issue?

I can draft maybe a sample app yes, do you know if between 10 and 11 version a new json config file needs to be updated?

Some people mentioned the updating their entitlements file helped too, so I am not sure if from brand new project issue does not exist, compared to older project

@rizafran
Copy link
Contributor

@yarodevuci, may I know which json config file you're referring to?

@yarodevuci
Copy link

@yarodevuci, may I know which json config file you're referring to?

GoogleService-Info.plist

@rizafran
Copy link
Contributor

Hi @yarodevuci, there's no need to update in your GoogleService-Info.plist file if you're updating to v11.0.

@yarodevuci
Copy link

yarodevuci commented Aug 26, 2024

@rizafran here is my update

I use to check in AppDelegate Auth.auth().currentUser != nil ... but now Auth.auth().currentUser is nil each time ..

I tried

Auth.auth().addStateDidChangeListener { auth, user in
         //Auth.auth().currentUser  is not nil here anymore
}

So I can't no longer use direct Auth.auth().currentUser in AppDelegate?

@minhnguyen-iosdev
Copy link

I also faced this bug, Auth.auth().currentUser doesn't return logged in user in AppDelegate in Firebase 11.1.0.

In my apps, user is signed in anonymously when Auth.auth().currentUser == nil so now it's always logged in as anonymous.

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        
        if Auth.auth().currentUser == nil {
            Auth.auth().signInAnonymously { _, error in
                if let error = error {
                    print(error)
                }
            }
        }
        
        return true
    }

So I decided to switch back to Firebase 10.29.0.

@yarodevuci
Copy link

@rizafran can you let us know if this an actual bug or updated implementation usage is now required?

@paulb777
Copy link
Member

paulb777 commented Sep 1, 2024

We're considering adding two alternative APIs:

  1. A published property that’s an enum:
  • unknown
  • loggedIn(User)
  • loggedOut
  1. An async API that waits for the keychain to be read before returning the current user

@jesus-mg-ios
Copy link
Author

@paulb777 could be that even the user data is available, the profile data is stalled or outdated? #13571

@yarodevuci
Copy link

@paulb777 can we expect a fix in the next version ?

@paulb777
Copy link
Member

paulb777 commented Sep 5, 2024

There are two problems discussed in this issue.

  • One is that the currentUser API is inconsistent at app startup. That has always been an issue that we're exploring alternative APIs in a future release.
  • The other is that the recommended workaround for the first issue is to use a listener. There is a report that the listener is not working correctly, but we have not reproduced that issue.

We don't yet have a plan for either of these.

@jesus-mg-ios
Copy link
Author

There are two problems discussed in this issue.

  • One is that the currentUser API is inconsistent at app startup. That has always been an issue that we're exploring alternative APIs in a future release.
  • The other is that the recommended workaround for the first issue is to use a listener. There is a report that the listener is not working correctly, but we have not reproduced that issue.

We don't yet have a plan for either of these.

if this is true @paulb777 , then when I request the currentUser after some time (e.g., 2 minutes after app launch), it should be updated. However, it seems that this is not always the case. For example, after changing the displayName within the same app, and restart it again, sometimes the displayName reverts to the old one and no changes are made along the app lifecycle to this property, even the reload function for the current user doesn't always work as expected, and only logging out and back in resolves it.

@paulb777
Copy link
Member

paulb777 commented Sep 7, 2024

@jesus-mg-ios A repro case of a change getting reverted would be helpful

@bryandubno
Copy link

@paulb777 I think there's actually a change in logic (or unintended consequence) going on between 10.29.0 and 11.0.0. With the use of @synchronized in the previous 10.x codebase, the cached user is being read from disk and stored as currentUser before configure completes, which allows us to make use of the cached authenticated user.

In 11.x, configure completes without the authenticated user (even if there's one cached on disk). If developers have been creating an anonymous user based on the state of current user after configure completes, we'll improperly create another anonymous user.

@Pigpocket
Copy link

Any update on this? I cannot get the user from auth.currentUser or auth.getStoredUser on version 11.2.0.

@bryandubno
Copy link

I had to downgrade until 11.x mimics the 10.x behavior

@ncooke3 ncooke3 assigned ncooke3 and unassigned rizafran Sep 30, 2024
@Pigpocket
Copy link

I still get nil for auth.currentUser when trying to delete anonymous users on all 10.x versions.

@paulb777
Copy link
Member

paulb777 commented Oct 2, 2024

@Pigpocket Does the addStateDidChangeListener API help? https://firebase.google.com/docs/auth/ios/start#listen_for_authentication_state

@raho
Copy link

raho commented Oct 17, 2024

Using Firebase SDK 11.3.0 I observe that addStateDidChangeListener initially callbacks with user=nil immediately followed by non-nil user data. I was testing on a real device (iPad) when NOT attached to the Xcode debugger (but still a debug version installed using Xcode). When the app was started using Xcode it properly provided the non-nil user on first listener callback.

@tsjamm
Copy link

tsjamm commented Nov 13, 2024

We've been seeing similar issues of currentUser not being available on an App I work on. After a bit of analysis, it could be due to a combination of:

  1. Using a Keychain User Access Group
  2. iOS App Pre-warming - if the auth is configured with access group in AppDelegate's didFinishLaunchingWithOptions, it might run even when device is locked, so keychain may not be accessible.
  3. The discussion above where configure call completes without currentUser being available in 11.x

I see a recent PR #14067
@paulb777 Would this handle the app pre-warming scenarios where keychain is not accessible when device is locked?

@yoching
Copy link

yoching commented Nov 15, 2024

Still happening on my project and cannot upgrade to 11.x. Are there any ways to avoid this?

@bryandubno
Copy link

Same here. Really hoping they look at this: #13231 (comment)

@jesus-mg-ios
Copy link
Author

Please @yoching, @bryandubno, @tsjamm, @raho, @Pigpocket, @dfmuir @yarodevuci @unxavi upvote the issue description to give it more visibility.

@yarodevuci
Copy link

yarodevuci commented Nov 16, 2024

Please @yoching, @bryandubno, @tsjamm, @raho, @Pigpocket, @dfmuir @yarodevuci @unxavi upvote the issue description to give it more visibility.

Firebase team is aware of the issue, but I feel like they not gonna do a fix for this...

@jesus-mg-ios
Copy link
Author

I hope they will do it, because it is a critical part of their SDK. @ncooke3, any updates on this? Do we have an ETA for a solution or any pathway to address it?

@ncooke3
Copy link
Member

ncooke3 commented Nov 18, 2024

Apologies for the delay everyone, and thank you for your patience. I'll be looking into this more this week.

@ncooke3
Copy link
Member

ncooke3 commented Nov 19, 2024

Hi everyone, thanks again for your patience. So far, I was able to make two fixes that should address some of the situations described in this thread. Theses were case related to updating from 10.x to 11.x (e.g. @bryandubno's #13231 (comment)).

I'm still looking into the original case that existed on 10.25.0 (see OP). @jesus-mg-ios, a couple questions to help my repro attempts:

  1. an "extension" is mentioned, is this an app extension?
  2. FirebaseApp configured in applicationDidFinishLaunching or somewhere else?
  3. Where is currentUser first accessed? (in applicationDidFinishLaunching or somewhere else?)
  4. is Auth.auth().useUserAccessGroup(_ accessGroup: String) used and, if so, where in relation to FirebaseApp.configure() and Auth.auth().currentUser?
  5. is iCloud keychain sharing being used Auth.auth().shareAuthStateAcrossDevices = true

At this time, it's unclear to me if app pre-warming is the culprit or an SDK threading issue.

@jesus-mg-ios
Copy link
Author

jesus-mg-ios commented Nov 19, 2024

  1. Yes, it is an app extension
  2. Being an app extension, the applicationDidFinishLaunching is not available. In the main app the FirebaseApp is configured in the applicationDidFinishLaunching.
  3. In the app extension life cycle, first access after initialize, and then few times during hours, the value is nil. The Auth.auth().useUserAccessGroup is correct when this value is nil.
FirebaseApp.configure()
try? Auth.auth().useUserAccessGroup(appGroup)
  1. No, the Auth.auth().shareAuthStateAcrossDevices is not set

@ncooke3
Copy link
Member

ncooke3 commented Nov 20, 2024

@jesus-mg-ios, a couple more questions to help guide my setup

  1. Which app extension type are you using? (e.g. widget)
  2. Can you describe more about where I could replicate the "first access after initialize" access?

@jesus-mg-ios
Copy link
Author

jesus-mg-ios commented Nov 20, 2024

  1. It is the Packet Tunnel Provider -> Network Extensions, VPN.
  2. In the NEPacketTunnelProvider init method, after calling FirebaseApp.configure(), I attempt to change the user group. If successful, I access Auth.auth().currentUser. If I am unable to change the user group (which happens occasionally), I retry after a random time delay. Even If I cannot change the user group, then I tried to add the listener in the same init, with the same auth object result, nil.

@ncooke3
Copy link
Member

ncooke3 commented Nov 20, 2024

@jesus-mg-ios, this is difficult for me to replicate, but I have a suspicion that this may be due to the app extension being prewarmed by the system.

Setting the user access group will write the given group to user defaults. If the NEPacketTunnelProvider's initializer is called during prewarming, my hunch is that setting the user access group may not successfully write to user defaults. Successive calls to Auth.auth().currentUser would return nil because the Auth SDK wouldn't include the desired access group when looking up the user.

I think a first step would be to confirm that the Auth.auth().currentUser is unexpectedly nil only when NEPacketTunnelProvider.init() is being run under prewarming conditions. In the NEPacketTunnelProvider.init(), prewarming can be checked like:

let isPrewarming = ProcessInfo.processInfo.environment["ActivePrewarm"] == "1"

I would recommend adding logs to understand if the unexpected behavior is happening when isPrewarming is true.

It doesn't look like prewarming can be reliably reproduced, but if you're able to intermittently reproduce the issue, there is a good chance the device's OS may try prewarming the extension if it's frequently used.

@jesus-mg-ios
Copy link
Author

Thanks @ncooke3, I will take a look at it in a few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests