Handle Firebase_Auth errors and show errors on screen - flutter

I want to handle firebase_auth exceptions and show the error messages on the screen. I have a couple of questions regarding displaying the error messages on the screen.
Is there something that displays the messages automatically?
or do I need to provide a textfield or label for displaying the message?
I am using the latest package: firebase_auth: ^3.0.1
Here is my code for logging in:
RoundedButton(
title: 'Log In',
colour: Colors.lightBlueAccent,
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
UserCredential userCredential = await _auth.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
},
),
Everything here works but I want to display the error messages rather than put them in the console. How do I do this?

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

Flutter_Bloc 8 and Firebase Verify Email -- Clear Prior State?

I am trying to utilize FirebaseAuth's verify email functionality in my Flutter app. I'm using Flutter_BLoC 8. The code works, but when I verify the email address by clicking the link in the generated email, the prior state is apparently still buffered in my app and I need to click TWICE on the 'Continue' button to proceed to the Home Screen.
Here's my code:
ElevatedButton(
onPressed: () async {
context.read<EmailVerificationBloc>().add(const IsEmailVerified());
final isVerified = context.read<EmailVerificationBloc>().state;
if (isVerified == const EmailVerificationState.verified()) {
context.router.replace(const HomeRoute());
} else {
showErrorFlash(context, 'Email Is Not Verified');
}
},
child: const Center(
child: Text('Continue'),
),
),
Here's the BLoC event:
Future<void> _onIsEmailVerified(IsEmailVerified event, Emitter emit) async {
final successOrFailure = await _authRepository.isUserEmailVerified();
successOrFailure.fold(
(failure) {
emit(EmailVerificationState.error(failure));
},
(success) {
if (success) emit(const EmailVerificationState.verified());
},
);
}
And lastly, here's the repository method that's being called:
Future<Either<AuthFailure, bool>> isUserEmailVerified() async {
try {
await _currentUser!.reload(); // We will only call on authenticated users, so we don't expect null
return right(_currentUser!.emailVerified);
} on FirebaseAuthException catch (e) {
final error = e.code;
switch (error) {
case 'network-request-failed':
return left(const AuthFailure.noNetworkConnection());
default:
return left(const AuthFailure.unexpectedError());
}
} on PlatformException {
return left(const AuthFailure.unexpectedError());
}
}
Any ideas on how I can, for lack of a better term, flush the prior state? I'm sort of new to Flutter and BLoC, so I'm hopeful it's a relatively easy thing I'm just overlooking.
Thanks in advance.

Flutter web firebase auth signInWithPhoneNumber showing error "captcha-check-failed" in release mode

I'm facing a problem with Flutter Web Firebase Phone Auth Verification. In debug it is working well and showing me the reCaptcha. But when I host it through GitHub pages in release mode, it shows an error "captcha-check-failed". Even the capcha isn't showing in release mode.
The signInWithPhoneNumber function:
Future<void> loginWithPhoneRequestOTPWeb(
WidgetRef ref,
GlobalKey<FormState> formKey,
String phoneNumber,
) async {
try {
EasyLoading.show();
await FirebaseAuth.instance
.signInWithPhoneNumber(
phoneNumber,
RecaptchaVerifier(
container: 'recaptcha',
size: RecaptchaVerifierSize.compact,
theme: RecaptchaVerifierTheme.dark,
onError: (e) {
print(e);
EasyLoading.showError(e.message!);
return;
},
onExpired: () {
print('Expired');
EasyLoading.showError('Session Expired');
return;
},
onSuccess: () {
EasyLoading.dismiss();
print('Captcha Success');
},
),
)
.then((ConfirmationResult result) {
// update the verificationphone provider
ref.read(sendOtpProvider(formKey).state).update((_) => true);
ref.read(confirmationResultProvider(formKey).state).update((_) => result);
EasyLoading.showSuccess(t!.otpSentSuccessfully);
});
} on FirebaseAuthException catch (e) {
if (e.code == 'invalid-phone-number') {
print('The provided phone number is not valid.');
EasyLoading.showError('The provided phone number is not valid.');
} else if (e.code == 'too-many-requests') {
print(
'You have exceeded the number of attempts allowed for this operation.');
EasyLoading.showError(
'You have exceeded the number of attempts allowed for this operation.');
} else {
print(e.code.toString());
EasyLoading.showError(e.code.toString());
}
} catch (e) {
print(e.toString());
EasyLoading.showError(e.toString());
}
}
I've tried without the RecaptchaVerifier as it is optional parameter.
Error Screenshot:
If I've missed anything please let me know. Thank You :)
Okay, I've figure out my problem. In the firebase authentication section, there is an "Authorized domains" section. Here I've to add my domains. But firebase only takes .com domains. As a result, I used firebase hosting and it is working fine

Update Form validator on boolean change

I created a flutter login / register screen and want to give an error if the firebase returns an error:
if (formState.validate()) {
formState.save();
try {
UserCredential userCredential = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
User user = userCredential.user;
Navigator.popAndPushNamed(context, HomeScreen.routeName);
} catch (e) {
print(e.message);
print("failded with error code ${e.code}");
//catch if user not found
if (e.code == "user-not-found") {
setState(() {
//set true to update validator
wrongEmailOrPassword = true;
print("Error caught");
});
}
//catch if password wrong
if (e.code == "wrong-password") {
setState(() {
//set true to update validator
wrongEmailOrPassword = true;
print("Error caught");
});
}
}
}
by setting the boolean to true u want to update the input validator so that it returns an error:
validator: (value) {
if (value.isEmpty) {
return (kPassNullError);
}
if (wrongEmailOrPassword) {
return (kWrongEmailOrPassword);
}
return null;
},
But it doesnt work and doesnt update the validator / error messages. It just updates it if I reload the form. How can I update the error messages after I pressed the submit button?
Thanks for reading the long text :)
The validator functions are only called when you validate() the form. So one simple solution would be to just call formState.validate() again after receiving and setting the error. You probably don't even need the setState there then.

Firebase authentication! I'm able to move to home page even if i enter a non registered user

I've successfully added firebase to my flutter2.0 project. I've enables authentication also.I'm able to register a new user also. But the logic to move to home page after authentication is not working. I'm able to login even if I enter a wrong user. I want if I enter proper user then I should navigate to home page, but if the user is not registered it one should not be able to navigate to next page. ie..the basic use of authentication.
But it's not happening here. I'm able to navigate to next place even if I enter wrong user.
Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email:email,
password:password,
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
Future newAccount(String email, String password) async {
try {
UserCredential userCredential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
} 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.toString());
}
}
}
//this is how I can this function and try to navigate to next page.
void logMeIn() {
if (formKey.currentState!.validate()) {
authMethods
.signInWithEmailAndPassword(usernameTextEditingContoller.text,
passwordTextEditingContoller.text)
.then((value) {
print('value is: ');
print(value);
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return Home();
}));
});
}
}**strong text**
signInWithEmailAndPassword returns a UserCredential object.
In your logic, you are using .then((value) {...etc})
This value is the result of signInWithEmailAndPassword.
Try changing your logic to this:
authMethods
.signInWithEmailAndPassword(usernameTextEditingContoller.text,
passwordTextEditingContoller.text)
.then((value) {
print('value is: ');
print(value);
if(value.user ==null) return "Error in authentication"; // this will prevent your function form going further down the navigation if the usercredential doesn't have a valid user.
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) {
return Home();