User info getting saved even after logout. Flutter Firebase - flutter

I want to sign a user out and sign a new user in. I am not able to do that. The information of previous user is somehow being saved, I can't deduce how. Any idea what should I do? I followed the answer in this post : How to Signout a user in Flutter with Firebase authentication
added await keyword but its still not quite working
This is the code to it. I am going to Log in page but after login previous users information is being shown to this new user
Future<void> signOut(BuildContext context) async {
try {
await firebaseObject.signOut().then((value) {
Timer(const Duration(seconds: 1), () {
Navigator.pushReplacementNamed(context, RoutesName.login);
});
Utils.flushBarErrorMessage("Logged out successfully", context,
color: Constants.blueColor);
});
} on FirebaseAuthException catch (e) {}
}

Related

Log out button for different type of accounts in flutter firebase Auth

I have a flutter app with multiple sign in options (Email and password, Google account, phone number). Once the user sign in to the application, he will then have a drawer.
There is a Sign out button inside this drawer which should sign the user out when he press it and send him back to the signup page. So I have been using the sign out instance from firebase auth
await FirebaseAuth.instance.signOut();
But since I added the google sign in options I started facing a problem which is that for google sign out, I nee dto disconnect the user first await googleSignIn.disconnect();
So I added this line to the sign out function to be like this:
Future<void> SignOut() async {
await googleSignIn.disconnect();
await FirebaseAuth.instance.signOut();
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => AuthPage(),
),
(route) => false,
);}
This button works fine when the user sign in with google but if he signs in with different method then an error will be thrown:
Unhandled Exception: PlatformException(status, Failed to disconnect., null, null)
How can I handle different type of users signout with one button?
Future<void> SignOut() async {
if (googleSignIn.currentUser != null){
await googleSignIn.disconnect();
await FirebaseAuth.instance.signOut();}
else{
await FirebaseAuth.instance.signOut();}

linkWithCredential and Flutter Web with Apple

I have a use case where a user, on Flutter Web, needs to link an Apple auth with their existing account, and the email may not match.
However, the only available method for Flutter Web Apple Authentication is signInWithPopUp. If the user's apple email is different from the User firebase account email, a new firebase account is created, and a user is returned, short circuiting the process of linking, this creates a new account in firebase, and I'm unable to linkWithCredential.
My method to try to link accounts is as follows:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await _auth.signInWithPopup(provider).then((appleCredential) async {
final authCredential = appleCredential.credential;
await user.linkWithCredential(authCredential!).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
});
} catch (e) {
return 'Error: $e';
}
return 'Success';
}
As you would expect, my project starts with Streaming a User Object, and when the pop up signs in, it returns the new user, which rebuilds the entire project. Is there a way to authenticate an apple user without returning a new user? I can link a google or phone authorization method fine. It's apple that is problematic. I don't fully understand why Google doesn't break in the same way, other than Firebase put in the work to ensure the functionality of linking for GoogleSignIn().signIn() I'm not using other social auth methods, and I don't use password/email.
This method is not documented in the Flutter Fire Docs, but works perfectly:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await user.linkWithPopup(provider).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
} catch (e) {
debugPrint('auth linkWithGoogle error: ${e.toString()}');
return 'Error: $e';
}
return 'Success';
}

Flutter how to stop auto login using firebase SMS

When users first open the app, I want them to authenticate themselves by phone number. When they get the sms code and hit login button, the phone number and other information are sent to the server together.
However, when I press the code verification button, it automatically logs the user in without login button pressing so I cannot send data accordingly.
FirebaseAuth.instance.authStateChanges().listen((user) {
if (user == null) {
print("signed out - MyAppState");
} else {
print("signed in - MyAppState");
Navigator.push(context,
MaterialPageRoute(builder: (context) => BottomBarScreen()));
}
});
try {
_testPhoneValidation(_phoneNumberController.text);
await _auth.verifyPhoneNumber(
phoneNumber: "+82" + _phoneNumberController.text.substring(1),
timeout: const Duration(seconds: 5),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: (verificationId) {},
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('failure: ${e.toString().substring(11)}'),
));
}
this is my current code related to login with Firebase.
I searched how to stop auto login but didn't quite find the right answer.
So I just changed the login logic to : send info when Firebase auth state changes.
There isn't much change in the code and I think it was a dumb mistake that I made not to think about changing the logic.
FirebaseAuth.instance.authStateChanges().listen((user) {
if (user == null) {
print("signed out");
} else {
print("signed in");
signIn();
}
});
Future<void> signIn() async {
await postAppToken(
await _getToken(),
_packageInfo.appName,
_packageInfo.version,
Theme.of(context).platform.toString().substring(15),
await _getPhoneNum())
.then((value) {
print("signIn");
Navigator.push(context,
MaterialPageRoute(builder: (context) => BottomBarScreen()));
}
);
}
So I just added a Future to post related information to the server when user is automatically logged in. This solved my problem.
You should do nothing on " verificationCompleted" callback.
just write like this
verificationCompleted: (PhoneAuthCredential credential) {},
Because verificationCompleted is for automatic handling of the SMS code on Android devices.

FS Document is not getting created after user is registered

When a user submits their information on the "Signup page", the user should have
an account registered within fire store and
a fire store document created with all of their information inside.
The user account gets registered fine, but the document never gets created. I'm not getting any error messages so I'm trying to use debug prints to find out where things are going wrong.
Debug Prints:
>> login: signUp // this starts the signUp function
>> login: Start hideNewUserOverlay // hide overlay prints before signUp finishes
>> signUp: current user got // the following prints are from signUp
>> signUp: user.id = L8pD6tng5NTAACN7VygK93F6crg1
>> signUp: document creation code Start // then nothing happens after this
Future that is supposed to register the user and create document: // this will eventually pass in first/last names too, that's why I'm using this function
Future<void> signUp(String email, String password) async {
try {
// ignore: unused_local_variable
UserCredential result = await auth.createUserWithEmailAndPassword(email: email, password: password); // <-- user account is created on first press
} catch (e) {
debugPrint('>> Authentication: create new user error');
}
user = auth.currentUser!;
debugPrint('>> signUp: current user got');
String userID = user.uid;
debugPrint('>> signUp: user.id = $userID'); // all debugs print out correctly here, even userID
debugPrint('>> signUp: document creation code Start');
await collectionReference.doc(userID).set({ // code does not run
'userID': userID,
'accountCreated': DateTime.now(),
'email': email,
});
debugPrint('>> Authentication: User Document Created');
}
Signup page:
onPressed: () {
debugPrint('>> login: signUp');
signUp(_email, _password); // this line should finish before the next debug statement is printed but it does not
debugPrint('>> login: Start hideNewUserOverlay'); // prints before signUp() is done
hideNewUserOverlay(); // this will close the Signup page
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => const Nav(),
));
}
At the bottom of the code, the document will get created if I route to a different class. Nav() >> Verify(). The weird part is that Verify does not take in any user information. Verify() has a timer so maybe that has something to do with it? I think it is because the signup() function does not complete before the overlay is hidden. Maybe Nav() needs init state?
Putting await in from of a statement that returns a Future makes that line block the rest of the execution. It does not however make any other call wait.
If you want to wait until signUp is done, use await there too:
await signUp(_email, _password);
That does mean you'll need to mark onPressed as an async method too.
If that is not an option, you can always use then:
onPressed: () {
debugPrint('>> login: signUp');
signUp(_email, _password).then(() {
debugPrint('>> login: Start hideNewUserOverlay'); // prints before signUp() is done
hideNewUserOverlay(); // this will close the Signup page
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => const Nav(),
));
}
}

Flutter: way to validate one sort of google account?

I'm building an app in flutter (latest build) for students on the university. every student has its own email and password (ex. s2170456#student.utwente.nl), which is integrated in google, so everyone is able to see notifications in Gmail.
This does also mean; if you want to log in with google, your studentEmail is an option to do so. I want to implement a google log-in feature where only student of the university (with their email sXXXXXXX#student.utwente.nl) are able to login.
My question is: is there a way to filter on the google login email? I thought about using normal email login and use RegEx to validate, but this means student should firstly signup. I would like to skip the whole sign-up and let the students use their already owned student email to signin.
it should look something like this (if it is even possible) VV
Widget googleLogin () {
googleLogin button()
if(googlelogin.email == sXXXXXXX#student.utwente.nl)
log user in;
} else {
return error message('invalid email')
}
I want this to be able to only register and login user with student email.
You can use google sign in integration like this.
GoogleSignInAccount _currentUser;
then in init state:-
#override
void initState() {
super.initState();
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount account) {
setState(() {
_currentUser = account;
print("User Name ${_currentUser.displayName}");
print("User Email ${_currentUser.email}");
});
if (_currentUser != null) {
var socialData = SocialData(
_currentUser.displayName, "", _currentUser.email, LoginType.GOOGLE);
_startHomeScreen(socialData);
} else {
_showError('Error, Please try again later');
}
});
}
on successful login, this will execute:-
_startHomeScreen(SocialData data) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return Home(socialData: data);
}));
}
Future<void> _handleSignIn() async {
try {
await _googleSignIn.signIn();
} catch (error) {
print(error);
}
}
Call _handleSignIn() on click of google sign in button.
The solution is to let anyone sign in but block the users from using the app unless they are using the university mail
void handleUser(FirebaseUser user) {
if(user.email==sXXXXXXX#student.utwente.nl) {
// handle sign in and UI changes
} else {
print('The user is not allowed');
}
}