Facebook login returns generic profile picture URL - firebase

Well I'm using the code from Firebase and the in the user object the photoURL which being returned is General facebook profile with no image
which is generic profile picture
Future signInWithFacebook() async {
try {
// Trigger the sign-in flow
final result = await FacebookAuth.instance.login();
// Create a credential from the access token
final FacebookAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(result.token);
// Once signed in, return the UserCredential
UserCredential res = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
User user = res.user;
//create a new document for the user with the uid
await UserProfileDatabaseService(uid: user.uid).updateUserData(
user.displayName,
user.email,
user.emailVerified,
user.phoneNumber,
user.isAnonymous
, {'helper': true},
250
); return user;
} catch (e) {
print(e.toString());
return null;
}
}

you can use the following code to display the Facebook profile picture URL after a successful login:
await FacebookAuth.instance.login();
final user = await FacebookAuth.instance.getUserData();
Image.network(user["picture"]['data']['url']);
This code logs the user in via FacebookAuth, retrieves their user data, and displays their profile picture using the Image.network widget.

Related

facebookAuthCredential.idToken is null in Flutter

I successfully integrated facebook login in android and ios, I also getting facebook access token on login but getting null in token id. Below is the code
Future<UserCredential> signInWithFacebook() async {
// Trigger the sign-in flow
final LoginResult loginResult = await FacebookAuth.instance.login();
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken!.token);
print(facebookAuthCredential.idToken); //Here getting null
// Once signed in, return the UserCredential
return FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
}
You won't get an idToken at this point with Facebook authentication flow, only accessToken. Use the following code skeleton to manage Facebook sign-in and evaluate the results at specific lines with breakpoints:
Future<UserCredential> signInWithFacebook() async {
final LoginResult loginResult = await FacebookAuth.instance.login();
if (loginResult.status == LoginStatus.success) {
final AccessToken accessToken = loginResult.accessToken!;
final OAuthCredential credential =
FacebookAuthProvider.credential(accessToken.token);
try {
return await FirebaseAuth.instance.signInWithCredential(credential);
} on FirebaseAuthException catch (e) {
// manage Firebase authentication exceptions
} catch (e) {
// manage other exceptions
}
} else {
// login was not successful, for example user cancelled the process
}
}
Then you can call this function with await, and once the future is completed, you can access user data:
final userCredential = await signInWithFacebook();
if (userCredential != null) {
// here you will have your Firebase user in:
// userCredential.user
final idToken = userCredential.user!.getIdToken();
}

firebase is not creating the user (user.uid = null)

I am trying to implemente facebook signin in flutter, however, firebase does not create a 'uid'. Doesn't the firebase create a uid automatically?
it returns:
The getter 'uid' was called on null.
Receiver: null
Tried calling: uid
below is the sign in method:
Future<UserCredential> signInWithFacebook(BuildContext context) async {
final LoginResult result = await FacebookAuth.instance.login();
if(result.status == LoginStatus.success) {
final OAuthCredential credential = FacebookAuthProvider.credential(result.accessToken.token);
return await FirebaseAuth.instance.signInWithCredential(credential)
.then((user) async {
final graphResponse = await http.get(Uri.parse(
'https://graph.facebook.com/v2.12/me?
fields=name,picture,email&access_token=${result
.accessToken.token}'));
final Map profile = jsonDecode(graphResponse.body);
if (profile != null){
authService.createUser(name: name, email: email, dob: dob, sex: sex);
}
return user;
});
}
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (context) => Profile()));
return null;
}
The sign in method returns a facebook alert dialog requesting the permission to share email, when press continue red screen with the error appears. why is the firestore not creating the user? Thanks! I am not familiar with the system and just learning.
create user method in authServices:
Future<bool> createUser(
{String name,
User user,
String email,
String password,
String phone,
String sex,
String dob}) async {
var res = await firebaseAuth.createUserWithEmailAndPassword(
email: '$email',
password: '$password',
);
if ((res.user != null)) {
await saveUserToFirestore(name, res.user, email, dob, phone, sex);
return true;
} else {
return false;
}
}
As far as I can understand your code you first login the user with Facebook and then again create a new user with createUserWithEmailAndPassword. If you use the same email for both the second one will fail and give you null.
To track the auth state for all providers use the onAuthStateChanged listener:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
// ...
} else {
// User is signed out
// ...
}
});
More about it here.

Check if user is logged in or not before authentication using google sign in - flutter

In my flutter app, am trying to check if a user is logged in or not before authenticating the user in firebase, so if he is not then do not authenticate
Future<String> loginUserWithGoogle() async {
String returnValue = "error";
GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: [
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
UserData _user = UserData();
try {
GoogleSignInAccount _googleUser = await _googleSignIn.signIn();
GoogleSignInAuthentication _googleAuth = await _googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(idToken: _googleAuth.idToken, accessToken: _googleAuth.accessToken);
UserCredential _authResult = await _auth.signInWithCredential(credential);
if (_authResult.additionalUserInfo.isNewUser) {
String userGoogleName = _authResult.user.displayName;
List userSplitName = userGoogleName.split(" ");
String userGoogleFirstName = userSplitName.first;
String userGoogleLastName = userSplitName.last;
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('googleUid', _authResult.user.uid);
await prefs.setString('googleEmail', _authResult.user.email);
await prefs.setString('googleFirstName', userGoogleFirstName);
await prefs.setString('googleLastName', userGoogleLastName);
await prefs.setString('googleUserType', "user");
returnValue = "new";
} else {
_currentUser = await RealDatabase().getUserData(_authResult.user.uid);
if (_currentUser != null) {
returnValue = "success";
}
}
} on PlatformException catch (e) {
returnValue = e.message;
} catch (e) {
print(e);
}
return returnValue;
}
}
Here what I want to check is that if it is a new user then save his google data in sharedpreference and take him to another page where he can complete some other registration and then sign him in. but what this code does is that if it is a new user it will authenticate, save the info in sharedpeference and then take him to the page and if maybe that user decided to go back to the previous page (since i use Navigator.push(context)) and still click the google sign in button again then it will take him to the home screen without him completing the other registration I want him to do because it already authenticated him first. So please is there a way to do this without first authenticating the user.
You can use stream provider to control if user logged in or not.
Here is an example how to use stream provider in your project;
https://flutterbyexample.com/lesson/stream-provider.

How can i check user id in login section?

I use Google sign in button with google package.
If user choose sign in with google, and if user login first time, then i want to create his/her account, but my code create when she/he login to app, everytime create like new user. I want to check with if statement, but how i do not know. If user uid exist in firestore, then it have not to be create new account.
This is my google sign in login function:
Future login() async {
isSigningIn = true;
final user = await googleSignIn.signIn();
if (user == null) {
isSigningIn = false;
return;
} else {
final googleAuth = await user.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
FirebaseFirestore.instance.collection('users').add({
'email': user.email,
'username': user.displayName,
'uid': user.id,
'userPhotoUrl': user.photoUrl
});
isSigningIn = false;
}
}
Firestore console image here
If you want to store per-user information in Firestore, you should use the user's UID as the ID of the document. It's guaranteed to be unique per user. Don't use add() to add the document with a random ID, use set() with the known ID to read and create the document.
Also, you should know that signInWithCredential returns the known user object, which lets you get their UID.
UserCredential userCrediental = await FirebaseAuth.instance.signInWithCredential(credential);
String uid = userCredential.user.uid;
await FirebaseFirestore.instance.collection('users').doc(uid).set(...)
If you want to check if the document was already created for that user, you can simply try to get() it first and see if it exists.
I solve this problem with my friend which is good person.
I replace this code :
await FirebaseAuth.instance.signInWithCredential(credential);
because there is a logical problem.

Flutter FirebaseUser how to access the user data

I am learning Firebase with Flutter.
Currently making an anonymous login option, here is the class I created:
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// sign in anonymously
Future signInAnonymous() async {
try{
// signs in as anon user
AuthResult signInResult = await _auth.signInAnonymously();
// retruns currently signed in user, else null
FirebaseUser userFromResult = signInResult.user;
return userFromResult; // HERE: if I add .uid, the id object is displayed
}catch(e){
print(e.toString());
return null;
}
}
}
In my login page after creating an instance and using the method, when I print the result I get FirebaseUser(Instance of 'PlatformUser') insted of the user information, here is the code:
onPressed: () async {
dynamic result = await _auth.signInAnonymous();
if(result == null){print('Error signing in.');}
else{
print('Signed in successfully');
print(result);
}
How can I access the user data?
UPDATE: If I change return userFromResult; to return userFromResult.uid; the id string is returned.
I still wonder, however, how to print the full object.
Your Result inside of the onpressed is a dynamic type cast, but it is a FirebaseUser inside.
// onPressed Callback
dynamic result = await _auth.signInAnonymous();
You can change your SignIn method with the right return type and use instead of dynamic the FirebaseUser.
Future<FirebaseUser> signInAnonymous() async {
// [...]
return userFromResult; // HERE: if I add .uid, the id object is displayed
}
onPressed: () async {
FirebaseUser result = await _auth.signInAnonymous();
print(result.uid); // should contain the id
// [...]
The difference is that in version 0.13.x the user data is available, but in the version used in this example the bersion used is 0.16.x.

Resources