Flutter: Firebase send me a wrong code in flutter app - firebase

I am using Firebase_auth package for verifying phone number, Firebase send code but when I check the validity of code it just show error. when I print code sent it is different with the code that I receive. any one know please help me.
thanks in advance.
here is my code:
await FirebaseAuth.instance.verifyPhoneNumber(
timeout: Duration(seconds: 60),
phoneNumber: phoneNumber,
verificationCompleted:
(PhoneAuthCredential phoneAuthCredential) {
print(phoneAuthCredential.smsCode);
print("complete");
},
verificationFailed: (e) {
print("failed");
print(e);
},
codeSent: (same, a) {
print(a);
print(same);
Navigator.of(context).pushNamed(
VerifyScreen.routName,
arguments: {
'code': a,
'customerId': customerId,
},
);
},
codeAutoRetrievalTimeout: (sa) {
print(sa);
print("timeout");
},
);

I know the code received cannot be printed, but it comes in encrypted form verificationId.
When the entered code is verified, you send the code that was entered by the user and the verificationId to Firebase to verify it.
If your goal is to be verified automatically without entering the code through this verificationCompleted, you can transfer the user automatically.
Note: Provided that the sim card is on the same phone to which the code was sent.
Additional information: If you want the process to be automatic, use the following code:
Future singInPhoneNumber() async {
FirebaseAuth _auth = FirebaseAuth.instance;
_auth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: Duration(seconds: 60),
verificationCompleted: (AuthCredential phoneAuthCredential) async {
//Automatically verify
Navigator.of(context).pushNamed(
VerifyScreen.routName,
arguments: {
'code': a,
'customerId': customerId,
},
);
debugPrint("Firebase Auth :Auto Verification Completed");
},
verificationFailed: (FirebaseAuthException error) {
debugPrint("ERROR Firebase Auth : AuthException : ${error.message}");
showToast(context, 'Something went wrong, please try again later');
},
codeSent: (String verificationId, [int forceResendingToken]) {
setState(() {
this.verificationId = verificationId;
});
},
codeAutoRetrievalTimeout: (String verificationId) {
return null;
},
);
}
If you only want to enter the code manually:
AuthCredential credential = PhoneAuthProvider.credential(
verificationId: verificationId, smsCode: codeController.text);
_auth
.signInWithCredential(credential)
.then((value) => {
print('The operation completed successfully')
})
.catchError((onError) {
print(onError.toString());
});

Related

Firebase Flutter error Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference

im having trouble with authentication on Firebase.
there is a login screen that asks for the number, then on the next button press it goes to the OTP screen that results in authenticating the user.
But after the verification number is typed, it doesnt authenticate and says Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
this is the code that i use to verify the user
final String PhoneNumber; //globally declared
_verifyPhone() async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: widget.PhoneNumber,
verificationCompleted: (PhoneAuthCredential credential) async {
await FirebaseAuth.instance
.signInWithCredential(credential)
.then((value) async {
if (value.user != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
EmailScreen(PhoneNumber: widget.PhoneNumber),
),
);
}
});
},
verificationFailed: (FirebaseAuthException e) {
print(e.message);
},
codeSent: (String verificationID, int resendToken) {
setState(() {
_verificationCode = verificationID;
});
},
codeAutoRetrievalTimeout: (String verificationID) {
setState(() {
_verificationCode = verificationID;
});
},
timeout: Duration(seconds: 60));
}
and this is the OnSubmit function of the PinEntryTextField
PinEntryTextField(
fields: 6,
showFieldAsBox: true,
onSubmit: (String pin) async {
try {
await FirebaseAuth.instance
.signInWithCredential(PhoneAuthProvider.credential(
verificationId: _verificationCode, smsCode: pin))
.then((value) async {
if (value.user != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EmailScreen(
PhoneNumber: widget.PhoneNumber,
)));
}
});
} catch (e) {
FocusScope.of(context).unfocus();
print(e);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Failed because $e"),
));
}
},
),
Now it works sometimes, but sometimes it doesn't, that's the weird thing.
any help would be appreciated..
thanks
Never mind, i had to wait a few seconds until the SMS code "arrives"..
Because i was using a test phone number
Silly me 😂😂
Please verify if the phone number is not going to be null. In my case phone number is going null so this error was come.

Firebase Phone Authentication just timing out and not sending SMS or Auto Login

I have implemented the Firebase phone authentication on my flutter application. But anytime I send invoke the initAuth method, I get code sent on my console then after 60 secs timed out. That I understand is simply coming from my code but I expected an SMS or an auto login. It seems I don't ever get the verificationCompleted method invoked.
Below is my code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class PhoneVerification{
initAuth({BuildContext context, String phoneNumber}) async{
print(phoneNumber);
var firebaseAuth = FirebaseAuth.instance;
await firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: Duration(seconds: 60),
codeSent:(String verificationId, [int forceResendingToken]){
print("Code Sent");
},
codeAutoRetrievalTimeout: (String verificationId){
print("Timed out");
},
verificationCompleted: (AuthCredential auth) async {
print("This User is authenticated by google play services");
firebaseAuth.signInWithCredential(auth)
.then((AuthResult result) =>{
if(result != null && result.user != null){
print("Authentication is Successful")
}else{
print("Authentication failed!")
}
})
.catchError((error){
print(error);
});
},
verificationFailed: (AuthException authException){
print('Error message: ' + authException.message);
},
);
}
}
This is the method I wrote to invoke the initAuth method:
Future<void> sendSMS({context}) async{
User user = Provider.of<UserProvider>(context, listen: false).user;
PhoneVerification phoneVerification = PhoneVerification();
await phoneVerification.initAuth(context: context, phoneNumber: user.phone);
}
Then finally, I am making the actual call onPress of a button in a component. Below is how I invoked the sendSMS method.
EnterPhone(onPress: ()=> sendSMS(context: context)),
for me :
// For firebase auth
final auth = FirebaseAuth.instance;
//
final PhoneVerificationCompleted verificationCompleted =
(AuthCredential phoneAuthCredential) async {
final res = await auth.signInWithCredential(phoneAuthCredential);
// Todo After Verification Complete
);
};
//
final PhoneVerificationFailed verificationFailed =
(AuthException authException) {
print('Auth Exception is ${authException.message}');
};
//
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
print('verification id is $verificationId');
verId = verificationId;
};
//
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) {
verId = verificationId;
};
//
await auth.verifyPhoneNumber(
// mobile no. with country code
phoneNumber: '+91${_mobile.text}',
timeout: const Duration(seconds: 30),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);

Flutter phone number authentication null verificationId?

I am trying to conduct a phone number login by sending sms code to my phone device using firebase auth. But the await keyword does not seem to work here. Why? my assumption is when I assign await to a function, Flutter prints the null value of the verificationId variable, verificationId gets its value within the _sendCodeToPhoneNumber function. Hence this could mean the function _sendCodeToPhoneNumber hasn't finished yet but the its next line of code (print(verificationId) in this case) is already executed. But if I am mistaken, then what is the problem? and more important, please teach me how to resolve problem? Because I have to get verificationId's value and pass it to the next class.
String verificationId;
Future<void> _sendCodeToPhoneNumber() async {
...
final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) async {
this.verificationId = verificationId; //this.verificationId here is not null because it has got a value
print('Code sent to ${_phoneNumberController.text} with $verificationId');
};
...
await FirebaseAuth.instance.verifyPhoneNumber(
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout,
phoneNumber: _phoneNumberController.text,
codeSent: codeSent,
timeout: const Duration(seconds: 120),
verificationCompleted: verificationCompleted,
verificationFailed: vericationFailed
);
}
...
FlatButton(onPressed: (){
await _sendCodeToPhoneNumber();
print(verificationId); // printed null despite having assigned `await` to the _sendCodeToPhoneNumber function
...
})
Change the function to the following and return the verificationId:
Future<String> _sendCodeToPhoneNumber() async {
final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) async {
this.verificationId = verificationId; //this.verificationId here is not null because it has got a value
print('Code sent to ${_phoneNumberController.text} with $verificationId');
};
await FirebaseAuth.instance.verifyPhoneNumber(
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout,
phoneNumber: _phoneNumberController.text,
codeSent: codeSent,
timeout: const Duration(seconds: 120),
verificationCompleted: verificationCompleted,
verificationFailed: vericationFailed
);
return this.verificationId;
}
Also change the onPressed, when using await you need to use async:
FlatButton(onPressed: (()async{
var result = await _sendCodeToPhoneNumber();
print(result);
}))
final PhoneCodeSent codeSent = (String verificationId, [int forceResendingToken]) async {
this.verificationId = verificationId; //this.verificationId here is not null because it has got a value
print('Code sent to ${_phoneNumberController.text} with $verificationId');
};
i think you dont need async here

Flutter Firebase authentication only work when you give test phone number

My code is working but it authenticate only the test phone no, which is given in the Firebase authentication.
when I'm trying with other number is directly going to PhoneVerificationFailed() and this is the exception msg im getting from this method :-
Error Message
Phone number verification failed. code: firebaseAuth. Message: this app is not authorized to use Firebase Authentication. Please verify that the correct package name and SHA-1 are configured in the Firebase Console. [ App validation failed]
Please have a look,and share your thoughts,may be im doing some mistakes.
// Example code of how to verify phone number
void _verifyPhoneNumber() async {
setState(() {
_message = '';
});
final PhoneVerificationCompleted verificationCompleted =
(AuthCredential phoneAuthCredential) {
_auth.signInWithCredential(phoneAuthCredential);
setState(() {
_message = 'Received phone auth credential: $phoneAuthCredential';
});
};
final PhoneVerificationFailed verificationFailed =
(AuthException authException) {
setState(() {
_message =
'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}';
});
};
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
widget._scaffold.showSnackBar(const SnackBar(
content: Text('Please check your phone for the verification code.'),
));
_verificationId = verificationId;
};
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) {
_verificationId = verificationId;
};
await _auth.verifyPhoneNumber(
phoneNumber: _phoneNumberController.text,
timeout: const Duration(seconds: 5),
verificationCompleted: verificationCompleted,
verificationFailed: verificationFailed,
codeSent: codeSent,
codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
}
// Example code of how to sign in with phone.
void _signInWithPhoneNumber() async {
final AuthCredential credential = PhoneAuthProvider.getCredential(
verificationId: _verificationId,
smsCode: _smsController.text,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
setState(() {
if (user != null) {
_message = 'Successfully signed in, uid: ' + user.uid;
} else {
_message = 'Sign in failed';
}
});
}
If u guys need full code please comment it,i'll share full code then
SHA-1 configuration is not completed at Firebase end,once SHA-1 Configuration is done it will start to run perfectly.
check this link for configuring SHA-1
https://stackoverflow.com/a/56091158/12072674

How to use the forceResendingToken in firebase phone auth in flutter to resend the otp

I am looking for a way to resend the OTP in firebase verifyPhoneNumber in flutter.
I have gone through the example about phoneAuth but could not find a way to resend OTP.
There is an option of forceResendingToken
final PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async {
this.verificationId = verificationId;
_smsCodeController.text = testSmsCode;
};
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: this._phone,
codeAutoRetrievalTimeout: autoRetrieval,
codeSent: smsCodeSent,
forceResendingToken: ,//how to get this token
timeout: const Duration(seconds: 40),
verificationCompleted: verifSuccessful,
verificationFailed: verifFailed);
}
How to use this token to resend the OTP.
From the Firebase reference documentation:
the ForceResendingToken obtained from onCodeSent(String, PhoneAuthProvider.ForceResendingToken) callback to force re-sending another verification SMS before the auto-retrieval timeout.
So in your case that'd be the PhoneCodeSent callback of the verifyPhoneNumber() call.
You have to record the value of resendToken from the codesent callback and pass it to the forceresendingtoken. Also, the inbuilt timeout duration is 30 seconds So make sure you tap on resend button after timeout seconds, you may use timerbutton package it's very handy in this case.
Firebase sends 3x same SMS code and then change it to different.
String _verificationId = "";
int? _resendToken;
Future<bool> sendOTP({required String phone}) async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: phone,
verificationCompleted: (PhoneAuthCredential credential) {},
verificationFailed: (FirebaseAuthException e) {},
codeSent: (String verificationId, int? resendToken) async {
_verificationId = verificationId;
_resendToken = resendToken;
},
timeout: const Duration(seconds: 25),
forceResendingToken: _resendToken,
codeAutoRetrievalTimeout: (String verificationId) {
verificationId = _verificationId;
},
);
debugPrint("_verificationId: $_verificationId");
return true;
}

Resources