Login works despite wrong user credentials - firebase

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(...)

Related

How can I create user profile and authenticate using phone and user password on flutter firebase?

There isn'y enough documentation on this subject. so I'm looking for some experiences from amazing people out here.
We need the main sign in method in the app to be using phone number as user name and user chosen password, Phone will be verified with OTP upon registration and when resetting password.
Flutter offers sign in using phone verification, as far as I know each time user has to go through OTP. I need the user to set a password and only verify phone once at signup or when resetting password.
also we wanna link the credentials to a firestore user profile (name, job, email, etc). How would we do that?
Code for sign in using email:
CustomMaterialButton(
onPressed: () async {
try {
final UserCredential _userCredential =
await _firebaseAuth.signInWithEmailAndPassword(email: _user.email, password: _user); //_user is a custom made class that has user profile data
if (_userCredential != null) Navigator.pushNamed(context, HomeScreen.screenId);
} catch (e) {
showCustomSnackBar(context, e.message);
}
},
text: "Log in"),
code for sign up:
CustomMaterialButton(
onPressed: () async {
try {
final UserCredential _newUserCredential =
await _firebaseAuth.createUserWithEmailAndPassword(email: _user.email, password: _user.password);
if (_newUserCredential != null) {
Navigator.pushNamed(context, VerifyPhoneScreen.screenId);
}
} catch (e) {
showCustomSnackBar(context, e.message);
}
},
text: "New user signup"),
Screen 1
Screen 2
Screen 3
Once a user is signed in to Firebase Authentication (whether with phone number or another method of signing in) they stay signed in, unless you either explicitly sign them out, or a compelling event (such as changing their password, disabling their account) happens.
As long as you listen to auth state changes, the app should reflect the user's sign-in state. If you're having trouble making this work in your app, edit your question to show that you tried.

Flutter | Firebase User Authentication & Profile creation

I am new to Flutter/Firebase and I want to program an app where a user can login/register and then he needs to create a profile with his information like his name, age... and only if he has created his profile, he should be able to continue and see the "main part" of the app.
I already implemented the Firebase Auth with a working Login / Register Page, but my question is now, how to create the Profile thing the most efficent.
At the moment I created this method here at my own:
Future checkUserProfile() async{
// get snapshot from document
final snapShot = await Firestore.instance.collection('profiles').document(uid).get();
if(snapShot == null || !snapShot.exists){
User.gotProfile = false;
} else {
User.gotProfile = true;
}
This method is checking if an user-profile with the Firebase Auth User UID already exists and if not, the user will be send to the "ProfilePage" with a FutureBuilder executing the method above and if it already exists, he will see the main part of the app.
As I already said, I tried it by myself and I wanted to ask if this is already an good implementation or is there even an easier & better way to do it?
Yes this is an good implementation. In my app I have the check User method like yours. The following method is an example. When the user is not registered he forwarded to the RegisterPage else he forwarded to the MainPage.
checkUserAlreadyExists(FirebaseUser user) async {
final userData = await Firestore.instance.collection('users').document(user.uid).get();
if (userData == null || !userData.exists) {
setState(() {
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (BuildContext context) => RegisterPage()), ModalRoute.withName('/'));
});
} else {
setState(() {
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (BuildContext context) => MainPage()), ModalRoute.withName('/'));
});
}
}

flutter firebaseauth signout() not working

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

Not Able To get the token Id in flutter

I am using below code to register new user in Flutter Application with Firebase as backend, but I am not able to retrieve the token id in my application, when I tried to save it the firestore database it is storing it as null.
FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailInputController.text,
password: pwdInputController.text)
.then((currentUser) =>
Firestore.instance
.collection("users")
.document(currentUser.user.uid)
.setData({
"id": currentUser.user.uid,
"tokenId": currentUser.user.getIdToken(),
"fullname": fullNameInputController.text,
})
I receive this in my logs about the tokenId
Invalid argument: Instance of 'Future<'IdTokenResult'>'
As indicated in the official documentation getIdToken(), it actually returns a promise, so you won't be able to directly access the value. You will need to await the value to be loaded and them manage it. You will need to handle as in the below code sample:
FirebaseAuth.instance.currentUser().then(user => {
if (user != null) {
user.getIdToken().then(token => {
//handle token
}
}
});
In case you want a more direct way, the below line should work for you too.
var token = await FirebaseAuth.instance.currentUser().getIdToken();
While this codes are untested,, I believe they should help you have handle the promise, you should have the value and saving it in your database should not face any more issues.
Let me know if the information helped you!

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

Resources