Set up a Flutter app and Implement Google Sign-In Using Firebase

Written by akshata26 | Published 2021/09/18
Tech Story Tags: flutter | firebase | authentication | google-sign-in-with-firebase | flutter-app | coding | software-development | programming

TLDR We'll be building a two-page app that allows users to log in using their Google Account. This is for a layer of security and to pull user's information associated with their Gmail accounts. Users can click on the "Sign In with Google" button, which will launch a view where users can provide their Google credentials. Upon success, control is returned to the user and Flutter navigates the user to the Welcome screen, where they can view their name, avatar, and be able to log out.via the TL;DR App

Today we will be discussing how we can set up a Flutter app and implement Google sign-in using Firebase.

We'll be building a two-page app that allows users to log in using their Google Account. This is for a layer of security and to pull user's information associated with their Gmail accounts such as the user name and avatar image etc. Our final app will look like follows:

Users can click on the "Sign In with Google" button, which will launch a view where users can provide their Google credentials. Upon success, control is returned to the user and Flutter navigates the user to the Welcome screen, where they can view their name, avatar, and be able to log out.

Getting Started

I have created my flutter application named social_login. If you have not created any, then you can create a flutter app using the following command:

flutter create social_login

Now we'll add the plugins required in this project. Open pubspec.yaml file and in dependencies add the plugins as:

firebase_auth: ^0.16.0
google_sign_in: ^4.4.4
flutter_auth_buttons: ^0.5.0

Save the file and run:

flutter pub get

Build the UI

Delete the code from the main.dart file and add the following code:

// main.dart
import 'package:flutter/material.dart';
import 'login_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Login',
      theme: ThemeData(
        primarySwatch: Colors.amber,
      ),
      home: LoginPage(),
    );
  }
}

Now we'll move ahead to the login page.

// login_page.dart file
import 'package:flutter/material.dart';
import 'package:flutter_auth_buttons/flutter_auth_buttons.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>[
              Image(
                image: AssetImage("assets/logo.png"),
                height: 150, 
                width: 150
              ),
              SizedBox(height: 50),
              GoogleSignInButton(
                onPressed: () {},
                darkMode: true
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Now we'll create a new file and name it as auth.dart. Here we'll keep our code for authentication.

First, we'll import the packages required.

// auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();

Here, we have created an instance of FirebaseAuth and GoogleSignIn. After creating an instance, we need methods as signIn (to authenticate the user) and then signOut(to just sign out from the current account).

Let's create our methods in auth.dart file.

// auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
Future<String> signInWithGoogle() async {
  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  final GoogleSignInAuthentication googleSignInAuthentication =
      await googleSignInAccount.authentication;
  final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );
  final AuthResult authResult = await _auth.signInWithCredential(credential);
  final FirebaseUser user = authResult.user;
  assert(!user.isAnonymous);
  assert(await user.getIdToken() != null);
  final FirebaseUser currentUser = await _auth.currentUser();
  assert(user.uid == currentUser.uid);
  return 'signInWithGoogle succeeded: $user';
}
void signOutGoogle() async{
  await googleSignIn.signOut();
}

We have created our functions but now we need to call our functions in our application to let the user authenticate.

So let's call our function to work for us. We'll update our login page to call signInWithGoogle() after clicking the sign-in button.

// login_page.dart file
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>[
              Image(
                image: AssetImage("assets/logo.png"),
                height: 150, 
                width: 150
              ),
              SizedBox(height: 50),
              GoogleSignInButton(
                onPressed: () {
                  signInWithGoogle().whenComplete(() {
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) {
                        return WelcomeScreen();
                        },
                      ),
                    );
                  });
                },
                darkMode: true
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Here, once our sign-in is successful, we are redirecting the user to the WelcomeScreen.

Build UI for WelcomeScreen

To do this, run the following code:

// welcome_screen.dart file
import 'package:flutter/material.dart';
class WelcomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Text(
          "Welcome $name to Flutter",
           style: TextStyle(
             fontSize: 30,
             fontFamily: 'DancingScript',
             fontWeight: FontWeight.bold,
           ),
        ),
      ),
    );
  }
}

Set Up a Firebase Project

To create a new firebase project, go to the firebase console.

Click to Add Project for creating a new project.

Now, enter your project name and click continue.

Follow the steps until the creation of the project.

This will lead you to the Project Overview page and from here we'll be able to add firebase to our flutter app.

For that, click on the Android icon and follow the steps required to create an android app.

Here, you have to add the SHA-1 hash. For generating the SHA-1 key, just hover over the help (?) and click See this page. This will redirect you to the Authenticating Your Client page where you'll find commands to generate the SHA key.

Then click on Register App. Next, download the google-services.json file and add it to your project-directory -> android -> app and click Next.

In the third step, add the given code to the respective files. Once done, click Next and continue to console.

Lastly, go to the Authentication Page -> Users tab and click on the Set up sign-in method.

In Sign-in providers under the Sign-in methods tab, hover over Google provider and edit to enable Google sign-in.

With this, we are done with the Google sign-in set up for our flutter app. The iOS setup is a little similar to this, but we are not going to implement it in our flutter app now.

Still, you can implement it if you wish to run it on an iOS emulator or iOS mobile. To access user data such as name and email in our app, we need to update our auth file.

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
String name;
String email;
String imageUrl;
Future<String> signInWithGoogle() async {
  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  final GoogleSignInAuthentication googleSignInAuthentication =
  await googleSignInAccount.authentication;
  final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );
  final AuthResult authResult = await _auth.signInWithCredential(credential);
  final FirebaseUser user = authResult.user;
  assert(user.email != null);
  assert(user.displayName != null);
  assert(user.photoUrl != null);
  name = user.displayName;
  email = user.email;
  imageUrl = user.photoUrl;
  if (name.contains(" ")) {
    name = name.substring(0, name.indexOf(" "));
  }
  assert(!user.isAnonymous);
  assert(await user.getIdToken() != null);
  final FirebaseUser currentUser = await _auth.currentUser();
  assert(user.uid == currentUser.uid);
  
  return 'Successfully loggedin: $user';
}
void signOutGoogle() async {
  await googleSignIn.signOut();
}

Complete UI of WelcomeScreen

Now we'll complete our UI of WelcomeScreen using the following code:

// WelcomeScreen.dart file
import 'package:flutter/material.dart';
import 'auth.dart';
import 'login_page.dart';
class WelcomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Example'),
      ),
      drawer: name != null ? Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                decoration: BoxDecoration(
                  color: Colors.amberAccent,
                ),
                child: Column(
                  children: <Widget>[
                    Padding(
                      padding: EdgeInsets.zero,
                      child: CircleAvatar(
                        backgroundImage: NetworkImage(
                          imageUrl,
                        ),
                      radius: 40,
                      backgroundColor: Colors.transparent,
                    ),
                  ),
                  SizedBox(height: 10),
                  Text(
                    name,
                    style: TextStyle(
                    fontSize: 20,
                    color: Colors.black,
                    fontWeight: FontWeight.bold),
                  ),
                  SizedBox(height: 5),
                  Text(
                    email,
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.black,
                      fontWeight: FontWeight.normal
                    ),
                  ),
                ],
              ),
            ),
            ListTile(
              leading: Icon(
              Icons.exit_to_app,
              color: Colors.red,
            ),
            title: Text(
              "Sign Out",
              style: TextStyle(
                fontSize: 18,
                color: Colors.red,
              ),
            ),
            onTap: () {
              signOutGoogle();
              Navigator.of(context).pushAndRemoveUntil(
                MaterialPageRoute(builder: (context) {
                  return LoginPage();
                }), ModalRoute.withName('/'));
              }),
            ],
          ),
        ): null,
        body: Container(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.max,
              children: <Widget>[
                FlutterLogo(size: 100),
                SizedBox(height: 20),
                Text(
                  "Welcome $name to Flutter",
                  style: TextStyle(
                    fontSize: 30,
                    fontFamily: 'DancingScript',
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }
}

Conclusion

Once done, let's run our app to do authentication using Google. You can find the code on my GitHub Repository.

I hope this is helpful.


Written by akshata26 | Software Engineer at www.udgama.com
Published by HackerNoon on 2021/09/18