I am working on a flutter application that uses Firebase Phone Number Authentication (SMS OTP). It is working perfectly on Android but having issues with the iPhone. I am testing with a real device. I am able to login with the phone number several times after installing the application. But after some time, I am not able to login with the same mobile number and it asks me to check the number correctly. The sim is on the same phone that I am testing in. The phone login is not working in a simulator or real device while debugging and hence I am having trouble figuring out this issue. Has anybody experienced such weird behaviour before? I am using flutter 1.12.13+hotfix.9 and firebase_auth 0.15.3+1 version. Any help would be appreciated. Thank you.
_verifyPhoneNumber(BuildContext context) async {
final FirebaseAuth _auth = FirebaseAuth.instance;
await _auth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: Duration(seconds: 0),
verificationCompleted: (authCredential) =>
_verificationComplete(authCredential, context),
verificationFailed: (authException) =>
_verificationFailed(authException, context),
codeAutoRetrievalTimeout: (verificationId) =>
_codeAutoRetrievalTimeout(verificationId),
// called when the SMS code is sent
codeSent: (verificationId, [code]) =>
_smsCodeSent(verificationId, [code])); }
_verificationComplete(AuthCredential authCredential, BuildContext context) {
FirebaseAuth.instance.signInWithCredential(authCredential);
if (!smsCodeSent) handleLogin(authCredential);}
_verificationFailed(AuthException authException, BuildContext context) {
showDialog(
context: context,
builder: (_) => AnimatedDialog(), // SHows diaglog box with check your number error message);}
_smsCodeSent(String verificationId, List<int> code) {
smsCodeSent = true;
_smsVerificationCode = verificationId;
smsOTPDialog(context) }
_codeAutoRetrievalTimeout(String verificationId) {
// set the verification code so that we can use it to log the user in
_smsVerificationCode = verificationId;}
smsOTPDialog(BuildContext context) {
Navigator.of(context).push(
_createRoute(userPhoneNumber, _smsVerificationCode, _fullname.text));}
You should get your number setup inside the phone authentication sign method as a test phone number. Firebase Auth will block your phone number from using the services when it detects that your phone number is calling the services repeatedly. They flag it then block it for almost 4hours. Phone authentication has a rate limit of around 5 calls per hour for every phone number.
Try checking that out.
Related
I have a strange error when I work in firebase flutter facebook login.
It always results in null email. And when I see the firebase console, the email field is registering with _.
I have searched on StackOverflow to figure out this error but could not succeed.
And I have followed the steps in facebook account for iOS setup.
What kind of possible reasons are there?
And If I try to log in with facebook, this shows "You previously logged in to this app with facebook account" even though I never logged in before...
Help me guys. I am struggling with this issue for more than 10 days!!!
// Sign in with Facebook.
static Future<Map<String, dynamic>> signInWithFacebook({bool isSignUp}) async {
try {
await signOutFacebook();
UserCredential userCredential;
// Trigger the sign-in flow
List<String> permissions = ['email', 'public_profile'];
final LoginResult loginResult = await FacebookAuth.instance.login(permissions: permissions);
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken.token);
// Once signed in, return the UserCredential
userCredential = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
final User user = userCredential.user;
print("User info after facebook login ${user.providerData[0].email} ${user.uid}");
// ************************************** This is showing null email ***** //
if (isSignUp) {
Map<String, dynamic> resultOfSaveSocialUserToDatabase = await saveSocialUserToDatabase(user, 'facebook');
return resultOfSaveSocialUserToDatabase;
} else {
Map<String, dynamic> resultOfValidateSocialLogin = await validateSocialLogin(user, 'facebook');
return resultOfValidateSocialLogin;
}
} catch (e) {
print(e);
return {'success': false, 'message': "Sign up with social account failed"};
}
}
This happens cause you might have created your facebook account using your phone number instead of email.
So, it turns out to be an empty email address as an empty identifier.
You can try out with a different fb account which may be created using an email address instead of phone number.
This can also happen when the user elects to not share his email when login in with his FB account for the first time.
I'm using Firebase PhoneAuth to authenticate users. I have done all the integrations as per instructions from reliable sources on the net.
The error that I'm facing is that, I'm not receiving call back for the code sent handler in verifyPhoneNumber method of Firebase Auth.
Here is methods used, once the user enters the phone number, the signInWithPhone() is called which in turn calls the verifyPhoneNumber().
Future<AuthUser> signInWithPhone(String phone) async {
await _firebaseAuth.verifyPhoneNumber(
phoneNumber: phone,
timeout: Duration(seconds: 60),
verificationCompleted: _phoneVerificationCompleted,
verificationFailed: _phoneVerificationFailed,
codeSent: _phoneCodeSent,
codeAutoRetrievalTimeout: _phoneCodeAutoRetrievalTimeout);
print("Phone Authentication Ended");
return null;
}
_phoneCodeSent(String verificationId, [int forceResendingToken]) async {
phoneVerificationId = verificationId;
}
Here the _phoneCodeSent() should get called when the otp has been sent. The verificationId received in this method is required for authentication purpose. Since the function doesn't get invoked I'm not receiving the verificationId but the otp is getting generated.
Any help will be appreciated.
Please make sure that you have followed these docs of firebase integration with flutter,
https://firebase.flutter.dev/docs/installation/ios
And iOS Specific setup as per this https://firebase.flutter.dev/docs/auth/phone#setup along with 4 specific handlers.
I am developing a PWA that requires Push-Notifications. Sadly IOS/Safari does not support https://w3c.github.io/push-api/#pushmanager-interface for now, so I think i might have to wrap a native APP around in some way.
In Android (before their "Trusted Web Activities" was a thing) you could use a WebView to basically display a headless Chrome-View in your App. Whats the equivalent in IOS and how does the interaction between push-notifications and the Webapp (the browser need to jump to a specific page) work?
One more thing I need is integration with our companys Mobile Device Management, which is Microsoft Intune. Having integrated MDMs in Android in the past i Know that this might be a major pain in the a**, so i'm considering to build the wrapper myself, for maximum flexibility. Another option would be something like Ionic, not sure now.
This may not necessarily work in your situation, but I had the exact same issue with a PWA for Safari and I solved it by just using long polling. It will allow you to get around all of the limitations with Safari and I was able to redirect and load sections within our SPA.
async function subscribe() {
let response = await fetch("/subscribe");
if (response.status == 502) {
// Status 502 is a connection timeout error,
// may happen when the connection was pending for too long,
// and the remote server or a proxy closed it
// let's reconnect
await subscribe();
} else if (response.status != 200) {
// An error - let's show it
showMessage(response.statusText);
// Reconnect in one second
await new Promise(resolve => setTimeout(resolve, 1000));
await subscribe();
} else {
// Get and show the message
let message = await response.text();
showMessage(message);
// Call subscribe() again to get the next message
await subscribe();
}
}
subscribe();
https://javascript.info/long-polling
How can I get the mobile phone number of the current phone where the application is running?
For example for this plugin? It would be cool to get the mobile phone number directly.
https://github.com/flutter/plugins/pull/329
this library in dart pub seem to do what you are looking for. check the package linked below:
https://pub.dev/packages/sms_autofill
PhoneFieldHint [Android only]
final SmsAutoFill _autoFill = SmsAutoFill();
final completePhoneNumber = await _autoFill.hint;
There is no way to do this with native Android/iOS code, so also not in Flutter. For example WhatsApp just ask the user to type their number and then sends an SMS with a verification code.
Edit: It is indeed now possible to ask for a phonenumber which makes it easier for the user on Android: https://pub.dev/packages/sms_autofill
However, these are phone numbers known by Google and not necessarily the phone number that is of the phone itself. Also, the user still has to select one themselves and you can't just get the info from the device.
Important: Note that mobile_number plugin asks a very special permission to make phone calls.
sms_autofill do not ask any permissions at all.
Use it like this:
#override
void initState() {
super.initState();
Future<void>.delayed(const Duration(milliseconds: 300), _tryPasteCurrentPhone);
}
Future _tryPasteCurrentPhone() async {
if (!mounted) return;
try {
final autoFill = SmsAutoFill();
final phone = await autoFill.hint;
if (phone == null) return;
if (!mounted) return;
_textController.value = phone;
} on PlatformException catch (e) {
print('Failed to get mobile number because of: ${e.message}');
}
}
There's another package now mobile_number
Its as simple as
mobileNumber = (await MobileNumber.mobileNumber)
Note: It works for Android only, because getting the mobile number of a sim card is not supported in iOS.
I was finishing up an app for somebody but needed some help with the script that I wrote for sending notifications via Cloud Functions for Firebase. Below this text you can find my code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Users/{userUid}/').onWrite(event => {
const followerUid = event.params.userUid;
const payload = {
notification: {
title: 'Update Received',
body: 'Please Check Your App',
badge: 1,
sound: 1,
}
};
return admin.database().ref('/Admin/notificationID').once('value').then(allTokens => {
if (allTokens.val()) {
// Listing all tokens.
const tokens = allTokens.value
return admin.messaging().sendToDevice(tokens, payload).then(response => {
});
};
});
});
Mainly there are only 3 issues that I am having. First of all, I am not sure if I am using the correct syntax for specifying the badge. Second of all, I don't know how to specify that I want a sound to be played for the notification. Lastly, I am unable to send the notification because the notificationID that is returned from the database is apparently incorrect even though I have a legible FCM ID stored in my database under /Admin/ with the key notificationID. I would appreciate it if one of you could help me fix these issues and get this app up and running.
Thanks,
KPS
The value for badge needs to be String:
Optional, string
Same in #1, sound value needs to be String:
Optional, string
The sound to play when the device receives the notification.
Sound files can be in the main bundle of the client app or in the Library/Sounds folder of the app's data container. See the iOS Developer Library for more information.
Hard to tell without any additional details. Are you positive that it's a valid registration token? Does it work when you send a message to it using the Firebase Console? If not, is it throwing an error?