Navigation

Add Google OAuth to the To-Do Client

Deployment Type:

Author: MongoDB Documentation Team

This tutorial walks you through adding the Google OAuth provider to your Stitch app and To-do client(s). The following diagram outlines the OAuth process in a Stitch application:

../../../_images/oauth.png

Time required: 20 minutes

What You’ll Need

If you have not yet built the To-do backend, follow the steps in this guide.

If you are building on a previous tutorial, be sure to remove and reinstall node dependencies, so you are working with the most up-to-date SDKs.

Procedure

A. Set up the Backend

There are 2 parts to setting up your Stitch backend app to use Google OAuth with Stitch: you create a Google Oauth client, and then you enable the Google auth provider in the Stitch backend.

For Android apps, you need to create and configure Google OAuth in two different Google tools, Google Cloud Platform and Firebase.

1

Create a project in GCP

  1. Navigate to the Google Cloud Platform (GCP). If you have not yet set up a GCP account, follow the instructions to do so.

  2. Create a new GCP project.

  3. In the project dashboard, click on the menu (upper-left), expand APIs & Services, and then select Credentials. You can also navigate directly to the Credentials page).

  4. Click Create Credentials, and then select OAuth client ID.

  5. Select Web Application, and then:

    • Give the application a name
    • Add http://mongodb.com in the authorized domains
    • Save your changes
  6. In the OAuth client dialog, click OK.

  7. When creating the OAuth client ID:

    • For Application Type, select Android.

    • For Name, enter a name to associate with the client ID.

    • For Signing-certificate fingerprint, enter the SHA1 fingerprint. To generate the SHA1 fingerprint, run the following command in a terminal or Windows Command Prompt:

      keytool -exportcert -alias androiddebugkey -keystore <path to debug.keystore> -list -v
      

      Terminal example:

      keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
      

      Windows Command Prompt example:

      keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore -list -v
      

      Tip

      If using debug.keystore, the password is android.

      Enter the SHA1 fingerprint. For more information and an example, see Google Setting up OAuth 2.0 Help page

    • For Package name, enter the following:

    com.mongodb.stitch.android.tutorials.todo
    

    The package name may be found in the ToDo Android application project’s AndroidManifest.xml

  8. Click Create.

  9. To create the Web app client credentials, Create credentials, and select OAuth client ID.

    • For Application Type, select Web application.

    • For Name, enter the name you want to associate with this client ID.

    • For Authorized JavaScript origins, enter the following:

      https://stitch.mongodb.com
      
    • For Authorized redirect URIs, enter the following:

      https://stitch.mongodb.com/api/client/v2.0/auth/callback
      
  10. Click Create.

  11. Note the Web app client ID and secret. You will use the information in the Users section of the MongoDB Stitch Admin Console.

2

Create & Configure an OAuth project in Firebase

  1. Navigate to https://console.firebase.google.com/u/0/.

  2. Click :guilabel:Add Project, and give the project the same name that you used in the GCP setup steps.

  3. Select the 2 checkboxes and then click Create Project.

  4. In the left-hand navigation, click Authentication, and then select the Sign-in Method tab.

  5. Click the Google row, and in the resulting popup, enable Google login, and then save your changes.

  6. Return to the project Overview page (link at the top of the left-hand navigation bar).

  7. Click the Add App button, and then select Android.

  8. Fill in the form with your app’s package name and the debug SHA-1 certificate for your computer.

    Note

    Refer to https://developers.google.com/android/guides/client-auth for instructions on how to generate your SHA-1 certificate.

  9. A Google services json file is created for you. Download it and copy the file to the root directory of your Android project.

  10. Firebase has also created a GCP client for you. You will now switch back to GCP to get that client’s ID and secret.

  11. Return to GCP (https://console.cloud.google.com/apis/credentials), and you will now see the new credentials that have been created.

  12. In the list of OAuth 2.0 client IDs, find the client labeled Web client (auto created by Google Service), and then click the edit icon ( pencil icon ).

  13. You will use this client ID and client secret when you configure the Google Auth provider in the following steps.

3

Enable & Configure Google Authentication in Stitch

  1. Navigate to your Stitch application.
  2. Select Users from the left-side navigation.
  3. Select the Providers tab.
  4. For Google, click the Edit button.
  5. In the Google provider settings:
    • Switch the Provider Status toggle to enabled.
    • Enter your new Client ID and
      Client Secret from the google Web App client credentials. When entering your secret, you are first prompted to name the secret, and then can paste in the secret value.
  6. Click Save.

For details on all authentication methods supported by Stitch, see User Authentication Overview.

B. Update your client

For the client work in this tutorial, you can start with the app you built in the previous tutorial or start with an app that already has some of the Android structural work done for you.

Note

If you chose to use your existing app, you will need to create a new layout file and class to handle the logon UI and logic. We recommend you view the pre-configured app for ideas on how this might be strcutured. The steps in this tutorial assume you are using the pre-configured app.

1

Get the latest code

In the MongoDB Stitch Android tutorial repo, run the following command to fetch the tagged version for this tutorial:

git checkout google-oauth

Note that the Android project now includes a LogonActivity.java file and logon.xml layout file. The layout provides the UI for logging in with Google and Facebook OAuth, and the LogonActivity class provides the logic to show the logon activity and handles the authentication.

2

Add Google Libraries to Gradle

  1. Open the project-level Gradle file.

  2. Add the following lines to the dependencies:

    implementation 'com.google.gms:google-services:4.0.1'
    implementation 'com.google.firebase:firebase-core:16.0.1'
    implementation 'com.google.android.gms:play-services-auth:16.0.0'
    
3

Update strings.xml

  1. Open the res/values/strings.xml file.

  2. Set the value of the stitch_client_app_id key to your Stitch App ID.

  3. Add a string key named google_web_client_id – or update the existing key – with the Web client ID that was generated during the Google setup process. This is the same ID you used when configuring the Google Auth Provider in your Stitch backend.

    Important

    Counter-intuitively, you specify the Web client ID, not the Android client ID. This is because the final step of authentication against Google comes from the Stitch backend, not the Android app.

    With these changes, your strings.xml file might look like this:

    <resources>
      <string name="app_name">Todo</string>
      <string name="login_action_label">Log in</string>
      <string name="add_item_action_label">Add</string>
      <string name="clear_checked_action_label">Clear Checked</string>
      <string name="clear_all_action_label">Clear All</string>
      <string name="edit_item_hint">Edit Item</string>
      <string name="stitch_client_app_id">todo_android_app-aabdc</string>
      <string name="google_web_client_id">153606348891-b0vmthckcud6dvlg60qi2rcilabcdef.apps.googleusercontent.com</string>
    </resources>
    
4

Add a button to logon.xml

The logon.xml file defines the logon activity layout, which currently only inlcudes a link for logging on anonymously.

  1. At the bottom of the LinearLayout, add a com.google.android.gms.common.SignInButton. The android:id property should be set to @+id/google_login_button. Your code may look like the following:

    <com.google.android.gms.common.SignInButton
      android:id="@+id/google_login_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
    
5

Add logon logic to LogonActivity.java

All of the logon logic for this app lives in the LogonActivity class. The Logon activity dislays when the app starts, and when a user authenticates (currently only as Anonymous), control is passed to the TodoListActivity. We are now going to add the logic for Google OAuth to the logon activity, so a user can choose to authenticate either as Anonymous or with their Google account.

The first step is to create a method that will encapsulate the Google logon logic, and then call that method from the existing setupLogin() method. In the downloadabe app, we have named this function enableGoogleAuth to follow the convention we started with the anonymous login code. This method will instantiate the Google classes needed to send an authorizaion request to Google when a user clicks the Google login button that you added to the layout.

Open the LogonActivity.java file and follow these steps:

  1. In the enableGoogleAuth method, you need to create a new GoogleSignInOptions object by calling build() on a GoogleSignInOptions.Builder object. Your code should look like this:

    // 1. Create a new GoogleSignInOptions object by calling build() on a
    //    new GoogleSignInOptions.Builder object.
    final GoogleSignInOptions gso =
      new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
      .requestServerAuthCode(googleWebClientId, true).build();
    
  2. The GoogleSignInOptions object is used to create a GoogleApiClient, which is the object passed to the Google auth servers when a user authenticates. We have created a _googleApiClient property, which you need to initialize by using a new GoogleApiClient.Builder object. Your code should look like this:

    // 2. Initialize the _googleApiClient
    _googleApiClient = new GoogleApiClient.Builder(LogonActivity.this)
      .enableAutoManage(LogonActivity.this, connectionResult ->
              Log.e("Stitch Auth", "Error connecting to google: " + connectionResult.getErrorMessage()))
      .addApi(GOOGLE_SIGN_IN_API, gso)
      .build();
    
  3. Now you need to attach an onClick hanlder for the button we added to the layout file above. Your code should look like this:

    // 3. Create an onclick listener for the google_login_button
    findViewById(R.id.google_login_button).setOnClickListener(v -> {
        if (!_googleApiClient.isConnected()) {
            _googleApiClient.connect();
        }
        GoogleSignInClient mGoogleSignInClient =
                GoogleSignIn.getClient(LogonActivity.this, gso);
    
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, GOOGLE_SIGN_IN);
    });
    

    Note

    The enableGoogleAuth method is called when the Logon activity is created.

  4. We now need a way to handle the request that comes back from Google. To do this, we’ve created a onActivityResult method at the bottom of the class. In this method, add code to make sure the request has come from google by checking that the requestCode is GOOGLE_SIGN_IN. If it is, we need to pass the returned information to Stitch for authentication. We want this method to have a single responsibility (handling the onActivityResult), so we’ll pass the task to a separate method. Your code should look like this:

    // 4. Handle the result that Google sends back to us
    if (requestCode == GOOGLE_SIGN_IN) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        handleGoogleSignInResult(task);
        return;
    }
    
  5. Now we need to add functionality to the handleGoogleSignInResult() that we call above. We need to convert the returned task to a GoogleSignInAccount. The GoogleSignInAccount carries the Google server authentication code, which we will send to the Stitch backend:

    // 5. Create a GoogleSignInAccount from the task result.
    GoogleSignInAccount account = completedTask.getResult(ApiException.class);
    
    // Create a GoogleCredential from the account.
    final GoogleCredential googleCredential =
      new GoogleCredential(account.getServerAuthCode());
    
  6. Now that we’ve authenticated against Google, we need to authenticate with Stitch. We already have a static StitchAppClient defined in the TodoListActivity, so we’ll pass the GoogleCredential to the loginWithCredential method and handle the result of that call. Your code should look like this:

    // 6. Authenticate against Stitch. If the task is successful, set the result to
    //    Activity.RESULT_OK and end this activity, returning control to the TodoListActivity
    TodoListActivity.client.getAuth().loginWithCredential(googleCredential).addOnCompleteListener(
      task -> {
        if (task.isSuccessful()) {
            setResult(Activity.RESULT_OK);
            finish();
        } else {
            Log.e("Stitch Auth", "Error logging in with Google", task.getException());
        }
    });
    

C. Build and Test

  1. You can now run the app (in the emulator or on a device) and see the logon screen with the newly-added Google button. In Android Studio, click the debug icon, or select Debug ‘stitch-tutorial-todo-android’ from the Run menu, and the app is loaded onto the emulator or device you have chosen:

    ../../../_images/android-todo-google-login1.png

    Clicking the button brings up the Google authentication options:

    ../../../_images/android-todo-google-login2.png
  2. Log in, add some items to your To-do list, and then log out (from the menu). When you log in again with the same account, your to-do list is shown.

A. Set up the Backend

There are 2 parts to setting up your Stitch backend app to use Google OAuth with Stitch: you create a Google Oauth client, and then you enable the Google auth provider in the Stitch backend.

1

Create a project in GCP

  1. Navigate to the Google Cloud Platform (GCP). If you have not yet set up a GCP account, follow the instructions to do so.

  2. Create a new GCP project.

  3. In the project dashboard, click on the menu (upper-left), expand APIs & Services, and then select Credentials. You can also navigate directly to the Credentials page).

  4. OAuth Consent Screen If this is a new project, you may be required to first configure the consent screen.

    • Application Type: Should remain public
    • Application Name: Can be whatever you wish to call it. We’ve the name Stitch Todo IOS
    • Authorized Domains: Add mongodb.com to this field.
    • Save your settings.
  5. Create Oauth Credentials for Stitch Now we must create OAuth credentials for Stitch to use. Later in the tutorial we’ll also create credentials for the Todo app itself.

    This may seem counter-intuitive or unecessary, but it makes sense when we think about the architecture. Because we want Stitch to manage our users, we must create credentials Stitch can use to comminicate with the Google Identity API.

    The flow is as follows:

    1. The user will login with Google.
    2. Google will respond with user information, including a special Server Authentication Code used by backend services to verify and manage Google OAuth users in their system.
    3. The user sends this code to Stitch.
    4. Stitch sends this code, and uses the web oauth client id and secret to authenticate with Google.
    5. Google responds with the user’s information.
    6. Stitch responds to the client with a successful login request.
  6. Click Create Credentials, and then select OAuth client ID.

  7. Select Web Application, and then:

    • For Application Type, select Web application.

    • For Name, enter the name you want to associate with this client ID.

    • For Authorized JavaScript origins, enter the following:

      https://stitch.mongodb.com
      
    • For Authorized redirect URIs, enter the following:

      https://stitch.mongodb.com/api/client/v2.0/auth/callback
      
  8. Click Create.

  9. Note the Web app client ID and secret. You will use the information in the Users section of the MongoDB Stitch Admin Console.

2

Update the Stitch Backend for Google Authentication

  1. Navigate to your Stitch application.
  2. Select Users from the left-side navigation.
  3. Select the Providers tab.
  4. For Google, click the Edit button.
  5. In the Google provider settings:
    • Switch the Provider Status toggle to enabled.
    • Enter your new Client ID and
      Client Secret from the google Web App client credentials. When entering your secret, you are first prompted to name the secret, and then can paste in the secret value.
  6. Click Save.

For details on all authentication methods supported by Stitch, see User Authentication Overview.

B. Update the iOS Application

1

Create the iOS OAuth Credentials

Now we must create the credentials for our iOS app to use. Navigate to your Google Console Credentials page

  1. Click Create Credentials, and then select OAuth client ID.

  2. Select iOS, and then:

    • For Application Type, select iOS.

    • For Name, enter a name to associate with the client ID.

    • For Bundle ID, enter your app’s Bundle ID. This can be found in Xcode by selecting the Project from the File Explorer and selecting the General tab.

      ../../../_images/xcode_general_tab.png
  3. Click Create.

2

Modify Podfile

It’s time to jump into Xcode. Open your Todo.xcworkspace project and find the Pods project. Open Podfile and add the following line after the line beginning with pod 'StitchSDK', ... to add support for Google Signin.

pod 'GoogleSignIn'

Exit Xcode, and in the project directory run the following command to have Cocoapods add the new dependency,

pod install --repo-update

Once this is complete reopen Todo.xcworkspace

3

Modify Constants.swift

We will add the constants we need to sign in with Google. We’ll add both the iOS Client ID we created for our iOS app, and we’ll add the Client ID we created for our web app for Stitch to use.

Add the following to the bottom of Constants.swift prior to the closing brace of the Constants struct.

// Google Sign-in Constants
static let GOOGLE_CLIENT_ID = "<your iOS client ID>" // <- update this!
static let GOOGLE_SERVER_CLIENT_ID = "<your web app client ID>" // <- update this!
4

Modify AppDelegate.swift

Now it’s time to modify AppDelegate.swift to allow our application to support signing in with Google.

First, add the following import right after the line import StitchRemoteMongoDBService.

import GoogleSignIn

Next, declare that class AppDelegate conforms to the GIDSignInDelegate protocol by added it to the declaration list.

Replace the following line:

class AppDelegate: UIResponder, UIApplicationDelegate {

With the following:

class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

Now it’s time to set up the Google Sign In instance. Within the lifecyle function didFinishLaunchingWithOptions, add the following code before the window set-up logic.

// google sign-in
GIDSignIn.sharedInstance()?.clientID = Constants.GOOGLE_CLIENT_ID
GIDSignIn.sharedInstance()?.serverClientID = Constants.GOOGLE_SERVER_CLIENT_ID
GIDSignIn.sharedInstance()?.delegate = self

Now we must add the required methods to conform to the GIDSignInDelegate protocol. Add the following code.

// added for google sign-in
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    return GIDSignIn.sharedInstance().handle(url as URL?,
                                             sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
                                             annotation: options[UIApplication.OpenURLOptionsKey.annotation])
}

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
    if let error = error {
        print("error received when logging in with Google: \(error.localizedDescription)")
    } else {
        switch user.serverAuthCode {
        case .some:
            let googleCredential = GoogleCredential.init(withAuthCode: user.serverAuthCode)
            stitch.auth.login(withCredential: googleCredential) { result in
                switch result {
                case .success:
                    print("successfully signed in with Google")
                    NotificationCenter.default.post(name: Notification.Name("OAUTH_SIGN_IN"), object: nil, userInfo: nil)
                case .failure(let error):
                    print("failed logging in Stitch with Google. error: \(error)")
                    // sign out in case of error
                    GIDSignIn.sharedInstance().signOut()
                }
            }
        case .none:
            // in testing, we found that the serverAuthCode won't be
            // returned if the user is already signed in to this
            // application. This ensures the user is signed out.
            print("serverAuthCode not retreived")
            GIDSignIn.sharedInstance()?.signOut()
        }

    }
}

func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!,
          withError error: Error!) {
    // Perform any operations when the user disconnects from app here.
    // ...
}

sign will be called after the user grants permission through Google to our application. If there was an error, we immediately exit.

Otherwise, we proceed and inspect the serverAuthCode. In testing, we found behavior for receiving this code to be a bit surprising. If the user is already signed in to our application, serverAuthCode will be nil.

It is important to always call GIDSignIn.sharedInstance().signOut() in any error case and when the user signs out of the application.

We initialize a GoogleCredential with the serverAuthCode, and check the result. If everything works, we post a notification of the event to be handled elsewhere in the app. If not, we print out an error message and call GIDSignIn.sharedInstance()?.signOut()

5

Modify WelcomeViewController.swift

In the previous version of this application where we only supported Anonymous Login, we were using an AlertController to log in. This worked for our needs then, but now we’d like to show the Google Sign In button.

We also need to add this view controller as a listener to the NotificationCenter for “OAUTH_SIGN_IN” events in order to move our view flow forward to the TodoTableViewController.

Replace the entire contents of WelcomeViewController.swift with the following:

import UIKit
import MongoSwift
import StitchCore
import GoogleSignIn

class WelcomeViewController: UIViewController, GIDSignInUIDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        title = "Welcome"
        // add self as observer to NotificationCenter
        NotificationCenter.default.addObserver(self, selector: #selector(didSignInWithOauth), name: NSNotification.Name("OAUTH_SIGN_IN"), object: nil)
        // Do any additional setup after loading the view.
        GIDSignIn.sharedInstance()?.uiDelegate = self

        if stitch.auth.isLoggedIn {
            self.navigationController?.pushViewController(TodoTableViewController(), animated: true)
        } else {

            let anonymousButton = UIButton(frame: CGRect(x: self.view.frame.width / 2 - 150, y: 100, width: 300, height: 50))
            anonymousButton.backgroundColor = .green
            anonymousButton.setTitle("Login Anonymously", for: .normal)
            anonymousButton.addTarget(self, action: #selector(didClickAnonymousLogin), for: .touchUpInside)

            let googleButton = GIDSignInButton(frame: CGRect(x: self.view.frame.width / 2 - 150, y: 200, width: 300, height: 50))

            self.view.addSubview(anonymousButton)
            self.view.addSubview(googleButton)

        }
    }


    @objc func didClickAnonymousLogin(_ sender: Any) {
        stitch.auth.login(withCredential: AnonymousCredential()) { [weak self] result in
            switch result {
            case .failure(let e):
                fatalError(e.localizedDescription)
            case .success:
                DispatchQueue.main.async {
                    self?.navigationController?.pushViewController(TodoTableViewController(), animated: true)
                }
            }
        }
    }

    @objc func didSignInWithOauth() {
        DispatchQueue.main.async {
            self.navigationController?.pushViewController(TodoTableViewController(), animated: true)
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

}
6

Modify TodoTableViewController.swift

We’re almost finished, only a few items remaining! We need to modify our logout functionality in TodoTableViewController. We’ll add a check to determine whether the user was logged in with Google. If so, we’ll call the GIDSignIn.sharedInstance()?.signOut() method. To do this, we’ll also make sure to import GoogleSignIn.

Add the following import to the top of the file:

import GoogleSignIn

Now, modify your logout function to match the following:

@objc func logout(_ sender: Any) {
   // check whether the user is logged in with Google
    if stitch.auth.currentUser?.loggedInProviderType == .some(.google) {
        GIDSignIn.sharedInstance()?.signOut()
    }
    stitch.auth.logout { result in
        switch result {
        case .failure(let e):
            print("Had an error logging out: \(e)")
        case .success:
            DispatchQueue.main.async {
                self.navigationController?.setViewControllers([WelcomeViewController()], animated: false)
            }
        }
    }
}
7

Add URL Types Information

The last thing we need to do is allow our application to call the Google OAuth URL for our iOS client.

To do this, navigate to your Google Cloud Credentials page and select your iOS credentials.

Copy the value of iOS URL scheme, which is your Client ID in reverse order.

In Xcode, select the Todo project from the Project Navigator, and select the Info tab. Find the URL Types section, click the + and paste the value you copied above into the the URL Schemes area. Leave Editor as the selected role.

C. Build and Test

  1. You can now run the app (in the emulator or on a device) and see the logon screen with the newly-added Google button:
  2. Log in, add some items to your To-do list, and then log out (from the menu). When you log in again with the same account, your to-do list is shown.

There are two parts to setting up your Stitch backend app to use Google OAuth with Stitch: you create a Google OAuth client, and then you enable the Google auth provider in the Stitch backend.

A. Set up the Backend

Your first step here is to set up the backend of your application. First, you need to create a Google Cloud Project that will handle user authentication. Then, you must configure the Google OAuth provider in the Stitch backend, so your app can receive and understand the user authenticaiton from the GCP.

1

Create a project in GCP

  1. Navigate to the Google Cloud Platform (GCP). If you have not yet set up a GCP account, follow the instructions to do so.

  2. Create a new GCP project.

  3. In the project dashboard, click on the menu (upper-left), expand APIs & Services, and then select Credentials. You can also navigate directly to the Credentials page).

  4. OAuth Consent Screen: If this is a new project, you may be required to first configure the consent screen.

    • Application Type: Should remain public
    • Application Name: Can be whatever you wish to call it. We’ve named ours Stitch Todo Web
    • Authorized Domains: Add mongodb.com to this field.
    • Save your settings.
  5. Create Oauth Credentials for Stitch: Now we must create OAuth credentials for Stitch to use. Later in the tutorial we’ll also create credentials for the To-do client application.

    This may seem counter-intuitive or unnecessary, but it makes sense when we think about the architecture. Because we want Stitch to manage our users, we must create credentials Stitch can use to communicate with the Google Identity API.

    The flow is as follows:

    1. The user logs in with Google.
    2. If the user successfully logs in, Google returns the user to the client app with a server auth code in the URL (redirect result).
    3. The user sends this code to Stitch.
    4. Stitch uses this code alongside the Web OAuth Client ID + Secret to authenticate with Google on the user’s behalf.
    5. Google responds with the user’s information.
    6. Stitch responds to the client with a successful login request.
  6. Click Create Credentials, and then select OAuth client ID.

  7. Enter the following information to create credentials:

    • For Application Type, select Web application.

    • For Name, enter the name you want to associate with this client ID.

    • For Authorized JavaScript origins, enter the following:

      https://stitch.mongodb.com
      
    • For Authorized redirect URIs, enter the following:

      https://stitch.mongodb.com/api/client/v2.0/auth/callback
      
  8. Click Create.

  9. Note the Web app client ID and secret. You will use the information in the Users section of the MongoDB Stitch Admin Console.

2

Update the Stitch Backend for Google Authentication

  1. Navigate to your Stitch application.
  2. Select Users from the left-side navigation.
  3. Select the Providers tab.
  4. For Google, click the Edit button.
  5. In the Google provider settings:
    • Switch the Provider Status toggle to enabled.
    • Enter your new Client ID.
    • Create a new Secret in the Client Secret box. You will first be prompted to enter a secret name. Then, paste in the secret value from the google Web App client credentials.
    • Note the Redirect URIs section. You do not need to update this section yet, but will revisit it in step 3 of this tutorial.
  6. Click Save.

Deploy Your Changes

Before moving on, be sure to Review and Deploy Changes to your Stitch app. You can do this by clicking the button in the blue bar at the top of your screen, or by clicking Deploy in the left sidebar.

For details on all authentication methods supported by Stitch, see User Authentication Overview.

B. Update Web Application

Now that you’ve established commmunication between the Stitch backend and your GCP, it’s time to edit the React and Stitch portions of the client web app to use the authentication you’ve just set up.

1

Add a Stitch Authentication Event Listener

In this section, you will alter the pre-existing React code for anonymous login to be compatible with Google OAuth. Namely, you will set up an event listener to determine when login occurs. The Stitch Browser SDK allows you to set up event listeners that can automatically respond to authentication events in your client application, such as when a user logs in or out.

  1. Add the following two functions to stitch/authentication.js. These two functions add and remove listeners, resepctively, based on a provided listener argument. You will build one such listener in the upcoming steps and will then better understand its structure.

    export function addAuthenticationListener(listener) {
        app.auth.addAuthListener(listener);
    }
    export function removeAuthenticationListener(listener) {
        app.auth.removeAuthListener(listener);
    }
    
  2. Now that you can add and remove authentication listeners, you need to actually create a listener object and add it in the React code. Add addAuthenticationListener and removeAuthenticationListener to your import from stitch/authentication.js in StitchAuth.js:

      import {
          hasLoggedInUser,
          loginAnonymous,
          logoutCurrentUser,
          getCurrentUser,
          addAuthenticationListener,
          removeAuthenticationListener,
      } from "./../stitch/authentication";
    
  3. Once you’ve imported the functions, you can use React’s effect hook to add the authentication listener when the app first loads and remove the listener when the app unmounts or the user navigates away. Before you can use the hook, import useEffect from React. This is what the very first line of StitchAuth.js should look like after doing so:

    import React, {useEffect} from "react";
    
  4. Now that useEffect has been imported, add the following code block directly above the handleAnonymousLogin function in StitchAuth.js:

    useEffect(() => {
        const authListener = {
            onUserLoggedIn: (auth, loggedInUser) => {
            if (loggedInUser) {
                setAuthState(authState => ({
                ...authState,
                isLoggedIn: true,
                currentUser: loggedInUser,
                }));
            }
            },
            onUserLoggedOut: (auth, loggedOutUser) => {
            setAuthState(authState => ({
                ...authState,
                isLoggedIn: false,
                currentUser: null,
            }));
            }
        };
        addAuthenticationListener(authListener);
        setAuthState(state => ({ ...state}));
        return () => {
            removeAuthenticationListener(authListener);
        };
    }, []);
    
  5. In the exisiting code, there is a handleAnonymousLogin function that (as its name implies) is specific to anonymous login. In this step, you will create the more generic handleLogin function, which will allow us to use multiple auth providers. Replace the entire handleAnonymousLogin function with the following:

    const handleLogin = async (provider) => {
      if (!authState.isLoggedIn) {
          switch(provider) {
          case "anonymous": return loginAnonymous()
          default: {}
          }
      }
    }
    
  6. Now that handleAnonymousLogin no longer exists in your code, you need to change existing calls to it. Scroll down in StitchAuth.js until you find the authInfo function. In the line beginning with “actions”, change handleAnonymousLogin to handleLogin. The result should look like this:

    actions: { handleLogin, handleLogout },
    
  7. Finally, alter the “Anonymous Login” button to call handleLogin when clicked, instead of handleAnonymousLogin. Modify the onClick handler as follows:

    <LoginButton provider="anonymous" onClick={() => actions.handleLogin("anonymous")}>
    

    At this point, your anonymous login should work exactly as it did before. Now you’re ready to add login functionality for other authentication providers.

2

Add Google OAuth Functions

Your next step in adding Google OAuth functionality is to write a loginGoogle function. The main difference between loginAnonymous and the loginGoogle function that you are about to write is the use of loginWithCredential vs loginWithRedirect. Some types of authentication, like Anonymous, use loginWithCredential, which means that it uses a regular Stitch credential to authenticate the user. The Google OAuth 2.0 provider, on the other hand, redirects the user away from the current page to a page owned by Google where the user authenticates. Upon successful authentication, Google returns the user to the original page with a token that proves their identity. The Stitch SDK uses the token to construct a redirect credential and log the user in.

  1. Before you can invoke loginWithRedirect in the loginGoogle function, you must add GoogleRedirectCredential to your import from mongodb-stitch-browser-sdk:

      import {
          AnonymousCredential,
          GoogleRedirectCredential
      } from "mongodb-stitch-browser-sdk";
    
  2. In the same file, add the following loginGoogle function.

    export async function loginGoogle() {
        return await app.auth.loginWithRedirect(new GoogleRedirectCredential());
    }
    
  3. Now that you’ve written your loginGoogle function, you must add it to handleLogin. Before you can do this, you must first import the function to StitchAuth.js. Add loginGoogle to your import from stitch/authentication.js

      import {
          hasLoggedInUser,
          loginAnonymous,
          loginGoogle,
          logoutCurrentUser,
          getCurrentUser,
          addAuthenticationListener,
          removeAuthenticationListener,
          handleOAuthRedirects,
      } from "./../stitch/authentication";
    
  4. Recall that handleLogin is meant to handle login across multiple auth providers. In this step, you will give the function the ability to handle login with Google OAuth. Navigate to StitchAuth.js, and add the following line of code within the switch statement in the handleLogin function.

    case "google": return loginGoogle()
    
  5. The final step is to create a button to provide the user with the option to login with Google. This button is similar to the anonymous login button, but when clicked, it passes "google" as the argument to handleLogin. Copy and paste the following React code for the Google login button immediately below the code for the Anonymous button:

    <LoginButton provider="google" onClick={() => actions.handleLogin("google")}>
      Log In with Google
    </LoginButton>
    
3

Handle Google Redirects

It may seem as though you now have all pieces needed to log in with Google. Try running your app to see what happens. You’ll notice that when you click the “Log In with Google” button, you get an error. This happens because you haven’t actually handled redirects with Google yet. You’ll address these in the upcoming steps.

  1. The first change you need to make is in your Stitch application. In this step, you will add a redirect URI to the Stitch backend. This how you “approve” a specific URL which lets Stitch know that it’s safe to redirect back to a specific domain.

    1. Select Users from the left-side navigation.

    2. Select the Providers tab.

    3. For Google, click the Edit button.

    4. In the Google provider settings, add the following to the Redirect URIs section:

      http://localhost:3000/
      

      Note

      Port 3000 is the default port on which your app will run. However, if you notice your app is running on a different port, update the port number in the above URI accordingly.

    Deploy Your Changes

    Again, make sure to Review and Deploy Changes to your Stitch app by clicking either the button in the blue bar at the top of the screen, or the Deploy button in the left sidebar.

  2. Although the loginGoogle function uses redirect credentials, your app currently has no way of knowing when an external login has redirected the user back to the app, and thus, does not actually log the user into the app. In this step, you will add the handleOAuthRedirects function, which checks that the user has returned to the app, and then completes the OAuth login. Copy the function below into stitch/authentication.js.

    export function handleOAuthRedirects() {
        if (app.auth.hasRedirectResult()) {
            return app.auth.handleRedirectResult();
        }
    };
    
  3. Import handleOAuthRedirects for use in your StitchAuth.js file. Add the highlighted line to your import from stitch/authentication.js:

     import {
         hasLoggedInUser,
         loginAnonymous,
         loginGoogle,
         logoutCurrentUser,
         getCurrentUser,
         addAuthenticationListener,
         removeAuthenticationListener,
         handleOAuthRedirects,
     } from "./../stitch/authentication";
    
  4. Finally, in StitchAuth.js, add a call to handleOAuthRedirects right after the call to addAuthenticationListener within the effect hook.

      useEffect(() => {
          const authListener = {
              //existing code
          };
          addAuthenticationListener(authListener);
          handleOAuthRedirects();
          setAuthState(state => ({ ...state}));
          return () => {
              removeAuthenticationListener(authListener);
          };
      }, []);
    

C. Build and Test

  1. You can now run the app and see the logon screen with the newly-added Google button.
  2. Log in, add some items to your To-do list, and then log out (from the menu). When you log in again with the same account, your to-do list is shown.

Summary

Congratulations! You now have a working to-do app that includes Google authentication.