Flutter local_auth dialog closes if authentication fails - flutter

I am using https://pub.dev/packages/local_auth library to implement local_auth in my app.
I am using the following code to authenticate.
Future<void> _authenticate() async {
bool authenticated = false;
try {
authenticated = await auth.authenticateWithBiometrics(
localizedReason: 'Scan your fingerprint to authenticate');
print('Authentitcated: $authenticated');
} on PlatformException catch (e) {
print(e);
}
}
If authentication is success it shows Authenticated: true but it does not show anything if authentication fails. Also, the authentication dialogue closes automatically if authentication fails.
How do I return the authentication false status also keep the dialogue open even after authentication is failed?

Related

Flutter Firebase phone Auth not catching errors

I am using phone authentification with OTP codes with flutter.
My code:
checkPin(String pin) async {
setState(() {
checkingPin = true;
});
UserCredential? response;
try {
PhoneAuthCredential? credential = PhoneAuthProvider.credential(
verificationId: verificationCode, smsCode: pin);
response = await FirebaseAuth.instance.signInWithCredential(credential);
} on FirebaseAuthException catch (err) {
print(err);
} on FirebaseException catch (err) {
print(err);
} on PlatformException catch (err) {
print(err);
} catch (err) {
print(err);
}
When purposely entering te wrong code, it throws a PlatformError. Despite me catching multiple errors (including PlatformError) in the ty catch block.
The error reads:
PlatformException (PlatformException(invalid-verification-code, The SMS verification code used to create the phone auth credential is invalid. Please resend the verification code SMS and be sure to use the verification code provided by the user., {code: invalid-verification-code, message: The SMS verification code used to create the phone auth credential is invalid. Please resend the verification code SMS and be sure to use the verification code provided by the user., nativeErrorMessage: The SMS verification code used to create the phone auth credential is invalid. Please resend the verification code SMS and be sure to use the verification code provided by the user., nativeErrorCode: 17044, additionalData: {}}, null))
I do not understand why it crashes the app rather than catching the error, when i explicity try to catch PlatformExceptions. My firebase_auth package version is :^3.3.5.

linkWithCredential and Flutter Web with Apple

I have a use case where a user, on Flutter Web, needs to link an Apple auth with their existing account, and the email may not match.
However, the only available method for Flutter Web Apple Authentication is signInWithPopUp. If the user's apple email is different from the User firebase account email, a new firebase account is created, and a user is returned, short circuiting the process of linking, this creates a new account in firebase, and I'm unable to linkWithCredential.
My method to try to link accounts is as follows:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await _auth.signInWithPopup(provider).then((appleCredential) async {
final authCredential = appleCredential.credential;
await user.linkWithCredential(authCredential!).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
});
} catch (e) {
return 'Error: $e';
}
return 'Success';
}
As you would expect, my project starts with Streaming a User Object, and when the pop up signs in, it returns the new user, which rebuilds the entire project. Is there a way to authenticate an apple user without returning a new user? I can link a google or phone authorization method fine. It's apple that is problematic. I don't fully understand why Google doesn't break in the same way, other than Firebase put in the work to ensure the functionality of linking for GoogleSignIn().signIn() I'm not using other social auth methods, and I don't use password/email.
This method is not documented in the Flutter Fire Docs, but works perfectly:
Future<String> linkWithAppleWeb() async {
try {
final User user = _auth.currentUser!;
final provider = OAuthProvider("apple.com")
..addScope('email')
..addScope('name');
await user.linkWithPopup(provider).then((result) {
DatabaseService().updateUserSocialAuth(user.uid, 'apple');
return 'Success';
}).catchError((e) {
return 'Error: $e';
});
} catch (e) {
debugPrint('auth linkWithGoogle error: ${e.toString()}');
return 'Error: $e';
}
return 'Success';
}

Google Auth Page always shown, how to Auth only first time

I am making a calendar app with flutter using googleApi library.
but, When you turn off the app, need to auth again in web site.
i want auth only first time.
is it possible?
// mycode
get _SCOPES => [CalendarApi.CalendarScope];
await clientViaUserConsent(_clientID, _SCOPES, prompt)
.then((AuthClient client) async {
CalendarClient.calendar = CalendarApi(client);
calendarId = await CalendarClient.calendar.calendarList
.list()
.then((value) => value.items[0].id);
});
void saveData(AccessCredentials credentials) {
GetStorage().write(credetialKey, {
"accessTokenData": credentials.accessToken.data,
"accessTokenExpiry": credentials.accessToken.expiry.toString(),
"refreshToken": credentials.refreshToken,
"scopes": credentials.scopes,
"idToken": credentials.idToken
});
}
AccessCredentials getCredetial() {
try {
var map = GetStorage().read(credetialKey);
return AccessCredentials(
AccessToken("Bearer", map["accessTokenData"] as String,
DateTime.parse(map["accessTokenExpiry"])),
map["refreshToken"],
map["scopes"].cast<String>(),
idToken: map["idToken"] as String);
} catch (e) {
return null;
}
}
Client cli = Client();
var c = await refreshCredentials(_clientID, getCredetial(), cli)
.catchError((e) {
print(e);
});
authenticatedClient(cli, c);
error :
DetailedApiRequestError(status: 401, message: Request is missing required authentication credential. Expected OAuth 2 access tok
You can save user session using for example sharedPreferences. Each time the user launch the app your must first check if the session is saved so you can skip the auth process, otherwise you initiate the authentication
i solved it.
save AccessCredentials,
and use autoRefreshingClient;
Client cli = Client();
var c = await refreshCredentials(_clientID, getCredetial(), cli)
.catchError((e) {
print(e);
});
cli = autoRefreshingClient(_clientID, c, cli);

Flutter: Google SignIn without Firebase

I am trying to implement Google SignIn in flutter without using Firebase.
I am using Google SignIn package, taking idToken from there and sending it to my backend API for authentication.
I am getting pop up for selecting user email but after selecting, I am getting following error:
error: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 12500: , null)
Below is my code in BLoC for handling Google SignIn:
if (event is GoogleSignInButtonPressed) {
yield LoginInProgress();
try {
GoogleSignIn _googleSignIn = GoogleSignIn(scopes:['email']);
GoogleSignInAccount user = await _googleSignIn.signIn();
print(user);
GoogleSignInAuthentication googleSignInAuthentication = await user.authentication;
String idToken = googleSignInAuthentication.idToken;
final token = await userRepository.authenticateWithGoogleSignIn(idToken: idToken);
authenticationBloc.add(AuthenticationLoggedIn(token: token));
yield LoginInitial();
} catch (error) {
yield LoginFailure(error: error.toString());
}
Firebase isn't required to use Google Sign-in. You can use google_sign_in plugin to authenticate the user. The ApiException that you're getting likely comes from not configuring the app properly on the Google Could API dashboard. Ensure that you've filled all the required fields on the OAuth console.

Flutter Pin/Password/Pattern Integration

I have went through the local_auth package and it works fine, but it does not have an option to authenticate with password or pin. Help appreciated!
String _authorized = 'Not Authorized';//Start
Future<Null> _authenticate() async {
final LocalAuthentication auth = new LocalAuthentication();
bool authenticated = false;
try {
authenticated = await auth.authenticateWithBiometrics(
localizedReason: 'Scan your fingerprint to authenticate',
useErrorDialogs: true,
stickyAuth: false);
authenticated = await auth.authenticateWithBiometrics(localizedReason: 'Authenticate');
} on PlatformException catch (e) {
print(e);
}
if (!mounted) return;
setState(() {
_authorized = authenticated ? 'Authorized' : 'Not Authorized';
});
}//End
So this is the example code and you can use biometric authentication but what about the default Pin/Password authentication that is also present with fingerprint.
For security reason, mobile (iOS/Android) will only authenticate user by biometrics, not system password/pin. If you want to let user authenticate by other methods than biometrics, the app itself must store and process (encrypted) credential which is totally separated from system password/pin.
You can see this behavior (to use system-biometrics AND app-specific credential) in many bank/financial related app, such as https://play.google.com/store/apps/details?id=com.konylabs.capitalone&hl=en