Unhandled Exception: NoSuchMethodError: The getter 'isEmailVerified' was called on null - firebase

I am getting the above mentioned error when logging in. This exception is raised even after I am ensuring that the isEmailVerified() is called only after checking whether the current user is null or not.
My authentication.dart file looks like below:
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
abstract class BaseAuth {
Future<String> signIn(String email, String password);
Future<String> signUp(String email, String password);
Future<FirebaseUser> getCurrentUser();
Future<void> sendEmailVerification();
Future<void> signOut();
Future<bool> isEmailVerified();
}
class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
AuthResult result = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return user.uid;
}
Future<String> signUp(String email, String password) async {
AuthResult result = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
sendEmailVerification();
return user.uid;
}
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
Future<void> sendEmailVerification() async {
FirebaseUser user = await _firebaseAuth.currentUser();
user.sendEmailVerification();
}
Future<bool> isEmailVerified() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user.isEmailVerified;
}
}
And inside the LoginPage, I am checking like this:
if(auth.signIn(email, password)!=null)
{
if(auth.getCurrentUser()!=null)
{
if(auth.isEmailVerified() != null) {
Toast.show("Login Successful!", context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
Route route = MaterialPageRoute(builder: (context) => HomePage());
Navigator.pushReplacement(context, route);
}
}
}
I don't know how to resolve this. Any help is appreciated.

From your Auth class, your methods have future signatures.
You will have to await their results since it will be needed by the other conditions.
You can do:
if((await auth.signIn(email, password))!=null){
if((await auth.getCurrentUser())!=null){
if((await auth.isEmailVerified()) != null) {
Toast.show("Login Successful!", context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
Route route = MaterialPageRoute(builder: (context) => HomePage());
Navigator.pushReplacement(context, route);
}
}
}
But the snippet above must be placed in within an async method.

Related

.uid: The getter 'uid' isn't defined for the type 'UserCredential'. - Flutter, FirebaseAuth

My .uid says: The getter 'uid' isn't defined for the type 'UserCredential'.
My Code:
import 'package:firebase_auth/firebase_auth.dart';
class AuthService { final FirebaseAuth _firebaseAuth =
FirebaseAuth.instance;
Stream<String> get onAuthStateChanged =>
_firebaseAuth.authStateChanges().map(
(User user) => user?.uid,
);
Future<String>
createUserWithEmailAndPassword(
String email, String password, String name) async {
final currentUser = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
var updateInfo = UserUpdateInfo();
await FirebaseAuth.instance.currentUser.updateProfile(displayName:name);
await FirebaseAuth.instance.currentUser.reload();
return FirebaseAuth.instance.currentUser.uid; }
Future<String>
signInWithEmailAndPassword(
String email, String password) async {
return (await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password))
.uid; }
signOut() {
return _firebaseAuth.signOut(); } }
class UserUpdateInfo { }
How can I fix it? Thanks!
The signInWithEmailAndPassword and createUserWithEmailAndPassword methods return a UserCredential object, which (as the error message says) doesn't have a uid property. To get to the UID from the UserCredential, you do credential.user.uid.
You're looking for:
await (_firebaseAuth.signInWithEmailAndPassword(email: email, password: password)).user.uid
Or a bit more readable when spread over two lines/statements:
var credentials = await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
return credentials.user.uid

Display error message instead of throw exception in console (Flutter Firebase)

How to show the error message when the user enters the incorrect username and password? Can I display a message when there are multiple conditions in authenticating the user? The message should show on the screen instead of throwing the exception in the console.
The exception I get in the console
The exception has occurred.
PlatformException (PlatformException(firebase_auth, com.google.firebase.auth.FirebaseAuthInvalidUserException: There is no user record corresponding to this identifier. The user may have been deleted., {code: user-not-found, additionalData: {}, message: There is no user record corresponding to this identifier. The user may have been deleted.}, null))
import 'package:firebase_auth/firebase_auth.dart';
abstract class BaseAuth {
Future<String> currentUser();
Future<String> signIn(String email, String password);
Future<String> createUser(String email, String password);
Future<void> signOut();
}
class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
UserCredential result = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
User user = result.user;
return user.uid;
}
Future<String> createUser(String email, String password) async {
UserCredential result = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
User user = result.user;
return user.uid;
}
Future<String> currentUser() async {
User user = _firebaseAuth.currentUser;
return user != null ? user.uid : null;
}
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
}
A simple try catch would do the trick
Future<String> signIn(String email, String password) async {
try{
UserCredential result = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
User user = result.user;
return user.uid;
}on AuthException catch(error){
return Future.error(error);
}
}
Now on how to handle the error in the UI assuming you know the basics :D
await signIn(email,password).then((onSuccess){
//do something with data or not up to you
}).catchError((err){
print(err);
});
Hope it helps :)

Google authentication problem (Flutter and Firebase)

I am flutter-newbie and I have one problem: I want to add Google authentication to my flutter app with firebase. This is my code for login screen:
import 'package:PixiCall/resources/firebase_repository.dart';
import 'package:PixiCall/screens/home_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
FirebaseRepository _repository = FirebaseRepository();
#override
Widget build(BuildContext context) {
return Scaffold(
body: loginButton(),
);
}
Widget loginButton() {
return FlatButton(
padding: EdgeInsets.all(35),
child: Text(
'Login',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w900,
letterSpacing: 1.2,
),
),
onPressed: () => performLogin,
);
}
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
void authenticateUser(User user, BuildContext context) {
_repository.authenticateUser(user).then((isNewUser) {
if (isNewUser) {
_repository.addDataToDb(user).then((value) {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
});
} else {
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) {
return HomeScreen();
}));
}
});
}
}
I have this error here:
lib/screens/login_screen.dart:39:25: Error: Too few positional arguments: 2 required, 1 given.
authenticateUser(user);
What is the other parameter which I have to add?
Also I think that I have one more mistake in other file. This is the code from other file:
import 'package:PixiCall/models/user.dart';
import 'package:PixiCall/utils/utilities.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class FirebaseMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
GoogleSignIn _googleSignIn = GoogleSignIn();
static final FirebaseFirestore firestore = FirebaseFirestore.instance;
//user class
User1 user = User1();
Future<User> getCurrentUser() async {
User currentUser;
currentUser = await _auth.currentUser;
return currentUser;
}
Future<User> signIn() async {
GoogleSignInAccount _signInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication _signInAuthentication =
await _signInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: _signInAuthentication.accessToken,
idToken: _signInAuthentication.idToken,
);
User user = await _auth.signInWithCredential(credential);
return user;
}
Future<bool> authenicateUser(User user) async {
QuerySnapshot result = await firestore
.collection('users')
.where('email', isEqualTo: user.email)
.get();
final List<DocumentSnapshot> docs = result.docs;
//if user is registered then length of list > 0 or else less than 0
return docs.length == 0 ? true : false;
}
Future<void> addDataToDb(User currentUser) async {
String username = Utils.getUsername(currentUser.email);
user = User1(
uid: currentUser.uid,
email: currentUser.email,
name: currentUser.displayName,
profilePhoto: currentUser.photoURL,
username: username);
firestore.collection('users').doc(currentUser.uid).set(user.toMap(user));
}
}
This is the mistake in console:
lib/resources/firebase_methods.dart:32:17: Error: A value of type 'UserCredential' can't be assigned to a variable of type 'User'.
Sorry if I confused you, as I said, I am newbie. If you want any other informations please ask here.
For the first mistake , you defined a function void authenticateUser(User user, BuildContext context) so when you use it, it expects 2 arguments a User type object and a BuildContext object
Then you are calling this function in
void performLogin() {
_repository.signIn().then((User user) {
if (user != null) {
authenticateUser(user);
} else {
print('There was an error');
}
});
}
You are passing only the User object, missing the BuildContext
For GoogleSingIn this was my solution:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
//create user object based on FB json
User _userFromFirebaseUser(FirebaseUser user) {
return user != null
? User(uid: user.uid, emailVerified: user.isEmailVerified)
: null;
}
//auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged.map(_userFromFirebaseUser);
}
Future<User> singInUsingGoogle() async {
int age;
String email;
String name;
String lastname;
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleAuth.idToken, accessToken: googleAuth.accessToken);
final result = await _auth.signInWithCredential(credential);
FirebaseUser user = result.user;
print(result.user.providerData);
await DatabaseService(uid: user.uid).createUserData(
//user info
)

FirebaseAuth.instance is null

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) {}
}
}

Failed to return to login page/screen after signing out (Not sure if sign out is successful or not)

I'm new in flutter and dealing with backend. I faced problem in signing out and I don't know how to fix it due to lack of experience. When I sign out, it would not return to the login screen (Authenticate). I'm not quite sure if the problem lies at the function I wrote at the wrapper or somewhere in auth.
The wrapper widget will be executed everytime the app runs:
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: new MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.redAccent,
),
home: Wrapper(),
),
);
}
}
The wrapper code is as below:
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
if (user == null) {
return Authenticate();
} else {
return MyBottomNavigationBar();
}
}
}
Sign out button function:
onPressed: () async {
await _auth.signOut();
print('signing out');
},
Auth code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:mudah_replica/models/user.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
//Create user object based on FirebaseUser
User _userFromFirebaseUser(FirebaseUser user){
return user != null ? User(uid: user.uid) : null;
}
//Auth change user stream
Stream<User> get user {
return _auth.onAuthStateChanged
//.map((FirebaseUser user) => _userFromFirebaseUser(user));
.map(_userFromFirebaseUser);
}
//Sign in anonymously
Future signInAnon() async {
try {
AuthResult result = await _auth.signInAnonymously();
FirebaseUser user = result.user;
return user;
} catch(e) {
print(e.toString());
return null;
}
}
//Sign in with Email & Password
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch(e){
print(e.toString());
return null;
}
}
//Register with Email & Password
Future registerWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch(e){
print(e.toString());
return null;
}
}
//Sign out
Future signOut() async {
try{
return await _auth.signOut();
} catch(e){
print('Fail to sign out');
print(e.toString());
return null;
}
}
}
in your wrapper class, you are returning auth widget instead of navigate to the right screen, so it doesn't route. Instead, you might wanna navigate to the Auth screen. Do something like this:
onPressed: () async {
await _auth.signOut();
Navigator.push(context,
MaterialPageRoute(builder: (context) => Authenticate())
},

Resources