Server-side authentication using Google accounts in a Chrome extension

I have a Web application that currently uses OAuth2 to authenticate users using their Google accounts. The flow is quite standard: the user logs in to Google, the web app gets a callback, retrieves the user identity and stores it in the session.

Now I need to create an accompanying Chrome extension. This extension needs to access the web app underneath, so it needs to authenticate against this app. I configured my extension using the official documentation, but during experiments, I realized this is not what I need. Since it uses the OAuth2 implicit flow, it doesn’t return a token that could be validated on the server side. This flow is suitable only for using Google APIs on the client side, which is not my use case. This documentation (and pretty much everything else I found on the Web) focuses on two possible cases:

  1. We want to access Google APIs on the extension side (chrome.identity.getAuthToken()).
  2. We want to authenticate using an alternative OAuth2 service (chrome.identity.launchWebAuthFlow()).

However, in my case, I’d like to authenticate users using Google accounts, but process the token on the server side of my Web app. I could use option 2 here, but it just doesn’t “feel right” to me to create my own “non-Google authentication service” that is just a wrapper over Google authentication service, only to be able to authenticate on the server side.

Is option 2 really the only way to go, or is there any simpler way?

I also saw someone recommending using the https://www.googleapis.com/oauth2/v3/tokeninfo endpoint to validate the token, but I find it hard to make sure that this is indeed an “official” and secure way of doing this.

Chrome extension google oauth 2 issue

I have an issue with chrome extension and google oAuth 2.

I added all oAuth2 stuff in manifest.json.

Trying run this code in background.js

chrome.identity.getAuthToken({'interactive': true}, function (token) {
    if (chrome.runtime.lastError) {
        console.log(chrome.runtime.lastError.message);
        return;
    }

    console.log(token);
});

Yesterday all was alright but today I got the error :

OAuth2 request failed: Service responded with error: ‘request
parameters violate OAuth2 client security restrictions’

What is the problem?

How to force the Google API/OAUTH consent screen?

I have a Chrome Extension that, in the manifest, includes the Drive API. On install, when the user opens a Google Doc, background.js pops the consent screen to get the user’s permission to access their Google Drive.

This works fine on install. But if the user removes the app from Drive the code does NOT pop the consent screen again – it just gets a token and tries Drive only to get a 401 error.

I would have thought the auth call would pop consent if it isn’t granted…

Obviously if a user removes your app you shouldn’t keep asking for permission, necessarily – I’m just trying to deal with the simplest situation for now.

Some of my users never saw the consent page, or saw it and closed it…and are not prompted again.

Manifest:

"oauth2": {
        "client_id": "xxxxxxxxxx-smaehlat7c66p1ns6t90ssj3jmlrrecm.apps.googleusercontent.com",
        "scopes": [
            "https://www.googleapis.com/auth/userinfo.email",
        "https://www.googleapis.com/auth/userinfo.profile",
            "https://www.googleapis.com/auth/drive.readonly"
      ]
  },

Background.js:

googleFileID = getIdFromUrl(activeURL);

chrome.identity.getAuthToken({ 'interactive': true }, function(token) {

  console.log('In Chrome Identity and obtained token: ' + token);

  $.ajax({
    type: "GET",
    beforeSend: function(request) {
      request.setRequestHeader("Authorization", "Bearer " + token);
    },
    url: "https://www.googleapis.com/drive/v3/files/" + googleFileID + "?fields=owners",
    dataType: 'json',
    processData: true,
    success: function(gDocsMeta1) {
      // DO STUFF

Google API Console:
I have set up the API and can see traffic, although 10% of my traffic is errors, which I attribute to the above problem.

I use Google Firebase for user authentication…if that is relevant. While some of my users opt for Google Authentication to create accounts, many use email signup. The problem afflicts both types of sign ups.

Any help appreciated!

Getting a List of Users/Email Addresses Using Chrome Extension

I built a Chrome extension with a free trial/monthly subscription model. I use Google OAuth 2.0 to have users login through Gmail before using the extension in order to run the free trial, give them a message if their free trial has run out, or give them access to all features if they have a full license. That’s all working fine.

Is there a way to get a list of users & their associated licenses, and preferably including the email addresses they logged in with?

firefox webextensions id_token and launchwebauthflow

I’m using the methods outlined here to get an id_token from google: Is it possible to get an Id token with Chrome App Indentity Api?

This works great for chrome, but I’d love to be able to easily support firefox. The above method works based on some “magic” “< id > chromiumapp.org” parsing. Is there a way to get firefox to do the same? If not can someone recommend a way that I can get an id_token from google inside a firefox webextextension?

A bit more info: I’m using id_token’s to validate my user who will sign up using google’s sign-in. I’m also using non-expired google id_tokens as a shared secret for signing stateless request tokens since both the client and server both have this shared secret and if it is intercepted and not expired I can’t really stop a 3rd party from using it.

Google sign-in button not working in Chrome Extension

I have a firebase app that requires users to be authenticated using Google.
I managed to hook up all settings and users can read/write to their prospective database location on firebase.

The only issue is: I am trying to display the Google-Sign-In button inside a chrome extension pop up. Here is my manifest.json

{
    "manifest_version" : 2,
    "name" : "MY EXTENSION",
    "version" : "0.0.6",
    "browser_action" : {
        "default_popup" : "welcome.html"
    },
    "background" : {
        "scripts" : ["js/jquery.min.js","js/firebase.js","js/firebase_config.js","js/background.js"],
        "persistent" : false
    },
    "oauth2" : {
        "client_id" : "686230544294-m9jfmc18cneiandadq8riborrjmq36in.apps.googleusercontent.com",
        "scopes" : [
            "openid", "email", "profile"
        ]
    },
    "content_security_policy" : "script-src 'self' 'unsafe-eval' https://apis.google.com; object-src 'self'"

}

Here is my welcome.html:



    

        
        

    
    
        

Welcome. Please sign in

The pop up opens up with everything except for the button. When I inspect its console, I get the following error:

Uncaught uO
message: "Invalid cookiePolicy"stack: "gapi.auth2.ExternallyVisibleError: Invalid cookiePolicy↵ at new uO (https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.iUeg......

From firebase side, I can see users signing in.
What am I doing wrong? why doesn’t the Sign-In button show up on the extension pop up?

How to use onSignInChanged event handler in chrome extension for gmail?

Here is the code of my google chrome extension

Manifest:

"content_scripts": [
  {
   "matches": [
   "https://mail.google.com/*",
   "https://inbox.google.com/*"
 ],
 "js": ["js/jquery-3.2.1.min.js", "js/content.js"],
 "css": ["css/custom.css"],
 "run_at": "document_end"
 }
],
"background":{
  "scripts": ["js/background.js"],
  "persistent": true
},
"permissions": [
  "https://mail.google.com/",
  "https://inbox.google.com/",
  "https://accounts.google.com/*",
  "identity",
  "identity.email",
  "storage"
],
"oauth2":{
  "client_id": "xxx",
  "scopes": [
    "profile",
    "https://www.googleapis.com/auth/gmail.readonly",
    "https://www.googleapis.com/auth/contacts.readonly",
    "https://www.googleapis.com/auth/plus.login",
    "https://www.googleapis.com/auth/userinfo.profile",
     "https://www.googleapis.com/auth/userinfo.email"
  ]
}

background.js

//get google OAuth Token
chrome.identity.getAuthToken({
  interactive: true
}, function(token) {
  if (chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError.message);
    alert(chrome.runtime.lastError.message);
    return;
  }
  console.log(token);
  currentSessionAccessToken = token;
  var x = new XMLHttpRequest();
  x.open('GET',
    'https://www.googleapis.com/oauth2/v2/userinfo?alt=json&access_token=' + token
  );
  x.onload = function() {
    console.log(x.response);
  };
  x.send();
});

//registered event handler for signIn change
chrome.identity.onSignInChanged.addListener(function(accountInfo, isSignedIn){
  console.log(accountInfo);
});

But, onSignInChanged event is not fired when I switch to another user. Actually, I want to revoke the token generated for previously logged in user when signIn is changed and generate a new token for newly logged in user.

Since, the event is not fired, my extension is loading contacts of previously logged in user. I have followed Google’s this documentation. No idea why the event is not getting fired. Am i missing anything?

Is it required to publish a Chrome extension to the Chrome web store in order to use Google’s OAuth?

I’m trying to use the chrome.identity.launchWebAuthFlow method to authenticate the Google user’s login in my chrome extension to get his email address, and my code is:

Manifest.json

"key": "Key_here",
"oauth2": {
    "client_id": "my_client_id.apps.googleusercontent.com",
    "scopes": [
        "https://www.googleapis.com/auth/userinfo.email"
    ]
}

popup.js

function startOAuth() {
    chrome.runtime.sendMessage({"message": "start_oauth"});
}

$("#login").on("click", startOAuth);

background.js

var manifest = chrome.runtime.getManifest();
var clientId = encodeURIComponent(manifest.oauth2.client_id);
var scopes = encodeURIComponent(manifest.oauth2.scopes.join(' '));
var redirect_uri = chrome.identity.getRedirectURL();

chrome.runtime.onMessage.addListener(
        function (request, sender, sendResponse) {
            if (request.message === "start_oauth") {
                chrome.identity.launchWebAuthFlow({
                    "url": "https://accounts.google.com/o/oauth2/v2/auth?" +
                            $.param({
                                "scope": scopes,
                                "response_type": "token",
                                "client_id": clientId,
                                "redirect_uri": redirect_uri,
                                "prompt": "consent"
                            }),
                    "interactive": true
                }, function (response) {
                    console.log('response: ' + response);
                });
            }
        }
);

But when I click the popup icon, I get in the background’s console:

response: undefined

Unchecked runtime.lastError while running identity.launchWebAuthFlow:
Authorization page could not be loaded.

When I open the url in the browser:

https://accounts.google.com/o/oauth2/v2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&response_type=token&client_id=&redirect_uri=https%3A%2F%2F.chromiumapp.org%2F&prompt=consent

I get the error:

Error: redirect_uri_mismatch

I’m loading the extension as unpacked extension, have put the extension’s id, which appears under its name in the chrome://extensions/, in the Application ID in the Google API’s credentials

But under this field it said:

Application ID

Last part of your app’s Chrome Web Store URL

Does this means that I have to publish the extension to the Chrome web store in order to make the redirect_uri match ?


Note:

To get the extension’s key, which I’m putting in the manifest and referring to it as "Key_here", I uploaded the manifest of the extension to the chrome web store developer’s dashboard, as a draft, and got the public key from there and put in the manifest.

Now the redirect_uri is the same in the the Google API’s console and in my unpacked extension id, what am I missing?

How can i securely use client_id and api key in gmail extension for chrome?

Right now i have hard-coded all my keys in the background page. Also, do i need to secure access_token that is generated after authorization is successful?