Skip to content

Commit

Permalink
feat!: Update google-auth-library to v10 (#1702)
Browse files Browse the repository at this point in the history
* feat!: Update `google-auth-library` to v10

* style: lint

* chore: streamline auth with rc.1

* fix: typo

* chore: bump rc

* chore: webpack

* test: fix

* refactor: extend `FetchParameters#headers` compat

* test: fix webpack config and tests
  • Loading branch information
d-goog authored Feb 27, 2025
1 parent 5ef89de commit 43a8cb8
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 329 deletions.
5 changes: 1 addition & 4 deletions gax/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@types/long": "^5.0.0",
"abort-controller": "^3.0.0",
"duplexify": "^4.1.3",
"google-auth-library": "^9.15.1",
"google-auth-library": "^10.0.0-rc.1",
"node-fetch": "^3.3.2",
"object-hash": "^3.0.0",
"proto3-json-serializer": "^3.0.0",
Expand All @@ -27,15 +27,12 @@
"@types/mocha": "^10.0.10",
"@types/ncp": "^2.0.8",
"@types/node": "^20.5.0",
"@types/node-fetch": "^2.6.12",
"@types/object-hash": "^3.0.6",
"@types/proxyquire": "^1.3.31",
"@types/pumpify": "^1.4.4",
"@types/sinon": "^17.0.3",
"@types/uglify-js": "^3.17.5",
"assert": "^2.1.0",
"c8": "^10.1.3",
"cheerio": "^1.0.0",
"codecov": "^3.8.3",
"execa": "^5.0.0",
"glob": "10.4.5",
Expand Down
67 changes: 32 additions & 35 deletions gax/src/fallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,7 @@ import * as protobuf from 'protobufjs';
import * as gax from './gax';
import * as routingHeader from './routingHeader';
import {Status} from './status';
import {
GoogleAuth,
OAuth2Client,
Compute,
JWT,
UserRefreshClient,
GoogleAuthOptions,
BaseExternalAccountClient,
} from 'google-auth-library';
import {GoogleAuth, AuthClient} from 'google-auth-library';
import {OperationsClientBuilder} from './operationsClient';
import type {GrpcClientOptions, ClientStubOptions} from './grpc';
import {GaxCall, GRPCCall} from './apitypes';
Expand Down Expand Up @@ -85,15 +77,16 @@ export interface ServiceMethods {
[name: string]: protobuf.Method;
}

export type AuthClient =
| OAuth2Client
| Compute
| JWT
| UserRefreshClient
| BaseExternalAccountClient;
/**
* @deprecated use `GoogleAuth` here instead
*/
type deprecatedAuthClientAlias = AuthClient;

export class GrpcClient {
auth?: OAuth2Client | GoogleAuth;
auth?: GoogleAuth<AuthClient> | deprecatedAuthClientAlias;
/**
* @deprecated use {@link GrpcClient.auth} instead
*/
authClient?: AuthClient;
fallback: boolean;
grpcVersion: string;
Expand All @@ -114,33 +107,36 @@ export class GrpcClient {
* gRPC-fallback version of GrpcClient
* Implements GrpcClient API for a browser using grpc-fallback protocol (sends serialized protobuf to HTTP/1 $rpc endpoint).
*
* @param {Object=} options.auth - An instance of OAuth2Client to use in browser, or an instance of GoogleAuth from google-auth-library
* to use in Node.js. Required for browser, optional for Node.js.
* @constructor
* @param options {@link GrpcClientOptions}
*/

constructor(
options: (GrpcClientOptions | {auth: OAuth2Client}) & {
options: (
| GrpcClientOptions
| {
/**
* @deprecated - use `authClient` for `AuthClient`s instead
*/
auth: AuthClient;
}
) & {
/**
* Fallback mode to use instead of gRPC.
* A string is accepted for compatibility, all non-empty string values enable the HTTP REST fallback.
*/
fallback?: boolean | string;
} = {},
) {
if (!isNodeJS()) {
if (!options.auth) {
throw new Error(
JSON.stringify(options) +
'You need to pass auth instance to use gRPC-fallback client in browser or other non-Node.js environments. Use OAuth2Client from google-auth-library.',
);
}
this.auth = options.auth as OAuth2Client;
if (options.auth) {
this.auth = options.auth;
} else if ('authClient' in options) {
this.auth = options.authClient;
} else {
this.auth =
(options.auth as GoogleAuth) ||
new GoogleAuth(options as GoogleAuthOptions);
this.auth = new GoogleAuth({
authClient: options.auth,
...options,
});
}

this.fallback = options.fallback ? true : false;
this.grpcVersion = require('../../package.json').version;
this.httpRules = (options as GrpcClientOptions).httpRules;
Expand Down Expand Up @@ -266,7 +262,7 @@ export class GrpcClient {

/**
* gRPC-fallback version of createStub
* Creates a gRPC-fallback stub with authentication headers built from supplied OAuth2Client instance
* Creates a gRPC-fallback stub with authentication headers built from supplied `AuthClient` instance
*
* @param {function} CreateStub - The constructor function of the stub.
* @param {Object} service - A protobufjs Service object (as returned by lookupService)
Expand All @@ -284,7 +280,7 @@ export class GrpcClient {
) {
if (!this.authClient) {
if (this.auth && 'getClient' in this.auth) {
this.authClient = (await this.auth.getClient()) as AuthClient;
this.authClient = await this.auth.getClient();
} else if (this.auth && 'getRequestHeaders' in this.auth) {
this.authClient = this.auth;
}
Expand Down Expand Up @@ -342,7 +338,7 @@ export class GrpcClient {
protocol,
servicePath,
servicePort,
this.authClient,
this.auth || this.authClient,
encoder,
decoder,
this.numericEnums,
Expand Down Expand Up @@ -425,6 +421,7 @@ export function createApiCall(
};
}
if (descriptor && 'streaming' in descriptor && !isNodeJS()) {
// TODO: with `fetch` this functionality is available in the browser...
return () => {
throw new Error(
'Server streaming over the REST transport is only supported in Node.js.',
Expand Down
23 changes: 12 additions & 11 deletions gax/src/fallbackServiceStub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import type {
RequestInit,
} from 'node-fetch' with {'resolution-mode': 'import'};
import {AbortController as NodeAbortController} from 'abort-controller';

import {AuthClient, GoogleAuth, gaxios} from 'google-auth-library';

import type nodeFetch from 'node-fetch' with {'resolution-mode': 'import'};
import {hasWindowFetch, hasAbortController, isNodeJS} from './featureDetection';
import {AuthClient} from './fallback';
import {StreamArrayParser} from './streamArrayParser';
import {pipeline, PipelineSource} from 'stream';
import type {Agent as HttpAgent} from 'http';
Expand All @@ -38,7 +40,9 @@ interface NodeFetchType {
// Node.js before v19 does not enable keepalive by default.
// We'll try to enable it very carefully to make sure we don't break possible non-Node use cases.
// TODO: remove this after Node 18 is EOL.
// More info: https://github.com/node-fetch/node-fetch#custom-agent
// More info:
// - https://github.com/node-fetch/node-fetch#custom-agent
// - https://github.com/googleapis/gax-nodejs/pull/1534
let agentOption:
| ((parsedUrl: {protocol: string}) => HttpAgent | HttpsAgent)
| null = null;
Expand Down Expand Up @@ -68,7 +72,7 @@ export interface FallbackServiceStub {
export type FetchParametersMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';

export interface FetchParameters {
headers: {[key: string]: string};
headers: {[key: string]: string} | Headers;
body: Buffer | Uint8Array | string;
method: FetchParametersMethod;
url: string;
Expand All @@ -79,7 +83,7 @@ export function generateServiceStub(
protocol: string,
servicePath: string,
servicePort: number,
authClient: AuthClient,
auth: GoogleAuth | AuthClient,
requestEncoder: (
rpc: protobuf.Method,
protocol: string,
Expand Down Expand Up @@ -147,20 +151,17 @@ export function generateServiceStub(
const cancelSignal = cancelController.signal as AbortSignal;
let cancelRequested = false;
const url = fetchParameters.url;
const headers = fetchParameters.headers;
const headers = new Headers(fetchParameters.headers);
for (const key of Object.keys(options)) {
headers[key] = options[key][0];
headers.set(key, options[key][0]);
}
const streamArrayParser = new StreamArrayParser(rpc);

authClient
auth
.getRequestHeaders()
.then(authHeader => {
const fetchRequest: RequestInit = {
headers: {
...authHeader,
...headers,
},
headers: gaxios.Gaxios.mergeHeaders(authHeader, headers) as {},
body: fetchParameters.body as string | Buffer | undefined,
method: fetchParameters.method,
signal: cancelSignal,
Expand Down
12 changes: 11 additions & 1 deletion gax/src/grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,17 @@ export class GrpcClient {
const client = await this.auth.getClient();
const credentials = grpc.credentials.combineChannelCredentials(
sslCreds,
grpc.credentials.createFromGoogleCredential(client),
grpc.credentials.createFromGoogleCredential({
// the `grpc` package does not support the `Headers` object yet
getRequestHeaders: async (url?: string | URL) => {
const headers = await client.getRequestHeaders(url);
const genericHeadersObject: Record<string, string> = {};

headers.forEach((value, key) => (genericHeadersObject[key] = value));

return genericHeadersObject;
},
}),
);
return credentials;
}
Expand Down
4 changes: 2 additions & 2 deletions gax/src/iamService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as gax from './gax';
import type {GrpcClient, ClientStubOptions} from './grpc';
import type {GrpcClient as FallbackGrpcClient} from './fallback';
import {createApiCall} from './createApiCall';
import {GoogleAuth, OAuth2Client} from 'google-auth-library';
import {GoogleAuth, AuthClient} from 'google-auth-library';
import {ProjectIdCallback} from 'google-auth-library/build/src/auth/googleauth';
import * as routingHeader from './routingHeader';
import * as gapicConfig from './iam_policy_service_client_config.json';
Expand All @@ -40,7 +40,7 @@ export class IamClient {
private _defaults: {[method: string]: gax.CallSettings};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _protos: any;
auth?: GoogleAuth | OAuth2Client;
auth?: GoogleAuth | AuthClient;
descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}};
innerApiCalls: {[name: string]: Function} = {};
iamPolicyStub?: Promise<{[name: string]: Function}>;
Expand Down
2 changes: 2 additions & 0 deletions gax/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import * as operationsClient from './operationsClient';
import * as routingHeader from './routingHeader';

export {GoogleAuth, GoogleAuthOptions} from 'google-auth-library';
export * as googleAuthLibrary from 'google-auth-library';

export {grpc};
export {CancellablePromise, OngoingCall} from './call';
export {createApiCall} from './createApiCall';
Expand Down
4 changes: 2 additions & 2 deletions gax/src/operationsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type {GoogleAuth, OAuth2Client} from 'google-auth-library';
import type {GoogleAuth, AuthClient} from 'google-auth-library';
import {ProjectIdCallback} from 'google-auth-library/build/src/auth/googleauth';
import type {ClientOptions, Callback} from './clientInterface';

Expand Down Expand Up @@ -62,7 +62,7 @@ export const ALL_SCOPES: string[] = [];
* @class
*/
export class OperationsClient {
auth?: GoogleAuth | OAuth2Client;
auth?: GoogleAuth | AuthClient;
innerApiCalls: {[name: string]: Function};
descriptor: {[method: string]: PageDescriptor};
operationsStub: Promise<{[method: string]: Function}>;
Expand Down
4 changes: 4 additions & 0 deletions gax/test/browser-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
"@types/node": "^20.5.0",
"@types/sinon": "^10.0.13",
"assert": "^2.1.0",
"browserify-zlib": "^0.2.0",
"core-js": "^3.40.0",
"crypto-browserify": "^3.12.1",
"google-gax": "./google-gax.tgz",
"https-browserify": "^1.0.0",
"is-docker": "^2.2.1",
Expand All @@ -39,6 +41,8 @@
"karma-sourcemap-loader": "^0.4.0",
"karma-webpack": "^5.0.1",
"mocha": "^10.0.0",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
"puppeteer": "^16.0.0",
"querystring-es3": "^0.2.1",
Expand Down
11 changes: 8 additions & 3 deletions gax/test/browser-test/test/test.endtoend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,17 @@ function sleep(timeout: number) {

describe('Run tests against gRPC server', async function () {
const authStub = {
getRequestHeaders: async () => {
return new Headers({
Authorization: 'Bearer zzzz',
});
},
getClient: async () => {
return {
getRequestHeaders: async () => {
return {
return new Headers({
Authorization: 'Bearer zzzz',
};
});
},
};
},
Expand Down Expand Up @@ -71,7 +76,7 @@ describe('Run tests against gRPC server', async function () {
}
if (retryCount === MAX_RETRIES) {
throw new Error(
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`
`gapic-showcase server did not respond after ${MAX_RETRIES} attempts, aborting end-to-end browser tests`,
);
}
});
Expand Down
Loading

0 comments on commit 43a8cb8

Please sign in to comment.