DEV Community

an-object-is-a
an-object-is-a

Posted on • Edited on

Google OpenID Connect for a Chrome Extension

Don't build your own authentication system; leverage Google OpenID Connect for your Google Chrome Extension


This tutorial assumes you know how Google Chrome Extensions work. Learn more here.


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'.

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"
    ]
}
Enter fullscreen mode Exit fullscreen mode

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/

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/ 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://.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>
Enter fullscreen mode Exit fullscreen mode

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);
    });
});
Enter fullscreen mode Exit fullscreen mode

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.

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()'.

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>
Enter fullscreen mode Exit fullscreen mode

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);
    });
});
Enter fullscreen mode Exit fullscreen mode

You can find the source files here.

If you want a more in-depth guide, check out my full video tutorial on YouTube, An Object Is A.

How to Use Google Login with Chrome Extensions | OAuth2/OpenID Connect

Top comments (0)