When you are building a chrome extension, you may need to authenticate the user with a third party service. If the third party service is google itself, it’s relatively easy as you can use google cloud platform plus firebase to authenticate the user. However if you are using other third party service, it’s a bit tricky and there are very few resources available online. I recently built a chrome extension that needs to authenticate the user with Notion and I would like to share my experience here.

Problem

If you are building a web application, the traditional way of authenticating the user is to use OAuth2.0. The OAuth2.0 flow is as follows: 1. The user clicks the login button on your website 2. The user is redirected to the third party service login page 3. The user logs in and is redirected back to your website with an authorization code 4. Your website exchanges the authorization code with an access token and refresh token 5. Your website can now access the third party service on behalf of the user.

However if you are building a chrome extension, the flow is a bit different. The chrome extension is a client side application and it doesn’t have a server to exchange the authorization code with the access token. Also the chrome extension doesn’t have a domain to redirect the user back to. So you need to figure out 1. Where do you host the server to exchange the authorization code with the access token 2. How do you redirect the user back to the chrome extension.

Solution

So in general my anwser is firebase. I used three components of firebase 1. Serveless Function 2. Firestore 3. Firebase Hosting. Serveless Function is used to exchange the authorization code with the access token. Firestore is used to store the access token and refresh token. Firebase Hosting is used to host an intermediate page to redirect the user back to the chrome extension.

Here is how it works to authenticate with Notion:

  1. Get a notion authentication uri from notion integration page
  2. On the chrome extension side, set up an option page to kick off the authentication flow by redirecting the user to the notion authentication uri
  3. The user logs in and authenticated with Notion, if successful, Notion will call the firebase serveless function with an authorization code
  4. The serveless function exchanges the authorization code with an access token and store
  5. The serveless function redirects the user back to the firebase hosting page which would then redirect the user back to the original chrome extension page with user_id
  6. On chrome extension you can store the user_id in the local storage
  7. If all works well, you can retrieve the user’s access token from firestore using firebase sdk, then you can use the access token to access the Notion API on behalf of the user.

The hosted static page is like:


<html>
<head>
  <title>Redirecting...</title>
  <script type="text/javascript">
    function redirectToOnboarding() {
      const params = new URLSearchParams(window.location.search);

      const newUrl = `chrome-extension://[your_extension_id]/options.html`;
      window.location.href = newUrl;
    }
  </script>
</head>
<body onload="redirectToOnboarding();">
  Redirecting...
</body>
</html>

As this page is public so it can be redirected from firebase. As it would be opend in your local browser so you can redirect to your extension page starting with chrome-extension://

I understand this is perhaps not the best way but it just works for me.

One more thing

I would like to shamelessly promote my chrome extension mentioned above. It’s called HunterNotes-Job which helps you organise & import job postings from various job boards to notion. If you are interested, please give it a try.