Firebase Google Sign In not working in Android for Flutter - flutter

I am trying to implement a Google Sign in feature for my Flutter app. I am using Firebase Authentication for this. I have generated SHA-1 fingerprint and added the same to the android app for this Firebase project. However, when I try to run the app in the emulator or any Android device, once the account is selected the account selection dialog closes and the app stays on the login screen. When I check my Firebase Authentication console, no new user is logged in or registered with the selected Google Account.
Note: Google signin works for my app in Firebase web, but doesn't work in Android.
My Code:
firebase_auth_methods.dart
//GOOGLE SIGN-IN
Future<void> loginWithGoogle(BuildContext context) async {
try {
if (kIsWeb) {
GoogleAuthProvider googleProvider = GoogleAuthProvider();
googleProvider
.addScope('https://www.googleapis.com/auth/contacts.readonly');
await _auth.signInWithPopup(googleProvider);
} else {
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
final GoogleSignInAuthentication? googleAuth =
await googleUser?.authentication;
if (googleAuth?.accessToken != null && googleAuth?.idToken != null) {
//create a new credential
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth?.accessToken,
idToken: googleAuth?.idToken);
UserCredential userCredential =
await _auth.signInWithCredential(credential);
//if we want to SignUp with Google (not SignIn)
// if (userCredential.user != null) {
// if (userCredential.additionalUserInfo!.isNewUser) {}
// }
}
}
} on FirebaseAuthException catch (e) {
showSnackBar(context, e.message!);
}
}
signin_screen.dart
RoundedButton(
width: screenWidth * 0.1,
height: screenWidth * 0.1,
onTap: () {
context
.read<FirebaseAuthMethods>()
.loginWithGoogle(context);
//Navigator.pushNamed(context, "/home");
//Navigator.pop(context);
},
url:
"https://cdn.icon-icons.com/icons2/2631/PNG/512/google_search_new_logo_icon_159150.png",
),
What am I doing wrong, and how to solve this problem?

Related

How to link phone number to already logged in email user which is using firebase

I want to link the already login user who has login from their email id when starting the website but after completing the signup process I want to add the phone number of the user but I am getting an error as firebase creates a new id every time when creating a new id after the phone OTP verification.
So, after some digging, I found out that there is a way to LINK already logged in the user with an email with a phone number.
But, the function is not working for me
here is my code for adding a phone number and then linking it with current user credentials.
sendOTP(String phoneNumber) async {
this.phoneNumber = phoneNumber;
FirebaseAuth auth = FirebaseAuth.instance;
print('${phoneCode}');
ConfirmationResult confirmationResult =
await auth.signInWithPhoneNumber('+${phoneCode}${phoneNumber}');
if (kDebugMode) {
print("OTP send to +${phoneCode} ${phoneNumber}");
}
return confirmationResult;
}
authenticateMe(ConfirmationResult confirmationResult, String otp) async {
UserCredential userCredential = await confirmationResult.confirm(otp);
signIn(AuthCredential userCredential) async {
//now link these credentials with the existing user
UserCredential? linkauthresult =
await existingUser?.linkWithCredential(userCredential);
print('linked');
}
firebaseOtp = otp;
}
here is my User existingUser = FirebaseAuth.instance.currentUser!; variable which is i am calling in init state
#override
void initState() {
super.initState();
existingUser;
print('this is current user from otp_container ${existingUser}');
}
and here is my button onPressed function
onPressed: () {
authenticateMe(
temp,
otpCodeController.text,
);
Future.delayed(const Duration(seconds: 3))
.then((value) {
if (!mounted) {
const CircularProgressIndicator();
}
setState(() {
if (otpCodeController.text ==
firebaseOtp) {
isAnimatedContainer =
!isAnimatedContainer;
} else {
setState(() {
verifyOtpcheck = !verifyOtpcheck;
});
}
});
});
},
and I am working on flutter web.

error when i click on google sign in flutter

When I click on the "google sign in" button and then instead of continuing I click on "cancel", this error comes out: "PlatformException (PlatformException (sign_in_canceled, com.google.GIDSignIn, The user canceled the sign-in flow., Null))."
The code is this:
Future<UserCredential?> signInWithGoogle() async {
try {
// Trigger the authentication flow
final GoogleSignInAccount? utenteGoogle = await GoogleSignIn().signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication? datiUtenteGoogle =
await utenteGoogle?.authentication;
// Create a new credential
final credenzialiGoogle = GoogleAuthProvider.credential(
accessToken: datiUtenteGoogle?.accessToken,
idToken: datiUtenteGoogle?.idToken,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credenzialiGoogle);
} catch (e) {
print(e);
return null;
}
}
I tried to catch the error but nothing

Error getting thrown when trying to sign in with Google Auth to Firestore

I am trying to create a google sign in option for my app. I appear to be getting back a valid Token Id from google but my app is crashing in the ios Emulator and the following error is being shown in console.
flutter: [firebase_auth/invalid-credential] Unable to parse Google id_token: ya29.A0ARrdaM_uqbYHorJh1kJXTXac7MEm2TjD.......
When I cancel the login an error is successfully being thrown from my code. Can anyone help me out?
flutter: [firebase_auth/sign_in_canceled] The user canceled the sign-in flow.
#override
Future<User?> signInWithGoogle() async {
final googleSignIn = GoogleSignIn();
final googleUser = await googleSignIn.signIn();
if (googleUser != null) {
final googleAuth = await googleUser.authentication;
if (googleAuth.idToken != null) {
final UserCredential = await _firebaseAuth
.signInWithCredential(GoogleAuthProvider.credential(
idToken: googleAuth.accessToken,
));
return UserCredential.user;
} else {
throw FirebaseAuthException(
code: 'ERROR_MISSING_GOOGLE_ID_TOKEN',
message: 'Missing Google ID Token',
);
}
} else {
throw FirebaseAuthException(
code: 'sign_in_canceled',
message: 'The user canceled the sign-in flow.',
);
}
}
I figured it out. This line needed to be changed to pass the idToken...not the accessToken.
idToken: googleAuth.idToken,

flutter how to catch error google sign in

Future<UserCredential> signInWithGoogle() async {
// Trigger the authentication flow
final GoogleSignInAccount googleUser = await GoogleSignIn().signIn();
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
// Create a new credential
final GoogleAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
}
Future signInWithFacebook() async {
// Trigger the sign-in flow
try {
final AccessToken accessToken = await FacebookAuth.instance.login();
// Create a credential from the access token
final OAuthCredential credential = FacebookAuthProvider.credential(
accessToken.token,
);
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
} on FacebookAuthException catch (e) {
// handle the FacebookAuthException
} on FirebaseAuthException catch (e) {
// handle the FirebaseAuthException
} finally {}
return null;
}
//pub.yaml
google_sign_in: ^5.0.1
make the social login auth but I can't catch error google sign in.
I'm already Facebook sign in and apple sign in error catch but
I can't catch error on google sign in
please help me
If you make the return type of <UserCredential?> nullable, you'd be able to work with it.
//this UserCredential?
Future<UserCredential?> signInWithGoogle() async {
// Trigger the authentication flow
try {
final GoogleSignInAccount? googleUser = await (GoogleSignIn().signIn());
// Obtain the auth details from the request
final GoogleSignInAuthentication googleAuth = await googleUser!.authentication;
// Create a new credential
final GoogleAuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
) as GoogleAuthCredential;
// Once signed in, return the UserCredential
return await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {
print(e);
return null ;
}
}
Right now I'm also facing this issue. Your code is fine. Run your app in Release mode and everything will work fine as expected. It's very strange behavior.
this only occurs in Emulators, not in the real devices.

Make flutter app force a user to choose an account with FirebaseAuth and GoogleSignInAuthentication

I want to force a user to select one of his account during login time. Is there any method to do so? I haven't found any configuration like prompt=select_account+consent.
Now, with these codes, after a user logout and then try to login again, it will automatically sign in with the selected account, there is no window showing up for user to select an account.
pubspec.yaml
firebase_auth: ^0.8.1+4
google_sign_in: ^3.2.4
Login part
GoogleSignInAccount googleUser = await _googleSignIn.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
user = await _auth.signInWithCredential(credential);
Logout part
await FirebaseAuth.instance.signOut();
GoogleSignIn _googleSignIn = GoogleSignIn();
await _googleSignIn.signOut();
Use GoogleSignInAccount.disconnect() before signing out to revoke the previous authentication:
await _googleSignIn.disconnect();
await FirebaseAuth.instance.signOut();
Harold's answer used to work for me, but recently the GoogleSignIn().currentUser appears null for some devices I tested, and then the disconnect function won't work. So, what solved that problem was ensuring it is signed in to Google.
final googleCurrentUser =
GoogleSignIn().currentUser ?? await GoogleSignIn().signIn();
if (googleCurrentUser != null)
await GoogleSignIn().disconnect().catchError((e, stack) {
FirebaseCrashlytics.instance.recordError(e, stack);
});
await _auth.signOut();
A simple way to go about it :-
In your sign out method just use
_auth.signOut();
Now inside Google Sign In package, inside google_sign_in.dart
Future<GoogleSignInAccount> signIn() {
final Future<GoogleSignInAccount> result =
_addMethodCall(GoogleSignInPlatform.instance.signIn, canSkipCall: false);
bool isCanceled(dynamic error) =>
error is PlatformException && error.code == kSignInCanceledError;
return result.catchError((dynamic _) => null, test: isCanceled);
}
Find the above method & set the canSkipCall parameter as false
final Future<GoogleSignInAccount> result =
_addMethodCall(GoogleSignInPlatform.instance.signIn, canSkipCall: false);
This will enable choosing a user every time you try to sign in