質問

I'm trying to use the YouTube Data API V3 with Node, in an attempt to provide an authenticated proxy around doing video searches. As the service is going to run on a server, I've created a service account.

This results in the download of a key file and the following information:

I have a very basic understanding of JWTs, but the service section on the OAuth2 page suggested that you should be using one of their libraries to do it, rather than implementing it yourself. However, they don't list a Node library in their supported libraries.

A little more digging and I came across the Google API Nodejs client: https://github.com/google/google-api-nodejs-client which claims to be supported by Google and has OAuth2 support out of the box.

The docs are fairly minimal and the examples for authentication involves printing a URL into a terminal and then visiting it in a browser to generate a token. I had a dig around the source to see whether it supported JWT and it does appear to have a JWTClient built in.

/**
 * @constructor
 * JWT service account credentials.
 *
 * Retrieve access token using gapitoken.
 *
 * @param {string=} email service account email address.
 * @param {string=} keyFile path to private key file.
 * @param {array=} scopes list of requested scopes.
 * @param {string=} subject impersonated account's email address.
 *
 */
function JWT(email, keyFile, key, scopes, subject) {
  JWT.super_.call(this);
  this.email = email;
  this.subject = subject;
  this.keyFile = keyFile;
  this.key = key;
  this.scopes = scopes;
  this.GAPI = GAPI;
}

This doc comment above the constructor seems to be the only explanation here and I'm still unsure of how to use this function.

I'm assuming:

  • email is the email address of your developer account
  • keyFile is the path to the private key
  • key is the private key? (If so, why include path as well?)
  • scopes is an array of API scopes you want to access
  • subject ???

Has anyone used this service before, or be able to shed a little light on the discrepancies here?

Just as a reference, this has to be server side as I need the authentication for requests to be autonomous and I can't just use non-authenticated requests as I exceed my daily allowance in 200 requests (or something like that).

役に立ちましたか?

解決

I've managed to piece together a working solution, so I'll leave it here for anyone else who has a similar problem in the future.

There is a JWT example in the repo, which shows in more detail how you use the constructor for the JWT object.

https://github.com/google/google-api-nodejs-client/blob/master/examples/jwt.js

Here's a slightly amended version of the doc comment.

/**
 * @constructor
 * JWT service account credentials.
 *
 * Retrieve access token using gapitoken.
 *
 * @param {string=} email service account email address from developer console.
 * @param {string=} keyFile absolute path to private key file.
 * @param {string=} key the contents of the key if you are loading it yourself (optional)
 * @param {array=} scopes list of requested scopes.
 * @param {string=} subject impersonated account's email address (optional).
 *
 */

And the finished code looks like this

// Create the JWT client
var authClient = new googleapis.auth.JWT(email, keypath, key,
  ['https://www.googleapis.com/auth/youtube']);

// Authorize it to produce an access token
authClient.authorize(function(err, tokens) {
  if(err) throw err;

  // Use discovery to get the youtube api
  googleapis.discover('youtube', 'v3')
  .execute(function(err, client) {

    // Create a search
    var search = client.youtube.search.list({
      q: '<query string>',
      part: 'snippet',
      maxResults: 50
    });

    // Authenticate with current auth client
    search.authClient = authClient;

    // Hey presto!
    search.execute(function(err, results) {
      if(err) throw err;
      console.log(results.items);
    });

  });

});

This code example is a mess, but it's enough to give you the idea. Based on the example you should be able to do:

client.youtube.search.list({
 ... 
})
.withAuth(authClient)
.execute(...); 

But for some reason the withAuth method isn't there. It took a bit of digging to work out what it did and as far as I can see, it works fine if you set the authClient property by hand, as shown above.

As a side note, the err arguments are not errors, but POJOs and throwing them as above doesn't actually work. Unless you're happy to see [Object object] as your debug info.

Hopefully that library will get some proper documentation attention soon and problems like this will be ironed out.

他のヒント

The sample above seams to be outdated, so I attach what I found out. There is no good documentation apart from intellisense for the library. I am using pubsub in my example:

const {google} = require('googleapis');
const path = require('path');
const util = require('util')


async function runSample () {

  // Create a new JWT client using the key file downloaded from the Google Developer Console
  const authClient = await google.auth.getClient({
    keyFile: path.join(__dirname, 'jwt.keys.json'),
    scopes: 'https://www.googleapis.com/auth/pubsub'
  });

  // Obtain a new pubsub client, making sure you pass along the authClient
  const pb = google.pubsub(
    {
        version:'v1',
        auth: authClient
    });

  //make a request to list subscriptions
  //the returned object is a axios response object
  const res = await pb.projects.subscriptions.list(
  {
      project: 'projects/my-project'
  });

  //return response data
  return res.data;
}

runSample().then(res =>{
    console.log(util.inspect(res, false, null))
}).catch(console.error);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top