From c2ead4cc7650f100b883c9296fce628f17085992 Mon Sep 17 00:00:00 2001 From: "Benjamin E. Coe" Date: Fri, 22 Jan 2021 11:49:30 -0800 Subject: [PATCH] fix: support PEM and p12 when using factory (#1120) --- src/auth/googleauth.ts | 18 ++++++++++++--- test/test.googleauth.ts | 49 +++++++++++++++++++++++++++++++++++++++++ test/test.jwt.ts | 2 +- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/auth/googleauth.ts b/src/auth/googleauth.ts index 29ff5d95..437677ab 100644 --- a/src/auth/googleauth.ts +++ b/src/auth/googleauth.ts @@ -518,9 +518,21 @@ export class GoogleAuth { .on('data', chunk => (s += chunk)) .on('end', () => { try { - const data = JSON.parse(s); - const r = this._cacheClientFromJSON(data, options); - return resolve(r); + try { + const data = JSON.parse(s); + const r = this._cacheClientFromJSON(data, options); + return resolve(r); + } catch (err) { + // If we failed parsing this.keyFileName, assume that it + // is a PEM or p12 certificate: + if (!this.keyFilename) throw err; + const client = new JWT({ + ...this.clientOptions, + keyFile: this.keyFilename, + }); + this.cachedCredential = client; + return resolve(client); + } } catch (err) { return reject(err); } diff --git a/test/test.googleauth.ts b/test/test.googleauth.ts index 109998de..e1039ba3 100644 --- a/test/test.googleauth.ts +++ b/test/test.googleauth.ts @@ -16,6 +16,7 @@ import * as assert from 'assert'; import {describe, it, beforeEach, afterEach} from 'mocha'; import * as child_process from 'child_process'; import * as crypto from 'crypto'; +import {CredentialRequest} from '../src/auth/credentials'; import * as fs from 'fs'; import { BASE_PATH, @@ -44,6 +45,8 @@ describe('googleauth', () => { const instancePath = `${BASE_PATH}/instance`; const svcAccountPath = `${instancePath}/service-accounts/?recursive=true`; const API_KEY = 'test-123'; + const PEM_PATH = './test/fixtures/private.pem'; + const P12_PATH = './test/fixtures/key.p12'; const STUB_PROJECT = 'my-awesome-project'; const ENDPOINT = '/events:report'; const RESPONSE_BODY = 'RESPONSE_BODY'; @@ -74,6 +77,11 @@ describe('googleauth', () => { 'gcloud', 'application_default_credentials.json' ); + function createGTokenMock(body: CredentialRequest) { + return nock('https://www.googleapis.com') + .post('/oauth2/v4/token') + .reply(200, body); + } describe('googleauth', () => { let auth: GoogleAuth; @@ -1524,4 +1532,45 @@ describe('googleauth', () => { .reply(200, {}); } }); + + // Allows a client to be instantiated from a certificate, + // See: https://github.com/googleapis/google-auth-library-nodejs/issues/808 + it('allows client to be instantiated from PEM key file', async () => { + const auth = new GoogleAuth({ + keyFile: PEM_PATH, + clientOptions: { + scopes: 'http://foo', + email: 'foo@serviceaccount.com', + subject: 'bar@subjectaccount.com', + }, + }); + const jwt = await auth.getClient(); + const scope = createGTokenMock({access_token: 'initial-access-token'}); + const headers = await jwt.getRequestHeaders(); + assert.deepStrictEqual( + headers.Authorization, + 'Bearer initial-access-token' + ); + scope.done(); + assert.strictEqual('http://foo', (jwt as JWT).gtoken!.scope); + }); + it('allows client to be instantiated from p12 key file', async () => { + const auth = new GoogleAuth({ + keyFile: P12_PATH, + clientOptions: { + scopes: 'http://foo', + email: 'foo@serviceaccount.com', + subject: 'bar@subjectaccount.com', + }, + }); + const jwt = await auth.getClient(); + const scope = createGTokenMock({access_token: 'initial-access-token'}); + const headers = await jwt.getRequestHeaders(); + assert.deepStrictEqual( + headers.Authorization, + 'Bearer initial-access-token' + ); + scope.done(); + assert.strictEqual('http://foo', (jwt as JWT).gtoken!.scope); + }); }); diff --git a/test/test.jwt.ts b/test/test.jwt.ts index dd569a03..aa70ea44 100644 --- a/test/test.jwt.ts +++ b/test/test.jwt.ts @@ -118,8 +118,8 @@ describe('jwt', () => { scopes: 'http://foo', subject: 'bar@subjectaccount.com', }); - const scope = createGTokenMock({access_token: 'initial-access-token'}); + jwt.authorize(() => { scope.done(); assert.strictEqual('http://foo', jwt.gtoken!.scope);