Flutter sign in with google lost authentication when the internet connection lost, how to re-auth it? - firebase

We are currently building an app that requires only google sign in and communicate with the Firebase depending on those data that we get with sign in.
The problem is this; after logging in to the app if the user lost internet connection and then re-establishes that connection without closing the app, FirebaseAuth.currentUser is not null but at the same time the user is not authenticated so the functions that i need to communicate with the DB is not working.
My question is simply this;
How do i check for the authentication and then re-authanticate the user.
My signin method is below, i tried to re-sign in every time when user enters some certain pages but that just not seemed good but does solves the problem. Is there a optimized way?
Future<String> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount? googleUser = await _googleSignIn!.signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication? googleAuth =
await googleUser!.authentication;
// Create a new credential
final GoogleAuthCredential credential = (GoogleAuthProvider.credential(
accessToken: googleAuth!.accessToken,
idToken: googleAuth.idToken,
) as GoogleAuthCredential);
// Once signed in, return the UserCredential
final UserCredential? authResult =
await _auth!.signInWithCredential(credential);
final User? user = authResult!.user;
//assert(user!.isAnonymous);
assert(await user!.getIdToken() != null);
final User? currentUser = _auth!.currentUser;
assert(user!.uid == currentUser!.uid);
return 'signInWithGoogle succeeded: $user';
}
Edit:
We were using connectivity_plus plugin so we created a listener for it and if the user changes its connection to wifi or mobile we simply re-signin them. It worked for us it may have work for you as well;
#override
void initState() {
subscription = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) {
if (result == ConnectivityResult.mobile ||
result == ConnectivityResult.wifi ||
result == ConnectivityResult.ethernet) {
Login().signInWithGoogle();
}
print("${result}");
});
// TODO: implement initState
super.initState();
}
dispose() {
super.dispose();
subscription.cancel();
}

The Flutter Firebase docs have a re-authenticate user option and it sounds quite similar to your situation.
Re-authenticate a user

Related

Cloud Firestore Read Quota [duplicate]

there guys, I do have an interesting problem here and I would be really glad if any of you it will be able to help me with that.
What's my app flow:
Register with the email, password and some other details:
User firebase in order to auth the user and create an account via email and password, at the same time I'm writing the custom data of the user to the database.
Log in the user.
That's it, that's all my basic logic, and how you can see I'm not doing any reading from the DB so far as I know.
Now... the problem is that from some weird reason when I'm registering my user I'm going to the firebase console to see the usage of my DB and I will see something like... for one user which was created I will have 1 write (which is fine as I was expected) but also 13-20 READS FROM DB.
Now that's my question, WHY on earth I have reads on firestorm when I'm doing just auth and writes?
Here it's my DB code which I'm using right now.
class DatabaseFirebase implements BaseDataBase {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
FirebaseUser _firebaseUser;
Firestore _firestore = Firestore.instance;
#override
Future<String> login(String email, String password) async {
_firebaseUser = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<String> register(String email, String password) async {
_firebaseUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<UserData> getCurrentUser() async {
if (_firebaseUser == null)
_firebaseUser = await _firebaseAuth.currentUser();
UserData user = UserData();
user.email = _firebaseUser?.email;
user.name = _firebaseUser?.displayName;
return user;
}
#override
Future<void> logout() async {
_firebaseAuth.signOut();
}
#override
Future<void> onAuthStateChanged(void Function(FirebaseUser) callback) async {
_firebaseAuth.onAuthStateChanged.listen(callback);
}
#override
Future<void> writeUser(UserData user) async {
_firestore.collection("Users").add(user.toMap()).catchError((error) {
print(error);
});
}
}
If some of you know could you explain to me where/how I need to search in order to find this bug? Because how you can see I'm not using any read what so ever.
It's impossible to know for sure given that we don't understand all possible routes of access into your database, but you should be aware that use of the Firebase console will incur reads. If you leave the console open on a collection/document with busy write activity, the console will automatically read the changes that update the console's display. This is very often the source of unexpected reads.
Without full reproduction steps of exactly all the steps you're taking, there's no way to know for sure.
Firebase currently does not provide tools to track the origin of document reads. If you need to measure specific reads from your app, you will have to track that yourself somehow.

How to find out if the user is logged in from Firebase Manual Authentication Or Google Authentication Flutter

My question is how to find out if a user who is currently signed in has been authenticated using firebase manual sign in or google sign in?
When I tap into the user property of class FirebaseUser , when I try to access the providerID, it returns "Firebase" even though I am currently signed in through the Google Sign In provider through Firebase. So, is there any way to find out what provider the user has used for registration of the app?
Thanks a lot for your help. Below is the code that I have already written.
Future<FirebaseUser> getFirebaseUser() async {
FirebaseUser user = await _auth.currentUser();
print(user.email);
return user;
}
#override
void initState() {
// TODO: implement initState
super.initState();
startTimer();
}
void startTimer() {
timer = Timer.periodic(Duration(seconds: 2), (timer) {
if (getFirebaseUser() != null) {
// I Need to push to the menu screen while providing the parameters so that it can recognise if the user is from Firebase Manual Auth or google sign in provider.
//print(_user.providerId);
// Navigator.push(context, MaterialPageRoute(
// builder: (context)
// {
// SideBarLayoutStateful(app: MenuScreen(), isFromGoogleSignIn: ,resultUser: _user, profilePicture: _user.photoUrl,);
// }
//));
}
Navigator.pushNamed(context, 'welcome');
timer.cancel();
});
}
I Need to push to the menu screen while providing the parameters so that it can recognise if the user is from Firebase Manual Auth or google sign in provider, which effects the content displayed on the menu screen.
Thanks for your help and I appreciate it!
Is this supposed to happen:
Future<FirebaseUser> getFirebaseUser() async {
FirebaseUser user = await _auth.currentUser();
print(user.email);
print(user.providerId);
return user;
}

Persistent log in using Firebase currentUser not working - Flutter app

My goal for this app is to have persistent log in, so that the user of my Flutter app needs to sign in only once (unless they sign out) and whenever my Flutter app restarts, they do not need to log back in. I saw many examples with using Firebase Authentication and the .currentUser() method, but I am still having to log in every time I restart the app. I have tested this on the simulator (ios) and on my physical iphone while running debug mode on xCode (usb connection). Is it possible that I cannot test this functionality this way? Because I do see a message pop up on both android studio and xCode terminals that mention lost connection to device or stopped running because of the restarting. If that's the case, how can I test that persistent log in is working?
If that isn't the case, what am I doing wrong?? I've included the code below. This is happening within a stateful widget, of course.
final _auth = FirebaseAuth.instance;
checkIfCurrentUserExists() async {
try {
await _auth.currentUser().then((user) {
print('this is the user $user');
if (user != null && user.email != null) {
userIsLoggedIn = true;
// this works fine!
}
});
} catch (e) {
print('current user was not found $e');
// this works fine!
}
}
// called inside initState()
setClientOnLoad() async {
await Spryte.checkIfCurrentUserExists();
var doesCurrentUserExist = userIsLoggedIn;
var currentUser = await returnCurrentUser();
if (doesCurrentUserExist == false) {
//if user is not authenticated, set anonymous user
// this works fine!
}
else {
//print('current user does exist');
await foo(currentUser.uid);
// 'foo' is meant to retrieve some data about the client on loading of the app
// so that the user doesn't have to log in every time the app restarts
// but for some reason it's not working for me
}
}
I have got the same problem. I was able to sign in but when restarting the app, I was getting another random UID.
It might sound stupid, but make sure you are not calling signInAnonymously(); at any point in your app without checking if there is already a current user.
This was my problem, I was always signing in anonymously at every app restart.
Here is what I did from my starting app page (which takes care of setting up the app including the user):
Future<FirebaseUser> signInAnonymously() async {
AuthResult result = await _auth.signInAnonymously();
final FirebaseUser user = result.user;
assert(user != null);
assert(await user.getIdToken() != null);
return user;
}
And here is the checking method:
Future<FirebaseUser> tryToFetchUser() async {
var user = await _auth.currentUser();
if (user == null) {
user = await FirebaseAuth.instance.onAuthStateChanged.first;
}
if (user == null) {
user = await signInAnonymously();
}
return Future.value(user);
}
I hope it will help some of you and avoid wasting time on stupid mistakes as I did!
You r calling setClientOnLoad() which is async inside init() method & other app navigation depends on this method so u need wrap all your async stuff in FutureBuilder().
if not then build() method ll be called before complete execution of setClientOnLoad()
e.g. :-
FutureBuilder(
future: setClientOnLoad(),
builder: (context, AsyncSnapshot<R> snapshot) {
if (snapshot.data == null) {
return Center(child: CircularProgressIndicator());
}
// after executing method completely
},
);

Google Firestore Database: Where are phantom document reads coming from? [duplicate]

there guys, I do have an interesting problem here and I would be really glad if any of you it will be able to help me with that.
What's my app flow:
Register with the email, password and some other details:
User firebase in order to auth the user and create an account via email and password, at the same time I'm writing the custom data of the user to the database.
Log in the user.
That's it, that's all my basic logic, and how you can see I'm not doing any reading from the DB so far as I know.
Now... the problem is that from some weird reason when I'm registering my user I'm going to the firebase console to see the usage of my DB and I will see something like... for one user which was created I will have 1 write (which is fine as I was expected) but also 13-20 READS FROM DB.
Now that's my question, WHY on earth I have reads on firestorm when I'm doing just auth and writes?
Here it's my DB code which I'm using right now.
class DatabaseFirebase implements BaseDataBase {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
FirebaseUser _firebaseUser;
Firestore _firestore = Firestore.instance;
#override
Future<String> login(String email, String password) async {
_firebaseUser = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<String> register(String email, String password) async {
_firebaseUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<UserData> getCurrentUser() async {
if (_firebaseUser == null)
_firebaseUser = await _firebaseAuth.currentUser();
UserData user = UserData();
user.email = _firebaseUser?.email;
user.name = _firebaseUser?.displayName;
return user;
}
#override
Future<void> logout() async {
_firebaseAuth.signOut();
}
#override
Future<void> onAuthStateChanged(void Function(FirebaseUser) callback) async {
_firebaseAuth.onAuthStateChanged.listen(callback);
}
#override
Future<void> writeUser(UserData user) async {
_firestore.collection("Users").add(user.toMap()).catchError((error) {
print(error);
});
}
}
If some of you know could you explain to me where/how I need to search in order to find this bug? Because how you can see I'm not using any read what so ever.
It's impossible to know for sure given that we don't understand all possible routes of access into your database, but you should be aware that use of the Firebase console will incur reads. If you leave the console open on a collection/document with busy write activity, the console will automatically read the changes that update the console's display. This is very often the source of unexpected reads.
Without full reproduction steps of exactly all the steps you're taking, there's no way to know for sure.
Firebase currently does not provide tools to track the origin of document reads. If you need to measure specific reads from your app, you will have to track that yourself somehow.

Firestore - unexpected reads

there guys, I do have an interesting problem here and I would be really glad if any of you it will be able to help me with that.
What's my app flow:
Register with the email, password and some other details:
User firebase in order to auth the user and create an account via email and password, at the same time I'm writing the custom data of the user to the database.
Log in the user.
That's it, that's all my basic logic, and how you can see I'm not doing any reading from the DB so far as I know.
Now... the problem is that from some weird reason when I'm registering my user I'm going to the firebase console to see the usage of my DB and I will see something like... for one user which was created I will have 1 write (which is fine as I was expected) but also 13-20 READS FROM DB.
Now that's my question, WHY on earth I have reads on firestorm when I'm doing just auth and writes?
Here it's my DB code which I'm using right now.
class DatabaseFirebase implements BaseDataBase {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
FirebaseUser _firebaseUser;
Firestore _firestore = Firestore.instance;
#override
Future<String> login(String email, String password) async {
_firebaseUser = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<String> register(String email, String password) async {
_firebaseUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return _firebaseUser.uid;
}
#override
Future<UserData> getCurrentUser() async {
if (_firebaseUser == null)
_firebaseUser = await _firebaseAuth.currentUser();
UserData user = UserData();
user.email = _firebaseUser?.email;
user.name = _firebaseUser?.displayName;
return user;
}
#override
Future<void> logout() async {
_firebaseAuth.signOut();
}
#override
Future<void> onAuthStateChanged(void Function(FirebaseUser) callback) async {
_firebaseAuth.onAuthStateChanged.listen(callback);
}
#override
Future<void> writeUser(UserData user) async {
_firestore.collection("Users").add(user.toMap()).catchError((error) {
print(error);
});
}
}
If some of you know could you explain to me where/how I need to search in order to find this bug? Because how you can see I'm not using any read what so ever.
It's impossible to know for sure given that we don't understand all possible routes of access into your database, but you should be aware that use of the Firebase console will incur reads. If you leave the console open on a collection/document with busy write activity, the console will automatically read the changes that update the console's display. This is very often the source of unexpected reads.
Without full reproduction steps of exactly all the steps you're taking, there's no way to know for sure.
Firebase currently does not provide tools to track the origin of document reads. If you need to measure specific reads from your app, you will have to track that yourself somehow.

Resources