Flutter PlatformException invalid email format - firebase

I'm tweaking my app as I go and I added a "full name" field to store in firebase and display on the user profile page. I'm getting the error "PlatformException(ERROR_INVALID_EMAIL, The email address is badly formatted., null)" when registering a new user. From other similar posts, I can't find any naming conventions which has me at a roadblock.
Register.dart:
SizedBox(height: 20.0),
TextFormField(
decoration:
textInputDecoration.copyWith(hintText: 'Full Name'),
validator: (val) =>
val.isEmpty ? 'Enter a Full Name' : null,
onChanged: (val) {
setState(() => fullname = val);
}),
SizedBox(height: 20.0),
TextFormField(
decoration:
textInputDecoration.copyWith(hintText: 'Email'),
validator: (val) =>
val.isEmpty ? 'Enter an email' : null,
onChanged: (val) {
setState(() => email = val);
}),
SizedBox(height: 20.0),
TextFormField(
decoration:
textInputDecoration.copyWith(hintText: 'Password'),
obscureText: true,
validator: (val) => val.length < 6
? 'Enter a password 6+ chars long'
: null,
onChanged: (val) {
setState(() => password = val);
}),
SizedBox(height: 20.0),
RaisedButton(
color: Colors.blue[400],
child: Text(
'Register',
style: TextStyle(color: Colors.white),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
dynamic result =
await _auth.registerWithEmailAndPassword(
fullname, email, password);
if (result == null) {
setState(() {
error = 'please supply a valid email';
loading = false;
});
}
}
}),
auth.dart
Future registerWithEmailAndPassword(String email, String password, String fullname) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}

You're function declaration says that your parameters come in this order String email, String password, String fullname, but the way you are using them is in this order fullname, email, password. Change
await _auth.registerWithEmailAndPassword(fullname, email, password);
to
await _auth.registerWithEmailAndPassword(email, password, fullname);
The only issue is a typo.
You could use named parameters, which might make it more obvious when there are issue like this, but I find it to be useful only with function or constructors with a lot of parameters.

you need to trim both email and password

Related

How to sync Firestore database and Firebase Authentication

I'm trying to create a simple banking app with flutter.I'm creating the user login information myself and trying to auth them with firebase. I already coded the authentication part of the app.Here is the code:
import 'package:banking_app_firebase/screens/customers_info.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import '../constants.dart';
class LoginScreen extends StatefulWidget {
static const String id = 'login_screen';
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _auth = FirebaseAuth.instance;
bool showSpinner = false;
String? email;
String? password;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Flexible(
child: Hero(
tag: 'logo',
child: Container(
height: 100,
child: Image.network(
"https://image.flaticon.com/icons/png/512/662/662622.png",
),
),
),
),
SizedBox(height: 20),
TextField(
keyboardType: TextInputType.emailAddress,
textAlign: TextAlign.center,
onChanged: (value) {
email = value;
},
decoration:
kTextFieldDecoration.copyWith(hintText: 'Enter your email'),
),
SizedBox(
height: 20,
),
TextField(
obscureText: true,
textAlign: TextAlign.center,
onChanged: (value) {
password = value;
},
decoration: kTextFieldDecoration.copyWith(
hintText: "Enter your password"),
),
SizedBox(
height: 24,
),
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Material(
elevation: 5,
color: Colors.white,
borderRadius: BorderRadius.circular(30),
child: MaterialButton(
onPressed: () async {
setState(() {
showSpinner = true;
});
try {
final user = await _auth.signInWithEmailAndPassword(
email: email!, password: password!);
if (user != null) {
Navigator.pushNamed(context, CustomerScreen.id);
}
setState(() {
showSpinner = true;
});
} catch (e) {
print(e);
}
},
height: 42,
child: Text(
"Login",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
),
);
;
}
}
Sample Users:
However, I don't know how to sync these information with my database so I can reach the data in the database. Here is my example database:
How can I get the informations about customers like name,surname,balance after auth is successful? I mean, how can I tell the Firebase, the auth email and password same as firestore database?
How can I get the information about customers like
name, surname, balance after auth is successful?
I understand that you want to link one document of the customers collection to each user. The classical solution to do so is to use the user uid as the Firestore document ID.
As soon as your user is created, you can get its uid and create the Firestore document, like, for example:
final user = await _auth.signInWithEmailAndPassword(
email: email!, password: password!
);
if (user != null) {
await addCustomer(user.uid, email, password);
Navigator.pushNamed(context, CustomerScreen.id);
}
...
CollectionReference customers = FirebaseFirestore.instance.collection('customers');
Future<void> addCustomer(userID, email, password) {
return customers
.doc(userID)
.set({
...
})
.then((value) => print("Customer added"))
.catchError((error) => print("Failed to add customer: $error"));
}
I understand from your comment below that you want to query the customers collection to find the user which has a specific email and password.
This is possible with a query, however I would recommend not using the password value for executing queries. This is a sensitive data that you should avoid using as a query parameter.
Actually you can very well query just by email: since you cannot create two Firebase users with the same email, you are sure that your query will return a unique result (if you didn't create some duplicate documents in the customers collection...).

Flutter check if username already exist in Firestore database

In my App I have to implement a SignUpScreen.
Everything works fine but one thing not. When someone wants to sign up he cannot use the same email like a other users, this works, but I want also that he cannot use the same username. I have a collection which is called 'SerX' and a document field which is called 'Username:' in cloud firestore. If anyone knows how to do that please comment your solution.
There should be a return like this return 'This username already exists!';
Widget _buildUserNameTF() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Username',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
keyboardType: TextInputType.text,
validator: (input) {
if (input.isEmpty) {
return 'Please enter a username';
}
if(input.length < 6){
return 'Your username needs to be at least 6 characters';
}else if(input.length > 12){
return 'Your username needs to be at most 12 characters';
}
if (!RegExp(
r'^[a-zA-Z0-9]+$')
.hasMatch(input)) {
return 'Please enter a valid username.';
}
},
onSaved: (input) => _Username = input,
style: TextStyle(
color: Colors.black,
fontFamily: 'Orbitron',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.supervised_user_circle,
color: Colors.black,
),
hintText: 'Enter your Username',
hintStyle: kHintTextStyle,
),
),
),
],
);
}
Here is a simple function for checking if the username is already exists on client side.
var _instance = Firestore.instance;
Future<bool> userExists(String username) async =>
(await _instance.collection("users").where("username", isEqualTo: username).getDocuments()).documents.length > 0;
Client side check is not a secure solution. You should use Cloud Functions for Firebase for it.
I don't know if it is the perfect solution but it works for me.
doesUserExist(currentUserName) async {
try {
// if the size of value is greater then 0 then that doc exist.
await FirebaseFirestore.instance
.collection('Users')
.where('email', isEqualTo: currentEmail)
.get()
.then((value) => value.size > 0 ? true : false);
} catch (e) {
debugPrint(e.toString());
}
}
var formKey = GlobalKey<FormState>();
var username = TextEditingController();
var password = TextEditingController();
Future<bool> userExists(username , password) async {
return await FirebaseFirestore.instance.collection('users')
.where('username', isEqualTo: username)
.where('password', isEqualTo: password)
.get()
.then((value) => value.size > 0 ? true : false);
}
login() async {
bool result = await userExists(username.text.toString(),
password.text.toString());
// ignore: unrelated_type_equality_checks
if(result == true){
Navigator.push(
context, MaterialPageRoute(builder: (context) => Home()));
}else{
password.text = '';
Fluttertoast.showToast(msg: "Incorrect Username or Password", toastLength:
Toast.LENGTH_LONG);
}
}

Return error message if password or user email wrong in flutter login form

Hy Guys I have connected flutter to my firebase project and used AUTH feature in Firebase but what I would do is to show an error message when a wrong password or Email user is wrong.
this is my code:
Widget submitButton (){
return Container(
child: SizedBox(
width: 220,
height: 40,
child: MaterialButton(
elevation: 5,
onPressed: () async {
setState(() {
showProgress = true;
});
try {
final newUser = await _auth.signInWithEmailAndPassword(email: email, password: password);
print(newUser.toString());
if (newUser != null) {
Navigator.push(context, PageTransition(
type: PageTransitionType.fade,
child: WelcomeScreen(),
));
setState(() {
showProgress = false;
});
}
} catch (e) {}
},
child: Text('Accedi',style: TextStyle(color: Colors.black),),
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: BorderSide(color: Colors.black12,width: 1)),
),
),
);
}
First you need to catch the error, you can do that by using catchError():
final newUser = await _auth.signInWithEmailAndPassword(email: email, password: password)
.catchError((err) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error"),
content: Text(err.message),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
});
Then the showDialog will have err.message which will contain the error received from Firebase Authentication.
You have two options:
1.Use an alert dialog
void _showAlertDialog(String message) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(message),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
full example
Use errorText property in InputDecoration
TextField(
decoration: InputDecoration(
errorText: this.errorText,
),
)
full example
You can use a Form() with TextFormField()
Something like this:
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
TextFormField(
key: ValueKey('email'),
validator: (value) {
if (value.isEmpty || !value.contains('#'))
return 'Please enter a valid Email address';
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(labelText: 'Email address'),
onSaved: (value) {
_userEmail = value;
},
),
It's just a dummy, but as you see there's some validation code in the validator attribute.
So what validator does is, if you return null everything is well and good, but if something is wrong, just return the String and it'll be shown below the text form field as an error message.
And to validate you can call a method like this to activate the method while form submission
void _trySubmit() {
final bool isValid = _formKey.currentState.validate();
FocusScope.of(context).unfocus();
if (isValid) {
_formKey.currentState.save();
widget.submitFn(
_userEmail.trim(),
_userName.trim(),
_userPassword.trim(),
_isLogin,
context,
);
}}
The method for getting isValid will invoke validation function of all TextFormFields, if all of them are okay, it'll return true else it'll return false.
All the _name are used to store the values in state variables using the onSaved attribute.
Let me know if you have anymore doubts.
Hope this helps✌

Error: Missing or insufficient permissions firestore

I'm having troubles with creating users in my app, I get an error that says I don't have sufficient permissions even though I should have permission. My security rules are allowing users to be created so I don't really understand why I am getting this error. What's even more strange is that it works on my mates computer, he can create users (with the exact same userdetails). He is on a pc and I on a mac not sure if that matters?
The error I get is the following:
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: PlatformException(Error 7, FIRFirestoreErrorDomain, Missing or insufficient permissions.)
Our security rules are:
service cloud.firestore {
//match /databases/{database}/documents {
match /databases/{database}/documents {
match /{document=**} {
allow read: if request.auth != null;
}
match /Users/{userId} {
allow update: if request.auth.uid == userId;
}
match /Users/{document=**} {
allow create;
}
match /Recipes/{document=**} {
allow create: if request.auth != null;
allow update, delete: if request.resource.data.userId == request.auth.uid;
}
match /Recipes/{document=**}/newRatings {
allow create, update: if request.auth != null;
}
}
} ```
Our code for registering users is:
´´´ import 'package:cibus/pages/loginScreens/username_screen.dart';
import 'package:cibus/pages/loginScreens/verify_screen.dart';
import 'package:cibus/services/colors.dart';
import 'package:flutter/material.dart';
import 'package:cibus/services/login/auth.dart';
import 'package:cibus/services/constants.dart';
import 'package:cibus/pages/loginScreens/e-sign_in_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_user_stream/firebase_user_stream.dart';
import 'package:cibus/services/my_page_view.dart';
import 'package:provider/provider.dart';
import 'package:cibus/services/login/user.dart';
import 'package:cibus/services/database.dart';
import 'package:cibus/pages/loading_screen.dart';
const registerButtonColor = kTurquoise;
const formSizedBox = SizedBox(height: 20.0);
const EdgeInsets formPadding =
EdgeInsets.symmetric(vertical: 10.0, horizontal: 50.0);
const TextStyle textStyleErrorMessage =
TextStyle(color: Colors.red, fontSize: 14.0);
const TextStyle textStyleRegisterButton = TextStyle(color: Colors.white);
OutlineInputBorder textInputBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(25.0),
);
class RegisterScreen extends StatefulWidget {
final Function toggleView;
RegisterScreen({this.toggleView});
#override
_RegisterScreenState createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>();
bool loading = false;
bool isVerified = false;
//final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
//text field state
String email = '';
String password = '';
String error = '';
String name = '';
String description = '';
String _currentUsername;
int age = 0;
int dropdownValue = null;
final TextEditingController _pass = TextEditingController();
final TextEditingController _confirmPass = TextEditingController();
#override
Widget build(BuildContext context) {
return loading
? LoadingScreen()
: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
elevation: 0.0,
title: Text('Sign up to Cibus', style: TextStyle(color: kCoral)),
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person, color: kCoral),
label: Text('Sign in', style: TextStyle(color: kCoral)),
onPressed: () {
//widget.toggleView();
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) {
return EmailSignIn();
},
),
);
},
),
],
),
body: Padding(
padding: formPadding,
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(children: <Widget>[
formSizedBox,
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: 'Email',
),
validator: (val) =>
val.isEmpty ? 'Enter an email' : null,
onChanged: (val) {
setState(() => email = val);
},
),
formSizedBox,
TextFormField(
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: 'Password',
),
obscureText: true,
controller: _pass,
validator: (String val) {
Pattern pattern =
r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!##\$&*~]).{8,}$';
RegExp regex = new RegExp(pattern);
print(val);
if (val.isEmpty) {
return 'Please enter password';
} else if (val.length < 8) {
return 'Minimum 8 characters required';
} else if (!val.contains(RegExp(r'[A-Z]'))) {
return 'One upper case letter required.';
} else if (!val.contains(RegExp(r'[a-z]'))) {
return 'One lower case letter required.';
} else if (!val.contains(RegExp(r'[0-9]'))) {
return 'One digit required.';
} else if (!val
.contains(RegExp(r'[!##$%^&*(),.?":{}|<>]'))) {
return 'One special character required.';
} /*
else {
if (!regex.hasMatch(val))
return 'Enter valid password: \n'
'Password must contain at least one upper case letter. \n'
'Password must contain at least one lower case letter. \n'
'Password must contain at least one digit. \n'
'Password must contain at least one special character.'; */
else
return null;
//}
},
onChanged: (val) {
setState(() => password = val);
},
),
formSizedBox,
TextFormField(
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: ' Re-enter Password',
),
obscureText: true,
controller: _confirmPass,
validator: (String val) {
if (val.isEmpty)
return 'Re-enter password field is empty';
if (val != _pass.text)
return 'passwords do not match';
return null;
},
onChanged: (val) {
setState(() => password = val);
},
),
formSizedBox,
TextFormField(
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: 'Name',
),
validator: (val) =>
val.isEmpty ? 'Enter your name' : null,
onChanged: (val) {
setState(() => name = val);
},
),
formSizedBox,
TextFormField(
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: 'Description',
),
minLines: 5,
maxLines: 10,
validator: (val) =>
val.isEmpty ? 'Enter your description' : null,
onChanged: (val) {
setState(() => description = val);
},
),
formSizedBox,
TextFormField(
maxLength: 20,
decoration: InputDecoration(
enabledBorder: textInputBorder,
border: textInputBorder,
labelText: 'Username',
),
validator: (val) {
if (val.length < 3)
return 'Username must be more than 2 characters';
/*else if (checkUsername == false)
return 'Username is allready taken';*/
return null;
},
onChanged: (val) {
setState(() {
_currentUsername = val;
print(_currentUsername);
});
}),
formSizedBox,
RaisedButton(
color: kCoral,
child: Text('Register', style: textStyleRegisterButton),
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() => loading = true);
bool isUsernameFree = await DatabaseService()
.isUsernameTaken(username: _currentUsername);
print(' checkUsername: $isUsernameFree');
if (!isUsernameFree) {
dynamic result =
await _auth.registerWithEmailAndPassword(
email, password, name, description, age);
if (result == null) {
setState(() {
error = 'Email is already registered';
_verificationEmailDialog();
});
} else {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) {
return VerifyScreen();
},
),
);
}
} else {
setState(() {
error = 'Username is already taken';
});
_usernameDialog();
}
}
},
),
Text(
error,
style: textStyleErrorMessage,
),
])),
),
));
}
Future<void> _usernameDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Username is already taken'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'Unfortunately it seems like your username is allready taken. Please try another one'),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Aight bruh'),
onPressed: () {
setState(() {
loading = false;
});
Navigator.of(context)
.pop(); //TODO: When popping try to keep text in forms
},
),
],
);
},
);
}
Future<void> _verificationEmailDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('Email is already in use'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(
'Unfortunately it seems like the email is already in use. Please try another one'),
],
),
),
actions: <Widget>[
FlatButton(
child: Text('Aight bruh'),
onPressed: () {
setState(() {
loading = false;
});
Navigator.of(context)
.pop(); //TODO: When popping try to keep text in forms
},
),
],
);
},
);
}
}
and here is the registerWithEmailAndPassword function:
Future registerWithEmailAndPassword(String email, String password,
String name, String description, int age) async {
try {
AuthResult result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
FirebaseUser user = result.user;
user.sendEmailVerification();
user.isEmailVerified;
print('Email verification sent?');
//create a new document for the user with the uid
await DatabaseService(uid: user.uid)
.updateUserData(name: name, description: description, age: age);
await DatabaseService(uid: user.uid).updateUserPicture(
pictureURL:
'https://firebasestorage.googleapis.com/v0/b/independent-project-7edde.appspot.com/o/blank_profile_picture.png?alt=media&token=49efb712-d543-40ca-8e33-8c0fdb029ea5');
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
It was a mistake on my part with the Security rules. I had that users could create users but they could only read if they were authenticated, so when I checked if username was taken the error occurred since I did not have the read permissions. I just added the read part on users and it works
match /Users/{document=**} {
allow create: if true;
allow read: if true;
}
´´´

how to display an error message if email and password is not valid in firebase flutter?

i have developed an login page,if the email and password matches from the database it successfully login's and moves to the new page,but if its wrong i want to display an error message email or password doesn't match.
Here's my code:
class _AdminLoginState extends State<AdminLogin> {
String _username, _password;
TextEditingController _email = TextEditingController();
final GlobalKey<FormState> _formkey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('LOGIN'),
backgroundColor: Colors.indigo[900],
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(top: 50),
child: SizedBox(
height: 150.0,
width: 300,
child: Image.asset("assets/admin.png",
fit: BoxFit.contain,),
),
),
Container(
child: Text("ADMIN",style: TextStyle(fontSize: 15,fontWeight: FontWeight.bold,color: Colors.indigo),),
),
Container(
padding: const EdgeInsets.only(bottom: 50),
child: Column(
children: <Widget>[
SingleChildScrollView(
child: Form(
key: _formkey,
child: Column(
children: <Widget>[
SizedBox(
height: 60,
),
SizedBox(
width: 380,
height: 70,
child: Container(
padding: EdgeInsets.all(4),
width: 500,
height: 60,
child: TextFormField(
autofocus: false,
obscureText: false,
keyboardType: TextInputType.emailAddress,
validator:(input){
if(input.isEmpty){
return 'please type username';
}
return null;
},
onSaved: (input) => _username =input ,
decoration: InputDecoration(
labelText: 'Email',
hintText: "Email",
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16,
),
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(20.0),
),
),
),
),
),
),
SizedBox(
width: 380,
height: 70,
child: Container(
padding: EdgeInsets.all(4),
width: 400,
height: 60,
child: TextFormField(
autofocus: false,
obscureText: true,
validator:(input){
if(input.isEmpty){
return 'please type Password';
}
return null;
},
onSaved: (input) => _password =input ,
decoration: InputDecoration(
labelText: 'Password',
hintText: "Password",
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16,
),
border: new OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(20.0),
),
),
),
),
),
),
Container(
padding: EdgeInsets.all(4),
width: 500,
height: 60,
child: RaisedButton(
onPressed: login,
textColor: Colors.white,
color: Colors.indigo[900],
child: Text('Login'),
),
)
],
),
),
),
],
),
),
],
),
),
);
}
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}catch(e){
print(e.message);
}
}
}
}
it will be really helpful if someone also helps me in validating the right email format and give give the proper validation for password
signInWithEmailAndPassword() returns an exception with a special code if the attempt is unsuccessful.
In order to print a message you need to add a catch block to your signInWithEmailAndPassword() method. Then you can use the error message.
Example:
firebase.auth().signInWithEmailAndPassword(email, password)
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
});
For security purposes I would suggest combining some of the messages together instead of giving a possible attacker a hint about if the email is already in the system or not.
I do not know how to use flutter so I can only give an idea;
In here you are directly trying to get the user from the method.
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Instead I would suggest using something like this (this is angular but I think you can easily apply to flutter with some modification)
final FirebaseUser user;
await firebase.auth().signInWithEmailAndPassword(email, password)
.then((data) => {
this.user = data.user;
})
.catch((error) => {
switch (error.code) {
case "auth/invalid-email":
case "auth/wrong-password":
case "auth/user-not-found":
{
this.accountErrorMessage = "Wrong email address or password.";
break;
}
case "auth/user-disabled":
case "user-disabled":
{
this.accountErrorMessage = "This account is disabled";
break;
}
}
You can find which kind of errors it may return from here:
https://firebase.google.com/docs/reference/js/firebase.auth.Auth.html#signinwithemailandpassword
Use errortext in InputDecoration
here is demo
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: _text,
decoration: InputDecoration(
labelText: 'email',
errorText: loginfail ? 'email not match' : null,
),
),
TextField(
controller: _text,
decoration: InputDecoration(
labelText: 'password',
errorText: loginfail ? 'password not match' : null,
),
),
RaisedButton(
onPressed: () {
login();
},
child: Text('Submit'),
textColor: Colors.white,
color: Colors.blueAccent,
)
],
),
),
);
}
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
if(!user.uid.isEmpty()){
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}else{
setState((){
loginfail = true; //loginfail is bool
});
}
}catch(e){
print(e.message);
}
}
hope it helps..
Following #Jaydeepchatrola answer's
I used a try catch block and checked if password was invalid or email, for better results!
try {
setState(() {
wrongEmail = false;
wrongPassword = false;
});
final newUser = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (newUser != null) {
Navigator.pushNamed(context, Done.id);
}
} catch (e) {
print(e.code);
if (e.code == 'ERROR_WRONG_PASSWORD') {
setState(() {
wrongPassword = true;
});
} else {
setState(() {
emailText = 'User doesn\'t exist';
passwordText = 'Please check your email';
wrongPassword = true;
wrongEmail = true;
});
}
}
You need to catch the specific error. I had the problem by myself, with this code I solved the problem.
try {
final user = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (user != null) {
Navigator.pushNamed(context, HomeScreen.id);
}
} on auth.FirebaseAuthException catch (e) {
//Here you catch the specific error
if (e.code == 'wrong-password') {
//The thing that should happen if the password is incorrect
//In my case it will the change the hinttext
setState(() {
hintTextPassword = 'Password incorrect. Please try again';
passwordHintColor = Colors.red;
});
} else if (e.code == 'user-not-found') {
setState(() {
hintTextEmail = 'No user found for that email.';
emailHintColor = Colors.red;
});
}
} catch (e) {
print(e);
}
add rflutter_alert: ^2.0.4 in your project file pubspec.yaml under dependencies: and save it
add import 'package:rflutter_alert/rflutter_alert.dart'; in your file of your auth screen
add
Alert(
context: context,
title: "Failed Login",
desc: "Incorrect Email Or Password.")
.show();
in catch(e){}
like that:
Future<void> login() async{
final formState = _formkey.currentState;
if(formState.validate()){
formState.save();
try{
final FirebaseUser user = (await FirebaseAuth.instance.signInWithEmailAndPassword(email: _username, password: _password)).user;
Navigator.push(context, MaterialPageRoute(builder: (context) => Admin()));
}catch(e){
Alert(
context: context,
title: "Failed Login",
desc: "Incorrect Email Or Password.")
.show();
}
}

Resources