flutter firebaseauth signout() not working - firebase

I am using the firebase auth signout method but it doesnt seem to be working properly. when i click on the logout button, it is supposed to log the current user out. however, after doing so, the console does not indicate that the firebase auth signout method is actually working, none!
the app has a sysmte where if the user is online then they will always be redirected to the home page upon opening the app unless they log out from the app (which they will be redirected to the login page). and the app always redirects me to the home page when opening the app, hence it is clear that the firebase auth signout method is not working even after i hit the logout button
this is my logout method and it is in the Authentication class
FirebaseAuth _auth = FirebaseAuth();
logOut() async {
return await _auth.signOut();
}
this is the callback and the logOutCurrentUser function is called when i click the logout button
Authentication authentication = Authentication();
logOutCurrentUser(BuildContext context) {
try {
authentication.logOut();
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LoginSignupToggle(true)), (route) => false);
}
catch (e) {
print(e.toString());
}
}
all in all, it seems like FirebaseAuth.instance.currentUser() is still not null even after i hit the logout button which i expect it to be null after logging out
i have tried searching for an answer as much as i could but nothing seems to work for me

My guess is that your sign-out is aborted because you're not waiting for it to finish. Since your logOut is async you need to use await when calling it:
await authentication.logOut();
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LoginSignupToggle(true)), (route) => false);

Related

Update firebase user information is not working properly

I am trying to update firebase user information, but it is not working properly where I need to hot restart the app to see the changes. This is the method that I am using
Future<void> saveUserNumber(
{String number, PhoneAuthCredential phoneCredential}) async {
try {
await user.updatePhoneNumber(phoneCredential);
await Get.find<FirestoreService>().saveUserPhoneNumber(user.uid, number);
print('user before reload $user');
await user.reload();
update();
print('user after reload $user'); //prints null phone number
} catch (e) {
print(e.message);
}
}
note that signing out works fine but I am not sure why this is not working as well as when I try to change the display name.
and this is what I am using to listen to the user changes with Getx package
// get firebase user, make it observable
Rx<User> _firebaseUser = FirebaseAuth.instance.currentUser.obs;
// getter for user
User get user => _firebaseUser.value;
#override
void onInit() {
super.onInit();
_firebaseUser.bindStream(_auth.authStateChanges());
}
Problem solved!
#override
void onInit() {
super.onInit();
// _firebaseUser.bindStream(_auth.authStateChanges());
_firebaseUser.bindStream(_auth.userChanges());
}
the reason why it was not working is that authStateChanges() listens to the authentication status of the user and doesn't listen to other things such as credentials.
the solution is to use userChanges() instead of authStateChanges() where the userChanges() method has the functionality of listening to the auth state as well as the credentails

Firebase and VueJS: How to handle users that login with Google and don't register in my app? User profile management

I have an app with a LOGIN page and a REGISTER page. Both pages have a "Sign in with Google" button, as well as a regular login and password input form for those that don't want to sign in with Google. I am also using FireStore to create user profile documents for registered users. When the user also logs in, the app will query the user's profile for use throughout the app. This all works fine.
I noticed that a google user does not need to "register"...he can still click the login button and it will "sign him up" automatically because that's how Google Auth Provider works. However, since he did not "register", he does not yet have a profile. In this case, I had to write some logic so a profile would be created for a Google user. Although this logic works, I just wonder if this is the best way to do this. Are there best practices for handling Google/Social logins for people skipping the traditional "registering" pages? I know most people would probably head to the register page and register, but there will undoubtedly be some people that will skip that and go start to the LOGIN page and sign in via Google that way.
Here's how I'm handling the login page with Google login button:
login.vue
async logInWithGoogle() {
try {
const provider = new this.$fireAuthObj.GoogleAuthProvider()
const userCredentials = await this.$fireAuth.signInWithRedirect(
provider
) ....
Then in my Store (in my case, Vuex state management pattern), I have the following actions:
store.js
First, this onAuthStateChanged observer will notice the new user state and do the following code:
async onAuthStateChangedAction({ commit, dispatch }, { authUser }) {
if (authUser) {
console.log('user committing from onAuthStateChangedAction...')
commit('SET_CURRENT_USER', authUser)
console.log(
'fetchUserProfile action dispatching from onAuthStateChangedAction...'
)
await dispatch('fetchUserProfile', authUser)
} else {
dispatch('logOutUser')
}
}
That onAuthStateChanged observer will fetch the user's profile (and this is the logic I am concerned with...not sure if this is an ideal way to handle user's logging in via Google for first time and bypassing registration:
async fetchUserProfile({ commit }, user) {
try {
const docRef = this.$fireStore.collection('users').doc(user.uid)
const profile = await docRef.get()
if (profile.exists) {
commit('SET_USER_PROFILE', await profile.data())
console.log(
'user profile EXISTS and set from fetchUserProfile action'
)
} else {
console.log('profile does not exist! Creating...')
await docRef.set({
displayName: user.displayName,
email: user.email,
uid: user.uid,
photoUrl: user.photoURL,
providerId: user.providerData[0].providerId,
createdAt: this.$fireStoreObj.FieldValue.serverTimestamp()
})
const p = await docRef.get()
commit('SET_USER_PROFILE', await p.data())
console.log('user profile set')
}
} catch (error) {
console.log('can not fetch profile', error)
}
},
Thanks for any tips or assurances that I am on the right (or wrong) path on handling this. Thank you!
Why not create an empty document with the user's uid and prompt them to "complete their profile"? Until they do so, force redirect them back to the profile page indefinitely.

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;
}

Is it possible to delete currentUser firebase authentication user?

I used firebase_auth package to work with flutter. And I used phone authentication to sign in. Everything is working well. But when signout user is not deleted on firebase.
Is it possible to delete firebase user?
RaisedButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
}
)
I tried this way,
but error is coming..
delete called null
_auth.onAuthStateChanged.listen((currentUser)=>{
currentUser.delete()
}).onError((e)=>print("Error is $e"));
Yes. You must use FirebaseAuth.instance.currentUser.delete() method before (on) signOut() method.
RaisedButton(
onPressed: () async {
FirebaseAuth.instance.currentUser.delete();
await FirebaseAuth.instance.signOut();
}
)
You can't delete the current user after they've signed out, because at that point there is no current user anymore.
But you can prevent this whole chicken-and-egg problem by simply deleting the user without signing out. This should be all that is needed for that:
currentUser.delete()
You can call this operation "logging out" for your users of course, but in code you're simply deleting their account.

Login works despite wrong user credentials

I am using Firebase and FirebaseAuth in my Flutter app to manage users and data.
The problem is that the users are always taken to the next screen even if they enter wrong credentials. They can enter data to non-existent user accounts, or wrong passwords, and they are still taken to the text screen which should only happen after a successful auth.
As far as I understood, if code inside (if user!= null) should only be executed if the auth was successful, but it still happens all the time.
The console does log a response from Firebase, stating either a non-existent user or wrong passsword, but the code proceeds nontheless.
Does anyone see what I did wrong?
I'm still a learner, so it's probably a basic mistake :(
Thank you!!
final _auth = FirebaseAuth.instance;
...
onPressed: () async {
try {
final user = _auth.signInWithEmailAndPassword(
email: email, password: password);
if (user != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CoursesListScreen(),
),
);
}
} catch (e) {
print(e.message);
}
},
When you call _auth.signInWithEmailAndPassword you get back a Future, which will never be nil. So indeed the navigator will always go to the next screen. Note that the user isn't signed in at this stage, your code merely detects the wrong condition.
It's more likely that you want to wait until the Future resolves, which you do with await:
final user = await _auth.signInWithEmailAndPassword(...)

Resources