16

I'm writing a Chrome extension and have been trying to use chrome.identity.launchWebAuthFlow to authenticate with Google. I would prefer this to chrome.identity.getAuthToken (which does work) because getAuthToken gets the token for the user currently logged in to Chrome -- who may be logged in to multiple Google accounts. I want the user to be able to hook up a specific Google calendar to my extension, and that calendar might belong to a different user than they've logged in to Chrome as.

So, I've been trying to do this with chrome.identity.launchWebAuthFlow and generally failing around a mismatched redirect_uri. I've tried just about every type of credential you can set up in the Google APIs developer console. ("Chrome App" seemed like the right thing, but I have also tried Web application, Other, and iOS.) I've tried using the results of both chrome.extension.getURL('string') and chrome.app.getRedirectURL('string') as my redirect_uri.

I tried out the example app referred to by https://stackoverflow.com/questions/40384255/oauth2-angular-chrome-extension but have not been able to get that to work either.

I have a suspicion I'm trying to do something that either used to be allowed and no longer is, or just never worked.

Here's an example of my code, but I think my problem is really in the API dev console -- I don't see a way to set up a configuration that will work for an extension:

    var auth_url = 'https://accounts.google.com/o/oauth2/v2/auth';
    var client_key = *[client id from API dev console]*
    var auth_params = { 
                        client_id: client_key,
                        redirect_uri: chrome.identity.getRedirectURL("oauth2.html")
                        scope: 'https://www.googleapis.com/auth/calendar'
                      };
    auth_url += '?' + $.param(auth_params);

    chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(token) { console.log(token); });

(I have also tried the https://accounts.google.com/o/oauth2/auth endpoint.)

Solution:

After reading the accepted answer, I wound up with this:

var auth_url = 'https://accounts.google.com/o/oauth2/auth';
var client_id = '[client ID from console]';
var redirect_url = chrome.identity.getRedirectURL("oauth2.html");
var auth_params = {
    client_id: client_id,
    redirect_uri: redirect_url,
    response_type: 'token',
    scope: 'profile'
};
auth_url += '?' + $.param(auth_params);
console.log(auth_url);
chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(responseUrl) { console.log(responseUrl); });

The responseUrl is my redirect_uri with parameters -- so Google oauth returned that instead of redirecting the browser to it -- and I could go on from there.

Community
  • 1
  • 1
A.K. Farrell
  • 270
  • 3
  • 9
  • Please [edit] the question to be on-topic: include a **complete** [mcve] that duplicates the problem. Usually, including a *manifest.json*, some of the background *and* content scripts. Questions seeking debugging help ("**why isn't this code working?**") must include: ►the desired behavior, ►a specific problem or error *and* ►the shortest code necessary to reproduce it **in the question itself**. Questions without a clear problem statement are not useful to other readers. See: "**How to create a [mcve]**", [What topics can I ask about here?](http://stackoverflow.com/help/on-topic), and [ask]. – Makyen Nov 03 '16 at 22:08
  • is this method still working for you? – seesoe Oct 05 '17 at 21:17
  • For some reason I'm still getting an error: Unchecked runtime.lastError: Authorization page could not be loaded. I created Web Application ID and followed the above steps. Tired both endpoints but to no avail. Am I missing something from this thread? – Armand May 20 '19 at 20:42
  • @Armand, I wound up not using this API, so I don't know whether this would still work. – A.K. Farrell May 21 '19 at 21:46

2 Answers2

10

Yes, in 2019 it still works. Finally got it working...

manifest.json

{
   "name": "Extension Name",
   "description": "Description",
   "version": "1.0.0",
   "manifest_version": 2,
   "icons": {
      "48": "icons/icon_48.png",
      "128": "icons/icon_128.png"
   },
   "background": {
      "scripts": [
         "background.js"
      ],
      "persistent": false
   },
   "oauth2": {
      "client_id": "Your Client ID from Google Develpers console (Must be Web Application)",
      "scopes": [
         "openid", "email", "profile"
      ]
   },
   "permissions": [
      "identity"
   ],
   "key": "Your Key from Google Developer Dashboard"
}

background.js

chrome.windows.create({
    'url': './content/auth/auth.html',
    'width': 454,
    'height': 540,
    'type': 'popup'
});

auth.html

standard HTML markup that calls auth.js file

auth.js

var auth_url = 'https://accounts.google.com/o/oauth2/auth?';
var client_id = '<Client ID>';  // must be Web Application type
var redirect_url = chrome.identity.getRedirectURL(); // make sure to define Authorised redirect URIs in the Google Console such as https://<-your-extension-ID->.chromiumapp.org/

var auth_params = {
    client_id: client_id,
    redirect_uri: redirect_url,
    response_type: 'token',
    scope: 'https://mail.google.com/',
    login_hint: 'real_email@gmail.com' // fake or non-existent won't work
};

const url = new URLSearchParams(Object.entries(auth_params));
url.toString();
auth_url += url;

chrome.identity.launchWebAuthFlow({url: auth_url, interactive: true}, function(responseUrl) { 
    console.log(responseUrl);
});
Armand
  • 2,611
  • 2
  • 24
  • 39
  • 1
    Thank you @Armand! This helped me out a lot today. The main issue on my end was not setting up the OAuth Client as a Web Application. I had set it up as a Chrome app before. After generating a new OAuth Client ID as a Web Application and setting the Authorized Redirect URIs, it worked like a charm. – Alexander Mar 16 '22 at 13:21
  • What I dont understand is why did you have to create a new window with auth.html that runs auth.js. Why couldn't this piece of js be run in any other extension page such as the background.js? – Moe Bazzi Apr 14 '22 at 14:51
  • because you need a window to load the google authentication interface, you can't achieve that from background/service worker – Armand Apr 14 '22 at 19:53
  • from the responseUrl how can i get the user profile info? – Sunil Garg Apr 26 '22 at 09:06
  • from this articale https://developers.google.com/identity/sign-in/web/server-side-flow point no 4 says i will get the google auth code in response after login with google that i can verify on my node server.. but all i get is the redirectUrl.. how can i get the code? – Sunil Garg May 03 '22 at 05:39
3

To get the Angular sample running, I needed to:

  1. Create my own Web Application client ID in the Google developer console with an Authorized redirect URI of https://bcgajjfnjjgadphgiodlifoaclnemcbk.chromiumapp.org/oauth2

  2. Copy that client ID into the config.json file of the sample.

The call to get redirectURI in that sample is like chrome.identity.getRedirectURL("oauth2"), the string parameter gets appended to the end of the URL based on extension ID.

lgaud
  • 2,430
  • 20
  • 30
  • I'll try to see if I can make this work and accept your answer soon. I have at least managed to enter an Authorized redirect URI of the form you specified in the Google developer console. I wound up constructing my app differently -- the extension communicates directly only with "our" server, and "our" server uses the Google APIs via oauth2 on behalf of the user. We needed the server-to-server communication anyway. – A.K. Farrell Feb 18 '17 at 00:12
  • Thanks! I haven't gone back to the angular sample, but your hints helped me get past this sticking point. (Possibly Google updated their chrome.identity docs too, because it's clear now that it doesn't do what I thought a few months ago). In addition to the dev console question, I needed to add a "response_type" parameter to the auth URL. When using a chrome.identity.getRedirectURL('whatever') URL as the redirect_uri, the callback you pass to launchWebAuthFlow gets the redirect_uri, with query params, as its single parameter. – A.K. Farrell Mar 21 '17 at 21:25