Google OpenID Connect for a Chrome Extension
Tags: javascript, webdev
Published: 2020-12-03 00:42:07

### <center>Don't build your own authentication system; leverage Google OpenID Connect for your Google Chrome Extension</center>

------------

#### <center>This tutorial assumes you know how Google Chrome Extensions work. Learn more [here](https://dev.to/anobjectisa/how-to-build-a-chrome-extension-4oig "here").</center>

------------
[![Google Oauth2/OpenID Authentication](https://user-images.githubusercontent.com/58220766/100047630-e605dc00-2de0-11eb-9f1c-324be067c2e6.png "Google Oauth2/OpenID Authentication")](https://user-images.githubusercontent.com/58220766/100047630-e605dc00-2de0-11eb-9f1c-324be067c2e6.png "Google Oauth2/OpenID Authentication")
### Before we even touch a line of code, we need to setup our development work space so that we have the ability to do two major things:

1. Giving our specific Chrome Extension the ability to use Google’s APIs and Services.

2. Gain the ability to interact with the Google OpenID Connect Endpoint.

### Let's Begin.

**First**, we'll need to **"register"** our Chrome Extension with the **Google store**.
There are **two ways to do this**, we either officially upload our Chrome Extension to the **Google Chrome Store** and receive a unique key value for our extension or we **faux register**” our extension with the **Google Chrome Browser** and receive a unique key that way.
Since we don't want to upload a development extension to the public store, ***we'll opt for the latter method***.

Navigate to the address **"chrome://extensions"** in your **Chrome Browser**.

Click on **"Pack Extension"** and choose the location of your Chrome Extension.

This will generate two files in the directory above your Chrome Extension location, a **crx** and **pem**; ***we're concerned with the **crx** file***.

Drag-and-drop the **crx** file into the **chrome://extensions** page.
You should get a prompt asking you to add the extension, click **'Yes'**.

![](https://cdn-images-1.medium.com/max/3288/1*7I77HVUS1WSQJk41H7HO5Q.png)

Now, **navigate to where your Chrome Extensions are located**.
For MacOS and Linux users, this will be different, but for Windows users you're looking for something along the lines of,

**"C:\Users\<Your UserName>\AppData\Local\Google\Chrome\User Data\Default\Extensions"**

We're looking for the folder with same name as your Chrome Extension ID. This id can be found back at your **"chrome://extensions"** page. Look for the **ID** attribute.

Enter into the folder with the same name as your Chrome Extension, enter into the version number folder and open the **"manifest.json"** file. Copy the **key** attribute.

***This is our unique Chrome Extension key***. Copy and paste that into the **"manifest.json"** of the Chrome Extension you're actually developing. (the folder you chose for the **"Pack Extension"** step)


```
// manifest.json
{
	"name": "Oauth2 test",
	"description": "",
	"version": "0.1.0",
	"manifest_version": 2,
	"key": "<your_key_here>",
	"icons": {
		"16": "./obj-16x16.png",
		"32": "./obj-32x32.png",
		"48": "./obj-48x48.png",
		"128": "./obj-128x128.png"
	},
	"background": {
		"scripts": [
			"./background.js",
			"./jsrsasign-all-min.js"
		]
	},
	"options_page": "./options.html",
	"browser_action": {
		"default_popup": "popup.html"
	},
	"permissions": [
		"identity"
	]
}
```


**Note:**
We require the **"identity"** permission.
We also use the **'jsrsasign-all-min.js'** library to help us deal with the JWT(JSON Web Token).
You can find that here: **[https://github.com/kjur/jsrsasign/releases/](https://github.com/kjur/jsrsasign/releases/)**

**Finally**, remove your Chrome Extension from the browser (click **"Remove"**) and install the development extension by clicking **"Load unpacked"** and choosing the folder for your development extension.

#### **This development extension now has the ability to use Google's APIs and Services**.


------------


### To gain authorization for Google's OAuth2 Endpoint...

Navigate to **[https://console.developers.google.com/](https://console.developers.google.com/)** and if you haven't already, create a project.

#### **We have to do two things here…**
Click on the **"OAuth consent screen"** link on the left.
Choose **"External"** and **"Create"**.
Just fill out the **"Application name"** field and **"Save"**.
The **"OAuth Consent"** screen tells the user we want access to their Google Data when they choose to login with their Google account.

Next, click on the **"Credentials"** link on the left.

Click the **"Create Credentials"** at the top of the page, choose **"OAuth Client ID"**.

Set the **"Application type"** to **"Web application"**, not **"Chrome app"**.

Fill in the **"Name"** field with anything you want then click on the **"Add URI"** at the bottom of the screen (***the Redirect URI***).

The URI should follow the pattern,

#### **"https://<chrome-ext-id>.chromiumapp.org/"**

The **"chrome-ext-id"** is the same one from your **"chrome://extensions"** page.

Click **"Create"**.

#### This development extension now has the ability to interact with Google OpenID Connect.

------------

### Let's login.

To demonstrate logging in, we'll just place a button in the **'popup.html'** page and attach a **'popup-script.js'**.

```
// popup.html
<!DOCTYPE html>
<html lang="en">
	<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
	body {
	width: 300px;
	height: auto;
	}

	div {
	position: relative;
	left: 50%;
	transform: translateX(-50%);
	width: 50%;
	height: 25%;
	padding: 5px;
	font-size: 2.5em;
	background-color: red;
	border-radius: 5px;
	text-align: center;
	color: white;
	font-family: monospace;
	font-weight: bold;
	margin-bottom: 15px;
	cursor: pointer;
	transition-duration: 0.3s;
	}

	div:hover {
	background-color: black;
	transform: translateX(-50%) scale(1.3);
	}
	</style>
	</head>
	<body>
	<h1>Sign-In With Your Google Account to Use This Extension</h1>
	<div id='sign-in'>Sign In</div>
	<button>User Status</button>
	<script src="./popup-script.js"></script>
	</body>
</html>
```

When the user clicks on the button, we'll send a message to our **'background.js'** script to initiate third-party Google authentication.




```
// popup-script.js
document.querySelector('#sign-in').addEventListener('click', function () {
	chrome.runtime.sendMessage({ message: 'login' }, function (response) {
		if (response === 'success') window.close();
	});
});
document.querySelector('button').addEventListener('click', function () {
	chrome.runtime.sendMessage({ message: 'isUserSignedIn' }, function (response) {
		alert(response);
	});
});
```


#### **To let our users log in with their Google account, we use the 'launchWebAuthFlow()' API.**
It allows us to request Google's OAuth2 Endpoint, **[https://accounts.google.com/o/oauth2/v2/auth](https://accounts.google.com/o/oauth2/v2/auth)**.

We need to send **7 URI encoded query parameters** with the URL:

1. **client_id**: this is the OAuth2 Client ID given by the Google Developer console
2. **response_type**: we need an **'id_token'** from Google
3. **redirect_uri**: once the user has logged into their Google account, we need to tell Google where to redirect the user (back to our Chrome Extension)
4. **scope**: we have to tell the endpoint what we want to do with the user
5. **state**: a random string used for security purposes
6. **prompt**: makes sure the user is "prompted" with the screen allowing them to login with a Google account
7. **nonce**: a random string used for security purposes

Once we have this information, we can construct the URL and fire it in **'launchWebAuthFlow()'**.

<script src="https://medium.com/media/abc83b8f8c528f821ac9b9112c30eb84"></script>

**Note:**
1. We strip the **'id_token'** out of the URL passed back to us in the callback of **'launchWebAuthFlow()'**.

2. We can check that the **'user_info.iss'** property's value is one of two possible Google domains and that the **'user_info.aud'** is the same as the OAuth2 Client ID.
*This check isn't really needed as Google guarantees the token wasn't tampered with*.

3. We keep track of the user's sign in status in a variable, **'user_signed_in'**, on our side (**background.js**).

If the user successfully signs in, we switch the **'popup.html'** to a **'popup-signed-in.html'** page.

```
// popup-signed-in.html
<!DOCTYPE html>
<html lang="en">
	<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
	body {
	width: 300px;
	height: auto;
	}

	div {
	position: relative;
	left: 50%;
	transform: translateX(-50%);
	width: 50%;
	height: 25%;
	padding: 5px;
	font-size: 2.5em;
	background-color: red;
	border-radius: 5px;
	text-align: center;
	color: white;
	font-family: monospace;
	font-weight: bold;
	margin-bottom: 15px;
	cursor: pointer;
	transition-duration: 0.3s;
	}

	div:hover {
	background-color: black;
	transform: translateX(-50%) scale(1.3);
	}
	</style>
	</head>

	<body>
	<h1>Successfully Signed-In</h1>
	<div id='sign-out'>Sign Out</div>
	<button>User Status</button>
	<script src="./popup-signed-in-script.js"></script>
	</body>
</html>
```

This allows the user to **'sign out'**.

```
// popup-signed-in-script.js
document.querySelector('#sign-out').addEventListener('click', function () {
	chrome.runtime.sendMessage({ message: 'logout' }, function (response) {
		if (response === 'success') window.close();
	});
});

document.querySelector('button').addEventListener('click', function () {
	chrome.runtime.sendMessage({ message: 'isUserSignedIn' }, function (response) {
		alert(response);
	});
});
```

------------

You can find the source files [here](https://github.com/an-object-is-a/google-openid-connect-chrome-extension "here").

#### <center>If you want a more in-depth guide, check out my full video tutorial on YouTube, **[An Object Is A](https://www.youtube.com/c/anobjectisa "An Object Is A")**.</center>

### <center>How to Use Google Login with Chrome Extensions | OAuth2/OpenID Connect</center>

{% youtube H-anyDrYHyg %}