A month of Flutter: Sign in with Google
Tags: flutter, tutorial, google, firebase
Published: 2018-12-18 23:39:08

_Originally published on [bendyworks.com](https://bendyworks.com/blog/a-month-of-flutter-sign-in-with-google)._

Building on the work configuring Firebase Auth for [Android](https://bendyworks.com/blog/a-month-of-flutter-configure-sign-in-with-google-android) and [iOS](https://bendyworks.com/blog/a-month-of-flutter-configure-sign-in-with-google-ios), it's time to go get a user's details. This will be leveraging the already installed [`google_sign_in`](https://pub.dartlang.org/packages/google_sign_in) and [`firebase_auth`](https://pub.dartlang.org/packages/firebase_auth) packages.

The big change is the addition of the `Auth` class.

~~~dart
class Auth {
  Auth({
    @required this.googleSignIn,
    @required this.firebaseAuth,
  });

  final GoogleSignIn googleSignIn;
  final FirebaseAuth firebaseAuth;

  Future<FirebaseUser> signInWithGoogle() async {
    final GoogleSignInAccount googleAccount = await googleSignIn.signIn();
    // TODO(abraham): Handle null googleAccount
    final GoogleSignInAuthentication googleAuth =
        await googleAccount.authentication;
    return firebaseAuth.signInWithGoogle(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
  }
}
~~~

This class gets passed a `FirebaseAuth` instance and a `GoogleSignIn` instance for interactions with the external authentication services. On `GoogleSignIn` the [`signIn` method](https://pub.dartlang.org/documentation/google_sign_in/latest/google_sign_in/GoogleSignIn/signIn.html) will trigger a user account selection prompt. When the user confirms their account selection a [`GoogleSignInAccount` instance](https://pub.dartlang.org/documentation/google_sign_in/latest/google_sign_in/GoogleSignInAccount-class.html) will be returned. On `GoogleSignInAccount` I'll call [`authentication`](https://pub.dartlang.org/documentation/google_sign_in/latest/google_sign_in/GoogleSignInAccount/authentication.html) to get the [current user's tokens](https://pub.dartlang.org/documentation/google_sign_in/latest/google_sign_in/GoogleSignInAuthentication-class.html). Finally I'll exchange the `GoogleSignInAuthentication` for a `FirebaseUser` with [`signInWithGoogle`](https://pub.dartlang.org/documentation/firebase_auth/latest/firebase_auth/FirebaseAuth/signInWithGoogle.html).

I added a TODO to [improve error handling](https://github.com/abraham/birb/issues/48) so it doesn't get forgotten.

The app now has an authenticated [`FirebaseUser`](https://pub.dartlang.org/documentation/firebase_auth/latest/firebase_auth/FirebaseUser-class.html) with all the accompanying details.

I'll now update `SignInFab` to leverage the new `Auth` service and print out the user's `displayName` in the Flutter logs.

~~~dart
void _handleSignIn() {
  auth
      .signInWithGoogle()
      .then((FirebaseUser user) => print('Hi ${user.displayName}'));
}
~~~

~~~log
I/flutter (29142): Hi Birb Dev
~~~

`SignInFab` will also need to be passed an `Auth` instance in `_MyHomePageState`.

~~~dart
SignInFab(
  auth: Auth(
    firebaseAuth: FirebaseAuth.instance,
    googleSignIn: GoogleSignIn(),
  ),
)
~~~

This is what the account selector looks like on Android:

![Sign in flow on Android](https://thepracticaldev.s3.amazonaws.com/i/tmcslg9phm3h73p5ckmd.png)

iOS prompts to allow access to google.com:

![Sign in flow on iOS](https://thepracticaldev.s3.amazonaws.com/i/mb3rgfgnb8slw67c1umc.png)

Most of the new code is actually tests and mocking the external Google and Firebase APIs. It's complected and deserves it's own article so come back tomorrow to learn more.

## Code changes

- [#44 Add sign in service](https://github.com/abraham/birb/pull/44)