Adding 'Sign in with Google' to your site with vanilla JS
Tags: webdev, beginners, javascript, googlecloud
Published: 2023-04-06 20:11:51

This blog is going to be a step-by-step guide on how to quickly add a 'Sign in with Google' button to your website. You won't need to install any modules for this to work. At the end, you'll be able to sign in with your Google account and use the data returned from the Google OAuth API to run conditional JS functions on your website.

I decided to put this together because I believe that a Google login is slicker and more functional than a bootstrapped HTML form, but I couldn't find a step-by-step resource oriented toward beginners. Please comment below your thoughts and any questions/issues you have while following these instructions. Happy coding!

_Please note that this guide will feature macOS/Linux terminal commands. If you are running Windows, you will have to research the corresponding command prompt syntax._

**Prerequisites:**

- A HTML & JS file open in your code editor of choice
- A Google account
- Python installed ([installation guide](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server))

**Links you'll need:**

- [Google credentials API dashboard](https://console.cloud.google.com/apis/credentials)
- [Google authentication docs](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid)

## Step 1: Get your site running on a localhost server

_This step with require the use of a Python command. If you do not have Python installed, follow the guide provided under 'Prerequisites'._

Navigate to the working directory in which your website lives. Make sure you have created HTML & JS files there. Your HTML file should contain at least one line of code.

![working directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8hb9tp93f4c6mftlhyv5.png)

Run the following Python command in your terminal.

```
python3 -m http.server
```

You should see the following output.

![terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k891a9l8ib2fwydfrafb.png)

Navigate to [http://localhost:8000](http://localhost:8000) in your browser. You should see your site! _When you are done working, you can use 'Ctrl + c' in the same terminal to terminate the server._

**Having issues?** If you are getting a different output, try the following steps.

Verify you have Python installed by running this command in a new terminal.

```
python3 -v
```
If you see a version number in the output, go ahead and terminate that terminal and check to see which ports are open with this command in a new terminal.

```
lsof -i -P | grep -i "listen"
```
In the image below, you can see that Python is running on port :8000 with the portID 30098.

![terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qnjurpxhy0fqrmz2hbfa.png)

If something else is running on port 8000, use the following command to terminate the port. Use the value found in the previous command for 'portID'.

```
kill portID
```

## Step 2: Create a Google Cloud project
Navigate to the Credentials API Dashboard and click to create a new project.

![Creating a project in Google Cloud](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7rg2b0dzql8yukk4kboe.png)

Once you have followed all of the prompts, navigate back to the dashboard if you are not automatically directed there.

## Step 3: Create your OAuth consent screen

Click 'OAuth consent screen' in the left-side navigation and enter an app name, user support email, and developer contact information. The rest of the fields can be left blank.

![Creating OAuth consent screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u5igl8mwwa3q45aw9ver.png)

![Creating OAuth consent screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1yjqyfbaoh9fihkhash8.png)

Continue clicking 'SAVE AND CONTINUE' until you are at the summary page and then navigate back to the dashboard. You do not need to fill out the 'Scope' or 'Optional Information' prompts.

## Step 4: Create your OAuth 2.0 Client ID

Click 'Credentials' in the left-side navigation, click 'CREATE CREDENTIALS' at the top of the page, and then click 'OAuth client ID'.

![Creating client ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0o7qtvngv55k4tngglbc.png)

Add a client name, and then add http://localhost:8000 and http://localhost under both the 'Authorized JavaScript origins' and 'Authorized redirect URIs' sections. 


![Configuring client ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o8xp5iiyqkwam9fc373m.png)

**Note that this screen is where you can find your 'Client ID'.** Click 'SAVE' and navigate back to the dashboard.

![Client ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/goqtwaaho5l4ei7xo54n.png)

If anything from steps 3 & 4 was confusing, checking out the [Google authentication docs](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid) may be helpful.

## Step 5: Configure your HTML headers

Per the docs linked above, you'll need to add two headers to your HTML document so that your login works with a localhost server. 

```
<meta name="referrer" content="no-referrer-when-downgrade">
<meta name="Cross-Origin-Opener-Policy" content="same-origin-allow-popups">
```
While we're here, check that your JS document is linked to your HTML document. If you choose to link it in the header as I have done, it is best practice to include the `defer` keyword.

![HTML header](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2vy9otr37wfhv1rqmdm.png)

## Step 6: Generate your button code

Follow this link to the [HTML code generator](https://developers.google.com/identity/gsi/web/tools/configurator). 

Add your Client ID, choose 'Swap to JavaScript callback', and then enter a name for your callback function.

![Code configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6k9d5n3i31cpv6qrrp69.png)

_In this example, we have to use a JS callback rather than a Login URI because we are using a localhost server._

Toggle the 'Enable Sign in with Google button', and make sure 'In a popup' is selected under the 'Behavior' dropdown.


![Code configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lyift6r1x5pj5pfplx06.png)

Edit the styling options as you wish, and then click 'Get code'. Copy the code output to your clipboard.

_In this example, we have not enabled OneTap as that requires additional configuration not covered in this blog._

## Step 7: Add the button to your HTML

Paste the code in your HTML document nested somewhere between your `<body>` tags. I recommend creating a parent `<div>` around the login button code for styling purposes.

![Resulting HTML code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e28ihqhq6tt3eilnul1b.png)

_Hint: You can use Cmd + k then Cmd + f on a selection in VS Code to automatically format it._

## Step 8: Add OAuth scripts to the bottom of your HTML doc

Add the following scripts to the bottom of the `<body>` section in your HTML document. The first script loads the Google client library and the second is the callback function that will handle the API response.

```
<script src="https://accounts.google.com/gsi/client" async defer></script>
<script>
    function handleCredentialResponse(response) {
        decodeJwtResponse(response.credential);
    }
</script>
```
In the callback function you'll notice I invoke another function called `decodeJwtResponse`. This function parses the JSON web token (JWT) that is returned from the Google API upon sign in. This JWT contains account information from the Google user that signed in via your button. Once parsed, you can store this information in different variables to supplement functionality on your webpage.

If this step is confusing, check out Google's documentation on [loading the client library](https://developers.google.com/identity/gsi/web/guides/client-library) and [handling the credential response](https://developers.google.com/identity/gsi/web/guides/handle-credential-responses-js-functions).

## Step 9: Parsing the JWT in your JS file

Parsing the JSON web token (JWT) can be accomplished several ways. In this example, I'm going to use a [solution](https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library) from Stack Overflow that doesn't require a library. If you would like to experiment with libraries, check them out [here](https://jwt.io/libraries).

Navigate to your JS file and add the following function.

```
function parseJwt (token) {
    var base64Url = token.split('.')[1];
    var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    var jsonPayload = decodeURIComponent(window.atob(base64).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));

    return JSON.parse(jsonPayload);
}
```
Now pass it the JWT by adding a second function.

```
function decodeJwtResponse(data){
    signIn(parseJwt(data))
}
```
This second function is invoked in the `handleCredentialResponse` callback and is where you can invoke other functionality related to signing in for your website. In the above example, I chose to invoke a function called `signIn` that takes the parsed JWT from the `parseJWT` function. If you would like to simply see the parsed JWT in your console log, replace `signIn(parseJwt(data))` with `console.log(parseJwt(data))`. 

**That's all there is to this blog! Thank you for following along. Feel free to comment below with your thoughts/questions.**