Originally published on bendyworks.com.
Building on the work configuring Firebase Auth for Android and iOS, it's time to go get a user's details. This will be leveraging the already installed google_sign_in
and firebase_auth
packages.
The big change is the addition of the Auth
class.
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,
);
}
}
~~~{% endraw %}
This class gets passed a {% raw %}`FirebaseAuth`{% endraw %} instance and a {% raw %}`GoogleSignIn`{% endraw %} instance for interactions with the external authentication services. On {% raw %}`GoogleSignIn`{% endraw %} the [{% raw %}`signIn`{% endraw %} 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 [{% raw %}`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 [{% raw %}`FirebaseUser`{% endraw %}](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 {% raw %}`displayName`{% endraw %} in the Flutter logs.{% raw %}
~~~dart
void _handleSignIn() {
auth
.signInWithGoogle()
.then((FirebaseUser user) => print('Hi ${user.displayName}'));
}
~~~{% endraw %}{% raw %}
~~~log
I/flutter (29142): Hi Birb Dev
~~~{% endraw %}
{% raw %}`SignInFab`{% endraw %} will also need to be passed an {% raw %}`Auth`{% endraw %} instance in {% raw %}`_MyHomePageState`{% endraw %}.{% raw %}
~~~dart
SignInFab(
auth: Auth(
firebaseAuth: FirebaseAuth.instance,
googleSignIn: GoogleSignIn(),
),
)
~~~{% endraw %}
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)