Flutter Firebase - failing to properly delete a Google authenticated user - firebase

I'm trying but failing to re-trigger the authentication steps that the user gets taken through when they authenticate themselves using Google sign-in, following deletion of the user. The deleted user simply gets signed in immediately (instead of being taken through the authentication steps), when using Google sign-in the second time. I want to be able to re-trigger the authentication steps for my own testing purposes.
Specifically, I've got a user who I've authenticated and signed in as per the FlutterFire documentation, i.e.
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);
}
I then proceed to delete the user; again, as per the FlutterFire documentation, i.e.
try {
await FirebaseAuth.instance.currentUser.delete();
} catch on FirebaseAuthException (e) {
if (e.code == 'requires-recent-login') {
print('The user must reauthenticate before this operation can be executed.');
}
}
That works, insomuch as the user is no longer listed amongst the authenticated users in the Firebase console. However, if I now proceed to call signInWithGoogle() again, then instead of getting taken through the authentication steps again (i.e. being prompted to enter an email, password, etc.), the user simply gets signed in straight away. It's as if the user hasn't been properly deleted. How would I go about re-triggering the authentication steps?

You must also call GoogleSignIn().signOut() after the Firebase sign out or delete.

In my case, I had to reauthenticate firebase user inside the delete functions try-catch as currentUser() always return null AND GoogleSignIn().signOut() didnt work. Maybe a bug.
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
//will need to sign in to firebase auth again as currentUser always returns null
//this try-catch block should be inside the function that deletes user
try {
//FirebaseUser user = await _auth.currentUser(); //returns null so useless
//signin to google account again
GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
//get google credentials
AuthCredential credential = GoogleAuthProvider.getCredential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken);
//use credentials to sign in to Firebase
AuthResult authResult = await _auth.signInWithCredential(credential);
//get firebase user
FirebaseUser user = authResult.user;
print(user.email);
//delete user
await user.delete();
//signout from google sign in
await _googleSignIn.signOut();
} catch (e) {
print('Failed to delete user ' + e.toString());
}

Related

Flutter Firebase Permission Denied

After i sign out, i try to log in again, yes it logs in succesfully but the problem is, i start to get error [cloud_firestore/permission-denied] but when i restart my application, it works again well. What am i missing?
PS: im logging in with Google.
This is my log in code:
Future 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 credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// Once signed in, return the UserCredential
await _auth.signInWithCredential(credential);
}
This is my sign out code:
await _googleSignIn.signOut().then((value) async {
await widget.firebaseAuth.signOut().then((value) {
Navigator.pop(context);
});
}).onError((error, stackTrace) {
print(error);
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("ERROR!! TRY AGAIN"),
));
});
The cloud_firestore/permission-denied error comes from Firestore (the database), not from Firebase Authentication.
Most likely you have some realtime listeners in your code that require the user to be signed in, and those get rejected by the database once you sign the user out.
You can either remove the listeners by canceling the subscriptions, or you can ignore the errors, as the listeners are also canceled automatically after this error occurs.
In my case, I forgot to activate "google-sign in" as an authentication method in firebase.

How to access Google username for flutter authentication. Lit Firebase Auth

I'm a bit new to this, but I'm confused about how to access a user's Google username when signing in with Google. I used Lit Firebase Auth so that basically I have to just say
context.signInWithGoogle();
But I need a display name as in my database when a user signed up with email they could enter a username, by which the text they entered would be stored and then later display as their username.
Here is my register.dart
try {
await Firebase.initializeApp();
UserCredential user = await FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
User updateUser = FirebaseAuth.instance.currentUser;
updateUser.updateProfile(
displayName: _usernameController.text);
userSetup(_usernameController.text);
Navigator.of(context).pushAndRemoveUntil(
HomeScreen.route, (route) => false);
}
And the important part is the
userSetup
Which from my database will take that text and update the displayName.
So I guess I'm asking what to fill userSetup() instead of _usernameController.text in the case of Google sign in.
You can try out the following code for the google signing in flutter and getting credential from google and use them to firebase and the variable user contain all the user information like email, imageurl and name.
GoogleSignIn _googleSignIn = new GoogleSignIn();
GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
AuthCredential credential = GoogleAuthProvider.credential(idToken: googleSignInAuthentication.idToken, accessToken: googleSignInAuthentication.accessToken);
var result = (await _auth.signInWithCredential(credential));
_user = result.user;

Flutter web google sign in - the popup doesn't show, sign in button does nothing

I have a Flutter web app which uses Google sign in, managed with Firebase. If I run it with flutter run -d chrome, when I click on the sign in button, it pops up the Google sign in pane, however after writing in my email address, it says that it's an unsafe browser and that I should try to use another browser. After some research, I founda workaround, opening the localhost:5000 from a separate chrome window. In this case, the issue is that it doesn't show the popup.
I don't know if it has to do anything with the issue, but when I inspect the element it shows this warning:
The code I use to handle the sign-in:
import "package:firebase_auth/firebase_auth.dart";
import "package:google_sign_in/google_sign_in.dart";
class GoogleSignInService {
final GoogleSignIn _googleSignIn;
final FirebaseAuth _auth;
GoogleSignInService(this._googleSignIn, this._auth);
Future<FirebaseUser> handleSignIn() async {
FirebaseUser user;
bool isSignedIn = await _googleSignIn.isSignedIn();
if (isSignedIn) {
user = await _auth.currentUser();
} else {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken, idToken: googleAuth.idToken);
user = (await _auth.signInWithCredential(credential)).user;
}
return user;
}
}
I call the handlesignin in the onPressed of my sign in button. I use version 4.5.4 of the google_sign_in package. I have done everything suggested here: https://pub.dev/packages/google_sign_in_web

Link Multiple Auth Providers to an Account

I have implemented Facebook and Google sign in.
But FireBase document says this will cause an error if the same user first signs up with Facebook and later try sign in with Google (with the same email).
So I follow doc and try to configure account linking.
But I do not know how to do.
Should I try link account every time user is logged in? Problem is I not know if the user already has signed in with another auth provider.
For example, the original code has:
Google:
void _signInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);
}
Facebook:
void _signInWithFacebook() async {
final AuthCredential credential = FacebookAuthProvider.getCredential(
accessToken: _tokenController.text,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);
}
Is correct to call every time in _signInWithFacebook() and _signInWithGoogle() :
user = await auth.linkWithCredential(credential);
For example:
void _signInWithFacebook() async {
final AuthCredential credential = FacebookAuthProvider.getCredential(
accessToken: _tokenController.text,
);
final FirebaseUser user = await _auth.signInWithCredential(credential);
user = await auth.linkWithCredential(credential); //new
}
How I can implement correctly?
Thanks!
When the user enters their email address to sign in, you'll want to use fetchSignInMethodsForEmail() to find out if that email address is already known.
If a user has already signed up with another provider, that's a good moment to ask them if they want to merge those accounts, and then call the account linking API.

Sign In Google will stuck on black screen when try to Add Users Flutter

Hi so i try to add firebase auth on my app, so i followed the documentations in here https://pub.dartlang.org/packages/firebase_auth from the plugin creators it self, It works well at first, but then i'm just ecounter an error or bug, its when i'm tried to add users instead of choose users that already login in my device, after add the users it will stuck forever in black sreen like the picture above, it not giving some error message it just stuck there. So is there anyone that already has same issues like me ? is there any solutions for this ? here is my code for handle the sign in
Future<FirebaseUser> _handleSignIn() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
GoogleSignInAccount googleUser = await _googleSignIn.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
FirebaseUser user = await _auth
.signInWithGoogle(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
Navigator.of(context).pushReplacementNamed('/HomeScreen');
await prefs.setString('accesToken', googleAuth.accessToken);
await prefs.setString('email', googleUser.email);
await prefs.setString('displayName', googleUser.displayName);
await prefs.setString('photoUrl', googleUser.photoUrl);
return user;
}
Most probably this happens because you have not enabled the Sign-in Method in Firebase Console.
Just enable Required Sign-in Methods and it should work fine.

Resources