I have a user management feature in my flutter app that uses firebase authentication. I can register new user accounts using firebase_auth's createUserWithEmailAndPassword() function.
return await FirebaseAuth.instance.
createUserWithEmailAndPassword(email: email, password: password);
The problem is when the registration is successful it automatically authenticates my FirebaseAuth instance as the new user even though I am already logged in.
I came across this answer: Firebase kicks out current user but it's in javascript and has a slightly different api.
How can I do the equivalent in dart?
Updated: firebase_core ^0.5.0 and firebase_auth ^0.18.0+1 has deprecated some of the old classes.
Below is code updated for firebase_core ^0.5.1 and firebase_auth ^0.18.2.
static Future<UserCredential> register(String email, String password) async {
FirebaseApp app = await Firebase.initializeApp(
name: 'Secondary', options: Firebase.app().options);
try {
UserCredential userCredential = await FirebaseAuth.instanceFor(app: app)
.createUserWithEmailAndPassword(email: email, password: password);
}
on FirebaseAuthException catch (e) {
// Do something with exception. This try/catch is here to make sure
// that even if the user creation fails, app.delete() runs, if is not,
// next time Firebase.initializeApp() will fail as the previous one was
// not deleted.
}
await app.delete();
return Future.sync(() => userCredential);
}
Original Answer
I experimented with the firebase authentication api and my current working solution is:
// Deprecated as of `firebase_core ^0.5.0` and `firebase_auth ^0.18.0`.
// Use code above instead.
static Future<FirebaseUser> register(String email, String password) async {
FirebaseApp app = await FirebaseApp.configure(
name: 'Secondary', options: await FirebaseApp.instance.options);
return FirebaseAuth.fromApp(app)
.createUserWithEmailAndPassword(email: email, password: password);
}
Essentially it comes down to creating a new instance of FirebaseAuth so the automatic login from createUserWithEmailAndPassword() do not affect the default instance.
Based on Swift's answer I post updated code for this work around.
Future signUpWithEmailPasswordAdminPastor(String email, String password, String role, String nama, String keuskupan, String kevikepan, String paroki) async {
try {
FirebaseApp tempApp = await Firebase.initializeApp(name: 'temporaryregister', options: Firebase.app().options);
UserCredential result = await FirebaseAuth.instanceFor(app: tempApp).createUserWithEmailAndPassword(
email: email, password: password);
// create a new document user for the user with uid
await DatabaseService(uid: result.user.uid).updateUserDataSelf(
true,
role,
nama,
keuskupan,
kevikepan,
paroki,
'',
DateTime.now(),
DateTime.now());
tempApp.delete();
return 'OK';
} catch (e) {
print(e.toString());
return null;
}
}
Above code works for firebase_core: ^0.5.0 and firebase_auth: ^0.18.0+1.
Related
In short, I want my Authenticated user by Email and Password in firebase firestore,
After successfully register my users only appears in a authentication pannel.
I am currently working with Flutter application where I use firebase_auth: ^1.1.1 package.
So I expect that after
UserCredential userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: "abc#example.com",
password: "SuperSecretPassword!"
);
The function called from firebase_auth package which is createUserWithEmailAndPassword
I want this registed user in Firebase Database.
Firebase authentication is used to register a user while firestore is used for storing data. If you want to add the user to firestore also then you need to add the cloud_firestore plugin to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
cloud_firestore: ^1.0.7
Then you can do:
final firestoreInstance = FirebaseFirestore.instance;
var firebaseUser = FirebaseAuth.instance.currentUser;
firestoreInstance.collection("users").doc(firebaseUser.uid).set(
{
"email" : "abc#example.com",
}).then((_){
print("success!");
});
This will create a collection called users with a document id equal to the authenticated user id, and inside of it you will have the email of the user.
.createUserWithEmailAndPassword creates a user in auth, if you check your auth tab you should see created user. It does not create user in firestore
for this you have to implement yourself .
below is a sample example
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
User user = (await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password))
.user;
//if create user succeeds
var user =UserModel(
userID:user.uid,
email:user.email)
FirebaseFirestore.instance
//save user based on their id from auth
.doc("users/${user.uid}")
.set(user.toJson());
Edit
you can create a user model
example:
class UserModel {
final String userID;
final String displayName;
final String email, pushToken;
final String phoneNumber;
final String profilePictureURL, dateJoined;
UserModel({
this.dateJoined,
this.userID,
this.email,
});
Map<String, Object> toJson() {
return {
'userID': userID,
'email': email == null ? '' : email,
'appIdentifier': 'my app',
'dateJoined': DateTime.now(),
};
}
}
....
check how to use json
In addition to the griffins answer, you could use a cloud function to respond to the user creation event (trigger onCreated). Then you can create the users collection, asynchronously, without overloading the flutter client. For example, an index.ts with the createUserInFirestore function:
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
const db = admin.firestore();
export const createUserInFirestore = functions.auth.user().onCreate(
async (user) => {
return db.collection('users').doc(user.uid).set({
"email" : user.email,
"name" : user.displayName,
});
}
);
is it possible to delete firebase account in authentication on flutter? if yes, how to do that? I have been search but not found the way.
Firestore.instance.collection("users").document(uid).delete().then((_){
// delete account on authentication after user data on database is deleted
});
Using flutter, if you want to delete firebase accounts together with the associated firestore user collection document, the following method works fine. (documents in user collection named by the firebase uid).
Database Class
class DatabaseService {
final String uid;
DatabaseService({this.uid});
final CollectionReference userCollection =
Firestore.instance.collection('users');
Future deleteuser() {
return userCollection.document(uid).delete();
}
}
Use Firebase version 0.15.0 or above otherwise, Firebase reauthenticateWithCredential() method throw an error like { noSuchMethod: was called on null }.
Authentication Class
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
Future deleteUser(String email, String password) async {
try {
FirebaseUser user = await _auth.currentUser();
AuthCredential credentials =
EmailAuthProvider.getCredential(email: email, password: password);
print(user);
AuthResult result = await user.reauthenticateWithCredential(credentials);
await DatabaseService(uid: result.user.uid).deleteuser(); // called from database class
await result.user.delete();
return true;
} catch (e) {
print(e.toString());
return null;
}
}
}
Then use the following code inside the clickable event of a flutter widget tree to achieve the goal;
onTap: () async {
await AuthService().deleteUser(email, password);
}
Code for deleting user:
FirebaseUser user = await FirebaseAuth.instance.currentUser();
user.delete();
To delete a user account, call delete() on the user object.
For more on this, see the reference documentation for FirebaseUser.delete().
User user = FirebaseAuth.instance.currentUser;
user.delete();
From this you can delete user
With a phpMySQL background, I'm a little bit lost.
I've successfully created a registration process with Flutter and Firebase Auth (simple email/password method) following a tutorial.
I would like add a "username" and "age" field to the registration form.
In Firebase I've created a database called "users", and in it a String typed "userid" that's blank. But is it even necessary? What do I do next? How is it mapped to the User UID in the authentication table? How do I push it and retrieve it with Flutter?
I've explored this post to no avail Add extra User Information with firebase
If that helps, my authentication file contains this:
class Auth implements BaseAuth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<String> signIn(String email, String password) async {
FirebaseUser user = await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
return user.uid;
}
Future<String> signUp(String email, String password) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
return user.uid;
}
Have tried this:
Future<String> signUp(String email, String password) async {
FirebaseUser user = await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
Firestore.instance.collection('users').document().setData({ 'userid': user.uid, 'displayName': 'bobby' });
return user.uid;
}
But it throws an error:
5.17.0 - [Firebase/Firestore][I-FST000001] Write at users/-L_6e1CFkU1YchxsSPay failed: Missing or insufficient permissions.
Ok seems the above is all good.
Just had to change the Database rules from false to true as per the below post:
https://stackoverflow.com/a/46925637/3475894
I'm creating app using Flutter with Firebase. I have some weird issues. I'm creating authentication and it is working fine but when i try to add some collections to my Firestore Database, the record of displayName is set to null.
Future<FirebaseUser> createUser(email, password, displayName) async {
final FirebaseUser user = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
UserUpdateInfo info = new UserUpdateInfo();
info.displayName = displayName;
_auth.updateProfile(info);
Firestore.instance.collection('users').document().setData({
'name': user.displayName,
'uid': user.uid,
'email': user.email,
'isEmailVerified': user.isEmailVerified,
'photoUrl': user.photoUrl,
});
return user;
}
this is Future class that creates user.
void _handleSubmitted() {
userAuth
.createUser(
emailController.text, passwordController.text, nameController.text)
.then((onValue) {
print("Sign Up button clicked: $onValue");
});
}
this method is handle when sign up button is clicked.
and collection looks like this picture.
If I recall correctly, the local user profile is not immediately updated when you call updateDisplayName or updatePhotoURL. This means you should either just write the local values to the database (easiest) or force a reload of the profile (safest).
Write the local values
As said, this is the simplest approach:
FirebaseFirestore.instance.collection('users').doc().set({
'name': displayName,
'uid': user.uid,
'email': user.email,
'isEmailVerified': user.emailVerified, // will also be false
'photoUrl': user.photoURL, // will always be null
});
Note that emailVerified will always be false, and photoUrl will always be null on a newly created email+password account.
Force a reload of the profile
You can force a reload of the user data by calling FirebaseUser.reload():
await _auth.currentUser!.updateDisplayName(displayName);
await _auth.currentUser!.updateEmail(newEmail);
await _auth.currentUser!.updatePhotoURL(photoURL);
await _auth.currentUser!.reload();
user = _auth.currentUser;
To Update users display name and photo url this will definitely helpful.
FirebaseUser user = await FirebaseAuth.instance.currentUser();
UserUpdateInfo userUpdateInfo = new UserUpdateInfo();
userUpdateInfo.displayName = name;
userUpdateInfo.photoUrl = url;
user.updateProfile(userUpdateInfo);
It's inconvenient the way Firebase Auth works, and they say it won't change for now, so I made a package to address this, grab it here: firebase_user_stream
In the Readme I explain the issues and how the package fixes them, there are examples and etc, enjoy!
EDIT (Jul/2020):
Firebase Auth for Flutter now has a userChanges stream:
which triggers whenever auth state, id token or profile changes occur. Essentially, this acts as a way to obtain realtime changes on currently stateless functionality (such as updateProfile).
I also tried everything but however, this works for me! Just call the FirebaseAuth.instance twice like the one in the code.
FirebaseUser currentUser = await _auth.currentUser();
await currentUser.reload();
currentUser = await _auth.currentUser();
print("Current User ${currentUser.displayName}");
print("Current User ${currentUser.photoUrl}");
hope this helps you!
First time implementing Firebase Auth, also new to Flutter dev, and I'm looking to use email and passwords, not Google sign-in. The only examples I see of Firebase Auth being used are anonymously or with Google. Is there a resource / tutorial that shows how to properly set up the calls with the signInWithEmailAndPassword method?
Many thanks!
In my app I have an auth class because I don't like to litter my widget classes with non-widget code, but you can plop this code inside your widget class if you want.
In auth.dart I have:
import 'package:firebase_auth/firebase_auth.dart';
class Auth {
final FirebaseAuth auth = FirebaseAuth.instance;
Future<User> handleSignInEmail(String email, String password) async {
UserCredential result =
await auth.signInWithEmailAndPassword(email: email, password: password);
final User user = result.user!;
return user;
}
Future<User> handleSignUp(email, password) async {
UserCredential result = await auth.createUserWithEmailAndPassword(
email: email, password: password);
final User user = result.user!;
return user;
}
}
Then in my login/register screen I create an instance of my auth class:
var authHandler = new Auth();
Finally, in my login buttons onPressed callback I have:
onPressed: () {
authHandler.handleSignInEmail(emailController.text, passwordController.text)
.then((FirebaseUser user) {
Navigator.push(context, new MaterialPageRoute(builder: (context) => new HomePage()));
}).catchError((e) => print(e));
}
Here is one example from my service. I ask for the email, name and password fields.
registerWithEmail(String name, String email, String password) async {
First I check if the email is already registered with facebook or something.
List<String> providers = await firebaseAuth.fetchProvidersForEmail(email: email);
This is not ideal solution, but you want to handle if the user is already registered, and than link email with current user
if (providers != null && providers.length > 0) {
print("already has providers: ${providers.toString()}");
return handleProviders(providers);
}
Create new User
FirebaseUser newUser = await firebaseAuth.createUserWithEmailAndPassword(email: email, password: password);
await newUser.sendEmailVerification();
This is basically it. I update the name filed of the user, since I have it.
var userUpdateInfo = new UserUpdateInfo();
userUpdateInfo.displayName = name;
await firebaseAuth.updateProfile(userUpdateInfo);
await newUser.reload();
And later You can save the user inside your firestore, where user uid is document ID. So I can get it later.
Git repo with full explanation example for Email/Password Sign in Firebase using flutter
This may help you.
Git Repo: https://github.com/myvsparth/firebase_email_signin
Full Article Step by Step: https://www.c-sharpcorner.com/article/how-to-do-simple-login-with-email-id-in-flutter-using-google-firebase/
This code is for register new user
fb_auth.UserCredential userCredential = await fb_auth
.FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email, password: password);
And this is for login previous user
fb_auth.UserCredential userCredential = await fb_auth
.FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password)
And that fb_auth is
import 'package:firebase_auth/firebase_auth.dart' as fb_auth;