Is there any error in the try-catch exception handling below? - flutter

I tried to handle an exception while a user is trying to login after being authenticated by firebase. But this try-catch is not working in my flutter project.
Can someone let me know where did i go wrong? I have attached my code below.
Thank you in advance.
class AuthService {
//Creating an instance of firebase.
final auth.FirebaseAuth _firebaseAuth = auth.FirebaseAuth.instance;
User? _userFromFirebase(auth.User? user) {
if (user == null) {
return null;
}
return User(user.uid, user.email);
}
Stream<User?>? get user {
return _firebaseAuth.authStateChanges().map(_userFromFirebase);
}
Future<User?> signInWithEmailAndPassword(
String email,
String password,
) async {
try {
final credential = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _userFromFirebase(credential.user);
} on Exception catch (_, e) {
//I want to display a toast message if the login fails here.
print(e);
}
}
Future<void> signOut() async {
return await _firebaseAuth.signOut();
}
}

In your try-catch block you are catching Exception types, but Firebase Authentication has its own exception type, FirebaseAuthException.
For possible error codes for this specific sign-in see here, but there are others as well.
Check the following code:
try {
final credential = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _userFromFirebase(credential.user);
} on FirebaseAuthException catch (e) {
// here you will have the different error codes in `e.code`
// for example `invalid-email` or `wrong-password`
}
It is up to you how do you handle these errors. You can return the error code for example and handle it from where you call this function (as h8moss suggested in comment).
And keep in mind that there are other possible reasons for a sign-in to fail than FirebaseAuthException. For example network connection can be down. So a more complete solution to catch other errors as well would be something like:
try {
// sign in
} on FirebaseAuthException catch (e) {
// handle Firebase Authentication exceptions
} catch (e) {
// handle other exceptions
}

Related

Cant register FireBase user from Flutter

I am unable to register an user from my app written in Flutter. I am also unable to get some form for error message. I can debug and see my createUser function is called and the arguments looks good. Nothing happens after I call "FirebaseAuth.instance.createUserWithEmailAndPassword". No exception and nothing is printed in the FireBase emulator console. What am I missing here? Here is what I got:
Emulator:
Running on 127.0.0.1:9099
main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform,);
try {
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
} catch (e) {
// ignore: avoid_print
print(e);
}
runApp(
MaterialApp(
title: "Foo",
home: buildContent(),
),
);
}
Registration function:
void createUser() async {
print("createUser()");
try {
final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: nameController.text,
password: passwordController.text,
);
//final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: nameController.text, password: passwordController.text);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
Edit:
I keep getting this message when i call "createUserWithEmailAndPassword"
W/System (26859): Ignoring header X-Firebase-Locale because its value was null.
In your createUser() Function i think you're sending empty values to firebase
request parameters like this and try it again
void createUser(String name, String Password) async {
print("createUser()");
try {
final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: name,
password: password,
);
print("User Created Success);
//final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: nameController.text, password: passwordController.text);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
}
} catch (e) {
print(e);
}
}
So after some trail and error I ended up adding:
android:usesCleartextTraffic="true"
To the manifest file:
...\my_project\android\app\src\main\AndroidManifest.xml
I am not sure I like the "fix" as I think the requests are sent unencrypted. A google search gives me this description:
Android 6.0 introduced the useCleartextTraffic attribute under application element in android manifest. The default value in Android P is “false”. Setting this to true indicates that the app intends to use clear network traffic

Catch block not called in async future flutter

Why is my catch block not called in this code when there is exception
Future registerWithCredentials() async {
if(state.status == RegisterStatus.loading) return;
emit(state.copyWith(status: RegisterStatus.loading));
try{
await _authRepository.register(email: state.email, password: state.password);
emit(state.copyWith(status: RegisterStatus.success));
}catch (e) {
//catch errors
debugPrint('except: "there is an error"');
emit(state.copyWith(status: RegisterStatus.error));
}
}
I have also tried like this:
try {
await _authRepository.register(email: state.email, password: state.password);
emit(state.copyWith(status: RegisterStatus.success));
} on FirebaseAuthException catch (e) {
debugPrint('except: "there is an error"');
emit(state.copyWith(status: RegisterStatus.error));
}
Repository -> register
Future<void> register({
required String email,
required String password,
}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email,
password: password);
} catch(_) {
//the catch here works but I need to send the error to cubit above and
also send to UI... how to do that
}
}
This what I want to do -> Send the error from repository to cubit to ui and display in widget/ui
If you catch the exception in the repository, then you have "used" (handled) the exception. If you want to catch the same exception in the bloc, you'll have to rethrow it. So, either re-throw the exception, or remove the try catch in the repository.

Try catch block doesn't catch rethrown error

UI code:
try {
authService.signInWithEmailAndPassword(
emailController.text, passwordController.text);
} catch (error) {
print("ui rethrow");
}
Auth service code:
Future<User?> signInWithEmailAndPassword(
String email,
String password,) async {
try {
final credential = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return _userFromFirebase(credential.user);
} catch (e) {
print("service throw");
rethrow;
}
}
I want to rethrow FirebaseAuthException from the authentication service to the UI, so I can give a user prompt with what went wrong, but the UI try-catch block doesn't catch the rethrown error.
Why doesn't my code work?

Flutter FirebaseAuth: SignInWithEmailAndPassword unable to handle error when the email address is badly formatted

Here is my email sign in method in my FirebaseAuthService class:
#override
Future<UserCustom> signInWithEmail(
String emailAddress, String password) async {
try {
UserCredential _signInWithEmailAndPasswordGoogle = await _auth
.signInWithEmailAndPassword(email: emailAddress, password: password);
if (_signInWithEmailAndPasswordGoogle.user != null) {
return _userToUserModel(_signInWithEmailAndPasswordGoogle.user);
} else {
throw PlatformException(
code: 'SIGN_IN_INTERRUPTED', message: 'Sin in interrupted');
}
} on PlatformException {
print('Happened');
rethrow;
}
}
And here is where the exception should be handled:
// creating the submit function
Future<void> _submit(EmailSignInModelProviderPattern model) async {
// if it is on sign in use sign in function ELSE use register function
try {
await model.submit();
Navigator.pop(context);
} on PlatformException catch (e) {
CustomErrorPlatformException(
title: 'Sign in failed',
exception: e,
).show(context);
} catch(e){
print(e.toString());
}
}
And yet when I enter a badly formatted address the process is interrupted at message_codecs.dart file at the method dynamic decodeEnvelope(ByteData envelope){... line 572 with error message:
Exception has occurred. PlatformException
(PlatformException(firebase_auth,
com.google.firebase.auth.FirebaseAuthInvalidCredentialsException: The
email address is badly formatted., {code: invalid-email,
additionalData: {}, message: The email address is badly formatted.}))
I couldn't figure out how to handle this exception, knowing that it never happened to me before upgrading to firebase_auth: ^0.18.0+1.
check this issues where it explains why is happens
https://github.com/FirebaseExtended/flutterfire/issues/1760
.
If you use an Emulator and change textfield with tab button then there's an extra space left behind on that email field ->*myemail#gmail.com *
to avoid this extra space you have to use .trim() method.
in your case
UserCredential _signInWithEmailAndPasswordGoogle = await _auth
.signInWithEmailAndPassword(email: emailAddress.trim(), password: password);
I guess this solves your problem.
I was having a similar issue, your code looks fine. Try disabling Uncaught Expectations in the Debugging panel for VScode solved the issue for me.
https://github.com/FirebaseExtended/flutterfire/issues/3303#issuecomment-687560133

Flutter: Checking (e) for error type after catch

I have the following code to log a user in using Firebase Auth. I'd like to display an error if the password is wrong, but not sure how to test e to see what error happened.
try {
final user = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (user != null) {
Navigator.pushNamed(context, ChatScreen.id);
}
setState(() {
showSpinner = false;
});
} catch (e) {
if (e.errorCode = ???) { <--- how to test e for the type of error ???
print(e.error);
}
}
Thanks for any help,
Paul
Firebase docs can help you with finding all the error codes. When e.code matches with a particular firebase auth code, you can generate your relevant error message.
For instance, for a wrong password entered you could do this.
if (e.code.contains('ERROR_WRONG_PASSWORD')) {
errorText = 'Wrong Password';
print(errorText);
Some of the error codes are - ERROR_WEAK_PASSWORD, ERROR_INVALID_EMAIL, ERROR_EMAIL_ALREADY_IN_USE, ERROR_USER_NOT_FOUND, ERROR_WRONG_PASSWORD