Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

How to overcome redirect_uri_mismatch on Oauth 2.0 for a Chrome extension

Hi,

I have been trying to log users into my Chrome extension with chrome.identity.launchWebAuthFlow, yet I keep getting the following error: Error 400: redirect_uri_mismatch (see screenshot below).

Context

  • I use Google Workspace and the extension is private to my domain
  • I have created a dedicated OAuth 2.0 Client ID of type "Chrome Extension" in the Google Cloud console Credentials, and have verified app ownership
  • I try to authenticate using the code below - I have double checked that the extension ID matches the redirect URI
  • My intention is to use the Google token to log users into Supabase

function login() {
  const manifest = chrome.runtime.getManifest();
  if (!manifest.oauth2?.scopes) throw new Error('No OAuth2 scopes defined in the manifest file');

  const url = new URL('https://accounts.google.com/o/oauth2/auth');

  url.searchParams.set('client_id', manifest.oauth2.client_id);
  url.searchParams.set('response_type', 'id_token');
  url.searchParams.set('access_type', 'offline');
  url.searchParams.set('redirect_uri', chrome.identity.getRedirectURL());
  url.searchParams.set('scope', manifest.oauth2.scopes.join(' '));

  return new Promise((resolve, reject) =>
    chrome.identity.launchWebAuthFlow(
      {
        url: url.href,
        interactive: true,
      },
      async (redirectedTo) => {
        if (chrome.runtime.lastError) {
              reject(`Could not login - ${chrome.runtime.lastError.message}`);
        } else {
          const url = new URL(redirectedTo!);
          const params = new URLSearchParams(url.hash);
          resolve(params.get('id_token'))
        }
      },
    ),
  );
}

 

{
  "manifest_version": 3,
  "permissions": ["identity", ...],
  "oauth2": {
    "client_id": "<client ID>",
    "scopes": ["openid", "email", "profile"]
  },
  ...
}

What else I have tried

  • For redirect_uri, in addition to the code above, I have also tried https://${chrome.runtime.id}.chromiumapp.org (without trailing slash) and chrome.identity.getRedirectURL('oauth2'), all leading to the same result
  • I have tried this solution - use a "Web application" client ID instead of a "Chrome extension" client ID, and add the redirect URL to the list of Authorized redirect URIs - still leads to the same result

What am I missing?
Thanks for your help!

Screenshot 2024-03-13 102140.png

0 7 5,370
7 REPLIES 7

All right I made it work with these four changes:

  1. I used a Client ID for Web application rather than for Chrome extension and added https://<extension_id>.chromiumapp.org (without trailing slash) to the list of Authorized redirect URIs
  2. Replace `chrome.identity.getRedirectURL()` with `https://${chrome.runtime.id}.chromiumapp.org`
  3. To make this work locally, I added the [manifest key](https://developer.chrome.com/docs/extensions/reference/manifest/key) to my extension - Google seems to check the extension ID at runtime as part of `launchWebAuthFlow`
  4. I replaced `const params = new URLSearchParams(url.hash)` with `const params = new URLSearchParams(url.hash.replace('#', ''))`. The reason is `url.hash` looks like `#id_token=<id_token>&...`, so the search param key looks like `%23id_token` and `params.get('id_token')` returns `undefined`.

Hope this helps... the two things that remain a mistery to me are:
1. Why doesn't the Chrome extension Oauth Client ID work properly?
2. Why doesn't chrome.identity.getRedirectURL() work properly (it returns a trailing slash, and I could only make it work without the trailing slash)?

I did the first step but it only worked when I included the trailing slash.

Thanks @larryco and @zekasp 👍

BTW, trailing slash worked for me.

Thanks @larryco it worked.

Thanks, @larryco , it works in my product. I use Edge, and I didn't setup the Manifest Key.

Is there any way to make it work with chrome extension client - without using Web application client?

I don't know, but if you make it work with the chrome extension client, I'd love to know how.

Top Labels in this Space
Top Solution Authors