Why is my signOut() method not setting the currentUser() to null??
When I click on logout on my homepage it checks the isAuthenticated() method which is returning a user instead of null. Also, just have a look at the two comments I've included inside the logout() method.
Thank You!!
Here's my code -
class Auth with ChangeNotifier {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
bool isAuthenticated() {
print('$currentUser inside the isAuthenticated');
if (currentUser == null) {
print('false');
return false;
}
print('true');
return true;
}
Future<FirebaseUser> get currentUser async {
return await _auth.currentUser();
}
Future<FirebaseUser> signInWithEmail(String email, String password) async {
try {
final response = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
print(response);
if (response == null) {
print('response is null');
} else {
notifyListeners();
return response.user;
}
} catch (error) {
print('some error');
throw error;
}
}
Future<FirebaseUser> signInWithGoogle() async {
try {
final GoogleSignInAccount _userDetails = await _googleSignIn.signIn();
if (_userDetails == null) {
print('No user found');
} else {
final GoogleSignInAuthentication googleAuth =
await _userDetails.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
return user;
}
notifyListeners();
print('google sign in ran successfully');
} catch (error) {
throw error;
}
}
Future<FirebaseUser> logout() async {
try {
print('logout ran');
print(currentUser); //THIS RETURNS AN INSTANCE OF USER
_auth.signOut().then( (response) {
print('signout successful');
});
await _googleSignIn.signOut();
print(currentUser); //THIS *ALSO* RETURNS AN INSTANCE OF USER
notifyListeners();
return currentUser;
} catch (error) {
print('an error');
}
}
}
I know there would a silly mistake that I'm unable to catch but it's tiring now!! I've tried other methods that I could find on stackoverflow
May be the future is not complete when you try getting current user, have you tried await instead of then in logout?
Future<FirebaseUser> logout() async {
try {
print('logout ran');
print(currentUser); //THIS RETURNS AN INSTANCE OF USER
await _auth.signOut();
await _googleSignIn.signOut();
//The problem is with this, you need to await this
//print(currentUser); //THIS *ALSO* RETURNS AN INSTANCE OF USER
var user = await currentUser;
print(user); //prints null
notifyListeners();
return currentUser;
} catch (error) {
print('an error');
}
}
I faced similar issue and worked it around by assigning null to currentUser. It works fine now!
case R.id.main_logout_option:
updateUserStatus(getString(R.string.strOffline));
mAuth.signOut();
currentUser = null;
goToLoginActivity();
break;
Related
I am building a Flutter/Firebase app with reset password functionality.
For modularity, I keep my auth functions in an AuthService Class.
class AuthService{
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// **8** FUNCTION TO RESET PASSWORD
Future<void> resetPassword(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
}
}
// **8**
}
Then I call it in my widget like this:
final auth = Provider.of<AuthService>(context);
...
await auth.resetPassword(email);
When I add a .then method to go to a route when successful, it redirects to the new route even when there is an error. I have tried to add a .catch method but that throws an exception.
How can I go about this?
await auth.resetPassword(email).then((value) =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const AndroidRecoverySuccess())));
Thanks.
Return bool value after sendPasswordResetEmail, also your Future should return bool. Here is the working code:
Future<bool> resetPassword(String email) async {
try {
await _auth.sendPasswordResetEmail(email: email);
return true;
} catch (e) {
print(e.toString());
return false;
}
}
(optional) You can use FirebaseAuthException for better UX:
Future<bool> resetPassword(String email) async {
try {
await _auth.sendPasswordResetEmail(email: email);
return true;
} on FirebaseAuthException catch (e) {
if (e.code.toString() == 'invalid-email') {
// setState(() {message 'Invalid email address.';});
}
if (e.code.toString() == 'missing-email') {
//...
}
if (e.code.toString() == 'user-not-found') {
//...
}
} catch (e) {
return false;
}
}
Firebase
Authentication: email/Password was already set to Enabled.
Realtime Database: users records exist.
Email and Password: thoroughly checked and verified correct.
below are the code for this issue;
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
void loginAndAuthenticateUser(BuildContext context) async
{
final User? firebaseUser = (await _firebaseAuth
.signInWithEmailAndPassword(
email: emailTextEditingController.text,
password: passwordTextEditingController.text
).catchError((errMsg){
displayToastMessage("Error: " + errMsg.toString(), context);
})).user;
if(firebaseUser !=null)
{
userRef.child(firebaseUser.uid).once().then((value) => (DataSnapshot snap){
if(snap.value != null){
Navigator.pushNamedAndRemoveUntil(context, MainScreen.idScreen, (route) => false);
displayToastMessage("Login successful", context);
}else{
_firebaseAuth.signOut();
displayToastMessage("No records exist. Please create new account", context);
}
});
}else{
displayToastMessage("Error: Cannot be signed in", context);
}
}
Try to use await with catch/try, instead of mixing with the .then/.catchError syntax (I don't know what's exactly in userRef, depending on it the database query might need to be adjusted):
try {
UserCredential userCredential = await _firebaseAuth
.signInWithEmailAndPassword(
email: emailTextEditingController.text,
password: passwordTextEditingController.text);
final User? firebaseUser = userCredential.user;
if (firebaseUser != null) {
final DatabaseEvent event = await
userRef.child(firebaseUser.uid).once();
if (event.snapshot.value != null) {
Navigator.pushNamedAndRemoveUntil(context, MainScreen.idScreen,
(route) => false);
displayToastMessage("Login successful", context);
} else {
displayToastMessage("No records exist. Please create new account",
context);
await _firebaseAuth.signOut();
}
} else {
displayToastMessage("Error: Cannot be signed in", context);
}
} catch(e) {
// handle error
}
I have the following problem. I want the message to be the correct exception type. i can only use set state within my sign in (because my auth class is not a statlesswidget)class and pass a message there with set state(), but the same for all errors. I've been trying for 9 hours and I can't figure it out. Please help. so I just want the correct exception to be displayed.Something like „The Email adress is badly formated“.the problem is i it dont let me to set the error message be the real error message and i dont know how to fix it
Widget _buildLoginBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: RawMaterialButton(
elevation: 5.0,
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
fillColor: Colors.white,
child: Text(
'LOGIN',
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
print('valid');
setState(() => loading = false);
dynamic result =
await _auth.signIN(email, password);
if (result == null) {
setState(() => error = 'Check your Input');
loading= false;
}
}
}),
);
}
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(), password: password)).user;
} catch (e) {
return null;
}
if (user != null) {
print(user);
}
return null;
}
So after im following # Gerpea advice I Get the following error when im just trying to catch the error without the statement on FIREBASEAUTHERROR and when im trying with the statement. When im trying to update my auth and cloud and core it gets me another error.And I can really say if the he ignored the catch block because it don't starts actually when im starting I get as I said before the error in console Im using:
cupertino_icons: ^1.0.2
firebase_auth: ^0.14.0+5
cloud_firestore: ^0.12.9+4
firebase_core_web: ^0.2.1+3
provider: ^4.3.3
flutter_svg: ^0.19.2+1
flutter_spinkit: "^4.1.2"
auto_size_text: ^2.1.0
firebase_core: ^0.4.0
get_it: ^5.0.6
The error ist this:
Invalid depfile: /Users/MYUSERNAME/Desktop/project neu2/flutter_application_2/.dart_tool/flutter_build/7e96e6ced6aa40f9bcd60c2328bbea3e/kernel_snapshot.d
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib/js.dart:8:1: Error: Not found: 'dart:js'
export 'dart:js' show allowInterop, allowInteropCaptureThis;
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/js-0.6.3/lib/js_util.dart:8:1: Error: Not found: 'dart:js_util'
export 'dart:js_util';
^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/js_interop.dart:24:7: Error: Method not found: 'hasProperty'.
if (util.hasProperty(jsObject, 'toDateString')) {
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:39:26: Error: Method not found: 'getProperty'.
map[key] = dartify(util.getProperty(jsObject, key), customDartify);
^^^^^^^^^^^
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:65:17: Error: Method not found: 'newObject'.
var jsMap = util.newObject();
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:67:7: Error: Method not found: 'setProperty'.
util.setProperty(jsMap, key, jsify(value, customJsify));
../../../flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-0.2.1+3/lib/src/interop/utils/utils.dart:73:12: Error: Method not found: 'allowInterop'.
OKafter trying the second correction that #Gerpea send I get the same error so I decide to update to the newest versions go auth.
No I got some problems but I think that's maybe be easyler to correct
but don't really how maybe you know?
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core_web/firebase_core_web_interop.dart';
import 'package:flutter_application_2/models/user.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
String error;
//create user obj based on FirebasedUser
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(uid: user.uid) : null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
//sign in anon
Future signInAnon() async {
try {
AuthResult result = await _auth.signInAnonymously();
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//sign in with passwort and email
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
//register with passwort an email
Future<String> signUp(String email, String password) async {
FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)) .user;
try {
await user.sendEmailVerification();
return user.uid;
} catch (e) {
print(e.toString);
return null;
}
}
//sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
//resetpassword
Future<void> sendPasswordResetEmail(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
return null;
}
}
}
that's the exceptions
enter image description here
OK now it logs very good I just have 2 exceptions. Code looks like that:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_application_2/models/user.dart' as Model;
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
String error;
//create user obj based on FirebasedUser
Model.User _userFromFirebaseUser(Model.User user) {
return user != null ? Model.User(uid: user.uid) : null;
}
//auth change user stream
Stream<Model.User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
//sign in anon
Future signInAnon() async {
try {
UserCredential result = await _auth.signInAnonymously();
User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
//sign in with passwort and email
Future<String> signIN(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
//register with passwort an email
Future<String> signUp(String email, String password) async {
User user = (await _auth.createUserWithEmailAndPassword(
email: email, password: password)) .user;
try {
await user.sendEmailVerification();
return user.uid;
} catch (e) {
print(e.toString);
return null;
}
}
//sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
//resetpassword
Future<void> sendPasswordResetEmail(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
return null;
}
}
}
And EXCEptions like that:
enter image description here
#Gerpea
So here's my code
Future<String> signUp(String email, String password, String fullname,String user) async {
try {
( await _auth.createUserWithEmailAndPassword(
email: email.trim(), password: password,)).user.sendEmailVerification();
await DatbaseService(uid: user.uid).updateUserData('username', 'fullname', 'Passwort', 'Email');
} on FirebaseAuthException catch (e) {
And the method from YouTube:
Future registerWithEmailAndAPassword(String email, String,Passwort)async {
try{
AuthResult result = await.createUserWithEmailAndPassowrd(email:email,password:password);
FirebaseUser user =result.user;
await DatabaseService(uid:user.uid).updateUserData('0','new crew member',100);
return _userFromFirebaseUser(user);
}catch (e){
signInWithEmailAndPassword() method in case of error will throw a FirebaseAuthException which contain code field with error code.
The full list of errors for this method can be found here.
So you can rewrite you method a bit, to return an error message instead just null.
Future<String> signIN(String email, String password) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on FirebaseAuthException catch (e) {
switch(e.code) {
case 'user-not-found': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
}
return null;
}
Now this method return null if there is no error and String if some error occurs.
Use this in onPressed callback.
onPressed: () async {
if (_formKey.currentState.validate()) {
print('valid');
String authError = await _auth.signIN(email, password);
if (authError != null) {
setState(() => error = authError);
}
setState(() => loading = false);
}
}
firebase_auth: ^0.14.0+5
This is a bit outdated and has some problems, so it will be better if you
will upgrade your dependencies.
But if you can't upgrade. This should work.
Future<String> signIN(String email, String password) async {
try {
FirebaseUser user = (await _auth.signInWithEmailAndPassword(
email: email.trim(),
password: password,
)).user;
} on AuthException catch (e) {
switch(e.code) {
case 'ERROR_USER_NOT_FOUND': {
return 'No user found';
}
default: {
return 'Unexpected error!';
}
}
} catch(e) {
return 'Some error that FirebaseAuth do not catch'!;
}
return null;
}
List of error codes can be found here.
Hey I'm new to flutter development and I got this message when trying to do SignUp to Firebase
I/flutter (23432): NoSuchMethodError: The method 'createUserWithEmailAndPassword' was called on null.
I/flutter (23432): Receiver: null
And here is the code
AuthServide.dart
class AuthServices {
static FirebaseAuth _auth = FirebaseAuth.instance;
static Future<SignInSignUpResult> signUp(String email, String password,
String name, List<String> selectedGenres, String selectedLanguage) async {
try {
log(_auth.toString());
log("Proses Sign Up");
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
log("Selesai Sign Up");
log(result.toString());
Users user = result.user.convertToUser(
name: name,
selectedGenres: selectedGenres,
selectedLanguage: selectedLanguage);
await UserServices.updateUser(user);
return SignInSignUpResult(user: user);
} catch (e) {
return SignInSignUpResult(message: e.toString());
}
}
}
After I check the log I know that FirebaseAuth.instance is null, but why?
I'm currently following a tutorial on an online flutter class and I got stuck here.
Anybody can help me?
Thanks
You can try this. I think it will work for you. Make sure you added the firebase auth pakage firebase_auth: ^0.18.4+1
import 'package:firebase_auth/firebase_auth.dart';
class AuthMethods {
// CONDITION ? TRUE: FLASE
User _userFromFirebaseUser(FirebaseUser user) {
return user != null ? User(userId: user.uid) : null;
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser);
} catch (e) {
print(e.toString());
}
}
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser firebaseUser = result.user;
return _userFromFirebaseUser(firebaseUser);
} catch (e) {
print(e.toString());
}
}
Future resetPass(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (e) {
print(e.toString());
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (e) {}
}
}
I am using the below code for google sign in flutter app with firebase, which is working successfully.
How should I check that whether the email id used is already existing in the firebase authentication?
This I need to ensure that I update the user information in the firestore database accordingly.
Future<User> _handleSignIn() async {
User user;
bool userSignedIn = await _googleSignIn.isSignedIn();
setState(() {
isUserSignedIn = userSignedIn;
});
if (isUserSignedIn) {
user = _auth.currentUser;
}
else {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
user = (await _auth.signInWithCredential(credential)).user;
userSignedIn = await _googleSignIn.isSignedIn();
setState(() {
isUserSignedIn = userSignedIn;
});
}
return user;
}
Please guide me for this
There is a Generic exception related to Firebase Authentication. which is the class FirebaseAuthException. It comes with codes related to errors including email already exists so you would write something like:
try {
//your signIn method here
//i assumed handleSignIn
handleSignIn();
} on FirebaseAuthException catch (e) {
//exception that occurs if e-mail already exists
if (e.code == 'email-already-in-use') {
// the rest of your code here
}
}
Then this is the method you should use I have used to solve my problem
this is my auth.dart file
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:gfd_official/User/User.dart';
import 'package:gfd_official/services/database.dart';
import 'package:google_sign_in/google_sign_in.dart';
String photoUrl;
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// create user obj based on firebase user
Userdat _userFromFirebaseUser(User user) {
return user != null ? Userdat(uid: user.uid) : null;
}
// auth change user stream
Stream<Userdat> get user {
return _auth
.authStateChanges()
//.map((FirebaseUser user) => _userFromFirebaseUser(user));
.map(_userFromFirebaseUser);
}
Future signInWithGoogle() async {
GoogleSignIn googleSignIn = GoogleSignIn();
final acc = await googleSignIn.signIn();
final auth = await acc.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: auth.accessToken, idToken: auth.idToken);
try {
final res = await _auth.signInWithCredential(credential);
User user = res.user;
photoUrl = user.photoURL;
UserHelper.saveUser(user);
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
Future logOut() {
try {
GoogleSignIn().signOut();
return _auth.signOut();
} catch (e) {
print(e.toString());
return null;
}
}
}
class UserHelper {
static FirebaseFirestore _db = FirebaseFirestore.instance;
static saveUser(User user) async {
Map<String, dynamic> userData = {
"name": user.displayName,
"email": user.email,
"role": "basic",
};
try {
final userRef = _db.collection("users").doc(user.uid);
if ((await userRef.get()).exists) {
await userRef.update({});
} else {
await _db
.collection("users")
.doc(user.uid)
.set(userData, SetOptions(merge: true));
}
} catch (e) {
print(e.toString());
}
}
}
In this the save user function will create database for new user and if user already exist then it will let it remain same as it is.
I am creating a document for every user with his/her uid.