-
Notifications
You must be signed in to change notification settings - Fork 4k
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]: getIdToken(false) doesn't refresh the token when it's expired or returns a null token #16771
Comments
Hi @Tom3652, thanks for the report. Unfortunately, I couldn’t reproduce this issue on my end. It's unfortunate that you’re unable to reproduce it locally as well. Providing a fully reproducible sample would be incredibly helpful in diagnosing the problem. |
Hi @SelaseKay yes i know believe me i wish i had a reproductible use case... Note : i have two ideas for this problem, i have put only the first one in my next release tonight :
Future<String> getIdToken({bool forceRefresh = false}) async {
String idToken = "";
try {
if (_currentUser != null) {
idToken = await FirebaseAuth.instance.currentUser!.getIdToken(forceRefresh) ?? "";
}
} catch (error) {
print("Could not get id token of user $error");
// This records a Crashlytics error non fatal
AnalyticsAPI.logError(error, reason: "Could not get id token of current user");
}
if (_idToken.isEmpty && !forceRefresh) {
return initToken(forceRefresh: true);
}
return idToken;
} This way, if it's empty by any ways without forcing the refresh, it will force it and send it.
I will keep updating here if i find a solution, but once again maybe it's not a bug and that's the expected behavior and i a am simply using it in a incorrect way... Thanks for your time anyway ! |
Hello, we are experiencing the same issue, it looks like it's only reproducible on 10k+ calls, our project has a range of 10k - 40k calls. For now we are going to force the refresh token if it's empty and come back with the results. |
I have a bit more information, i have checked my crashlytics logs and seen actually plenty of logs :
So that can explain some of the logs. I wonder then if there are some real network issues or if the users are "terminating" the app during the request, but once again my backend would not be reached in that case... I have an expired token because my var So my new function looks like this : String _idToken = "";
User? get _currentUser => FirebaseAuth.instance.currentUser;
/// Handle the fact the token is refreshed
Future<void> initToken({bool forceRefresh = false}) async {
if (forceRefresh) {
LogManager.printDebug("Forcing token refresh...");
AnalyticsAPI.logEvent("refresh_id_token_forced");
}
else {
AnalyticsAPI.logEvent("refresh_id_token");
}
try {
if (_currentUser != null) {
String newToken = await _currentUser!.getIdToken(forceRefresh) ?? "";
if (newToken.isNotEmpty) {
_idToken = newToken;
}
else {
AnalyticsAPI.logError("[initToken]: New id token is empty.");
if (!forceRefresh) {
await initToken(forceRefresh: true);
}
}
}
else {
AnalyticsAPI.logError("[initToken]: Current user is null.");
}
} catch (error) {
LogManager.printDebug("Could not get id token of user $error");
AnalyticsAPI.logError(error,
reason: "Could not get id token of user.");
}
} I am going to release that tonight and see how is it going then, will keep updating. |
We're having the same issue with our app as wel. Based on user feedback we've gathered, we've found that users get signed out of the app. The following network error gets logged a couple dozen times a day (we have somewhere about ~10K to ~20K active daily users). |
Hi @Tom3652, thanks for the additional feedback. What authentication methods do you use in your app? |
Hi @SelaseKay , i am using the Sign in With Apple & with Google only. Future<LoginResult> signInWithApple() async {
AppleAuthProvider appleAuthProvider = AppleAuthProvider();
appleAuthProvider.addScope("email");
appleAuthProvider.addScope("fullName");
return _signInWithProvider(provider: appleAuthProvider);
} final GoogleSignIn _googleSignIn = GoogleSignIn(scopes: ['profile', 'email']);
Future<OAuthCredential?> _signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) return null;
debugPrint("Google user got : ${googleUser.email}");
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
debugPrint("Google auth : ${googleAuth.idToken!}");
// Create a new credential
final OAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
return credential;
}
Future<LoginResult> signInWithGoogle() async {
OAuthCredential? credential = await _signInWithGoogle();
return _signInWithProvider(credential: credential);
} Future<LoginResult> _signInWithProvider(
{AuthProvider? provider, OAuthCredential? credential}) async {
_loginResult.reset();
try {
UserCredential? userCredential = provider != null
? await FirebaseAuth.instance.signInWithProvider(provider)
: credential != null
? await FirebaseAuth.instance.signInWithCredential(credential)
: null;
if (userCredential?.user != null) {
_loginResult.onSuccess();
}
} on FirebaseAuthException {
_loginResult.setError(ErrorState.userDisabled);
} on Exception {
_loginResult.setError(ErrorState.generic);
}
return _loginResult;
} |
Faced the same issue. We are using email link sign in, google and apple. It's completely random but if it happens for a particular user, it keeps on happening. One of our prod users complained about this and we were not able to trace it down because locally it's not reproducible. I feel there were some API changes (internally) because earlier everything was working fine. We also got the user bug report around a week ago. Our use case was that we were sending the token to our backend and luckily due to backend logs, we were able to catch the bug! As of now, the only solution (assuming) is to forceRefresh |
Hi @AbhishekDoshi26, I agree. This could be coming from upstream. I've been trying to reproduce this locally but haven't made much progress. |
I am adding a new error log to the above ones still getting the ID Token :
|
Is there an existing issue for this?
Which plugins are affected?
Auth
Which platforms are affected?
Android, iOS
Description
I am not sure this is an issue with the SDK or my misunderstanding of how it works, but i have a live app with few thousands of active users.
I have daily 2 recurring error from my Cloud Monitoring Dashboard from my Cloud functions, where i use the
firebase_admin
sdk in python.ERROR:root:check_token : Illegal ID token provided: b''. ID token must be a non-empty string.
ERROR:root:check_token : Token expired, 1732476868 < 1732476998
The dart code called before each of my Cloud Function request is :
And i put the
idToken
in theheaders
of the HTTP request (i have public endpoints), not using thecloud_function
package of firebase for Flutter.The python code that throws the error is simply :
Now, this means either
getIdToken(false)
gives an outdated token, or a null one and my dart code returns an empty string instead.In my
Crashlytics
dashboard i have no trace of any error coming from theAnalyticsAPI.logError(error, reason: "Could not get id token of current user");
so i am guessing thegetIdToken()
method is handling errors itself and returnsNull
in that case.The documentation states :
Questions / bugs :
-> I have checked around on internet / SO / ChatGPT and the clock's phone could lead to this problem, so i have started to believe that when the app is backgrounded for a long time without causing an app restart, is it possible it may delay the local checks for the clock and get "non-expired" token for the local auth but that is actually expired ?
-> As a workaround, i have tried to use the second part of the documentation :
And i am calling
getIdToken(forceRefresh: true)
instead of false on theAppLifeCycleState.resumed
case to refresh the tokens more often. This actually didn't change anything...Note : i am guessing that calling
getIdToken(forceRefresh: true)
for each requests will increase the network response time as it consumes an extra call to Firebase auth backend right ?-> If the expiration is not a bug, how to deal with that ?
getIdToken(false)
returnsNull
with my code, it happens actually very often but i don't know the reason, and it's not obvious to guess what is going on here unfortunately :/Reproducing the issue
This is actually very hard to reproduce since i have never encounter this error myself when i debug or even when i use my own app live version... And especially if this is not a real bug but rather a behavior that i don't fully understand.
Firebase Core version
3.8.0
Flutter Version
3.24.5
Relevant Log Output
No response
Flutter dependencies
Expand
Flutter dependencies
snippetAdditional context and comments
No response
The text was updated successfully, but these errors were encountered: