Flutter firebase: reauthentication - flutter

I have a section of an app dedicated to deleting all of a user's data. Firebase auth requires a user to reathenticate before deleting its data, so im trying the following function:
onPressed: () async {
try {
AuthCredential
credential =
EmailAuthProvider
.credential(
email: '',
password: '',
);
_firebaseAuth.currentUser!
.reauthenticateWithCredential(
credential);
BlocProvider.of<
ProfileBloc>(
context)
.add(DeleteProfile(
user: user,
stingrays: stingrayState
.stingrays,
));
Navigator.pushNamed(
context, '/wrapper/');
} on Exception catch (e) {
print(e.toString());
}
},
In this case, setting the email and password as '' should throw an error. My current idea is that the function should run until reauthenciation is called, then an error should be thrown and it does not finish the deleting process. However, it currently does not operate like this, instead running through the entire function. Any idea how to fix this conditional reauthentication method?
Thank you!

You can just call return whenever you want your code to stop and it will.
So after your authentication do this.
_firebaseAuth.currentUser!.reauthenticateWithCredential(credential);
return;
Also reauthenticateWithCredential() is a Future<void> so you have to await it:
return await _firebaseAuth.currentUser!.reauthenticateWithCredential(credential);

Related

Flutter Firebase OTP verification fails even though both sent and entered OTP are the same

I am trying to implement OTP verification in my Flutter app using Firebase, but I am facing an issue where the verification fails even though both the sent and entered OTP are the same.
I am using the following function to verify the OTP:
void verifyOtp({
required BuildContext context,
required String verificationId,
required String userOtp,
required Function onSuccess,
}) async {
_isLoading = true;
notifyListeners();
try {
PhoneAuthCredential creds = PhoneAuthProvider.credential(
verificationId: verificationId, smsCode: userOtp);
User? user = (await _firebaseAuth.signInWithCredential(creds)).user!;
print('signwithcredential passed');
if (user != null) {
_uid = user.uid;
onSuccess();
}
} on FirebaseAuthException catch (e) {
print('failed Userotp: $userOtp');
showSnackBar(context, e.message.toString());
_isLoading = false;
notifyListeners();
}
}
The error I am getting is "FirebaseAuthException: sms code has expired please resend the verification code to verify again."
I am new to Flutter and Firebase, so any help in fixing this problem would be greatly appreciated.
Here are couple of things I have found maybe they will work:
Check the Firebase Console to ensure that the phone number being verified is correctly set up and that the SMS code is being sent to the right number.
Make sure that the phone number is being passed in the correct format.
FirebaseAuthException is being caught correctly. Make sure the message inside the catch block is being logged or displayed to the user.
Ensure that the dependencies and packages are correctly installed and imported.
The solution is itself an error you are getting. You have to enter the code before it expire. Try to verify the otp as soon as you get the code as it's saying "I/flutter ( 9598): error on firebaseAuthexception: [firebase_auth/session-expired] The sms code has expired. Please re-send the verification code to try again. ".

Error when trying to authenticate users with google in firebase

I've been struggling with this for months, sinc.e I'm just learning firebase with flutter.
I have a simple button that when pressed should give the option to register or start section with google, but when running I get errors in the console.
There are so many that I don't know which one it is.
Error: Assertion failed:
file:///C:/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.7.2/lib/src/firebase_core_web.dart:207:11
options != null
"FirebaseOptions cannot be null when creating the default app."
Error: [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
here in onpress of the button:
child: MaterialButton(
onPressed: () async {
User? user = await Authenticator.IniciarSesion(context: context);
print(user?.displayName);
},
and the class that authenticates
class Authenticator {
static Future<User?> IniciarSesion({required BuildContext context}) async {
FirebaseAuth authenticator = FirebaseAuth.instance;
User? user;
GoogleSignIn objGooglesignIn = GoogleSignIn();
GoogleSignInAccount? objGooglesignInAccount =
await objGooglesignIn.signIn();
if (objGooglesignInAccount != null) {
GoogleSignInAuthentication objGoogleSignInAuthentication =
await objGooglesignInAccount.authentication;
AuthCredential credential = GoogleAuthProvider.credential(
accessToken: objGoogleSignInAuthentication.accessToken,
idToken: objGoogleSignInAuthentication.idToken);
try {
UserCredential userCredential =
await authenticator.signInWithCredential(credential);
user = userCredential.user;
return user;
} on FirebaseAuthException catch (e) {
print("error de auth");
}
}
}
}
Sorry if I put a lot of code. I don't know exactly what the error could be.
There are two issues with your application, first one seems like you are not initializing firebase in the main function properly. Please refer mentioned link for setup.
Flutter firebase setup guide
Additionally as I can see there is no firebase_options.dart in your lib directory which basically manages (api key) configurations for different platforms.
If you have followed steps mentioned in guide correctly you can create these configs using
flutterfire configure
command only after you have already installed flutterfire cli using following command
dart pub global activate flutterfire_cli

Why am I not getting a password reset email from the Firebase service?

I am trying to implement a password reset function that incorporates a SnackBar to display either success or error messages. The code shown below produces both the success message and the various error messages, as appropriate - but I never receive the password reset email from the Firebase service. I'm not sure if it's a Firebase setup issue or an issue with the code.
Future resetPassword() async {
try {
await FirebaseAuth.instance
.sendPasswordResetEmail(email: _emailController.text.trim());
_showSnackBar('Password reset link sent');
} on FirebaseAuthException catch (e) {
_showSnackBar(e.message.toString());
return;
}
}
Future<void> _showSnackBar(String msg) async {
final snackBar = SnackBar(
content: Text(msg),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
Disregard. Code seems to work fine - problem was either with Firebase Auth service or my internet service provider last night. All good now.
Make sure to check your spam, because if did not add authorize rules in firebase then the reset link goes in spam mail.
.

creating user is changing the current user

I have following code to login in firebase using flutter. This works fine.
FirebaseAuth.instance.signInWithEmailAndPassword(email: myemail, password: mypassword);
After successful authentication, I am creating nw user using below code.
UserCredential userCredentials = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: myemail, password: mypassword);
but, with approach, the current user changes. I want to create the user without changing the current User. Is this possible?
I have found one solution and it's working for me
In main dart file initializeApp like this
void main() async{
await Firebase.initializeApp();
runApp(MyApp());
}
Create a simple/admin user
FirebaseAuth.instance.signInWithEmailAndPassword(email: myemail, password: mypassword);
Add another user
FirebaseApp app = await Firebase.initializeApp(
name: 'secondary', options: Firebase.app().options);
await FirebaseAuth.instanceFor(app: app)
.createUserWithEmailAndPassword(
email: _email, password: _password);
app.delete();
This is a duplicate of Flutter: Firebase Authentication Create User Without Automatically Logging In, but I can't flag the question as it has an open bounty.
You need to create a second instance of FirebaseApp and create the new user with that instance:
static Future<UserCredential> register(String email, String password) async {
FirebaseApp app = await Firebase.initializeApp(
name: 'Secondary', options: Firebase.app().options);
try {
UserCredential userCredential = await FirebaseAuth.instanceFor(app: app)
.createUserWithEmailAndPassword(email: email, password: password);
}
on FirebaseAuthException catch (e) {
// Do something with exception. This try/catch is here to make sure
// that even if the user creation fails, app.delete() runs, if is not,
// next time Firebase.initializeApp() will fail as the previous one was
// not deleted.
}
await app.delete();
return Future.sync(() => userCredential);
}
What you are trying to do is not secure (generating someone else's password)
And you are correct in that sense there is no way to create a password for another email, as an admin.
What you want to do is sendSignInLinkTOEmail.
This is just the same procedure to sign up with GSuit and other popular services as well.
In case if you really need to set up users, you have to use a separate auth module (should be easy to write your own) and not firebase, and then link the users together when they sign up. It's a hacky way and I don't recommend it.

I can't catch the exception of Firebase Auth on flutter

I'm trying to making a signin feature on my app using firebase auth on flutter.
There are many exceptions I have to deal with but I can't catch them at all.
Here is my code.
Future<void> onSubmitted(
String email, AnimationController controller, BuildContext context) async {
controller.repeat();
FirebaseAuth _auth = FirebaseAuth.instance;
try {
_auth.signInWithEmailAndPassword(email: email, password: "1");
} on PlatformException catch (e) {
debugPrint(e.toString());
} on FirebaseAuthException catch (e) {
debugPrint(e.toString());
}
}
This is simplified form for testing. Anyway it doesn't even reach the catch statement. It raises PlatformException before it reaches the catch statement. I don't understand.
The error code is like this.
Unhandled Exception: [firebase_auth/user-not-found] There is no user record corresponding to this identifier. The user may have been deleted.
I explicitly specified the type of the exception and it's supposed to print the error message but it doesn't even reach debugPrint() function.
How should I catch the exception?
The problem was 'they were actually caught'.
There is no problem in catch statement or anywhere but the behavior of the debugger was the problem. On Android Studio I can adjust the setting so it doesn't stop when the exception raises but on VSCode, no matter what I do, it will stop when the exception is raised before the catch statement.
So if I want to continue to the next lines, I just have to click continue in the debugging toolbar.
But I really hope I can change the setting of the breaks on exceptions on VSCode as well.
According to the official FlutterFire Documentation, you should store the `UserCredential`
retrieved from method `signInWithEmailAndPassword()` object in a variable. So your code should look something like this:
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: email,
password: "1"
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user exists with this email.');
} else if (e.code == 'wrong-password') {
print('Incorrect Password.');
}
}
Have you done all the necessary?
Create the ios/Android apps in Firebase console
Enable the different sign-in methods (google, email, etc.)
Download the google-services.json and GoogleService-info.plist and place them in their appropriate folders
Also, _auth.signInWithEmailAndPassword(email: email, password: "1") is a async process and takes time to complete.
You need to have await
This appears to be an issue with how errors are thrown and caught when dealing with async, FlutterFire hasn't gotten around to putting theirs into try/catch yet - which we can't do anything about.
Here they discuss it: https://github.com/FirebaseExtended/flutterfire/issues/3475
Here is a pending fix: https://github.com/FirebaseExtended/flutterfire/pull/3700
At the moment the answer seems to be essentially to either step through the exceptions, or uncheck 'Uncaught exceptions' in the debugger (which is not great since it won't catch actual exceptions..)