Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compatibility with Chrome's Manifest V3 extension platform #713

Open
dotproto opened this issue Jan 13, 2021 · 48 comments
Open

Compatibility with Chrome's Manifest V3 extension platform #713

dotproto opened this issue Jan 13, 2021 · 48 comments

Comments

@dotproto
Copy link

dotproto commented Jan 13, 2021

Devs, what features GAPI you're using an your extensions?

If you are an extension developer affected by this issue, please describe what GAPI capabilities you are using and what alternative approaches you've considered.

Issue description

Chrome is in the process of transitioning extension to a new platform we commonly refer to as Manifest Version 3 (MV3). This new platform introduces a number of changes to improve the security and privacy of extension users. One of the major changes coming to the platform is that extensions will no longer be allowed to run code retrieved from remote servers. In other words, extensions won't be able to fetch https://apis.google.com/js/api.js as described in the Getting Started guide.

On the Chrome extension team, we have been advising developers to package third-party libraries with their extensions in order to work around this limitation. I'm not personally familiar with the JS GAPI library, so I'd like to ask whether this guidance is appropriate for this library or whether we need to explore alternative approaches.

EDIT 2021-04-02: Grammar fixes.
EDIT 2021-04-05: Added an intro section
EDIT 2021-05-19: Chromium issue 1164452 is also related.

@sergentj
Copy link

sergentj commented Jan 13, 2021 via email

@kospl
Copy link

kospl commented Jan 13, 2021

This is known bug, circa 2012:
#586
#312
#261
#64

@Arthur404
Copy link

https://www.google.com/recaptcha/api.js - here are the comments that this code DO NOT COPY AND PASTE.
It's not possible to add a recaptcha to the extension Manifest V3 if don't allowed to add third party code

@thdoan
Copy link

thdoan commented Jan 16, 2021

I hope that GAPI and Extensions teams can agree on a vetted list of internal libraries that can be remotely hosted if a bundling solution does not come to fruition.

@ccdunder
Copy link
Collaborator

It looks like this is also being tracked in crbug here.

@luciferpd13
Copy link

luciferpd13 commented Apr 1, 2021

Hi @dotproto Any Update on this ? We need some solution for this. Also is Google thinking something for remote hosting code, we have to deploy our changes according to requirements and google review process is very slow. we can't deploy it to chrome web store again and again

Chrome is in the process of transitioning to extension developers to a new extension platform called Manifest Version 3 (MV3). ThisNew platform introduces a number of changes to improve the security and privacy of extension users. One of the major changes coming to the platform is that extensions will no longer be allowed to run code retrieved from remote servers. In other words, extensions won't be able to fetch and https://apis.google.com/js/api.js as described in the Getting Started guide.

On the Chrome extension team, we have been advising developers to package third-party libraries with their extensions in order to work around this limitation. I'm not personally familiar with the JS GAPI library, so I'd like to ask whether this guidance it's appropriate for this library or whether we need to explore alternative approaches.

@thdoan
Copy link

thdoan commented Apr 1, 2021 via email

@luciferpd13
Copy link

afaik GAPI isn't a framework that can be packaged into a local file.

On Thu, Apr 1, 2021, 5:30 AM Prasanna Dubey @.***> wrote: Hi @dotproto https://github.com/dotproto Any Update on this ? We need some solution for this. Also is Google thinking something for remote hosting code, we have to deploy our changes according to requirements and google review process is very slow. we can't deploy it to chrome web store again and againg Chrome is in the process of transitioning to extension developers to a new extension platform called Manifest Version 3 (MV3). ThisNew platform introduces a number of changes to improve the security and privacy of extension users. One of the major changes coming to the platform is that extensions will no longer be allowed to run code retrieved from remote servers. In other words, extensions won't be able to fetch and https://apis.google.com/js/api.js as described in the Getting Started https://github.com/google/google-api-javascript-client/blob/master/docs/start.md guide. On the Chrome extension team, we have been advising developers to package third-party libraries with their extensions in order to work around this limitation. I'm not personally familiar with the JS GAPI library, so I'd like to ask whether this guidance it's appropriate for this library or whether we need to explore alternative approaches. — You are receiving this because you commented. Reply to this email directly, view it on GitHub <#713 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7LRZ4JU6OF533GZAPXNMTTGRRPPANCNFSM4WAHPP6Q .

So what's the solution ?

@kospl
Copy link

kospl commented Apr 2, 2021

@thdoan whitelist is SO away from web standards, I don't think Google will like this idea

@thdoan
Copy link

thdoan commented Apr 2, 2021 via email

@dotproto
Copy link
Author

dotproto commented Apr 5, 2021

@kospl, @Arthur404, @thdoan, @luciferpd13, what capabilities of the GAPI are you currently leveraging in your Manifest V2 extensions? What, if any, alternatives have you considered to using this library?

@luciferpd13
Copy link

@dotproto This library doesnot support Google Location API's . Its very important.

@luciferpd13
Copy link

Due to New CSP Policy. None alternatives are working

@thdoan
Copy link

thdoan commented Apr 5, 2021

@dotproto I'm using GAPI for Google Sheets integration; there is currently no GAPI replacement that I'm aware of. If Google is willing to provide a local GAPI library that we can download and package with our extensions, I'm all for it.

@zamiang
Copy link

zamiang commented Apr 5, 2021

Based on some earlier threads linked above, I have successfully made requests to Google APIs from MV3 extensions using the approach below. This is meaningfully less convenient that using gapi, but it does work 🤷‍♂️

In short, you log the user in with fetchToken() and then use that token to make further requests (see the tasks API example at the end).

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
const oauth2SignIn = (additionalScope?: string) => {
  // NOTE: this needs to be a form: https://stackoverflow.com/questions/48925165/cors-issue-with-google-oauth2-for-server-side-webapps

  // Create element to open OAuth 2.0 endpoint in new window.
  const form = document.createElement('form');
  form.setAttribute('method', 'GET');
  form.setAttribute('action', oauth2Endpoint);
  const params = getParams();
  if (additionalScope) {
    params.scope = `${params.scope} ${additionalScope}`;
  }

  // Add form parameters as hidden input values.
  for (const p in params) {
    const input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }
  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  return form.submit();
};

// Parameters to pass to OAuth 2.0 endpoint (I recommend having these in some config file)
const getParams = () => ({
  client_id: config.GOOGLE_CLIENT_ID,
  redirect_uri: config.REDIRECT_URI,
  scope: config.GOOGLE_SCOPES.join(' '),
  state: window.location.pathname,
  include_granted_scopes: 'true',
  response_type: 'token',
});

const fetchToken = async () => {
  const params = getParams();
  // localStorage is used for convenience and speed and is not required
  const currentAccessToken = localStorage.getItem('oauth2');
  const currentScope = localStorage.getItem('scope');

  if (currentAccessToken) {
    // Test the auth token with an endpoint to make sure it is still valid
    const result = await fetchSelf(currentAccessToken); // use whatever works for you, this hits the /me people endpoint i think
    if (result.id) {
      return {
        accessToken: currentAccessToken,
        scope: currentScope || params.scope,
      };
    }
  }

  const fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  const urlParams: any = {};
  const regex = /([^&=]+)=([^&]*)/g;
  let m = null;
  while ((m = regex.exec(fragmentString))) {
    urlParams[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(urlParams).length > 0) {
    localStorage.setItem('oauth2', urlParams.access_token);
    localStorage.setItem('scope', urlParams.scope);
    window.location.hash = '';
    if (urlParams.state) {
      history.pushState('', 'Dashboard', urlParams.state);
    }
  } else {
    oauth2SignIn();
  }
  return {
    accessToken: urlParams.access_token,
    scope: urlParams.scope,
  };
};

// Example API request using the accessToken above
const taskResponse = await fetch(
  `https://tasks.googleapis.com/tasks/v1/lists/${taskListId}/tasks/${taskId}`,
  {
    method: 'PATCH',
    headers: {
      'Content-Type': 'application/json',
      authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify(body),
  },
);

@luciferpd13
Copy link

luciferpd13 commented Apr 5, 2021

Every one not use Google login to sign in the user, there is also a manual login. MV3 requires some serious work here

@zamiang
Copy link

zamiang commented Apr 5, 2021

@luciferpd13 Quite sure I am using MV3 :) - the migration process was very memorable.

In the example scenario, I am not making these requests from service workers but from the popup. I also don't believe you can create and submit form elements from service workers - that is the more critical part in that example (local storage is easily worked around or not used).

@luciferpd13 In this case there is no manual login since the user is already logged into the chrome browser - you just get a token back from chrome.identity.getAuthToken and then pass that to your endpoints (as accessToken in the task example). My code is shared across a chrome extension and a webapp (as was originally possible with gapi), so I implemented a platform-agnostic auth solution.

@luciferpd13
Copy link

luciferpd13 commented Apr 5, 2021

@zamiang That's what I am saying every one don't use Google Login. Also I see you are just making an api calls using token but there's more to that in GAPI. I believe @dotproto might come with the solution

@zamiang
Copy link

zamiang commented Apr 5, 2021

My examples assume OAUTH2. But you are correct that GAPI also handles the 'simple' auth method that uses an API key (https://github.com/google/google-api-javascript-client/blob/master/docs/auth.md).

For the simple method, you would just put the API key in the url params of your GET request. For example, looking at these docs (https://developers.google.com/maps/documentation/javascript/get-api-key), you would make a http GET request to this endpoint -https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=-33.8670522,151.1957362&radius=500&types=food&name=harbour&key=YOUR_API_KEY&callback=initMap.

Are there other auth methods not covered by OAUTH2 or API keys?

@luciferpd13
Copy link

@zamiang Already tried not working in manifest v3 due to CSP

@luciferpd13
Copy link

luciferpd13 commented Apr 5, 2021

Also we can't make every api calls in terms of url there are too many methods there ,that's why we are using Google scripts

@zamiang
Copy link

zamiang commented Apr 5, 2021

@luciferpd13 Just to clarify, so script-src 'self' prevents the extension from loading external script files. It does NOT prevent the extension from making external HTTP requests (that would be connect-src). The reason gapi does not work in a chrome extension, is because it is a script file hosted outside of the chrome extension, not because it makes http requests to google.

If you want to make AJAX requests from a chrome extension, you need to list those urls in host_permissions (https://developer.chrome.com/docs/extensions/mv3/match_patterns/ & https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#host-permissions) in MV3 but I believe we are getting a bit off track and into debugging your specific issue with your MV3 manifest file as it is certainly possible to make AJAX requests from a MV3 chrome extension.

The issue is more usability (I miss having automatic typescript types personally) and do wish this package could be released in a similar way to how the typescript types are packaged. As mentioned above, it is still possible to build extensions in MV3 that use google apis, it is just a bit less fast and maintainable.

@nielm
Copy link
Contributor

nielm commented Apr 6, 2021

@kospl, @Arthur404, @thdoan, @luciferpd13, what capabilities of the GAPI are you currently leveraging in your Manifest V2 extensions? What, if any, alternatives have you considered to using this library?

I am using GAPI to call oauth-authenticated Google APIs from my MV2 background page in my extension.
My extension makes these calls in the background so cannot use the pop-up or the foreground page as a context to execute the GAPI calls.
I leverage the chrome.identity API to take care of all the OAuth flow...

Potential Workarounds for MV3?

  • Figure out how to make a static JS dump of GAPI and include it in my extension (not possible according to first response in this issue)
  • Create, run and maintain a JSON/REST -> GAPI proxy service (with all the associated security and reliability risks) (no, that's not going to happen)
  • delete my extension.
  • continue using MV2

@luciferpd13
Copy link

luciferpd13 commented Apr 6, 2021

@luciferpd13 Just to clarify, so script-src 'self' prevents the extension from loading external script files. It does NOT prevent the extension from making external HTTP requests (that would be connect-src). The reason gapi does not work in a chrome extension, is because it is a script file hosted outside of the chrome extension, not because it makes http requests to google.

If you want to make AJAX requests from a chrome extension, you need to list those urls in host_permissions (https://developer.chrome.com/docs/extensions/mv3/match_patterns/ & https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/#host-permissions) in MV3 but I believe we are getting a bit off track and into debugging your specific issue with your MV3 manifest file as it is certainly possible to make AJAX requests from a MV3 chrome extension.

The issue is more usability (I miss having automatic typescript types personally) and do wish this package could be released in a similar way to how the typescript types are packaged. As mentioned above, it is still possible to build extensions in MV3 that use google apis, it is just a bit less fast and maintainable.

@zamiang I already know this things. Also as I said we can't every make api calls in terms of url. That's why I am asking @dotproto to provide some solution in MV3 extension. Also this discussion is not about making api calls from extension i don't know what are you trying to prove here 🤷🏻‍♂️. Everyone here wants to get some way to use GAPI and some other 3rd party scripts which are not locally available

@nathandpeterson
Copy link

Just want to add another voice here and check to see if there are any updates on this issue. We use maps.googleapis.com in our extension and we'd love to continue to use it in MV3 but it looks like the new CSP prohibits it. @dotproto Is there a solution in the works or a workaround that you recommend?

@twschiller
Copy link

twschiller commented Jun 22, 2021

In the PixieBrix extension, we use GAPI for the following so far:

  • File Picker (necessary to avoid requiring permissions to the whole Google Drive). The File Picker is the preferred/secure way to integrate with Google Drive: https://developers.google.com/picker/docs
  • Google Sheets
  • Big Query

References:

@e-roy
Copy link

e-roy commented Sep 11, 2021

To just be able to have a user log in with popup. I can make it work in MV2, but MV3 would be great! I'm using:

const googleProvider = new firebase.auth.GoogleAuthProvider()
firebase.auth() .signInWithPopup(googleProvider)

manifest.json :

  "content_security_policy": {
    "extension_pages": "script-src 'self'; script-src-elem 'self' https://apis.google.com https://www.gstatic.com https://www.googleapis.com https://securetoken.googleapis.com; object-src 'self';"
  },

and I get back in my console log an error:

Refused to load the script 'https://apis.google.com/js/api.js?onload=__iframefcb41660' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

@dotproto I love everything about firebase, if you could just get the PM from firebase and PM from chrome extensions together for coffee once a week I'll buy the coffee. :)

So many possibilities could be built using firebase in extensions

@luciferpd13
Copy link

@dotproto Any updates on this issue ?

@kospl
Copy link

kospl commented Nov 16, 2021

Looks like it's now deprecated and being replaced.

From https://developers.google.com/identity/gsi/web/guides/migration#object_migration_reference_for_user_sign-in

JavaScript libraries

Old New Notes
apis.google.com/js/platform.js accounts.google.com/gsi/client Replace old with new.
apis.google.com/js/api.js accounts.google.com/gsi/client Replace old with new.

So a question is now changed to what kind of support of Chrome MV3 new library will have.

@rendomnet
Copy link

@e-roy Did you found solution? I'm migrating from manifest2 to manifest3. And have same problem.

@apena94
Copy link

apena94 commented Feb 7, 2022

manifest v2 is being deprecated, will there be a solution for this in v3? In my particular use case i would like to have access to reCaptcha from the extension.

https://developer.chrome.com/docs/extensions/mv3/mv2-sunset/

@nielm
Copy link
Contributor

nielm commented Apr 14, 2022

I got some (disappointing) clarification from the GAPI team that chrome extensions are not and will not be a supported environment.

The documentation has been updated in #795
https://github.com/google/google-api-javascript-client/blob/master/docs/start.md#supported-environments

@merchalex
Copy link

@dotproto Late reply to your thread, but I have a question. Is the ablity to use the file picker removed entirely from v3? I cannot seem to find a ton of discussion on this specific feature.

Thank you

@eliasab16
Copy link

eliasab16 commented Aug 5, 2022

@nielm so does this mean that we can no longer use gapi in Chrome Extensions? Or were you able to find some workarounds?

@j-d-carmichael
Copy link

Seems that way @eliasab16 8c95515

@nielm do you happen to know if this restriction for Google's own code/APIs will be lifted at any point in the future?

We would really like to use the JS Google Maps in our Chrome ext.

@george-thomas-hill
Copy link

(Subscribing to this thread.)

@darbid
Copy link

darbid commented Oct 14, 2023

MV3 produces another inexplicable result. You cannot use Google’s own APIs in a chrome extension by virtue of the way they are packaged but you can make http requests all day long. Who ever is making these decisions needs to be let go.

@albertpratomo
Copy link

@dotproto In the productivity Chrome extension I'm building I want to use GAPI to auth the user, and fetch their Google Calendar events.

image

Isn't it a good idea to whitelist script-src from google.com domain? This way Chrome extension developers can consume Google APIs more easily.

@nielm
Copy link
Contributor

nielm commented Nov 17, 2023 via email

@enmanuelmag
Copy link

(Subscribing to this thread)

@DaisyXten
Copy link

DaisyXten commented Mar 2, 2024

Fine it seems gapi is deprecated in manifestv3 but a lot of samples (updated recently) in official documents are still using gapi, at least write some notes above those samples. I think I saw this thread before, but after some time I go to refer to official doc and see gapi again. I tried, met obstacles, google around and get back to this page again... : (

@patrickkettner
Copy link

patrickkettner commented Mar 2, 2024 via email

@e-roy
Copy link

e-roy commented Mar 2, 2024

Fix for Chrome Extensions and Firebase MV3

import { initializeApp } from "firebase/app";
import { initializeAuth } from "firebase/auth";

const app = initializeApp(firebaseConfig);

export const auth = initializeAuth(app, { popupRedirectResolver: undefined });

Hope this helps everyone :)

@DaisyXten
Copy link

DaisyXten commented Mar 2, 2024

@passwordslug
Copy link

Extension examples are here:

https://github.com/GoogleChrome/chrome-extensions-samples

I don't think there are GAPI MV3 examples.

@patrickkettner
Copy link

@e-roy thanks for sharing! We actually made an extension specific channel in firebase auth, so those steps are no longer needed (unless you have a hard dependency on an old version of firebase)

@lidanqing-i neither of those are extensions, so they are not impacted by manifest v3 changes.

@rast22
Copy link

rast22 commented May 13, 2024

Hi everyone, does any body found any general workaround for this issue. Our extension sometimes requires solving captcha, but with Manifest V3, it is impossible to load recaptcha script https://www.google.com/recaptcha/api.js...

Снимок экрана 2024-05-13 в 20 21 03

@patrickkettner
Copy link

Hey @rast22

There is firebase documentation on how to handle this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests