Login using firebase and flutter
Abdelouahedd
Posted on June 18, 2020
In this article, I will show you how to create a login and register in firebase using Flutter.
First , create your project in firebase a,d activate a mode of authentification in firebase auth after configurate your project and put your file google-service.json in the folder app in project.
First we create a model of our user :
class User {
String _id;
String username;
String email;
String city;
DateTime birthDay;
String profileImg;
String _password;
double rank;
User({
String id,
this.username,
this.email,
String password,
this.city,
this.birthDay,
this.profileImg,
this.rank = 0,
}) : _id = id,
_password = password;
String get id => _id;
void setId(String uuid) => _id = uuid;
String get password => _password;
factory User.fromRawJson(String str) => User.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
username: json["username"],
email: json["email"],
password: json["password"],
city: json["city"],
birthDay: (json["birthDay"] as Timestamp).toDate(),
profileImg: json["profileImg"] == null ? null : json["profileImg"],
rank: json["rank"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"username": username,
"email": email,
"password": password,
"city": city,
"birthDay": birthDay,
"profileImg": profileImg == null ? null : profileImg,
"rank": rank,
};
@override
String toString() {
return """
User : { \n
username : $username - \n
email : $email - \n
password : $password -\n
city : $city -\n
profileImg : $profileImg -\n
rank : $rank\n
}\n""";
}
}
After that we cant create a class that contient our methodes of sign in and sign ou :
class UserController {
final FirebaseAuth _auth = FirebaseAuth.instance;
User _user;
UserController({User user}) : _user = user;
Future signIn(String email, String password) async {
try {
await _auth
.signInWithEmailAndPassword(email: email, password: password)
.then((value) => this.getUser(value.user.uid))
.timeout(new Duration(seconds: 60))
.catchError(
(onError) =>
print("Error while sign in to app :${onError.message}"),
);
return _user;
} catch (e) {
print("Error while sign in to app :${e.message}");
return null;
}
}
Future<bool> signOut() async {
try {
await _auth.signOut();
print("Success log out");
return true;
} catch (err) {
print("Error while user sign out : ${err.message}");
return false;
}
}
Future getUser(String uid) async {
await Firestore.instance
.collection("users")
.document(uid)
.get()
.then((value) => {
_user = User.fromJson(value.data),
print("Returned user from getUser ${_user.toString()}")
})
.catchError((onError) =>
print("Error while getting information of user : $onError"));
}
}
after creating our logic of controlling data we move to create the UI of login and register:
firstly we create a class of Textfield :
class CustomTextField extends StatelessWidget {
CustomTextField({
this.icon,
this.hint,
this.obsecure = false,
this.read = false,
this.validator,
this.onSaved,
this.tap,
this.textEditingController,
});
final FormFieldSetter<String> onSaved;
final Function tap;
final Icon icon;
final String hint;
final bool obsecure;
final FormFieldValidator<String> validator;
final TextEditingController textEditingController;
final bool read;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(left: 20, right: 20, top: 5),
child: TextFormField(
readOnly: read,
controller: this.textEditingController,
onSaved: onSaved,
validator: validator,
autofocus: true,
obscureText: obsecure,
onTap: tap,
style: TextStyle(
fontSize: 15,
color: Theme.of(context).primaryColor,
),
decoration: InputDecoration(
hintStyle: TextStyle(fontSize: 15, color: Colors.blue),
hintText: hint,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
width: 2,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide(
color: Theme.of(context).primaryColor,
width: 3,
),
),
prefixIcon: Padding(
child: IconTheme(
data: IconThemeData(color: Theme.of(context).primaryColor),
child: icon,
),
padding: EdgeInsets.only(left: 30, right: 10),
)),
),
);
}
}
after creating our CustomTextField we can get data from it using the methode onSave and validated using the validator of every filed.
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool _autoValidate = false;
the _formKey is very important for cheking the state of our form is validated or not .
Form(
key: _formKey,
autovalidate: _autoValidate,
child: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
new CustomTextField(
icon: Icon(Icons.email),
hint: "Email",
validator: (v) {
Pattern pattern = r'^(([^<>()[\]\\.,;:\s@\"]+'
r'(\.[^<>()[\]\\.,;:\s@\"]+)*)|'
r'(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.'
r'[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)'
r'+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (v.length == 0) return "* require";
if (!regex.hasMatch(v))
return 'Enter Valid Email';
},
onSaved: (newValue) => {
_email = newValue,
print("New value in email field $newValue"),
},
),
// Input("Email", Icons.email, 10, emailController),
// InputPassword(passwordController, 32),
new CustomTextField(
icon: Icon(Icons.vpn_key),
hint: "Password",
obsecure: true,
validator: (v) {
if (v.length == 0) return "* require";
if (v.length < 2)
return 'Password can\'t be less then 6 characteres ';
},
onSaved: (newValue) => _password = newValue,
),
forgotPassword,
SizedBox(
height: 25,
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MyButton("sign in", 3, this.signIn),
MyButton("Sign up", 3, this.signUp),
],
)
],
),
)
],
),
),
the fonction for submit our form :
First we check if the form is validate
bool validateForm() {
if (!_formKey.currentState.validate()) {
this.setState(() {
_autoValidate = true;
});
return false;
}
return true;
}
we can use methode for crypting our password :
static String hashPass(String password) {
var key = utf8.encode("pass@word/user*APP");
var bytePass = utf8.encode(password);
var hmacSha256 = new Hmac(sha256, key);
var hashPass = hmacSha256.convert(bytePass);
return hashPass.toString();
}
because when I am register the user I am using this methode
for crypting the password.
void signIn() {
final FormState form = _formKey.currentState;
if (validateForm()) {
form.save();
print("$_email -- ${Util.hashPass(this._password)} \n");
print("$_email -- $_password");
String hashPassword = Util.hashPass(this._password);
this.setState(() {
isLoading = true;
});
controller.signIn(_email, hashPassword).then((value) => {
print("Value retun from signIn methode : $value"),
if (value == null)
{
this.setState(() {
isLoading = false;
}),
_scaffoldKey.currentState.showSnackBar(
SnackBar(
backgroundColor: Colors.white,
content: new ShowSnackBar(
color: Colors.red,
msg: "email or password are wrong",
),
),
),
}
else
{
userSession.saveSessionUser(value).then((value) => {
print("User saved in sharedRefrences"),
this.setState(() {
isLoading = false;
}),
print("User authentified"),
sleep(new Duration(milliseconds: 5)),
Navigator.push(
context, SlideRightRoute(page: ControllerScreens()))
}),
}
});
}
}
Posted on June 18, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.