Flutter - function to create user using firebase - flutter

I'm learning flutter on my own, and I'm using firebase on a small project. I'm in the stage of working with login and registrations, so I needed to use a plugin called firebase_auth: ^ 0.20.0 + 1.
However, I have reached a point in my code where one occurs, and I don't know what can cause it.
When I create the user, I indicate an email and a password in .createUserWithEmailAndPassword, if it works it should return a function to indicate success in the creation, there is no error log because I did not complete the code and performed this step, however the error is in the syntax that I'm using in this function, it doesn't seem to be in accordance with the syntax of firebase, I must be doing something wrong. He says these lines are wrong .then ((user) {firebaseUser = user;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:scoped_model/scoped_model.dart';
import 'dart:async';
import 'package:flutter/material.dart';
class UserModel extends Model {
//usuario atual
FirebaseAuth _auth = FirebaseAuth.instance;
FirebaseUser firebaseUser;
Map<String, dynamic> userData = Map();
bool isLoading = false;
void signUp(Map<String, dynamic> userData, String pass, VoidCallback onSucess,
VoidCallback onFail) {
isLoading = true;
notifyListeners();
_auth
.createUserWithEmailAndPassword(
email: userData["email"], password: pass)
.then((user) async{
firebaseUser = user;
onSucess();
isLoading = false;
notifyListeners();
}).catchError((e) {
onFail();
isLoading = false;
notifyListeners();
});
}
void signIn() async {
isLoading = true;
notifyListeners();
await Future.delayed(Duration(seconds: 3));
isLoading = false;
notifyListeners();
}
void recoverPass() {}
//bool isLoggedIn() {}
}
class FirebaseUser {}

The call to createUserWithEmailAndPassword creates a user and returns a Future<UserCredential>.
In the then (which takes care of the Future part of this result), you assign the UserCredential to your firebaseUser variable, which is defined as FirebaseUser firebaseUser. And the error message tell you that FirebaseUser and UserCredential are not compatible types.
To get the FirebaseUser from the UserCredential, use:
.then((credentials) async{
firebaseUser = credentials.user;
Depending on the version of the firebase_auth plugin you use, you might need to declare firebaseUser as:
User firebaseUser
That is the correct type in the latest version of the FlutterFire libraries, while older builds had it as FirebaseUser.
I've linked the relevant reference documentation above, as I find that most helpful when troubleshooting these types of problems. I highly recommend keeping them open while you're learning about the API.

Related

how to keep user logged in

this is how I login using Google and firebase. but I couldn't figure it out as to how to keep the use logged in.. when the app restarts it log the user out automatically
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<String> signInWithGoogle() async {
final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount!.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final authResult = await _auth.signInWithCredential(credential);
final User? user = authResult.user;
assert(!user!.isAnonymous);
final User? currentUser = _auth.currentUser;
assert(user!.uid == currentUser!.uid);
return 'signInWithGoogle succeeded: $user';
}
You can call await _auth.currentUser() at the start of your app to check the current user. Further you may want to store the token in shared preferences.
Firebase automatically persists the user credentials in the shared storage, and restores them when the app restarts. There's nothing you need to do for that.
What you will need to do though is listen for the authentication state as shown in the first code snippet in the documentation on getting the current user:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user != null) {
print(user.uid);
}
});
This code needs to run when the app starts, so I typically have it in my top-level widget and then store the user in the state so that my build method can use it. By listening to auth state changes, the code is run automatically when the user sign-in state is restored at startup (which happens asynchronously, so may take a few moments) but also when the user would later be logged out (for example, if you disable the account in the Firebase Authentication console).
It may not be the best way to do it but this worked.
chooseLogin() {
if (_auth.currentUser == null) {
return const SignUo();
} else {
return const Splash();
}
}

I'm trying to implementation Facebook SDK using Firebase but I keep getting an error on the when I copy this code in the correct spot

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
dependencies {
// Import the Firebase BoM
implementation platform('com.google.firebase:firebase-bom:29.0.1')
// Add the dependency for the Firebase SDK for Google Analytics
// When using the BoM, don't specify versions in Firebase dependencies
implementation 'com.google.firebase:firebase-analytics'
// Add the dependencies for any other desired Firebase products
// https://firebase.google.com/docs/android/setup#available-libraries
implementation 'com.facebook.android:facebook-android-sdk:latest.release'
}
}
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
abstract class AuthBase{
User get currentUser;
Stream<User> authStateChanges();
Future<User>signInAnonymously();
Future<User> signInWithGoogle();
Future<void>signOut();
}
class Auth implements AuthBase {
final _firebaseAuth = FirebaseAuth.instance;
Stream<User> authStateChanges() => _firebaseAuth.authStateChanges();
#override
User get currentUser => _firebaseAuth.currentUser;
#override
Future<User> signInAnonymously() async {
final userCredential = await _firebaseAuth.signInAnonymously();
return userCredential.user;
}
#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.idToken,
accessToken: googleAuth.accessToken,
));
return userCredential.user;
} else {
throw FirebaseAuthException(
code:'ERROR_MISSING_GOOGLE_ID_TOKEN',
message:'Missing Google ID Token',
);
}
}
else {
throw FirebaseAuthException(
code: 'ERROR_ABORTED_BY_USER',
message: 'Sign in aborted by user'
);
}
}
Future<User> signInWithFacebook() async{
final fb = FacebookLogin();
}
#override
Future<void> signOut() async {
final googleSignIn = GoogleSignIn();
await googleSignIn.signOut();
await _firebaseAuth.signOut();
// TODO: implement signOut
throw UnimplementedError();
}
}
`]1][1][I'm trying to implement facebook SDK into my project.I have followed all of the steps up to this point and you can find the link below but I'm still getting an error When I copied this code in to the Main activity page.What am I doing wrong?I posted my auth.dart file and the dependencies as well
package com.example.time_trackerpractice
import io.flutter.embedding.android.FlutterActivity
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
class MainActivity: FlutterActivity() {
}
The problem that you have (see image) its because you don't have any flutter packages related to facebook auth.
In this line of your code you are try instance a FacebookLogin, but doesn't exits any import related to facebook login.
final fb = FacebookLogin();
You can use this package to facebook login (flutter_facebook_auth), and replace your inside code of your function signInWithFacebook for this:
Future<User> signInWithFacebook() async {
final result = await FacebookAuth.instance
.login(permissions: ['email', 'public_profile']);
final accessToken = result.accessToken;
final credential = FacebookAuthProvider.credential(accessToken.token);
userCredential = await _firebaseAuth.signInWithCredential(credential);
return userCredential.user
}

show display name after signUp

I have a flutter firebase createUserWithEmailAndPassword function with the displayName update.
display name prints normally at the moment of fb user creation.
After signup MainPage loads with the users email and displayName. But displayName returns null value error. If I delete displayName from the MainPage - all works fine.
If I reload app, it works fine.
When I login, it works fine.
It can't pass the displayName at the moment of signup only.
Where I am wrong?
class AuthServiceProvider extends ChangeNotifier {
final auth.FirebaseAuth _firebaseAuth = auth.FirebaseAuth.instance;
final googleSingIn = GoogleSignIn();
UserModel? _userFromFirebase(auth.User? user) {
if (user == null) {
return null;
}
return UserModel(
user.displayName,
user.uid,
user.email,
);
}
Stream<UserModel?>? get user {
return _firebaseAuth.authStateChanges().map(_userFromFirebase);
}
Future<UserModel?> createUserWithEmailAndPassword(
String name,
String email,
String password,
) async {
try {
final userCred = await _firebaseAuth.createUserWithEmailAndPassword(
email: email,
password: password,
);
auth.User? firebaseUser = _firebaseAuth.currentUser;
if (firebaseUser != null) {
await firebaseUser.updateDisplayName(name);
await firebaseUser.reload();
firebaseUser = _firebaseAuth.currentUser;
}
print('FIREBASE USER IS $firebaseUser');
return _userFromFirebase(firebaseUser);
} catch (e) {
print(e.toString());
return null;
}
}
}
If your class were to extend either StatelessWidget or StatefulWidget, then all you'd have to do is to pass the data (displayName) between the screens.
This is not an answer but a suggestion:
You should try changing the ChangeNotifier to a StatefulWidget
and pass the data between screens...
You could also setup an
Authentication class that will hold all these Future methods so that
these calls can be reusable in your code. With this method, all you have to do is to call the specific function and give its required parameters.
As usually the solution is very simple if you think a little bit.
As all this is through the firebase auth, at the main page loading I just grab the firebase user with its display name that is saved in FB both for GoogleSignIn and createUserWithEmailAndPassword (required at registration)
import 'package:firebase_auth/firebase_auth.dart' as auth;
final auth.FirebaseAuth _firebaseAuth = auth.FirebaseAuth.instance;
final String firebaseUser =
_firebaseAuth.currentUser!.displayName ?? 'Unknown user';

How can a method which accepts parameters be called without passing it's needed values?

I found this code snippet below on GitHub:
import 'package:flutter/widgets.dart';
import 'package:firebase_auth/firebase_auth.dart';
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class UserRepository with ChangeNotifier {
final FirebaseAuth auth;
FirebaseUser _user;
Status _status = Status.Uninitialized;
UserRepository.instance({this.auth}) {
auth.onAuthStateChanged.listen(onAuthStateChanged);
}
Status get status => _status;
FirebaseUser get user => _user;
Future<bool> signIn(String email, String password) async {
try {
_status = Status.Authenticating;
notifyListeners();
await auth.signInWithEmailAndPassword(email: email, password: password);
return true;
} catch (e) {
_status = Status.Unauthenticated;
notifyListeners();
return false;
}
}
Future signOut() async {
auth.signOut();
_status = Status.Unauthenticated;
notifyListeners();
return Future.delayed(Duration.zero);
}
Future<void> onAuthStateChanged(FirebaseUser firebaseUser) async {
if (firebaseUser == null) {
_status = Status.Unauthenticated;
} else {
_user = firebaseUser;
_status = Status.Authenticated;
}
notifyListeners();
}
}
At the top where UserRepository was instantiated,
UserRepository.instance({this.auth}) {
auth.onAuthStateChanged.listen(onAuthStateChanged);
}
on auth.onAuthStateChanged.listen he passes the onAuthStatechanged method. This method as you can see below the code snippet takes in parameter FirebaseUser firebaseUser but this is never passed when called.
My question is, how can this work then if it receives no value when called?
Full disclosure: This code isn't mine, it was/is available on GitHub. I only posted it here for whoever has an answer to my question to fully understand.
"auth.onAuthStateChanged.listen" itself is a function which takes
Future<void> Function(FirebaseUser) as an argument. Function eating function thats all.
OG author could've passed a unnamed function right there like this
auth.onAuthStateChanged.listen((FirebaseUser firebaseUser){});
but that would be less readable

Cannot sign-out from Facebook using flutter with firebase

I have a flutter app where I am authenticating with Facebook and firebase on iOS. However, I cannot get the login in page again although I am calling the logout function
I always get the facebook confirmation screen which has some text that inform me that I have already logged in.
How do I logout so that the next time I am ask to enter my email/pass
here is a snippet of my code
Future<FirebaseUser> signInWithFacebook();
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<FirebaseUser> signInWithFacebook() async {
FirebaseUser user;
var result = await _facebookLogin
.logInWithReadPermissions(['email', 'public_profile']);
if (result.status == FacebookLoginStatus.loggedIn) {
FacebookAccessToken myToken = result.accessToken;
AuthCredential credential =
FacebookAuthProvider.getCredential(accessToken: myToken.token);
user = await _auth.signInWithCredential(credential);
}
return user;
}
Future<void> signOut() async {
await _facebookLogin.logOut();
await _auth.signOut();
}
Thanks for your help
Firebase saves the FirebaseUser object in cache so the user won't need to re-signin every time he leaves the app. So the signOut function should look like this:
Future<void> signOut() async {
await _facebookLogin.logOut();
await _auth.signOut();
_user = null;
}
And the FirebaseUser user; should be moved out of the signInWithFacebook function (I renamed it to _user).