authenticating a service account to call a Google API with JavaScript client library
Asked Answered
P

1

8

I want to make JSON-RPC calls from localhost (WAMP environment) to the Google FusionTables API (and a couple of other APIs) using the Google Client Library for JavaScript

Steps I have taken:

  1. setup a project on the Google Developer Console
  2. enabled the FusionTables API
  3. created a service account and downloaded the JSON file.
  4. successfully loaded the JS client library with the auth package: gapi.load('client:auth2', initAuth);
  5. constructed the init method parameter the following 3 ways:
    • the downloaded JSON verbatim
    • the downloaded JSON modified to include the scope
    • just the client ID and scope
  6. tried (and failed) to initialize the GoogleAuth instance: gapi.auth2.init(params)

    function failed(reason) {
        console.log(reason);
    }
    gapi.load('client:auth2', initAuth);

    function initAuth() {

        var APIkey = 'MY API KEY';
        gapi.client.setApiKey(APIkey); //I understand this to be unnecessary with authorized requests, included just for good measure

        var GDTSAKey = 'MY SERVICE ACCOUNT KEY';
        var scopes = 'https://www.googleapis.com/auth/fusiontables';
        gapi.auth2.init({
            client_id: "101397488004556049686",
            scope: 'https://www.googleapis.com/auth/fusiontables'
        }).then(signin, failed("couldn't initiate"));
        //passing the downlaoded JSON object verbatim as parameter to init didn't work either
    } //initAuth()

    function signin() {
        gapi.auth2.getAuthInstance().signIn().then(makeAPIcall), failed("couldn't sign-in");
    }

    function makeAPIcall(){
        gapi.client.load('fusiontables', 'v2', function(){
            var tableId = '1PSI_...';
            var table = gapi.client.fusiontables.table.get(tableId);
            document.querySelector("#result").innerHTML = table;            
        });
    }

based on JS client library >> Samples

the gapi.auth2.init method invokes the second callback (which I understand to be an error handler): failed("couldn't initiate"), but then, curiously, I also get `couldn't sign in' which could only have originated from within the provided success handler. What's going on? How do I get this to work?

Note: I am only willing to try the CORS/xhr, if there is no way to do it with JS client lib.

Pattern answered 3/10, 2016 at 6:24 Comment(8)
Where in the documentation of the Google JavaScript client library does it say it supports service accounts? All I see is public API and Oauth2.Sarthe
I don't remember having seen it explicitly. But then, I didn't read anywhere that it didn't, so I just assumed it does; real pity that it doesn't.Pattern
If something is supported the documentation will state that and show you how to use it. Otherwise we will have to have documentation that clearly states it does not help you to make a pizza, cook hotdogs, ... or everything else in the world that It wouldn't support.Sarthe
My assumption was based on the recommendation on this page: OAuth 2.0 for Service Accounts. One wouldn't reasonably expect a client library to directly help you make pizza or cook hotdogs. But expecting a Google API client library to be compatible with all account types by Google isn't too far-fetched I suppose and very natural to assume unless it is explicitly excluded. While it's a great piece of work and much appreciated, the documentation is ambiguous if not outright misleading.Pattern
Consider that js is client sided then consider the security ramifications of having the service account info in the file for everyone to see and download. Service accounts and js don't mix. Google isn't going to help you do something that would be a security nightmareSarthe
Sorry my previous comment may have been a little ott.Sarthe
You're right. That is such an obvious folly that would be trivial to point out. But as an English teacher just dabbling at programming, I just failed to see it.Pattern
Welcome to the fun then :)Sarthe
S
10

What's going on?

You are trying to use a service account with the Google JavaScript client library which does not support service accounts.

How do I get this to work?

Switch to Oauth2 authentication or if you must use a service account switch to a server sided language like PHP or python for example. Which support service account authentication.

Sarthe answered 3/10, 2016 at 6:36 Comment(2)
My original intention was to use the FusionTables as a lightweight db to power a standalone GAS deployed as a Web App accessed by anyone, even anonymous. And to reduce latency, I decided to make the request from the client-side (HTMLService). I was trying to figure out how to do it, when I came across the JS client library, and although it explicitly says that sandbox environments like iframes are not supported (I guess that precludes my original environment), I decided to experiment with it a bit to learn to use it in other projects. So how do you suggest I approach the original problem?Pattern
I think you should open another question with your original problem. Try and point out what you have tried and what hasn't worked.Sarthe

© 2022 - 2024 — McMap. All rights reserved.