0.Introduction
Have you ever wanted to implement user authentication in your flutter Application? Well, you've come to the right place..!
Let's see how to add GoogleSignIn() auth using Firebase Authenticationn.
What you'll learn
- Adding SplashScreen to your app
- Navigating user from the SplashScreen to AuthScreen or HomeScreen
- GoogleSignIn Authentication
Demo of the final implementation...
What is Firebase? (quick intro..)
Firebase is Google's mobile platform with a variety of services to build & ship our apps quickly. It is categorized as a NoSQL database and stores data in JSON like documents.
1.Setup Firebase Project
Head over to Firebase Console then add a new project.
To keep things simple and short I'm not explaining every step here. Trust me next steps are pretty clear to add your app to firebase.
- Make sure to set up a sign-in method in the Authentication section of firebase console. Otherwise, things are not gonna work as expected.
At a particular step, it asks you to enter SHA-1 Key to complete the process. Run this command in your cmd to get the SHA-1 key.
keytool -list -v -alias androiddebugkey -keystore C:\Users\YOUR_USER_NAME_HERE\.android\debug.keystore
2.Write some Code
Before writing code let's understand what we are going to build.
When the user opens app for the first time we should navigate user from SplashScreen to AuthScreen.
Next time when the user opens the app we should check if user is already logged in or not.
If user = loggedIn then navigate toHomeScreen
by skippingAuthScreen.
ELSE navigate user fromSplashScreen
toAuthScreen
.
Let's write some code🥳
Packages that we'll use:
- firebase_auth: ^0.18.3
- firebase_core: ^0.5.2
- google_sign_in: ^4.5.6
Add the above 3 packages to your pubspec.yaml
file
And for every flutter app using Firebase, we must use the firebase_core
package. And then you must initialize the app.
await Firebase.initializeApp();
If you don't initialize the app you may get the below error.
[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
- Fire-up your preferred code editor and open your main.dart file. Remove all the boiler-plate code in main.dart file and add the below code.
import 'package:YOUR_PROJECT_NAME/screens/splashscreen.dart';
import 'package:YOUR_PROJECT_NAME/screens/authscreen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
// Defining routes for navigation
var routes = <String, WidgetBuilder>{
"/auth": (BuildContext context) => AuthScreen(),
};
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'FaceBase',
routes: routes,
home: SplashScreen(),
));
}
2.Let's build UI for the remaining screens
- SplashScreen UI and Logic
Create a new dart file named splashscreen.dart
inside the lib/screens
folder.
Your splashscreen.dart
should look like this..
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_gsignin/screens/homescreen.dart';
import 'package:flutter/material.dart';
class SplashScreen extends StatefulWidget {
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
User _user;
@override
void initState() {
super.initState();
initializeUser();
navigateUser();
}
Future initializeUser() async {
await Firebase.initializeApp();
final User firebaseUser = await FirebaseAuth.instance.currentUser;
await firebaseUser.reload();
_user = await _auth.currentUser;
// get User authentication status here
}
navigateUser() async {
// checking whether user already loggedIn or not
if (_auth.currentUser != null) {
// && FirebaseAuth.instance.currentUser.reload() != null
Timer(
Duration(seconds: 3),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
HomeScreen(username: _auth.currentUser.displayName)),
(Route<dynamic> route) => false),
);
} else {
Timer(Duration(seconds: 4),
() => Navigator.pushReplacementNamed(context, "/auth"));
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Text("Design Your splash screen"),
),
),
);
}
}
Create a another dart file named homescreen.dart
inside the lib/screens
folder.
And paste the below code into your homescreen
import 'package:firebase_gsignin/screens/authscreen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class HomeScreen extends StatefulWidget {
final String username;
HomeScreen({Key key, @required this.username}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Hello "+ widget.username),
actions: <Widget>[
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () async {
await FirebaseAuth.instance.signOut();
await googleSignIn.disconnect();
await googleSignIn.signOut();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => AuthScreen()),
(Route<dynamic> route) => false);
},
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
await googleSignIn.disconnect();
await googleSignIn.signOut();
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => AuthScreen()),
(Route<dynamic> route) => false);
},
child: Text("Log Out"),
color: Colors.redAccent,
),
SizedBox(
height: 10.0,
),
],
),
),
);
}
}
Let's implement Firebase Authentication
Create a new file named authscreen.dart
inside lib/screens
folder in which we'll set up google sign in and AuthScreen UI.
- Code for the
authscreen.dart
UI and logic:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_gsignin/screens/homescreen.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
String name;
String email;
String imageUrl;
final FirebaseAuth auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
bool isVisible = false;
Future<User> _signIn() async {
await Firebase.initializeApp();
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken,
);
// final AuthResult authResult = await auth.signInWithCredential(credential);
// final User user = authResult.user;
User user = (await auth.signInWithCredential(credential)).user;
if (user != null) {
name = user.displayName;
email = user.email;
imageUrl = user.photoURL;
}
return user;
}
@override
Widget build(BuildContext context) {
var swidth = MediaQuery.of(context).size.width;
return Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/bg.png"),
fit: BoxFit.cover)),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Visibility(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Color(0xFFB2F2D52)),
),
visible: isVisible,
)
],
),
Container(
margin: const EdgeInsets.only(
bottom: 60.0,
),
child: Align(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 54.0,
width: swidth / 1.45,
child: RaisedButton(
onPressed: () {
setState(() {
this.isVisible = true;
});
_signIn().whenComplete(() {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => HomeScreen(username: name)),
(Route<dynamic> route) => false);
}).catchError((onError) {
Navigator.pushReplacementNamed(context, "/auth");
});
},
child: Text(
' Continue With Google',
style: TextStyle(fontSize: 16),
),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
elevation: 5,
color: Color(0XFFF7C88C),
),
),
),
),
],
),
);
}
}
3.Conclusion
Well, we've successfully implemented authentication in our flutter app.
If you've any doubts, you can find the GitHub repo of this super simple project in the following link:
Sai7xp / DEV.to-FirebaseAuth-Flutter
Flutter + Firebase Google SignIn Demo
App ScreenShots
keep Fluttering!
Thank you for reading, if you found the article useful make sure to show some love.
-Moving Melody
Let's catch up on Twitter!
Top comments (14)
Sir, first time the program is run without error. Bt second time I open this app show error In home screen. Invalid arguments. What to do??
Hey Nikhil, thank you for noticing and pointing out the error. (fixed error now)
Cause for error : When the user enters home screen second time it fails to retrieve the name,imageUrl some other details because we haven't stored user details globally.
Anyway, I've fixed the issue and updated the article.
If you found this article useful sharing is highly appreciated. Twitter : @movingmelody :)
Sir how to resolve these error. Becz I'm beginner in Flutter.
I've updated the code in the article or you can find the code in GitHub repo. Go through the code again. Your error will solve.
Ok sir.
Still, If you find any issues comment the error. And let me know if error is solved
Invalid argument(s)
The relevant error-causing widget was
HomeScreen
lib\screens\authscreen.dart:79
When the exception was thrown, this was the stack
0 _StringBase.+ (dart:core-patch/string_patch.dart:262:57)
1 _HomeScreenState.build
package:firebase_gsignin/screens/homescreen.dart:17
2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4619
3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4502
4 StatefulElement.performRebuild
Sir kindly help
Check the updated code and article
Were you able to find a solution to this? I'm having the same problem right now. :/
Actually, that was because the null value is passed to the homescreen from the splashscreen(username). Fixed ✅✅ the error now. You can update the code as i updated the article.
Or else simply store the user details in localstorage using the SharedPreferences. It enables you to access the details even in offline mode.
I have commited the new changes to github. If you stuck anywhere look over github repo.
Hello Sir, last time the program is run Perfectly. Bt now in AuthScreen
=> Error in following lines
1) final AuthResult authResult = await auth.signInWithCredential(credential);
2) final FirebaseUser currentUser = await auth.currentUser();
assert(firebaseUser.uid == currentUser.uid);
return firebaseUser;
& in Splash Screen has returned error.
=> Error in following lines
1) FirebaseAuth.instance.currentUser().then((currentUser) {
if (currentUser == null) {
Timer(Duration(seconds: 2),
() => Navigator.pushReplacementNamed(context, "/auth"));
} else {
Timer(
Duration(seconds: 2),
() => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) =>
HomeScreen(username: currentUser.displayName)),
(Route route) => false),
);
}
});
What to do, please help me to find these issue??
Sir, how to call username, imageUrl and Email in another page ?
I have a problem when i close my app ,then error
Store the user details locally in your phone using SharedPreferences when user signup. Then simply retrieve the user details in the page you want to use them. Additionally it enables offline access 🦸♀️