PETER FRIESE: Hey, everyone. This is Peter from
the Firebase team. In this video, I'm
going to show you how to implement Google Sign-In
using Firebase Auth in your app on iOS. This video assumes that you know
the basics about Firebase Auth already. If you'd like a
little refresher, I recommend you watch my
introductory video first and then come back here. At the end of this
video, you will know how Google
Sign-In works, how to handle the sign-in
flow in your iOS app, and how to sign out again. Let's get started. I've created a sample
app to demonstrate how you can implement
Google Sign-In in your app. The code is available in
this GitHub repository. There is a start up
project you can use if you want to follow along. But if you just want
to see the final result or if you get stuck,
there is also a folder with the final finished site. The app allows users to
choose their favorite number and then stores it
locally in user defaults. This is great for now. But I like to implement
a feature that allows users to retrieve
their favorite number on all their other
devices or share it with their best friends. Cloud Firestore sounds
like a great tool to implement this
kind of data storage. But before I can store my
users favorite numbers in Cloud Firestore, I need to get hold
of some unique identifier that I can use to tell all
of those favorite numbers apart and know exactly which
user has which favorite number. Firebase authentication provides
access to such an identifier. Each user has a unique
identifier called the UID. Whenever a person signs
up to your app using Firebase authentication, their
newly created user account gets an identifier that
is unique to your Firebase project. Before we can use
Firebase authentication, we need to add the
Firebase SDK to our app. I've already done this
for my sample app. But if you'd like to
know how I did that, check out this other
video in which I walk you through the steps of setting
up a Firebase project using Swift Package Manager. The next step is to add
the Firebase Auth library to all the targets
in which I want to use Firebase authentication. However, since I already did
this in the previous video about Firebase Auth, I
don't need to do this again. To allow users to sign into
my app with Google Sign-In, I need to add the
Google Sign-In SDK. The Google Sign-In SDK is
not part of the Firebase SDK. It's a separate download,
just like other authentication providers, such as Facebook. So before I can use it, I
need to add the Google Sign-In SDK to my Xcode project
using Swift Package Manager. Let me open the
add packages dialog and then place the URL
of the Google Sign-In SDK into the search field. After a short moment, I can
see the readme of the package. The Google Sign-In
SDK team has just released a new major
version of the SDK, which makes configuring the
SDK easier than before. So let's choose up
to next beta version and enter the version number
of the latest release. I'll click on Add Package. And Xcode will go and fetch
the package information by downloading the package file. Once that's done, I can
select both the Google Sign-In and Google Sign-In
Swift library, and then click on the
Add Package button to add them to my Xcode project. There is one more step we need
to complete in Xcode before we can activate Google Sign-In
in the Firebase Console. And this is to add
the reverse client ID to the list of URL schemes. You can find the reverse client
ID in the Google services info [INAUDIBLE] file. Copy it and then go back into
your target configuration. Navigate to the Info tab. Export the URL type section. Then tap the plus button
to create a new URL type and paste the reverse client
ID in the URL schemes field. Leave all the other
fields untouched. To use Firebase
Authentication, we need to activate it in
the Firebase Console. But as you can see, I already
did this for my project, so no need to do it again. However, I do need
to enable Google Sign-In in the list of
authentication providers for my app. You can enable and use as
many authentication providers in your app as you like. By doing so, you
enable users to sign in using their preferred
authentication mechanism. Some users might prefer signing
in with email and password. While others might prefer Google
Sign-In or sign in with Apple, as this gives them this
really smooth one-tap login experience. This also allows you
to let users link multiple sign in mechanisms. For example, if your user signed
in using email and password but they later would like
to connect their Google account to your
app, that's possible if you implement
account linking. This is something we will look
at in one of the next videos. In this video though,
I want to show you how to implement Google
Sign-In, so let me go ahead and activate the Google Sign-In
authentication provider. One thing you need
to keep in mind. If you use any OAuth-based
authentication mechanism such as Google Sign-In
or a Facebook login, Apple's App Store
review guidelines require you to also
implement sign in with Apple. There are some
exceptions to this rule. So I recommend you check out
the current version of the App Store review guidelines
to be on the safe side. By the way, if you forget
to enable a provider, Firebase Auth will
throw an error message when you try to sign in. That's one of the
reasons why you want to implement some
error handling in your app. It makes it a lot
easier to figure out what's wrong when things
aren't working as expected. To make development
easier, I recommend using the Firebase Emulator. You can think of the
Firebase Emulator Suite as your own personal
instance of Firebase running on your local
development machine. Since everything
runs locally, you don't run the risk of messing
up your production data. And you also avoid stepping
on each other's toes when you're sharing
a development project with your teammates. Another benefit is that
the Emulator Suite also works when you're offline
or on a slow network. I've already installed
and configured the Firebase Emulator Suite
in the previous video. So feel free to check
this out if you'd like to see how to
do this for yourself. I'll start the emulator using
the following command line. This tells the
emulator to persist any user accounts we create
and later restore them the next time I run
the same command. In fact, I've previously
created a user account. And as you can see, the
emulator has restored this user from disk. This saves quite a bit
of time, especially if you have more than
just a few test accounts. To connect your app
to the Emulator Suite, add the following code to
your Firebase setup code. Now, with all this preliminary
work out of the way, I can start implementing
Google Sign-In in my app. The first thing I want to do
is add a Google Sign-In button to my login view. The Google Sign-In SDK
contains a sign in button. But I want more control. So I will add a custom
SwiftUI button to my view. Let's take a look. So basically, it is
a SwiftUI button. And inside the
label closure I use a text view to display the
text "Sign in with Google". To make it look
like a real button, I set the button
style to bordered. And I also set the
foreground color of the text depending on whether we're
in dark or light mode. For the colorful G logo,
I put an image view in the background
of the text view and make sure it is aligned to
the left side of the text view. The logo should
have a width of 30 and be aligned in the
center of its frame. Now this is starting
to look quite nice. But the logo and the text
overlap in an unsightly way. So I will use the
frame view modifier to tell the label to use
all the available space. In SwiftUI, the order of
the view modifiers matter. So it is really important
to apply the frame modifier before the background. Otherwise, the logo will not
be pushed out to the left edge. And finally, I will add
some vertical padding to the text to make sure the
button has the same height as the login button just above. When the user taps
on the button, I will call the sign in
with Google function, which will forward the
call to the view model to sign the
user in using Google. But before we can
implement this function, let's talk about how the
process of signing in a user to Firebase works when
using an OAuth provider. There are three main
steps to this process. First, the user has to sign
in to the OAuth provider. And you will be using
the provider's SDK or their endpoint
to handle this step. If the user signed
in successfully, you will receive an ID
token for this user. Take this ID token and any
additional information that might be required and create
a credential object using one of Firebase's OAuth providers. There is a generic
OAuth provider, but also some specialized ones, like
the one for Google Sign-In. And finally, use this
credential object to sign in to Firebase and
exchange the provider's ID token for a Firebase ID token. But before we can actually
call the Google Sign-In SDK, we need to configure it using
your app's OAuth client ID. There are two ways to do this,
one using your project's target properties and the other one
using the GID configuration object. Remember the updated
configuration flow I told you about? Well, for using this first way
to configure the Google Sign-In SDK, you don't even
need to write any code. Let me show you how. First, let's get the
client ID for our project. You can get this by looking into
your project's Google services [INAUDIBLE] file or look it up
on the Google Cloud Console. Remember, every Firebase project
is also a Google Cloud project, so you can see all your
project's details by visiting the Google Cloud Console. To get the client
ID for your project, go to the Google Cloud Console
at console.cloud.google.com, then find APIs and Services in
the navigation bar on the left. On the fly out menu, select
credentials to see all API keys and/or client IDs
for your project. You should now see an OAuth2
client ID for your iOS project. It's name should start with
iOS client and the bundle ID of your iOS app. Click on this item
to see its details. In the next screen, you will see
the client ID and the iOS URL scheme for this OAuth client ID. Copy the client ID. Alternatively, if you don't
want to use the Google Cloud Console, you can just open
your project's Google services [INAUDIBLE] file. The client ID and
the reverse client ID are at the very top of the file. In the next step, we
will add this client ID to our app's target properties. First, select the
project's target in the project configuration. Then hover over the Custom
Target properties table and click one of the
little plus icons. This will insert a new key. Name the key GID client ID. Make sure the type
is set to string. And then place the client
ID into the value column. If you don't want to
use this approach, you can also configure the
Google Sign-in client SDK programmatically. Let's first import the
Google Sign-In module, so we can use it
in our view model. Next, we will
fetch the client ID from the project's Google
services [INAUDIBLE] file. But instead of reading
the file directly, we can use the options object
on the Firebase app instance. This is populated when you
call FirebaseApp.configure at application startup. After reading the
client ID, we create a GID configuration object
and configure the shared GID sign in instance with it. The Google Sign-In
client SDK will always try to read the property from
your app's target properties first, and then
overwrite it with any programmatic configuration
you might be using. To help Google Sign-In to
present its sign in flow correctly, we also need
to provide a reference to the presenting
view controller. This is particularly
important on devices with a larger screen. You will want to make
sure the sign in dialogue appears in the
center of the screen and not somewhere tucked
away in a sidebar. Now that we've got
everything in place, we can invoke the sign
in flow by calling GIDsignin.chatinstance.signin. When I open the code completion
for the sign in method, I can see all the
available overloads. The first ones all require me to
implement a completion handler, as we can see by looking
at their signature. And these other
ones here allow me to use a single
way to call them, which will make my
code look a lot nicer. So let me call this method
and pass in the root view controller. And now I will try to assign
the result of this method call to a local variable. I will use try await
since I want to call this method asynchronously. But there is a
warning which tells me that this method
needs to be called from an asynchronous context. When I click on
the error message, Xcode offers two
different fixes for this. Since I am interested in getting
the return value of this call, I will pick this first one here,
which adds the async keyword to the function signature. And now I need to
wrap the call in a do catch block to properly
handle any errors. Unfortunately, Xcode doesn't
have a quick fix for this. So I'll have to
implement this manually. If an error is thrown,
we will return false. Otherwise, we will return true. So this was the first step. In the next step,
we will extract the ID token and
the access token from the result of this call. If there is no ID token,
we will throw an error. And now, let's use the
Google OAuth provider to create a credential
object from the ID token and the access token. And finally, we can use
this credential object to sign into Firebase. The OAuth object has a method
sign in with credential that takes our credential
and returns a Firebase user. Since this is a
server call, we need to call this function
asynchronously using try await. Let's extract the
user from the result, and then print a
little log message. Sweet, we are now ready
to run the application. I'll be using a
demo account that has two-factor authentication
enabled to provide that extra layer of security. So here I am in the application. And I am not yet signed in. I open the sign in dialog. And here is the Sign In button. All right, let me tap on it
to trigger the sign in flow. iOS will show this alert
to let the user know that we're now about to use
a third party to sign in. Once I tap on Continue,
the Google Sign-In dialog will appear. And you will notice
that this is actually running in the web browser. I can now type in the
credentials for the Google account I want to sign in with. Since this user
has 2FA enabled, I will now be given
a number of options to receive the second
factor, for example, by using an authenticator app,
like Google Authenticator, or receiving a
one-time code by SMS. When running this on
a physical device, the verification code by
SMS is the smoothest option, as iOS will offer to
autofill the code for me once it has arrived
in the messages app. And voila, I am signed in. In the previous
video, I showed you how to make sure the app
retains its authentication state across launches
by registering an authentication
state listener. And as expected, this works for
any authentication provider. So if I quit the app and
then launch it again, I am still signed in
using my Google account. Signing the user out works just
like for all the other Firebase authentication providers. A call to oauth.signout
is all that it takes to sign the user out locally. Firebase will remove the cached
ID token from the keychain, so the next time the
user starts the app, they will have to sign in again. Keep in mind that you
will have to reset your app into an unauthorized
state after a call to sign out. The easiest way to do this is
to use the authentication state listener and reset the UI when
you receive nil as the user. As you can see in
my implementation, it will reset the UI
and authentication state when it receives nil. And there you have it. Your users can now sign into
your app using Google Sign-In. In my opinion, federated
identity providers, like Google Sign-In
and Sign In with Apple are a much better
option than signing in with email and password. From the user's perspective,
it is so much more convenient. You don't have to come up with a
new and strong enough password. And since most of the providers
remember your username, you don't even have
to type in your email address all of the time. Another benefit is that most
federated identity providers support second factor
authentication, which adds an extra layer of
protection for your users. So happy faces all around. As mentioned earlier,
the sample app is available on our
GitHub repository. And the link is in
the description below. Hey, if this video
helped you, I'd love it if you could
give me a thumbs up, so I know you'd like to
see more content like this. Also, be sure to check out the
Firebase Fundamentals playlist, as we've got a bunch
of other videos about Firebase Auth and all the
other Firebase features coming up. Stay safe. And I will see you
in the next one.