# How to setup Google OAuth2 Login

**URL:** <https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969>\
**Category:** Parse Server 📡\
**Created:** [October 25, 2020, 12:14pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969 "2020-10-25T12:14:19Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![gutaku](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/g/9fc348/32.png) [@gutaku](https://community.parseplatform.org/u/gutaku)\
**Post date:** [October 25, 2020, 12:14pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/1 "2020-10-25T12:14:19Z")

</div>

Hi,

I am trying to create a simple example to perform OAuth and 3rd Party Authentication using Google using React for my Client Application. While reading the documentation, I realized that there is no available API that allows me to do that in a single shot.

According to the [documentation](https://docs.parseplatform.org/js/guide/#linking-users), Parse allows you to link your users with **3rd party authentication** , enabling your users to sign up or log into your application using their existing identities. While reading other part of the documentation, the format for authData is the following

```auto
    {
      "google": {
        "id": "user's Google id (string)",
        "id_token": "an authorized Google id_token for the user (use when not using access_token)",
        "access_token": "an authorized Google access_token for the user (use when not using id_token)"
      }
    }

```

Now, in order to get the id, id\_token, and access\_token, I need to follow the OAuth process. This is roughly described [here](https://www.back4app.com/docs/platform/sign-in-with-google). The thing is that in the document they don’t describe clearly how to do the Cloud Functions needed for this purpose

I wrote a couple of functions in Nodejs that allowed me to retrieve this authData

With this function, I can redirect to the Google Sign In page, and retrieve the code

```
  app.get("/googleSignIn", function (req, res) {
  // Create an OAuth2 client object from the credentials in our config file
  const oauth2Client = new OAuth2(
    CONFIG.oauth2Credentials.client_id,
    CONFIG.oauth2Credentials.client_secret,
    CONFIG.oauth2Credentials.redirect_uris[0]
  );
  // Obtain the google login link to which we'll send our users to give us access
  const loginLink = oauth2Client.generateAuthUrl({
    // Indicates that we need to be able to access data continously without the user constantly giving us consent
    access_type: "offline",
    // Using the access scopes from our config file
    scope: CONFIG.oauth2Credentials.scopes,
  });
  return res.render("index", { loginLink: loginLink });
});

```

Then, with this code below I get the id, id\_token and access\_token

```
app.get("/redirect", function (req, res) {
  // Auth data for Parse
  const authData = {
    google: {
      id: "",
      id_token: "",
      access_token: "",
    },
  };
  // Create an OAuth2 client object from the credentials in our config file
  const oauth2Client = new OAuth2(
    CONFIG.oauth2Credentials.client_id,
    CONFIG.oauth2Credentials.client_secret,
    CONFIG.oauth2Credentials.redirect_uris[0]
  );

  if (req.query.error) {
    // The user did not give us permission.
    return res.status(500).send('Server Error');
  } else {
    oauth2Client.getToken(req.query.code, (err, token) => {
      if (err) return res.status(500).send('Server Error');
      oauth2Client.setCredentials({ access_token: token.access_token });
      var oauth2 = google.oauth2({
        auth: oauth2Client,
        version: "v2",
      });

      oauth2.userinfo.get(function (err, user) {
        if (err) return res.status(500).send('Server Error');
          authData.google.id = user.data.id;
          authData.google.id_token = token.id_token;
          authData.google.access_token = token.access_token;
          return res.status(200).json(authData);
      });
    });
  }
});

```

The thing is that I need **googleapis** to make this work. But, I cannot install those API in the Cloud Function.

At this point, I got stuck. It’s been two days since I am trying to get this done. Have anyone managed to get an end-to-end flow to use Google OAuth SignIn with React?

Any help will be appreciated

Guz

---

<div class="post-metadata">

**Author:** ![gutaku](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/g/9fc348/32.png) [@gutaku](https://community.parseplatform.org/u/gutaku)\
**Post date:** [October 25, 2020, 6:13pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/2 "2020-10-25T18:13:46Z")

</div>

I was digging into the subject, and I realized why I don’t see the **googleapis** at the Cloud Function. I needed to add a package.json file at the deploy folder with the entry

```
{ 
    "dependencies": {
        "googleapis": "^61.0.0"
    }
}

```

Now that I see the APIs, I created this Cloud Function to trigger the callback and retrieve the code

```
Parse.Cloud.define("GoogleSignIn", async (request) => {
      const google = require("googleapis").google;
      const CONFIG = require("./config");
      // Google's OAuth2 client
      const OAuth2 = google.auth.OAuth2;
      // Create an OAuth2 client object from the credentials in our config file
      const oauth2Client = new OAuth2(
        CONFIG.oauth2Credentials.client_id,
        CONFIG.oauth2Credentials.client_secret,
        CONFIG.oauth2Credentials.redirect_uris[0]
      );
    // Obtain the google login link to which we'll send our users to give us access
      const loginLink = oauth2Client.generateAuthUrl({
    // Indicates that we need to be able to access data continously without the user constantly giving us consent
        access_type: "offline",
        // Using the access scopes from our config file
        scope: CONFIG.oauth2Credentials.scopes,
      });
      return loginLink;
});

```

Then, I created this second function to retrieve the id, id\_token and access\_token

```
Parse.Cloud.define("GoogleRedirect", async (request) => {
  const google = require("googleapis").google;
  const CONFIG = require("./config");
  // Google's OAuth2 client
  const OAuth2 = google.auth.OAuth2;
  // Create an OAuth2 client object from the credentials in our config file
  const oauth2Client = new OAuth2(
    CONFIG.oauth2Credentials.client_id,
    CONFIG.oauth2Credentials.client_secret,
    CONFIG.oauth2Credentials.redirect_uris[0]
  );

  if (request.params.query.error) {
    // The user did not give us permission.
    return request.params.query.error;
  } else {
    try {
      const { tokens } = await oauth2Client.getToken(request.params.query.code);
      oauth2Client.setCredentials(tokens);
      var oauth2 = google.oauth2({
        auth: oauth2Client,
        version: "v2",
      });
      const usr_info = await oauth2.userinfo.get();
      // Auth data for Parse
      const authData = {
        google: {
          id: usr_info.data.id,
          id_token: tokens.id_token,
          access_token: tokens.access_token,
        },
      };
     return authData;
    } catch (error) {
      return error;
    }
  }
});

```

Now, the last part that is missing is to “glue” that with my Front-End application in React

---

<div class="post-metadata">

**Author:** ![davimacedo](https://community.parseplatform.org/user_avatar/community.parseplatform.org/davimacedo/32/316_2.png) [@davimacedo](https://community.parseplatform.org/u/davimacedo)\
**Post date:** [October 26, 2020, 4:01am UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/3 "2020-10-26T04:01:08Z")

</div>

What have you tried so far on your frontend?

---

<div class="post-metadata">

**Author:** ![gutaku](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/g/9fc348/32.png) [@gutaku](https://community.parseplatform.org/u/gutaku)\
**Post date:** [October 26, 2020, 8:05am UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/4 "2020-10-26T08:05:47Z")

</div>

Basically, I call

`const res = await Parse.Cloud.run("GoogleSignIn");`

This will return the link to authenticate the user with Google. Then, I redirect to that link using

`window.location.href = oauthLink;`

When the user login, Google will redirect to the link that I specified in my Google Settings (e.g. [http://localhost:3000/redirect](http://localhost:3000/redirect))

Then, on page Redirect I run this code when the page loads

```
const authData = await Parse.Cloud.run("GoogleToken", params);
const user = new Parse.User();
const res = await user.linkWith("google", { authData });

```

In my Database Browser, I saw that the user is created and that the id, id\_token, and access\_token are inside authData

 ![auth](https://parse-community-forum-uploads.s3.dualstack.us-east-1.amazonaws.com/original/1X/63f24f295a3e20d8a62d8effd042c3a32d7a9d2f.jpeg)

However, I don’t have the correct username and the email is not there neither. So, I need to adapt that

---

<div class="post-metadata">

**Author:** ![davimacedo](https://community.parseplatform.org/user_avatar/community.parseplatform.org/davimacedo/32/316_2.png) [@davimacedo](https://community.parseplatform.org/u/davimacedo)\
**Post date:** [October 26, 2020, 4:10pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/5 "2020-10-26T16:10:32Z")

</div>

It looks you made a good progress so far. Let me know if you need any help.

---

<div class="post-metadata">

**Author:** ![gutaku](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/g/9fc348/32.png) [@gutaku](https://community.parseplatform.org/u/gutaku)\
**Post date:** [October 26, 2020, 6:28pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/6 "2020-10-26T18:28:21Z")

</div>

Thanks 👍

There is actually one thing. Apart from the id, id\_token and access\_token, I returned the user name and email. Then, right before using **linkWith** , I do this

```
const authData = await Parse.Cloud.run("GoogleToken", params);
const user = new Parse.User();
user.set("username", authData.name);
user.set("email", authData.email);
const res = await user.linkWith("google", { authData });

```

This allows me to properly store the user name and email. However, the verification email is not sent when the user SignUp for the first time.

Instead, when I use the Parse.User.signUp() I do receive the verification email

Is this a functionality that is not supported, or some bug within the platform?

---

<div class="post-metadata">

**Author:** ![davimacedo](https://community.parseplatform.org/user_avatar/community.parseplatform.org/davimacedo/32/316_2.png) [@davimacedo](https://community.parseplatform.org/u/davimacedo)\
**Post date:** [October 27, 2020, 3:39pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/7 "2020-10-27T15:39:48Z")

</div>

I believe the verification e-mail is not sent when you use the Google authentication by default since Google already handled that for you.

---

<div class="post-metadata">

**Author:** ![gutaku](https://community.parseplatform.org/letter_avatar_proxy/v4/letter/g/9fc348/32.png) [@gutaku](https://community.parseplatform.org/u/gutaku)\
**Post date:** [October 28, 2020, 9:53am UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/8 "2020-10-28T09:53:06Z")

</div>

Well, not really. Maybe what I can do at the Cloud Function is to Verify by default when the user signs up with a 3rd Pary Application. In that way the functions that can only be accessed by verified users are available.

Now, the other issue that I have is: if a user already signed up with the email and tries to login with the Google Account, it doesn’t work. I received an error, `the user already exists.` Any tips on how to fix that?

---

<div class="post-metadata">

**Author:** ![davimacedo](https://community.parseplatform.org/user_avatar/community.parseplatform.org/davimacedo/32/316_2.png) [@davimacedo](https://community.parseplatform.org/u/davimacedo)\
**Post date:** [October 28, 2020, 3:19pm UTC](https://community.parseplatform.org/t/how-to-setup-google-oauth2-login/969/9 "2020-10-28T15:19:38Z")

</div>

You need to fetch the current user and call `linkWith` function to this existing instance and not to a new one.
