displayname returns null after registration on flutter - firebase

Display name returns null right after registration. However, if i login with the same email id, the display name shows up magically. Looked up some of the answers here but didn't find anything relevant to implementation in flutter.
My Code:
Future createUserWithEmailAndPassword(
String email, String password, String name) async {
try {
UserCredential userCredential = await _auth
.createUserWithEmailAndPassword(email: email, password: password);
await userCredential.user.updateProfile(displayName: name);
print(userCredential.user.displayName);
User user = userCredential.user;
db.setProfileonRegistration(user.uid, name);
return _userFromFireBase(userCredential.user);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
return null;
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
return null;
}
} catch (e) {
print(e);
return null;
}
}

The rest of the function is not waiting for line 6, but you are expecting the code is waiting for successful execution of that line before continue
Instead of using
await userCredential.user.updateProfile(displayName: name);
Try using this
Future createUserWithEmailAndPassword(
String email, String password, String name) async {
try {
UserCredential userCredential = await _auth
.createUserWithEmailAndPassword(email: email, password: password);
userCredential.user.updateProfile(displayName: name).then((_) {
print(userCredential.user.displayName);
User user = userCredential.user;
db.setProfileonRegistration(user.uid, name);
return _userFromFireBase(userCredential.user);
});
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
return null;
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
return null;
}
} catch (e) {
print(e);
return null;
}
}
It will wait until
userCredential.user.updateProfile(displayName: name)
Future resolves and then continues with the rest of the code in the .then block

Related

FlutterFire authentication using role authentication

I'm trying to sign in based on the role of the user from firebase. But mostly, the tutorials i saw are using older firebase version, therefore I'm using firebase documentation and my logic.
here is my function for auth role sign in
Future<User?> signIn(String email, String password) async {
try {
UserCredential userCredential = await _auth.signInWithEmailAndPassword(
email: email, password: password);
User? user = userCredential.user;
await FirebaseFirestore.instance
.collection('users')
.doc(user!.uid)
.get()
.then((DocumentSnapshot documentSnapshot) {
var docData = documentSnapshot.data();
var role = docData['role'];
if (documentSnapshot.data()['roles'] == 'dosen') {
return 'ok';
} else {
return 'err';
}
});
return user;
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
}
but mostly having problem with this section
the error is like this
"The method '[]' can't be unconditionally invoked because the receiver can be 'null'. Try making the call conditional (using '?.') or adding a null check to the target ('!')."
await FirebaseFirestore.instance
.collection('users')
.doc(user!.uid)
.get()
.then((DocumentSnapshot documentSnapshot) {
var docData = documentSnapshot.data();
var role = docData['role'];
if (documentSnapshot.data()['roles'] == 'dosen') {
return 'ok';
} else {
return 'err';
}
});
Thank you.
---------------EDIT---------------
i've solved it using this
Map<String, dynamic> data =
documentSnapshot.data()! as Map<String, dynamic>;
so then i can pass the data using string, in which i call it like this
role = data['role'].toString();
thank you for the help :)
REPLACE THIS:
if (documentSnapshot.data()['roles'] == 'dosen')
WITH:
if (documentSnapshot.data()!['roles'] == 'dosen')

Flutter User creation and Signing in

Here is my code
I am trying to run this code with no avail.
import 'package:firebase_auth/firebase_auth.dart';
class AuthClass {
FirebaseAuth auth = FirebaseAuth.instance;
//create account
Future<String> createAccount(
{required String email, required String password}) async {
try {
await auth.createUserWithEmailAndPassword(
email: email, password: password);
return "Account created";
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
return 'The password provided is too weak.';
} else if (e.code == 'email-already-in-use') {
return 'The account already exists for that email.';
}
} catch (e) {
return 'Error Occured';
}
}
//sign in user
Future<String> signIn(
{required String email, required String password}) async {
try {
await auth.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
return 'No user found for that email.';
} else if (e.code == 'wrong-password') {
return 'Wrong password provided for that user.';
}
}
}
// reset password
Future<String> resetPassword({
required String email,
}) async {
try {
await auth.sendPasswordResetEmail(
email: email,
);
return 'Email Sent';
} catch (e) {
return 'Error Occured';
}
}
//sign out
void signOut() {
auth.signOut();
}
}
I need some help I am getting this error,
The body might complete normally, causing 'null' to be returned, but the return type is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
Future signIn(...) "signIn"
Future createAccount(...) "createAccount"
is where i am getting the error
try on catch blocks work like this.
try executes code. If that fails, it throws an Exception.
Now, that Exception can be of many types and using on and catch together we can catch a specific exception and get that value inside e.
But the on FirebaseAuthException catch (e), only catches Exceptions of type FirebaseAuthException.
So, in a case where your try block throws something else, maybe NumberException, then it won't be caught.
For catching all other types of Exceptions, you need to add another catch block.
Like this,
try {
await auth.signInWithEmailAndPassword(email: email, password: password);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
return 'No user found for that email.';
} else if (e.code == 'wrong-password') {
return 'Wrong password provided for that user.';
}
} catch (e) {
return 'Unknown Error.'; // Change this to whatever you want.
}
Think of the try like an if block. Then your on FirebaseAuthException catch (e) would be an if else block. But you also need to handle the else block and that is your catch (e).
Hope it makes sense.

Flutter Firebase try catch does not fire

When using firebase auth and type not registered email,
although I used try - catch, that does not fire.
fAuth.signInWithEmailAndPassword definitely throw PlatformException but that code does not catch that.
I suffered this problem about 2days..... please help me
Future<bool> signInWithEmail(String email, String password) async {
try {
var result = await fAuth.signInWithEmailAndPassword(
email: email, password: password);
if (result != null) {
setUser(result.user);
FirebaseFirestore.instance.collection("User").doc(_user.uid).get().then((doc) {
info.set(
name: doc["name"],
email: doc["email"],
phoneNumber: doc["phoneNumber"],
follower: doc["follower"],
following: doc["following"],
like: doc["like"],
review: doc["review"],
visited: doc["visited"],
favorite: doc["favorite"],
);
print(doc['name']);
notifyListeners();
});
return true;
}
return false;
} on PlatformException catch (e) {
List<String> result = e.toString().split(", ");
setLastFBMessage(result[1]);
return false;
} on Exception catch (e) {
List<String> result = e.toString().split(", ");
setLastFBMessage(result[1]);
return false;
} catch (e) {
List<String> result = e.toString().split(", ");
setLastFBMessage(result[1]);
return false;
}
}

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?

Couldn't catch new FlutterFire Firebase Auth

I've been trying to catch exception from the new https://firebase.flutter.dev/ Firebase Auth and failed.
Not sure what went wrong, here is my code for signIn with email and password function:
try {
UserCredential userCredential = await _firebaseAuth
.signInWithEmailAndPassword(email: email, password: password);
if (userCredential != null) {
_user = userCredential.user;
}
} on FirebaseAuthException catch (e) {
print(e.code);
} on PlatformException catch (e) {
print(e.message);
} catch (e) {
print(e.toString());
}
return _user;
}
Have you check at firebase console authentication whether your user is listed there or not.
If it not that's the problem, you can add new user at the console and try again login with email and password u just add.
You can use something like this,
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}
More Error Codes: https://firebase.google.com/docs/reference/js/firebase.auth.Auth#error-codes_12

Resources