Skip to content

Commit 11532f2

Browse files
authored
Merge branch 'main' into expose-gaxios
2 parents 3397e97 + 9b69a31 commit 11532f2

18 files changed

+145
-56
lines changed

src/auth/authclient.ts

+18
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,22 @@ export abstract class AuthClient
279279
}
280280
return headers;
281281
}
282+
283+
/**
284+
* Retry config for Auth-related requests.
285+
*
286+
* @remarks
287+
*
288+
* This is not a part of the default {@link AuthClient.transporter transporter/gaxios}
289+
* config as some downstream APIs would prefer if customers explicitly enable retries,
290+
* such as GCS.
291+
*/
292+
protected static get RETRY_CONFIG(): GaxiosOptions {
293+
return {
294+
retry: true,
295+
retryConfig: {
296+
httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'],
297+
},
298+
};
299+
}
282300
}

src/auth/awsclient.ts

+5
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ export class AwsClient extends BaseExternalAccountClient {
192192
// Generate signed request to AWS STS GetCallerIdentity API.
193193
// Use the required regional endpoint. Otherwise, the request will fail.
194194
const options = await this.awsRequestSigner.getRequestOptions({
195+
...AwsClient.RETRY_CONFIG,
195196
url: this.regionalCredVerificationUrl.replace('{region}', this.region),
196197
method: 'POST',
197198
});
@@ -240,6 +241,7 @@ export class AwsClient extends BaseExternalAccountClient {
240241
*/
241242
private async getImdsV2SessionToken(): Promise<string> {
242243
const opts: GaxiosOptions = {
244+
...AwsClient.RETRY_CONFIG,
243245
url: this.imdsV2SessionTokenUrl,
244246
method: 'PUT',
245247
responseType: 'text',
@@ -266,6 +268,7 @@ export class AwsClient extends BaseExternalAccountClient {
266268
);
267269
}
268270
const opts: GaxiosOptions = {
271+
...AwsClient.RETRY_CONFIG,
269272
url: this.regionUrl,
270273
method: 'GET',
271274
responseType: 'text',
@@ -290,6 +293,7 @@ export class AwsClient extends BaseExternalAccountClient {
290293
);
291294
}
292295
const opts: GaxiosOptions = {
296+
...AwsClient.RETRY_CONFIG,
293297
url: this.securityCredentialsUrl,
294298
method: 'GET',
295299
responseType: 'text',
@@ -313,6 +317,7 @@ export class AwsClient extends BaseExternalAccountClient {
313317
): Promise<AwsSecurityCredentialsResponse> {
314318
const response =
315319
await this.transporter.request<AwsSecurityCredentialsResponse>({
320+
...AwsClient.RETRY_CONFIG,
316321
url: `${this.securityCredentialsUrl}/${roleName}`,
317322
responseType: 'json',
318323
headers: headers,

src/auth/baseexternalclient.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ export abstract class BaseExternalAccountClient extends AuthClient {
381381
// Preferable not to use request() to avoid retrial policies.
382382
const headers = await this.getRequestHeaders();
383383
const response = await this.transporter.request<ProjectInfo>({
384+
...BaseExternalAccountClient.RETRY_CONFIG,
384385
headers,
385386
url: `${this.cloudResourceManagerURL.toString()}${projectNumber}`,
386387
responseType: 'json',
@@ -395,12 +396,12 @@ export abstract class BaseExternalAccountClient extends AuthClient {
395396
* Authenticates the provided HTTP request, processes it and resolves with the
396397
* returned response.
397398
* @param opts The HTTP request options.
398-
* @param retry Whether the current attempt is a retry after a failed attempt.
399+
* @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure.
399400
* @return A promise that resolves with the successful response.
400401
*/
401402
protected async requestAsync<T>(
402403
opts: GaxiosOptions,
403-
retry = false
404+
reAuthRetried = false
404405
): Promise<GaxiosResponse<T>> {
405406
let response: GaxiosResponse;
406407
try {
@@ -426,7 +427,7 @@ export abstract class BaseExternalAccountClient extends AuthClient {
426427
const isReadableStream = res.config.data instanceof stream.Readable;
427428
const isAuthErr = statusCode === 401 || statusCode === 403;
428429
if (
429-
!retry &&
430+
!reAuthRetried &&
430431
isAuthErr &&
431432
!isReadableStream &&
432433
this.forceRefreshOnFailure
@@ -554,6 +555,7 @@ export abstract class BaseExternalAccountClient extends AuthClient {
554555
token: string
555556
): Promise<CredentialsWithResponse> {
556557
const opts: GaxiosOptions = {
558+
...BaseExternalAccountClient.RETRY_CONFIG,
557559
url: this.serviceAccountImpersonationUrl!,
558560
method: 'POST',
559561
headers: {

src/auth/downscopedclient.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,12 @@ export class DownscopedClient extends AuthClient {
250250
* Authenticates the provided HTTP request, processes it and resolves with the
251251
* returned response.
252252
* @param opts The HTTP request options.
253-
* @param retry Whether the current attempt is a retry after a failed attempt.
253+
* @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure
254254
* @return A promise that resolves with the successful response.
255255
*/
256256
protected async requestAsync<T>(
257257
opts: GaxiosOptions,
258-
retry = false
258+
reAuthRetried = false
259259
): Promise<GaxiosResponse<T>> {
260260
let response: GaxiosResponse;
261261
try {
@@ -281,7 +281,7 @@ export class DownscopedClient extends AuthClient {
281281
const isReadableStream = res.config.data instanceof stream.Readable;
282282
const isAuthErr = statusCode === 401 || statusCode === 403;
283283
if (
284-
!retry &&
284+
!reAuthRetried &&
285285
isAuthErr &&
286286
!isReadableStream &&
287287
this.forceRefreshOnFailure

src/auth/externalAccountAuthorizedUserClient.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class ExternalAccountAuthorizedUserHandler extends OAuthClientAuthHandler {
113113
};
114114

115115
const opts: GaxiosOptions = {
116+
...ExternalAccountAuthorizedUserHandler.RETRY_CONFIG,
116117
url: this.url,
117118
method: 'POST',
118119
headers,
@@ -248,12 +249,12 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient {
248249
* Authenticates the provided HTTP request, processes it and resolves with the
249250
* returned response.
250251
* @param opts The HTTP request options.
251-
* @param retry Whether the current attempt is a retry after a failed attempt.
252+
* @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure.
252253
* @return A promise that resolves with the successful response.
253254
*/
254255
protected async requestAsync<T>(
255256
opts: GaxiosOptions,
256-
retry = false
257+
reAuthRetried = false
257258
): Promise<GaxiosResponse<T>> {
258259
let response: GaxiosResponse;
259260
try {
@@ -279,7 +280,7 @@ export class ExternalAccountAuthorizedUserClient extends AuthClient {
279280
const isReadableStream = res.config.data instanceof stream.Readable;
280281
const isAuthErr = statusCode === 401 || statusCode === 403;
281282
if (
282-
!retry &&
283+
!reAuthRetried &&
283284
isAuthErr &&
284285
!isReadableStream &&
285286
this.forceRefreshOnFailure

src/auth/googleauth.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,10 @@ export class GoogleAuth<T extends AuthClient = JSONClient> {
11301130
data: {
11311131
payload: crypto.encodeBase64StringUtf8(data),
11321132
},
1133+
retry: true,
1134+
retryConfig: {
1135+
httpMethodsToRetry: ['POST'],
1136+
},
11331137
});
11341138

11351139
return res.data.signedBlob;

src/auth/identitypoolclient.ts

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ export class IdentityPoolClient extends BaseExternalAccountClient {
225225
headers?: {[key: string]: string}
226226
): Promise<string> {
227227
const opts: GaxiosOptions = {
228+
...IdentityPoolClient.RETRY_CONFIG,
228229
url,
229230
method: 'GET',
230231
headers,

src/auth/impersonated.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider {
143143
payload: Buffer.from(blobToSign).toString('base64'),
144144
};
145145
const res = await this.sourceClient.request<SignBlobResponse>({
146+
...Impersonated.RETRY_CONFIG,
146147
url: u,
147148
data: body,
148149
method: 'POST',
@@ -157,11 +158,8 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider {
157158

158159
/**
159160
* Refreshes the access token.
160-
* @param refreshToken Unused parameter
161161
*/
162-
protected async refreshToken(
163-
refreshToken?: string | null
164-
): Promise<GetTokenResponse> {
162+
protected async refreshToken(): Promise<GetTokenResponse> {
165163
try {
166164
await this.sourceClient.getAccessToken();
167165
const name = 'projects/-/serviceAccounts/' + this.targetPrincipal;
@@ -172,6 +170,7 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider {
172170
lifetime: this.lifetime + 's',
173171
};
174172
const res = await this.sourceClient.request<TokenResponse>({
173+
...Impersonated.RETRY_CONFIG,
175174
url: u,
176175
data: body,
177176
method: 'POST',
@@ -227,6 +226,7 @@ export class Impersonated extends OAuth2Client implements IdTokenProvider {
227226
includeEmail: options?.includeEmail ?? true,
228227
};
229228
const res = await this.sourceClient.request<FetchIdTokenResponse>({
229+
...Impersonated.RETRY_CONFIG,
230230
url: u,
231231
data: body,
232232
method: 'POST',

src/auth/oauth2client.ts

+20-5
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ export class OAuth2Client extends AuthClient {
669669
code_verifier: options.codeVerifier,
670670
};
671671
const res = await this.transporter.request<CredentialRequest>({
672+
...OAuth2Client.RETRY_CONFIG,
672673
method: 'POST',
673674
url,
674675
data: querystring.stringify(values),
@@ -733,6 +734,7 @@ export class OAuth2Client extends AuthClient {
733734
try {
734735
// request for new token
735736
res = await this.transporter.request<CredentialRequest>({
737+
...OAuth2Client.RETRY_CONFIG,
736738
method: 'POST',
737739
url,
738740
data: querystring.stringify(data),
@@ -956,6 +958,7 @@ export class OAuth2Client extends AuthClient {
956958
callback?: BodyResponseCallback<RevokeCredentialsResult>
957959
): GaxiosPromise<RevokeCredentialsResult> | void {
958960
const opts: GaxiosOptions = {
961+
...OAuth2Client.RETRY_CONFIG,
959962
url: this.getRevokeTokenURL(token).toString(),
960963
method: 'POST',
961964
};
@@ -1024,7 +1027,7 @@ export class OAuth2Client extends AuthClient {
10241027

10251028
protected async requestAsync<T>(
10261029
opts: GaxiosOptions,
1027-
retry = false
1030+
reAuthRetried = false
10281031
): Promise<GaxiosResponse<T>> {
10291032
let r2: GaxiosResponse;
10301033
try {
@@ -1078,11 +1081,16 @@ export class OAuth2Client extends AuthClient {
10781081
this.refreshHandler;
10791082
const isReadableStream = res.config.data instanceof stream.Readable;
10801083
const isAuthErr = statusCode === 401 || statusCode === 403;
1081-
if (!retry && isAuthErr && !isReadableStream && mayRequireRefresh) {
1084+
if (
1085+
!reAuthRetried &&
1086+
isAuthErr &&
1087+
!isReadableStream &&
1088+
mayRequireRefresh
1089+
) {
10821090
await this.refreshAccessTokenAsync();
10831091
return this.requestAsync<T>(opts, true);
10841092
} else if (
1085-
!retry &&
1093+
!reAuthRetried &&
10861094
isAuthErr &&
10871095
!isReadableStream &&
10881096
mayRequireRefreshWithNoRefreshToken
@@ -1157,6 +1165,7 @@ export class OAuth2Client extends AuthClient {
11571165
*/
11581166
async getTokenInfo(accessToken: string): Promise<TokenInfo> {
11591167
const {data} = await this.transporter.request<TokenInfoRequest>({
1168+
...OAuth2Client.RETRY_CONFIG,
11601169
method: 'POST',
11611170
headers: {
11621171
'Content-Type': 'application/x-www-form-urlencoded',
@@ -1222,7 +1231,10 @@ export class OAuth2Client extends AuthClient {
12221231
throw new Error(`Unsupported certificate format ${format}`);
12231232
}
12241233
try {
1225-
res = await this.transporter.request({url});
1234+
res = await this.transporter.request({
1235+
...OAuth2Client.RETRY_CONFIG,
1236+
url,
1237+
});
12261238
} catch (e) {
12271239
if (e instanceof Error) {
12281240
e.message = `Failed to retrieve verification certificates: ${e.message}`;
@@ -1290,7 +1302,10 @@ export class OAuth2Client extends AuthClient {
12901302
const url = this.endpoints.oauth2IapPublicKeyUrl.toString();
12911303

12921304
try {
1293-
res = await this.transporter.request({url});
1305+
res = await this.transporter.request({
1306+
...OAuth2Client.RETRY_CONFIG,
1307+
url,
1308+
});
12941309
} catch (e) {
12951310
if (e instanceof Error) {
12961311
e.message = `Failed to retrieve verification certificates: ${e.message}`;

src/auth/oauth2common.ts

+18
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,24 @@ export abstract class OAuthClientAuthHandler {
181181
}
182182
}
183183
}
184+
185+
/**
186+
* Retry config for Auth-related requests.
187+
*
188+
* @remarks
189+
*
190+
* This is not a part of the default {@link AuthClient.transporter transporter/gaxios}
191+
* config as some downstream APIs would prefer if customers explicitly enable retries,
192+
* such as GCS.
193+
*/
194+
protected static get RETRY_CONFIG(): GaxiosOptions {
195+
return {
196+
retry: true,
197+
retryConfig: {
198+
httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'],
199+
},
200+
};
201+
}
184202
}
185203

186204
/**

src/auth/stscredentials.ts

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ export class StsCredentials extends OAuthClientAuthHandler {
195195
Object.assign(headers, additionalHeaders || {});
196196

197197
const opts: GaxiosOptions = {
198+
...StsCredentials.RETRY_CONFIG,
198199
url: this.tokenExchangeEndpoint.toString(),
199200
method: 'POST',
200201
headers,

0 commit comments

Comments
 (0)