Adding a Google sign-in to your Flutter app involves various steps. It might sound not easy but in this article, everything is explained in detail along with the example code and screenshots. We will create the example project and do the part that we need to do from the front side if you’re building the application in the company.
For Bigger projects always there is a backend involved while building the complex application. For the front end, we gather the user information and the auth token from the OS where the user has already logged in with the Gmail account.
That Auth token will be sent to the backend to verify and backend check if the user has already logged in with this email or not. depending upon the check backend registers the user and sends back the access token to the frontend.
For now, it seems a bit difficult, let start with the implementation everything will be cleared with the steps.
First Create a Firebase and Flutter project
Create the Fluter project in my case I am making a test project, for you guys you might have created all and also the login page or dashboard screen where you want to land the user.
Also, create the Firebase Project where we have the functionality to use the Google Sign-in feature.
Install Require Dependencies
After creating the Flutter app add some required dependencies to pubspec.yaml file.
- firebase_core: for initializing Firebase
- firebase_auth: for implementing Firebase authentication
- google_sign_in: to use Google Sign-In
firebase_core: ^3.2.0
firebase_auth: ^5.1.2
google_sign_in: ^6.2.1
After adding them just git pub get button on the top of that file. or run the command in the terminal flutter pub get
Link your Firestore app to our Flutter App
As I created myTest project in Firebase now let’s connect the Firebase app to our Flutter app. Now we have the new option to connect the application to our Flutter app in Firebase as you can see the the image below (Flutter icon to connect our app).
Click on the flutter icon and follow the three steps.
Prepare your workspace
For this, Install the Firebase CLI, which alow to run the Firebase login command on the terminal. For easy installation Install the node on PC and run the NPM comment to add Firebase CLI.
For more detail to install Firebase CLI here is the link to Firebase CLI.
Install and run the FlutterFire CLI
After installing Firebase CLI there are two commands we need to run one is to activate the flutterfire_cli, which can be run on the terminal on any directory. The second command will be run on the project-level directory
For the second command open your project in any IDE in my case I am using Android Studio, but it will be the same in Visual Studio. After opening the project, open your IDE terminal which will open up the terminal in the project-level directory.
To complete the second command, you must select the platform from which you want to configure the Firebase. Then provide the bundleId/Package name which seems like com.example.appname get this package name from the app level gradle.
Once this second command is completed you can see a new file added to the libs folder called firebase_options.dart
Initialize Firebase
Now add the initialization code for the main.dart file which will send the Firebase option for initialization depending on our platform. Also, add the widgetFlutterBinding initializer before initializing the Firebase app code
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
Enable Sign-in with google from firebase
Go to the authentication tab from the sidebar and click the Get Started button. Next from the top bar select sign-in methods and select Google.
Then hit enable and add your email ID in the Support email for project help field as shown in the image below and hit save.
Now after this 80% of the Firebase setup is ready let’s start with the coding part, after that, we will go over the rest of the 20% steps we need to do for Firebase while implementing the Google Sign-in With Apple part.
Android Setup: Add SHA Certificate Fingerprints
This is an important step in testing the app on Android. We need to add the SHA fingerprint of the app to the Firestore. For this, we need to create the keyStore for the Android app.
Here is the easy way of creating the keystone.
How to generate a keystore file in Flutter
After creating the key and adding the key-related code to the gradle file also adding key.properties now need to run the command to generate the fingerprint of the app.
Open the terminal inside of the Android studio and go to the Android directory by using the command cd android and run the command below.
./gradlew signingReport
Before this make sure to check the compatible version of your gradle with the JAVA version. check your gradle version with this command ./gradlew –version and Java version with this command java -version.
Here is the official site for checking the gradle compatibility LINK.
Add signature to firebase
Once you run the command you will get the SHA1 and SHA-256 for both debug mode and release mode. Add both of them to the firebase. Scroll up and from the start of the command, you will find all the values of your Android app, below that there are fingerprints of the Android folders of the packages we used.
So pick the ones that are at the top of the command results
Open the Firebase and click on project settings, go all the way down and you will see the Your Apps column inside of which you have the Add fingerprint button.
Click the Add Fingerprint button, And add the SHA-1 and also SHA-256 values.
IOS Setup: Add plist file from Firebase
Just like we added the fingerprint to Firebase General settings on that part where it says Your Apps and select the IOS app of your Firebase.
Now from here Download the GoogleService-info.plist and add it to Ios>Runner folder of your project.
Open this file (GoogleService-info.plist) and copy the value String of key REVERSED_CLIENT_ID we need that to add that in info.plist file. Also, Copy the Client_ID from this file.
Now paste the code below, and replace the REVERSED_CLIENT_ID String and CLINIC ID string tag with the one copied from the file we newly added from firebase.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>REVERSED_CLIENT_ID</string>
</array>
</dict>
</array>
<key>GIDClientID</key>
<string>CLINIC ID</string>
While pasting the above code make sure to change the
Create Login Screen UI
First, create the screens folder inside the libs folder and create two files inside that loginscreen.dart and dashboardScreen.dart
For the login Screen, there is a basic UI with AppBar that says login! and a sign-in with a Google Button on it. The button is created in a separate function which returns the widget
Also, I added the inkwell to the button which will handle the functionality part of our Google signing. The example code for Screen is in the code snippet below.
Login Screen Code:
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.redAccent,
title: const Text("Login!",style: TextStyle(color: Colors.white, fontWeight: FontWeight.w500),),
),
body: SafeArea(
child: Center(
child: signInWithGoogleUI(),
),
),
);
}
signInWithGoogleUI() {
return InkWell(
onTap: (){
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 30.0,vertical: 8.0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.black.withOpacity(0.2)
),
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 30,
width: 30,
child: Image.network(
"https://cdn.iconscout.com/icon/free/png-256/free-google-1772223-1507807.png",
height: 40,
width: 40,
),
),
const SizedBox(
width: 10.0,
),
const Text("Sign In With Google", style: TextStyle(color: Colors.black, fontWeight: FontWeight.w600, height: 0),)
],
),
),
);
}
}
Here is what the screen UI looks like:
Warning!
Before running your code in Android make sure to change the minSdkVersion: 23 in App level gradle file.
Create Google Sign Class for Signin Handling
Now just separate the part of Google sign-in to a different class so that it will be common to just call the function from this class from anywhere. Also, this will be a common class that can be used in different projects as well.
First, create a folder in the libs folder social_login and inside of this create a dart file google_login.dart. Create the Class GoogleLogin inside of this file.
class GoogleLogin {
}
Now let’s create the static function for Google signin functionality which returns the GoogleLoginModal which will also be created in this file as a data modal to handle the returned data by Google.
Add the Modal Class to the same file, which has 2 properties User and GoogleSignInAuthentication in this User is the object from the firebase_auth package and GoogleSignInAuthentication is from the google_sign_in package.
here the modal class looks like this:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleLoginModal {
User? user;
GoogleSignInAuthentication googleSignInAuthentication;
GoogleLoginModal({required this.googleSignInAuthentication,this.user});
}
Also add the function that returns GoogleLoginModal object, a Future function that looks like this:
static Future<GoogleLoginModal?> signInWithGoogle() async {
}
Now, The google_login.dart look like
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleLogin {
static Future<GoogleLoginModal?> signInWithGoogle() async { }
}
class GoogleLoginModal {
User? user;
GoogleSignInAuthentication googleSignInAuthentication;
GoogleLoginModal({required this.googleSignInAuthentication,this.user});
}
One modal class and the GoogleLogin class to handle all the functionality let start populating the signInWithGoogle Function with the functionality.
Let’s discuss the function step by step there will be a discussion of each step
- Create the instance of FirebaseAuth
- Create the function of our modal GoogleLoginModal
- Also the instance of the GoogleSignIn plugin
- Call the signIn() function with googlesignin instance
- Save the Account in the GoogleSignInAccount Object which comes from the GoogleSignIn plugin
- Check if the googlesignInAccount is not null
- Then Create the instance of GoogleSignInAuthentication
- Also, Get the GoogleAuthProvider credentials.
- Pass those credentials to auth.signInWithCredential(credential)
- Get the values and add them to our model, Also handle the Exceptions
Although this list seems a bit long if you don’t want to understand these all, Copy the last code and call this function on your code.
Creating the FirebaseAuth instance which can be used in the signInWithCredential function later on. And also create the instance of our GoogleLoginModal to store the response and sent it back in the return of the function.
Along with this also add a GoogleSignIn instance which will let us call the signIn function.
FirebaseAuth auth = FirebaseAuth.instance;
GoogleLoginModal? googleLoginModal;
final GoogleSignIn googleSignIn = GoogleSignIn();
Now let’s call the signIn() function with the googleSignIn instance created, this function will open up the dialog which lists the number of Gmails entered in os or lets you log in with the mail.
In return, this function provides GoogleSignInAccount which will be used further to get the credentials.
final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
Next, add the check if googleSignInAccount is not null, sometimes user just cancels out the popup and this will be returned null. So in the other case just show the toast message or snackBar. If the account is not null then there are still several steps that need to be followed.
let’s get the authentication details from googlesigninaccount and googleSignInAccount.authentication returns the GoogleSignInAuthentication object add these details to a different variable.
if (googleSignInAccount != null) {
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
}
And get the credentials with the Auth GoogleAuthProvider.credential() function.
Now use the try-catch block for signInWithCredentials we get from googleSignInAuthentication and add the values to our googleLoginModal
try {
final UserCredential userCredential = await auth.signInWithCredential(credential);
googleLoginModal = GoogleLoginModal(googleSignInAuthentication: googleSignInAuthentication,user: userCredential.user);
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
print("Account exists with different credential");
}
else if (e.code == 'invalid-credential') {
print("Invalid Credential");
}
} catch (e) {
print(e.toString());
}
In the above block also some exceptions are handled to show these errors such as snack bar or toast messages to give feedback to the user.
After the if condition return the googleLoginModal if it has some values and all the flow runs without any exception then it returns with values otherwise, it will be returned as a null object.
Full Code of sign-in function
static Future<GoogleLoginModal?> signInWithGoogle() async {
FirebaseAuth auth = FirebaseAuth.instance;
GoogleLoginModal? googleLoginModal;
final GoogleSignIn googleSignIn = GoogleSignIn();
final GoogleSignInAccount? googleSignInAccount = await googleSignIn.signIn();
if (googleSignInAccount != null) {
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
try {
final UserCredential userCredential = await auth.signInWithCredential(credential);
googleLoginModal = GoogleLoginModal(googleSignInAuthentication: googleSignInAuthentication,user: userCredential.user);
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
print("Account exists with different credential");
}
else if (e.code == 'invalid-credential') {
print("Invalid Credential");
}
} catch (e) {
print(e.toString());
}
}
return googleLoginModal;
}
Now go to the Login Screen and add the function to the inkwell button of signing.
InkWell(
onTap: (){
GoogleLogin.signInWithGoogle().then((data){
print(data?.googleSignInAuthentication.accessToken);
});
},
child: ...
)
Called the static function of the GoogleLogin class, which will get back with the data in return. Future data will be returned that’s why here we used then() function.
The print statement will print the accessToken, which will be sent to the backend with API which will be provided to you by the Backend itself.
In response to that API, you will get the logging access token of the app. Or depending upon the way you handle the login with your backend.
In IOS it will work exactly you just need to do the steps mentioned above.
For now, let’s land the user on the Dashboard screen with mail and user’s name which comes with the data from Google after login.
Create Dashboard Screen
This is just a basic screen that welcomes the user with the green app bar and welcome message on it. In the body of the screen, there is the name and the email of the user who logged inside of the Column. This Screen accepts the Name and Email from the previous one.
import 'package:flutter/material.dart';
class Dashboardscreen extends StatelessWidget {
final String? name;
final String? email;
Dashboardscreen({super.key,this.email,this.name});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
leading: const SizedBox(),
leadingWidth: 0,
title: const Text("Welcome!",style: TextStyle(color: Colors.white, fontWeight: FontWeight.w500),),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(name ?? "",style: const TextStyle(fontSize: 22,)),
Text(email ?? "")
],
),
),
);
}
}
Now let’s pass the values from the login screen after getting the data from Google sign-in, Change the then function with Navigator.push(). and add the values.
InkWell(
onTap: (){
GoogleLogin.signInWithGoogle().then((data){
Navigator.push(context, MaterialPageRoute(builder: (_){
return Dashboardscreen(
email: data?.user?.email,
name: data?.user?.displayName,
);
}));
});
},
child: . . .
);
Remember we created the GoogleLoginModal in this we added the user Object, use this object to get the user name and email.
For more Flutter tutorials, Tips, Tricks, Free code, Questions, and Error Solving.
Remember FlutterDecode.com