Automate your development process
This article was updated in September 2020.
Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook and Twitter, and more.
In this article, I will be showing how to set up Flutter app and implement Google sign-in using Firebase authentication.
The sample app is tested on Flutter 1.20 (stable) and using all the latest versions of the plugins.
In this article you will learn how to:
- Create a new Firebase project
- Set up Firebase for Android
- Set up Firebase for iOS
- Configure Firebase on Codemagic (CI/CD for Flutter)
So let’s get started.
Google sign-in using Flutter
There are a few new steps you have to do in order to use Google sign-in in your app. Without completing all these steps, if you try to use Google sign in, your app will just crash. Let’s see how to set up Google sign-in from scratch using Firebase.
App screenshots
Our final app will look like this:

Implementation
Before diving into the real coding part, let’s see what are the plugins and assets required in this project.
Plugins
The plugins needed for this project are:
- firebase_core (for initializing Firebase)
- firebase_auth (for Firebase authentication)
- google_sign_in (to implement Google Sign-In)
You will need to include the
firebase_core
plugin for using any other firebase related plugins as it is used for initializing theFirebaseApp()
. This is required due to the recent updates on Flutter and Firebase, check this article for more details.
Assets
Only one image is needed for this project. We will be requiring it when designing the Google sign-in button in our app.
You can get the image from here.
Creating a new Flutter project
Let’s create a new Flutter project with AndroidX compatibility.
Open Terminal or use the terminal in your code editor.
If necessary, you can check your current Flutter version with the command:
flutter --version
If you are on Flutter 1.12 or above, AndroidX compatibility is added to the project by default. Just navigate to the folder where you want to create the project and use the following command:
flutter create sign_in_flutter
If you are using an older Flutter version, you can add the
--androidx
flag.
Importing packages
Add the following packages to your
pubspec.yaml
file:firebase_core: ^0.5.0 firebase_auth: ^0.18.0+1 google_sign_in: ^4.5.3
Save it to run
flutter packages get
.
Also, create a new folder called assets
in your project directory and insert the image (google_logo.png
) that you downloaded.
Now, add the assets
folder in your pubspec.yaml
file.

Building the UI
Just delete everything from the main.dart
file and paste the boilerplate code given below.
import 'package:flutter/material.dart';
import 'login_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Login',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: LoginPage(),
);
}
}
Let’s build the UI for LoginPage
.
Create a new dart file called login_page.dart
inside the lib
folder.
The LoginPage
design would look like this:

This screen contains the two main components:
- Flutter Logo
- Sign in with Google button
LoginPage
should be a Stateful Widget because we will be making some changes to the UI later which will need the widgets to be redrawn.
The code for the LoginPage
UI:
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(size: 150),
SizedBox(height: 50),
_signInButton(),
],
),
),
),
);
}
Widget _signInButton() {}
}
Now we have to design the Sign in with Google button inside the function _signInButton
.
The code for button design:
Widget _signInButton() {
return OutlineButton(
splashColor: Colors.grey,
onPressed: () {},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("assets/google_logo.png"), height: 35.0),
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
),
),
)
],
),
),
);
}
We will fill up the onPressed
method later.
Firebase authentication
Create a new dart file sign_in.dart
where we will set up the Firebase authentication and Google sign-in.
First of all, import the three packages:
firebase_core
firebase_auth
google_sign_in
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
Now, we will need to create an instance of FirebaseAuth
& GoogleSignIn
.
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Then, create two methods:
signInWithGoogle
signOutGoogle
Future<String> signInWithGoogle() async {}
void signOutGoogle() async{}
In the signInWithGoogle
method, we have to use the Google sign-in data to authenticate a FirebaseUser
and then return that user.
In the signOutGoogle
method, we have to just sign out of the current Google account.
The final methods will look like this:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<String> signInWithGoogle() async {
await Firebase.initializeApp();
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final UserCredential authResult = await _auth.signInWithCredential(credential);
final User user = authResult.user;
if (user != null) {
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final User currentUser = _auth.currentUser;
assert(user.uid == currentUser.uid);
print('signInWithGoogle succeeded: $user');
return '$user';
}
return null;
}
Future<void> signOutGoogle() async {
await googleSignIn.signOut();
print("User Signed Out");
}
Now, we have to update the onPressed
method of _signInButton
inside the LoginPage
class, so that the signInWithGoogle
method gets called.
onPressed: () {
signInWithGoogle().then((result) {
if (result != null) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
}
});
},
If the Google Sign-In is successful, we will be taken to the FirstScreen
which we will be implementing next.
For now, we will just add a Container
with a light blue background in the FirstScreen
to test the Google sign-in.
Test UI for FirstScreen
:
import 'package:flutter/material.dart';
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(color: Colors.blue[100]),
);
}
}
Set up a Firebase project
To create a new Firebase project, you will need to go here.
Click Add project to create a new project.
Enter a Project name and click Continue.
Turn off Google Analytics for this project and click Create project.
Now wait for the creation to complete and then click Continue.
This will lead you to the Project Overview. From here you will be able to add Firebase to your Flutter project.
Android setup
First, we will set up Firebase for the Android side.
Click on the Android icon.
In this form, you have to first enter the Android package name. You can find this from your project directory → android → app → src → AndroidManifest.xml. On the second line, there will be your package name. Just copy & paste it in the form.
Now you can choose an App nickname. It is optional and if you leave this field empty, an auto-generated app name will be used.
Android Setup Now, you have to enter the SHA-1 hash. Just hover over the help (?) and click See this page. This will take you to the Authenticating Your Client page.
Here you will get the command to generate the SHA-1 hash. Paste this in your IDE terminal to get the SHA-1 hash. Just copy & paste this in the form.
Click Register App.
This will take you to the second step. Download the google-services.json file and just drag & drop it in your project directory → android → app. Then, click Next.
In the third step, just follow the instructions and add the code snippets in the desired position. Then, click Next.
Click Continue to Console.

Go to Authentication Page → Users tab and click Set up sign-in method.
In the sign-in providers page, edit Google sign-in.
Here, you have to enter the project name and support email. Enable this by clicking the toggle on the top-right corner. Then, click Save.
Google sign-in edit page The Google sign-in setup is now complete. Run the app on your device to check if it is working properly.
Note: To get a functional Firebase app, make sure you follow all these steps properly without skipping any of them.
iOS setup
If you have skipped the Android setup and arrived directly at the iOS setup, then make sure that you check out the steps 9-12; otherwise, you might face errors later.
Go to Settings → General tab.
Scroll down and click Add app.
Now, select iOS.
Enter the iOS bundle ID and your App nickname. Then, click Register app.
You can find the Bundle ID inside ios → Runner.xcodeproj → project.pbxproj by searching for “PRODUCT_BUNDLE_IDENTIFIER” with
Ctrl + F
.iOS Bundle ID In the second step, download the GoogleService-Info.plist file.
Open the ios folder of the project directory in Xcode by right-clicking and selecting Open in Xcode.
Xcode Now, drag & drop the file that you downloaded into the Runner subfolder. When a dialog box appears, make sure that Runner is selected in “Add to targets” box. Then click Finish.
Close Xcode. In your IDE go to ios → Runner → Info.plist. Here, you have to add something.
Open this google_sign_in flutter package page. Inside iOS integration you will find a code snippet. Just copy & paste it inside the Info.plist file and save it, like this:
Info.plist Here, you will see that there is a TODO written to replace the value within the string tag with REVERSED_CLIENT_ID. You will find the REVERSED_CLIENT_ID in the file GoogleService-Info.plist.
GoogleService-Info.plist We reached the third step. You don’t need to change anything in this step because we are using the Flutter Firebase plugin which takes care of all these things. You will only need to do this step if you are building a standalone iOS app. So just click Next.
Add Firebase SDK In the fourth step, you also do not need to do anything. Just click Next.
Now, run the app on your iOS device and attempt a Google sign-in to complete the fifth step.
After completing this step, click Continue to console.
Finally, this completes the whole setup process for Sign in with Google using Firebase for both Android and iOS. If you follow the described steps properly, you should get past the setup pretty quickly.
Improving the UI
Let’s complete our FirstScreen
UI. The final UI will look like this:

I will not go deep into this UI coding part. You have to include some lines of code within the sign_in.dart file to retrieve the image URL, name & email of the user.
Thus, you have to add the following in sign_in.dart
:
// Add these three variables to store the info
// retrieved from the FirebaseUser
String name;
String email;
String imageUrl;
Future<String> signInWithGoogle() async {
// ...
final UserCredential authResult = await _auth.signInWithCredential(credential);
final User user = authResult.user;
if (user != null) {
// Add the following lines after getting the user
// Checking if email and name is null
assert(user.email != null);
assert(user.displayName != null);
assert(user.photoURL != null);
// Store the retrieved data
name = user.displayName;
email = user.email;
imageUrl = user.photoURL;
// Only taking the first part of the name, i.e., First Name
if (name.contains(" ")) {
name = name.substring(0, name.indexOf(" "));
}
// ...
return '$user';
}
return null;
}
The full UI code for FirstScreen
is given below:
import 'package:flutter/material.dart';
import 'package:sign_in_flutter/login_page.dart';
import 'package:sign_in_flutter/sign_in.dart';
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topRight,
end: Alignment.bottomLeft,
colors: [Colors.blue[100], Colors.blue[400]],
),
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
imageUrl,
),
radius: 60,
backgroundColor: Colors.transparent,
),
SizedBox(height: 40),
Text(
'NAME',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
name,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Text(
'EMAIL',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
email,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 40),
RaisedButton(
onPressed: () {
signOutGoogle();
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) {return LoginPage();}), ModalRoute.withName('/'));
},
color: Colors.deepPurple,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Sign Out',
style: TextStyle(fontSize: 25, color: Colors.white),
),
),
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40)),
)
],
),
),
),
);
}
}
Configuring Firebase on Codemagic
In our local configuration, we have downloaded the google-services.json
and GoogleService-Info.plist
files and kept it in the android
& ios
directory of the Flutter app respectively. These files contain sensitive data, like the API key and information about the app. These files shouldn’t be checked in to version control or exposed to the world. We have to take certain steps to secure our sensitive data.
Ignore the files in the version control system
First of all, we have to list the two private files, google-services.json
(present in the folder android/app/
) and GoogleService-Info.plist
(present in the folder ios/Runner/
) in the .gitignore
file, to avoid them being checked into version control, such as Git.
Once you have added the two files into .gitignore
, commit the .gitignore
file.
Encode the files
At this stage, we have ensured that we won’t commit the sensitive files to the version control system. However, the continuous integration server will expect to find this file in order to successfully build the Flutter app.
To encode the files, run the following two commands from your terminal in the project directory:
openssl base64 -in android/app/google-services.json
openssl base64 -in ios/Runner/GoogleService-Info.plist
This command will print the encoded content which we need to paste into the Codemagic environment variable.
Adding the environment variable in Codemagic
Log in in to your Codemagic account using GitHub, GitLab or Bitbucket.
Find your project in your Applications list.
Click the Settings button to go to the app settings.
Expand the Environment variables tab.
Add the two encoded content strings generated from the terminal as:
ANDROID_FIREBASE_JSON
(Variable name) -> encoded string fromgoogle-services.json
(Variable value)IOS_FIREBASE_JSON
(Variable name) -> encoded string fromGoogleService-Info.plist
(Variable value)
Don’t forget to check the Secure checkbox to ensure that the values won’t be displayed in the build logs.
Click Save.
Adding a pre-build script
In the Codemagic app settings, click on the + button before the Build stage.
Pre-build Add the following Pre-build script.
#!/bin/sh echo $ANDROID_FIREBASE_JSON | base64 --decode > $FCI_BUILD_DIR/android/app/google-services.json echo "Listing android Directory to confirm the google-services.json is there! " ls android/app/ echo $IOS_FIREBASE_JSON | base64 --decode > $FCI_BUILD_DIR/ios/Runner/GoogleService-Info.plist echo "\nListing iOS Directory to confirm the GoogleService-Info.plist is there! " ls ios/Runner/
Click Save
Pre-build script
Start building
Click the Start new build button to start the build process.

While the build process is running, you can click the Pre-build tab to see the output of the code we added to the pre-build script. You can see that both files, google-services.json
and GoogleService-Info.plist
, are present, although we did not add them to the version-control system. They are generated from the encoded strings.

After the build is finished successfully, you can also download the artifacts to test it on a real device.

If you want to generate a release build of your app, then check out the following articles:
Dependency caching
Firebase dependencies take longer to build, in order to prevent this you can use dependency caching on Codemagic to lower the build time.
To cache your Gradle and CocoaPods, enable dependency caching and include the following two paths to the Dependency caching section in your Codemagic project settings:
$HOME/.gradle/caches
$HOME/Library/Caches/CocoaPods



Troubleshooting some common issues
Some of the common issues that people face while working with a project containing Firebase:
Releasing to Play Store
Having a completely configured app with Firebase doesn’t mean it is ready to be published in Play Store. The biggest mistake done by people while generating a release build of an app containing Firebase, is not updating the google-services.json
file.

After creating a new project in Play Console, a new SHA-1
key is generated. Copy the new SHA-1
and go your Firebase project -> Project settings -> Add fingerprint to add the new key.

Download the latest google-services.json
file and replace with this in your Flutter project.
iOS Podfile issue
The Podfile format is changed in Flutter version 1.20, more about it here. If you have created your Flutter project post v1.20
then you might face Podfile is out of date
warning or something related to this.

If you do not have any custom configuration changes to the default Podfile
generated by Flutter, it is pretty easy to fix.
Just follow these steps:
Run Flutter clean:
flutter clean
Run the following from the
ios/
folder:pod repo update
Delete
ios/Pods/
,ios/Podfile.lock
&/ios/Podfile
Then again run the Flutter build, this should fix the issue
If you are having custom configurations in Podfile
, then follow the above steps and then include the custom changes again.
Xcode signing identifier error
If you have not set the organization (using --org
flag) while creating the Flutter project, it will be set to the default. But, for running the project on an iOS device you will need to use an unique signing identifier. Otherwise, you will get the following error:

Open the ios/
folder in Xcode by right-clicking and selecting Open in Xcode
. Now, select Runner, under General tab set an unique Bundle Identifier
.

Also, go to the Signing & Capabilities tab and select your Team
& check if the Bundle Identifier
is correct.

If you now close Xcode and build your Flutter app again, the issue should be solved.
Conclusion
Our Log-in Demo app is now completed and we have successfully tested it with Codemagic by setting up Firebase with encoded files. I hope that you found some useful information from this article.
You can find the GitHub repo for this project HERE.
More articles about Firebase:
- Firebase App Distribution using CLI
- Deploying Flutter app to Firebase App Distribution using Fastlane
- Firebase App Distribution using the Gradle plugin in Codemagic
- Practical guide: Flutter + Firebase + Codemagic
This article is written by Souvik Biswas. He is a passionate Mobile App Developer (Android and Flutter) and has worked on a number of mobile apps throughout his journey. Loves open source contribution on GitHub. He is currently pursuing a B.Tech degree in Computer Science and Engineering from Indian Institute of Information Technology Kalyani. He also writes Flutter articles on Medium - Flutter Community.