Write to Firebase Firestore denied - Flutter - firebase

I am trying to save the users who sign in in the firebase database.
this is the function which is used to update the signed in user in the firebase, the fuction uses a uid to create a document with this id :
final Firestore _db = Firestore.instance;
void upadteUserData(FirebaseUser user) async {
DocumentReference ref = _db.collection("users").document(user.uid);
print("in update");
return ref.setData({
"uid": user.uid,
'email': user.email,
'displayName': user.displayName,
//'emergency': []
}, merge: true);
}
and here is the sign in fuction:
Future signInWithEmailAndPassword(String email, String password) async {
try {
AuthResult result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
upadteUserData(user);
print("signing in");
print(result.user.email);
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
here's the console after signing in
I tried it twice and it was working perfectly fine 3 weeks ago. However, when I try to sign in today with different e-mails, it did not update the fire base. Any idea?

Related

How to get the UID Authentication from Firebase in Flutter and save in Firestore

I'm trying to get the uid, but it always returns the uid of the previously created account.
createUserWithEmailAndPassword does not execute the login after being completed.
So it should be returning the uid correctly, right?
Below are 2 pictures of the database and Authentication, as well as the code.
Future _singUp() async {
final User? user = auth.currentUser;
final uid = user!.uid;
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
await FirebaseFirestore.instance.collection('users').add({
'email': _emailController.text,
'name': _nameController.text,
'Id_usuario': uid
});
} on FirebaseAuthException catch (e) {
_handleSingUpError(e);
}
}
When you use createUserWithEmailAndPassword it will return a UserCredential as a result, you can use that to update your user variable, so in code it would be something like this:
UserCredential result = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
User? user = result.user;

Avoid user Login with Firebase on Creation [duplicate]

This question already has an answer here:
Flutter - remove auto login after registration in Firebase
(1 answer)
Closed 1 year ago.
I have an app where users are supposed to be created only by Admin User's the problem is that when a new user is created in Firebase the app sign's in with the new user information, so the original logged user (Admin User), has to logged out, and log back in to create a new user.
This is my function to create a new User:
void createUser(
String email,
String password,
String nombre,
String dui,
DateTime fechaNacimiento,
String telefono,
String nombreContacto,
String telefonoContacto,
DateTime fechaIngreso,
String radio,
File foto,
String acceso,
) async {
try {
final auth = FirebaseAuth.instance;
UserCredential authResult = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
//var uploadUid = authResult.user?.uid;
final ref = FirebaseStorage.instance
.ref()
.child('user_images')
.child(authResult.user!.uid + '.jpg');
await ref.putFile(foto);
final url = await ref.getDownloadURL();
await FirebaseFirestore.instance
.collection('users')
.doc(authResult.user!.uid)
.set({
'nombre': nombre,
'dui': dui,
'fechaNacimiento': fechaNacimiento,
'telefono': telefono,
'nombreContacto': nombreContacto,
'telefonoContact': telefonoContacto,
'fechaIngreso': fechaIngreso,
'radio': radio,
'foto': url,
'acceso': acceso,
'uid': authResult.user!.uid,
'correo': email,
'contrasena': password,
});
} catch (err) {
print(err);
}
}
Any Ideas on what to do to avoid the log in on user creation of the newly created user.
Kind Regards
The original admin user does not have to be logged out to create a new user. Simply do this.
FirebaseApp secondaryApp = await Firebase.initializeApp(
name: 'SecondaryApp',
options: Firebase.app().options,
);
try {
UserCredential credential = await FirebaseAuth.instanceFor(app: secondaryApp)
.createUserWithEmailAndPassword(
email: 'email',
password: 'password',
);
if (credential.user == null) throw 'An error occured. Please try again.';
await credential.user.sendEmailVerification();
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
return _showError('The password provided is too weak.');
} else if (e.code == 'email-already-in-use') {
return _showError('An account already exists for this email.');
}
} catch (e) {
return _showError('An error occured. Please try again.');
}
...
// after creating the account, delete the secondary app as below:
await secondaryApp.delete();
The above code will not logout the admin user, the admin user can still continue with normal operations after creating the account.

User displayName returns null in Firebase Auth

I want to add a user's DisplayName upon creating a new user. When I tried to use updateProfile method, it gives below warning
/// Updates a user's profile data.
#Deprecated(
'Will be removed in version 2.0.0. '
'Use updatePhotoURL and updateDisplayName instead.',
How can get around this ??
String email, String password) async {
final UserCredential userCredential =
await _firebaseAuth.createUserWithEmailAndPassword(
email: email.trim(), password: password.trim());
await userCredential.user.updateDisplayName('Mohamed Rahuman');
User user = userCredential.user;
print(user);
return _userFromFirebaseUser(user);
}
flutter: User(displayName: null, email: test1#gmail.com, emailVerified: false, isAnonymous: false, metadata: UserMetadata(creationTime: 2021-06-06 10:35:13.689, lastSignInTime: 2021-06-06 10:35:13.689), phoneNumber: null, photoURL: null, providerData, [UserInfo(displayName: null, email: test1#gmail.com, phoneNumber: null, photoURL: null, providerId: password, uid: test1#gmail.com)], refreshToken: , tenantId: null, uid: gghhhhhhhh55555666)
THIS IS FIXED: with firebase_auth 1.3.0 (see the Changelog)
Had the same issue. Solved by calling:
await user.reload();
user = await _auth.currentUser;
this is the full code snippet:
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
User? user = result.user;
if (user != null) {
//add display name for just created user
user.updateDisplayName(displayName);
//get updated user
await user.reload();
user = await _auth.currentUser;
//print final version to console
print("Registered user:");
print(user);
}
I had the same issue in my signup function while updating (updatePhotoURL)
You need to update your user by
ourUser = FirebaseAuth.instance.currentUser;
await ourUser!.updatePhotoURL(defaultProfileImage);
await ourUser!.displayName(userName);
Check how I did it
Future register(
String email,
String password,
String? name,
String? mob,
String? description,
//DateTime? signUPDate,
) async {
setIsLoading(true);
try {
UserCredential authResult = await _firebaseAuth
.createUserWithEmailAndPassword(email: email, password: password,);
ourUser = authResult.user;
setIsLoading(false);
//create new doc for the user with his unique uid
await UserDatabaseServices(uid: ourUser!.uid)
.addUserData(ourUser!.uid,email,password,name,mob,description,currentTime);
ourUser = _firebaseAuth.currentUser;
await ourUser!.updatePhotoURL(defaultProfileImage);
notifyListeners();
return ourUser;
} on SocketException {
setIsLoading(false);
setMessage('No internet');
} on FirebaseAuthException catch (e) {
setIsLoading(false);
setMessage(e.message);
}
}
The cause of this issue was displayName and photoURL is unable to be set to null. More details are discussed here. As you've mentioned, this issue should be fixed as of version 1.3.0.
To fetch the display name configured during Registration, you can fetch by calling currentUser on your FirebaseAuth instance.
var currentUser = FirebaseAuth.instance.currentUser;
debugPrint('${currentUser.displayName}');

How to get uid of currentUser after sign up in flutter firebase

I want to get the uid and display it on screen after a user signs up.
FirebaseAuth.instance.auth.currentUser.uid;
After the user signs up the uid is null and I cant display the uid. It works only when a user signs in but not when user signs up.
How can I show the uid just after user signs up?
EDIT:
This is the provider model
class UserModel extends ChangeNotifier {
final FirebaseAuth auth = FirebaseAuth.instance;
getUid() {
final User user = auth.currentUser;
return user.uid;
}
}
I am creating the user in a separate file (auth_helper.dart)
class AuthHelper {
static FirebaseAuth _auth = FirebaseAuth.instance;
static createAccountWithEmail({email, password}) async {
final res = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
final User user = res.user;
return user;
}
}
I want to save the User in my UserModel from inside the auth_helper.dart file above. How can I do so??
You can get the signed up user's data after creating it. It will look like this:
// Example code for registration.
void _register() async {
final User user = (await _auth.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
))
.user;
if (user != null) {
setState(() {
_success = true;
_userEmail = user.email;
});
} else {
_success = false;
}
}
You can check this official Github project of the firebase_auth package.

Flutter - Get Firebase custom claims while writing Firebase user to own user instance

I am trying to implement the example given at How do I access custom claims? to my existing code.
I have a Stream which listens to auth changes and updates my own user object with the responded Firebase user. When I store my user object, I would like to get the custom claims of that user as well.
The problem is in _userFromFirebaseUser.
It says "The await expression can only be used in an async function.
Try marking the function body with either 'async' or 'async*'."
But when I do so, the error is hops to my stream where it then says "The argument type 'Future Function(User)' can't be assigned to the parameter type 'User Function(User)'." for "_userFromFirebaseUser" in
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
Here is my complete authentication class:
import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// create user obj based on firebase user
local.User _userFromFirebaseUser(auth.User user) {
final isAdmin = (await _currentUserClaims)['admin'] == true;
return user != null
? local.User(
uid: user.uid,
email: user.email,
displayName: user.displayName,
isAdmin: isAdmin)
: null;
}
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
// sign in anon
Future signInAnon() async {
try {
auth.UserCredential result = await _auth.signInAnonymously();
auth.User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
print('Successfully logged in, User UID: ${user.uid}');
return user;
} catch (error) {
print(error.toString());
return null;
}
}
// register with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
// create a new document for the user with the uid
await DatabaseService(uid: user.uid).updateUserData(null);
print('Successfully registered, User UID: ${user.uid}');
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
print('User signed out');
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
Future<Map<dynamic, dynamic>> get _currentUserClaims async {
final user = _auth.currentUser;
// If refresh is set to true, a refresh of the id token is forced.
final idTokenResult = await user.getIdTokenResult(true);
return idTokenResult.claims;
}
}
Am I heading into the wrong direction? Is there anything obvious, that I simply do not consider?
Thanks for your help!
For those, heading into the same problem, I found the solution after further research:
You will have to change the .map to .asyncMap.
Here is the code, which works for me:
import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// create user obj based on firebase user
Future<local.User> _userFromFirebaseUser(auth.User user) async {
final isAdmin = (await _userClaims)['admin'] == true;
return user != null
? local.User(
uid: user.uid,
email: user.email,
displayName: user.displayName,
isAdmin: isAdmin)
: null;
}
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().asyncMap(_userFromFirebaseUser);
}
// sign in anon
Future signInAnon() async {
try {
auth.UserCredential result = await _auth.signInAnonymously();
auth.User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
print('Successfully logged in, User UID: ${user.uid}');
return user;
} catch (error) {
print(error.toString());
return null;
}
}
// register with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
// create a new document for the user with the uid
await DatabaseService(uid: user.uid).updateUserData(null);
print('Successfully registered, User UID: ${user.uid}');
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
print('User signed out');
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
Future<Map<dynamic, dynamic>> get _userClaims async {
final user = _auth.currentUser;
// If refresh is set to true, a refresh of the id token is forced.
final idTokenResult = await user.getIdTokenResult(true);
return idTokenResult.claims;
}
}
Found here: In flutter, how can I "merge" Firebase onAuthStateChanged with user.getTokenId() to return a Stream?

Resources