Dive into Firebase Auth on Flutter: GitHub and Google Authentication

Paul Ruiz
Firebase Developers
13 min readOct 13, 2020

Firebase includes various tools to help developers build, grow, and improve their apps. One of the most used of these tools is authentication, as it allows developers to restrict who can read or write data to the Firebase backend and provides a secure environment for their user’s data.

This is part two of a short series covering Firebase Authentication with the FlutterFire plugin. In the previous article we learned how to add Firebase to a Flutter project using this plugin, how to register and authenticate a new user in Firebase using an email and password, and how to authenticate a user with an emailed link. You can find that post here:

In this article we will be learning about Firebase Authentication with third-party identity providers. Firebase Authentication is built on the idea that these identity providers are trusted by Firebase to authenticate a user within their own system, and that trust is carried over to authenticating with Firebase. We will start on this topic by looking at the process and flow of authentication in the context of GitHub authentication. After learning how everything works on a more technical level, we will look at how we can use a third-party plugin, in this case the Google Sign-In, to handle a portion of the authentication process with even less code.

Setup

Before we dive into using third-party identity providers for Firebase Authentication, let’s create a base app that we can use while learning how everything works together. Start by creating a new Flutter application and linking it to a Firebase project. If you need a quick refresher on how to do this, you can find instructions in the previous article in this series. For this article I will use the Android platform to demo everything done in Flutter, but the general concepts will still apply to iOS.

After we create our app and link it to Firebase, we can add the following dependencies to pubspec.yaml (firebase_core should already be there from the initial setup process):

The google_sign_in plugin will be used later in this article to streamline our authentication process using Google’s authentication framework, url_launcher is used for starting a web browser on the user’s device and going to a specified URL, and uni_links is used to handle intercepting opened webpages and instead opening our app. The two Firebase dependencies are used for interacting with, as you can probably guess, Firebase from our app.

Next we can copy the following snippet into our main.dart file. This is a simple “Hello World” app that initializes Firebase, and will be our starting point for going over the steps to implement Firebase Authentication using third-parties.

At this point we’re ready to start learning about third-party identity providers and Firebase Authentication.

Authenticate Using GitHub Sign-In

In this section we’ll take a look at how to use a third-party identity provider without assistance from any plugins that may be available from that provider. While a plugin would significantly streamline this process, as we’ll see when we discuss Google’s Sign-In, for now we will focus on providing a background on how Firebase Authentication works as an overall system. While we will use GitHub as this example’s identity provider, the concepts behind it will still apply to other third-party identity providers that we could use for authentication.

The goal for third-party authentication is to be able to exchange a trusted OAuth token with Firebase in order to authenticate a Firebase user. The process using GitHub to authenticate against Firebase can be summed up in six steps:

  1. Our Flutter app launches the GitHub OAuth page with a client ID (we’ll create that in this article soon). The user is prompted to sign in through their web browser, then to authorize our app to access their GitHub account.
  2. Once the user has authenticated and authorized, GitHub redirects them to a callback URL with a temporary handshake code appended onto the URL.
  3. Our app listens for that URL on the user’s device, and intercepts the redirect. Once intercepted, our app can extract the code from the URL.
  4. Using the extracted code, GitHub client ID, and GitHub client secret, our app can request an access token from GitHub for that specific user.
  5. If the supplied information is accepted, GitHub sends a response that contains an access token string that our app can extract from the response.
  6. Using that token, our app can create a new credentials request with Firebase and authenticate. At this point the user is logged in to our Firebase project. If they log out or their session expires, then the process can be repeated.
Steps for Firebase Authentication Using GitHub

Now that we know the process that GitHub authentication goes through to work with Firebase, we should do a little more setup before we dig into the code. Let’s start by going to the Firebase Console and selecting the project that we have linked with our Flutter app. From there go into the Authentication section on the left of the console.

From the Authentication page, we can navigate to the Sign-in method tab and select GitHub from the Sign-in providers section. This will bring up a dialog box that asks for a Client ID and Client secret, as well as provides an authorization callback URL that we can use with a GitHub app.

Start by clicking on the copy icon next to the callback URL. We’ll come back to this screen in a moment, but next open up a new tab and navigate to the new GitHub applications screen here:

We can fill in whatever information we want for the Application name and Homepage URL sections, but we’ll want to paste the link that we just copied into the Authorization callback URL section.

After filling out that information and clicking on the green Register application button, we’ll be taken to a screen that provides the Client ID and Client Secret that we need back in the Firebase Console.

I’ve already deleted this demo app :)

Once we’ve filled out the information in the console, we can click on the blue Save button and return to our Flutter app.

Let’s start by updating our UI. We’ll want to create an instance of FirebaseAuth and a UserCredential object at the top of _MyHomePageState in main.dart, and then add a button to the AppBar for signing out of Firebase. We will also want to add a single button in the body of the UI that will kick off our GitHub authentication process, and a Text widget to display user status. We can replace the current _MyHomePageState class with the code from this snippet. Be sure to import any missing packages.

At this point our app doesn’t compile, so let’s go ahead and fix that. We will need to create two new methods within this class: signOut() and signInWithGitHub(). signOut() will simply tell Firebase Authentication to sign out any currently authenticated users, and will update the user property to null so that the UI will update as a state change.

For now, let’s just stub signInWithGitHub() as an empty async method inside of this class so we can run our app and make sure our UI looks how we expected.

If everything has gone as expected, our app should look like this:

If it does, then great job! We can finally get on to Step 1 of the GitHub authentication flow. We’ll start by declaring our client ID and secret at the top of this class (make sure you use your own values here!). We won’t need the secret yet, but at least we’ll have it later when we do need it. It’s also worth noting that it would be a better practice to include these values in a separate file that gets merged into our app at build time, but we’ll keep everything in main.dart for this article to simplify this process.

Back in the signInWithGitHub() method we can create a new String that points to GitHub’s OAuth authorize URL, and then check to see if our user’s device is able to launch that URL. If they are, then we can launch the page in their device’s browser using the url_launcher package.

If you’re wondering where that URL came from, or what else you can do with it, you can read up on GitHub’s OAuth API here:

If we click on the Sign In With GitHub button now, our device should open a browser and either prompt our user to sign in to GitHub, or go directly to our app’s authorization page.

When our user clicks on the green Authorize button, GitHub will continue on to Step 2 of the process by redirecting to our callback URL with an appended code. Next we will want to follow through with Step 3 by intercepting that callback URL and opening it with our app. This process will vary a little bit between Android and iOS, but we will focus on the Android implementation for this exercise. Let’s open the AndroidManifest.xml file in our Flutter project and add the following intent-filter to the activity node:

While the scheme property will remain the same, you will want to change your host to reflect the URL used by your own Firebase project.

Now that we’re prepared to capture requests to our callback URL, we need to react to them. We’ll do this by using the Universal Links plugin that we added earlier. Let’s return to main.dart and add a new StreamSubscription (from the dart:async package) to the top of the _MyHomePageState class. We will also override the initState() method in this class to listen for links and extract the code from our callback URL using a simple regular expression. For reference, the callback URL should look something like this:

https://flutterfire-ptruiz.firebaseapp.com/__/auth/handler?code=cdd66a34ddfc098156e9

Now that we have the code, we can add a new method call to initState() called loginWithGithub() that will run through Steps 4 through 6 in quick succession.

The first thing loginWithGitHub() will do is make an HTTP post request with the client ID, secret, and code to GitHub in order to receive an access token.

At this point our IDE will throw an error at http.post. We can fix this by importing the http package into our project by adding this line at the top of main.dart:

The expected response is outlined in GitHub’s API documentation that was linked above, though this particular response should look something like this:

{
access_token: 6900def89db9435a6337be75aa1b59088bc133d3,
token_type: bearer,
scope:
}

After receiving the response from GitHub, we can continue to Step 5 in the process and extract the access token for use with Firebase’s GitHubAuthProvider object.

We can wrap up this method by moving on to Step 6 in the authentication process by using the access token we retrieved from GitHub and using that to authenticate with Firebase.

To wrap up using GitHub authentication, we will want to override the dispose() method in order to clear out the deepLinkSubscription listener.

At this point we should be able to authenticate a user in Firebase using GitHub as our third-party identity provider. If we return to the Firebase console, we should be able to see that we currently have no users saved under the Authentication page.

Now we can run our app and let our user run through the entire authentication process, as shown in this clip:

After our user has authenticated, we should be able to see them in the Firebase console.

Authenticate Using Google Sign-In

Now that we’ve seen the entire process behind authenticating with a third party identity provider, let’s take a look at how this process works when there’s an additional plugin involved. For this example we’ll take a look at how we can use Google as an identity provider for Firebase authentication. While using the Google sign-in SDK, we have four main steps that we will need to follow:

  1. Retrieve the user’s Google account information.
  2. Authenticate the user’s account through Google in order to retrieve a GoogleSignInAuthentication object that contains their ID token, access token, and other relevant information.
  3. Create a new GoogleAuthCredential object using the user’s access and ID tokens.
  4. Authenticate in Firebase with the user’s credentials.

We can start by adding a new button to the body of our build() method in the _MyHomePageState class.

All four steps will be covered by this new signInWithGoogle() method. We can retrieve the user’s Google account information with the following code:

Once we have the user’s account, we can authenticate against it with Google.

At this point our next two steps are very similar to what we did with GitHub, so we can combine them here and finish out the signInWithGoogle() method.

And that’s all we need to do in our Flutter app to authenticate with Google. We will need to go back into the Firebase console and enable Google sign-in, similar to what we did with GitHub. Fortunately, this is about the extent of the setup process. It is worth noting that we will need to include our Android signing key SHA-1 when linking an Android app to Firebase in order to use Google sign-in on an Android device, though this process is discussed in the previous article in this series.

Since Android devices have a built in Google sign-in feature, we’ll need to take an additional step to get Google authentication working with Firebase on iOS devices. We will need to take the REVERSED_CLIENT_ID value out of our iOS GoogleService-Info.plist file and add it as a new URL type in our project. Detailed instructions can be found on this documentation page under step 2.1. Luckily, after doing that step, the rest of that page is handled by the Flutter code that we’ve already put together.

At this point we can run our app and see how authentication with Google works on a device. You’ll notice that Step 2 even includes its own UI on Android, allowing users to select an email account that they are already logged in with.

and on iOS the user will be prompted to go to a Google sign-in page where they can enter their email and password.

If we return to the Firebase console, we can see that the user is still authenticated with Firebase using the same ID, but the provider icon has switched from GitHub to Google. I promise this isn’t a bug! :) This is because Google is a more trusted identity provider in Firebase for this situation, so it takes precedent over GitHub as an identity provider.

Conclusion

In this article we learned about the entire process behind authenticating in Firebase with GitHub as a third-party identity provider in Flutter. We also looked into Google sign-in for Firebase, and how to streamline the process with Google’s plugin. Now that you know how to use both of these, the other third-party authentication options should be relatively straightforward to implement in your Flutter apps. In the next article in this series we will learn about phone SMS authentication and anonymous sign-in, so I hope to see you there!

Resources

--

--

Paul Ruiz
Firebase Developers

Developer Programs Engineer on Android, Maker, @ptruiz_dev