Getting a null user id while accessing the id of current user in firebase flutter? - flutter

Actually I'm trying to get current user id after authentication but I don't know how to do it. While registering email/password authentication only stores email, password as well as uid. I tried to fetch that uid by calling following function after pressing login button but it return null. I am not able to get the uid of current user.
Calling a function after pressing login button:
final FirebaseAuth auth = FirebaseAuth.instance;
Future<void> inputData() async {
final User? user = await auth.currentUser;
final uid = user?.uid;
// here you write the codes to input the data into firestore
print("User id: ${uid}");
}
You can see in the console it prints null:

Most likely your inputData function runs before the user is signed in. To ensure your code can properly react to when the user is signed in or out, use an auth state listener as shown in the first snippet in the documentation on getting the current user.
Future<void> inputData() async {
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user != null) {
print(user.uid);
}
});
}

one reason why you might be getting null is you're not awaiting the getToken function, so make it a future and await it, I'm sure you'll get the token provided the user is authenticated.

Related

How to Get a Current user Information even when the User is Not Logged In ..Firebase Flutter

I'm trying to work on Forgot Password but without using firebase's sendPasswordResetEmail method..
Is it possible to reset firebase user password without logged-in. I am implementing forget-password screen where the user enter their email address and will send OTP to user email address, once OTP is verified then they can reset their password from flutter app itself.
Is there anything I can do to get the user's information while the user is Not Signed In.
Obviously it is returning Null because the user's is not signed in
I tried to get the current user information
Future validatePassword() async {
print("Inside Validate Password");
try {
var auth = FirebaseAuth.instance;
User currentUser = auth.currentUser!;
print("Current User $currentUser");
if (currentUser != null) {
print(currentUser.email);
}
} catch (e) {
print("Current user is Not Found");
}
}

Getting previous user data in flutter using firebase instead of actual user

i'm trying to show a list of data coming from the cloud firestore, and applied a filter to get this data by month. Everything works pretty fine unless once another user logs in, the data received afterwards is his data and not of the actual logged in user. Once I remove the app from the background it gets me data correctly at that time.
After some research, I realized that it has to do with cache data. I tried adding the following lines to my code:
Logout function:
await FirebaseFirestore.instance.clearPersistence();
await FirebaseFirestore.instance.disableNetwork();
Login function:
await FirebaseFirestore.instance.enableNetwork();
But nothing actually changes, is there anything I can edit/add to solve this?
Here is the code of full functions:
Future<void> loginWithEmailAndPassword(String email, String password) async {
await FirebaseFirestore.instance.enableNetwork();
UserCredential userCredential =
await auth.signInWithEmailAndPassword(email: email, password: password);
}
Future<void> logOut() async {
await FirebaseFirestore.instance.clearPersistence();
await FirebaseFirestore.instance.disableNetwork();
await auth.signOut();
}
}
Edited my code and now getting this error:
FirebaseException ([cloud_firestore/failed-precondition] Operation was rejected because the system is not in a state required for the operation's execution. If performing a query, ensure it has been indexed via the Firebase console.)

Flutter: how do I get Apple credential to link an apple account to an account on my firebase app?

The Official Firebase docs say:
...
3.Get a Credential object for the new authentication provider:
// Google Sign-in
final credential = GoogleAuthProvider.credential(idToken: idToken);
// Email and password sign-in
final credential =
EmailAuthProvider.credential(email: emailAddress, password: password);
// Etc.
4.Pass the Credential object to the sign-in user's linkWithCredential() method:
try {
final userCredential = await FirebaseAuth.instance.currentUser
?.linkWithCredential(credential);
} on FirebaseAuthException catch (e) {
// ...
}
I have not found any way to get a credential (more specifically, an AuthCredential) for Apple, which is needed as an argument to the function:
FirebaseAuth.instance.currentUser.linkWithCredential(AuthCredential credential)
I have found ways to link Google and Facebook accounts to existing accounts on my firebase app by following the above described methods, just couldn't figure out a way to get that credential object for Apple. Here's what I tried:
For Google, there is:
final credential = GoogleAuthProvider.credential(...);
For Facebook, there is:
final credential = FacebookAuthProvider.credential(...);
I could not find this in any docs, I checked, and yes, for Apple there is a similar function:
String accessToken = ? //how do I get this???
final credential = AppleAuthProvider.credential(accessToken);
The problem is, how do I get this accessToken String, which is required as a parameter? I have searched everywhere, and couldn't find a solution.
The only possibility I see now to link an apple account to an existing account on my app, is to:
call the same code that I use for Signing in With Apple
and warn the user that he should use "Show My Email" and NOT "Hide My Email", so that this "Sign in With Apple" gets added to the existing firebase account (important: I link accounts that have the same email in my firebase auth settings).
Because if the user chooses "Hide My Email" instead, a new firebase account will be created with the randomly generated email address (for anonymity) from Apple.
I have used the "the_apple_sign_in" package before. In this package:
You can get the access token from the credantial as String.fromCharCodes(appleIdCredential.authorizationCode!).
You can get the id token from the credantial as String.fromCharCodes(appleIdCredential!.identityToken!).
Perhaps you can similarly get the Firebase credential. Also here you can find a sample code with this package:
final FirebaseAuth _auth = FirebaseAuth.instance;
Future<UserModel?> signInWithApple(
{List<Scope> scopes = const [Scope.email, Scope.fullName]}) async {
UserModel userModel;
// 1. perform the sign-in request
final result = await TheAppleSignIn.performRequests(
[AppleIdRequest(requestedScopes: scopes)]);
// 2. check the result
switch (result.status) {
case AuthorizationStatus.authorized:
final appleIdCredential = result.credential;
final oAuthProvider = OAuthProvider("apple.com");
final credential = oAuthProvider.credential(
idToken: String.fromCharCodes(appleIdCredential!.identityToken!),
accessToken:
String.fromCharCodes(appleIdCredential.authorizationCode!),
);
final authResult = await _auth.signInWithCredential(credential);
final firebaseUser = authResult.user;
firebaseUser!.updateDisplayName(
'${appleIdCredential.fullName!.givenName} ${appleIdCredential.fullName!.familyName}');
userModel = UserModel(
uid: firebaseUser.uid,
name: firebaseUser.displayName,
email: firebaseUser.email,
image: firebaseUser.photoURL,
idToken:
String.fromCharCodes(appleIdCredential.authorizationCode!));
return userModel;
case AuthorizationStatus.error:
return null;
case AuthorizationStatus.cancelled:
return null;
}
}

How to increase Firebase Authentication Session Time using Flutter?

I developed an Agro App and I have enabled offline persistence because, after logging in, operators can spend 3-4 hours recording information offline until they return to the central point where there is internet.
The problem I have is that sometimes the application asks for credentials (login and password) again when they do not have internet, which means that they cannot record information offline or they have to go back to the central point to authenticate which is not efficient.
I understand that the Firebase auth token lasts up to an hour, how can I extend this time?
The way I am authenticating users using a provider is like following:
class UsuarioProvider {
final FirebaseAuth _firebaseAuth;
DatabaseReference db = FirebaseDatabase.instance.reference();
UsuarioProvider({FirebaseAuth firebaseAuth})
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
Future <Map<String, dynamic>> signIn(String email, String password) async {
try {
UserCredential result = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password);
User user = result.user;
final token = await user.getIdToken();
return {'ok' : true, 'token' : token, 'localId': user.uid, 'email' : user.email};
} catch (e) {
print(e);
return {'ok': false, 'code': '${e.code}', 'mensaje': '${e.message}' };
}
}
How can I increase the Firebase Token Time? or How can I prevent users from being prompted for credentials when they are offline?
UPDATE:
The way I'm using to call firebase is:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final prefs = new PreferenciasUsuario();
await prefs.initPrefs();
final pushNotificationsProvider = new PushNotificationsProvider();
pushNotificationsProvider.initNotifications();
FirebaseDatabase database;
database = FirebaseDatabase.instance;
database.setPersistenceEnabled(true);
database.setPersistenceCacheSizeBytes(10000000); // 10MB de cache
runApp(MyApp());
}
Firebase Authentication uses two types of tokens: a refresh token that "never" expires, and a short-lived ID token that is valid for an hour but is auto-refreshed by the SDK. There is no way to expand the life-time of the ID tokens.
If you want to pass a value along to a client that they can use for a longer period of time, you can mint an authentication cookie, which can be valid for up to two weeks. Note that this is a sensitive operation, so it can only be performed in trusted environments (typically by using the Firebase Admin SDK). For a full walkthrough of the process, see the Firebase documentation on Managing Session Cookies.

Getting data of currently signed in user in real time - Flutter & Firestore

I want each user to see his/her data in real time. The app requires
the user data to change in real time. The code I wrote is only
showing the data of the first user in the firestore collection. When
a second logs in, the details of the first user is shown, instead of
the second user. Here is my code:
_getTapCount(){ Firestore.instance.collection('user_collection').where('userId',
isEqualTo: _uid).snapshots().listen((event) {
if(event.documents.isNotEmpty){
var mydata = event.documents[0].data;
setState(() {
_tapCount = mydata['tapCount'];
});
} }); }
To become the data from the current logged in user you can use the following code as an example.
FirebaseUser currentUser = await FirebaseAuth.instance.currentUser();
var userData = await Firestore.instance.collection("user_collection").document(currentUser.uid).get();
print(userData['userDataFieldYouWant']);
With the currentUser() method you become the current logged in user. After this you can become the uid from the FirebaseUser object (here currentUser) and then you can access the data from the user with the get() method.