diff --git a/package.json b/package.json index a3dadaf9..e6df7999 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "jws": "^3.1.5", "lodash.isstring": "^4.0.1", "lru-cache": "^4.1.3", - "retry-axios": "^0.3.2", "semver": "^5.5.0" }, "devDependencies": { diff --git a/src/auth/computeclient.ts b/src/auth/computeclient.ts index 030504d1..6b9459b5 100644 --- a/src/auth/computeclient.ts +++ b/src/auth/computeclient.ts @@ -14,9 +14,9 @@ * limitations under the License. */ -import axios, {AxiosError, AxiosPromise, AxiosRequestConfig, AxiosResponse} from 'axios'; +import {AxiosError, AxiosPromise, AxiosRequestConfig, AxiosResponse} from 'axios'; import * as gcpMetadata from 'gcp-metadata'; -import * as rax from 'retry-axios'; + import {CredentialRequest, Credentials} from './credentials'; import {GetTokenResponse, OAuth2Client, RefreshOptions} from './oauth2client'; @@ -28,10 +28,6 @@ export interface ComputeOptions extends RefreshOptions { serviceAccountEmail?: string; } -// Create a scoped axios instance that will retry 3 times by default -const ax = axios.create(); -rax.attach(ax); - export class Compute extends OAuth2Client { private serviceAccountEmail: string; @@ -67,20 +63,10 @@ export class Compute extends OAuth2Client { */ protected async refreshTokenNoCache(refreshToken?: string| null): Promise { - const url = this.tokenUrl || - `${gcpMetadata.HOST_ADDRESS}${ - gcpMetadata.BASE_PATH}/instance/service-accounts/${ - this.serviceAccountEmail}/token`; + const tokenPath = `service-accounts/${this.serviceAccountEmail}/token`; let res: AxiosResponse; - // request for new token try { - // TODO: In 2.0, we should remove the ability to configure the tokenUrl, - // and switch this over to use the gcp-metadata package instead. - res = await ax.request({ - url, - headers: {[gcpMetadata.HEADER_NAME]: 'Google'}, - raxConfig: {noResponseRetries: 3, retry: 3, instance: ax} - } as rax.RaxConfig); + res = await gcpMetadata.instance(tokenPath); } catch (e) { e.message = 'Could not refresh access token.'; throw e; @@ -95,7 +81,6 @@ export class Compute extends OAuth2Client { return {tokens, res}; } - protected requestAsync(opts: AxiosRequestConfig, retry = false): AxiosPromise { return super.requestAsync(opts, retry).catch(e => { diff --git a/src/auth/oauth2client.ts b/src/auth/oauth2client.ts index be0413aa..033f8d57 100644 --- a/src/auth/oauth2client.ts +++ b/src/auth/oauth2client.ts @@ -236,11 +236,6 @@ export interface GenerateAuthUrlOpts { code_challenge?: string; } -export interface AuthClientOpts { - authBaseUrl?: string; - tokenUrl?: string; -} - export interface GetTokenCallback { (err: AxiosError|null, token?: Credentials|null, res?: AxiosResponse|null): void; @@ -306,8 +301,6 @@ export interface OAuth2ClientOptions extends RefreshOptions { clientId?: string; clientSecret?: string; redirectUri?: string; - authBaseUrl?: string; - tokenUrl?: string; } export interface RefreshOptions { @@ -322,8 +315,6 @@ export class OAuth2Client extends AuthClient { private certificateCache: {}|null|undefined = null; private certificateExpiry: Date|null = null; protected refreshTokenPromises = new Map>(); - protected authBaseUrl?: string; - protected tokenUrl?: string; // TODO: refactor tests to make this private _clientId?: string; @@ -348,27 +339,17 @@ export class OAuth2Client extends AuthClient { * @constructor */ constructor(options?: OAuth2ClientOptions); - constructor( - clientId?: string, clientSecret?: string, redirectUri?: string, - opts?: AuthClientOpts); + constructor(clientId?: string, clientSecret?: string, redirectUri?: string); constructor( optionsOrClientId?: string|OAuth2ClientOptions, clientSecret?: string, - redirectUri?: string, authClientOpts: AuthClientOpts = {}) { + redirectUri?: string) { super(); const opts = (optionsOrClientId && typeof optionsOrClientId === 'object') ? optionsOrClientId : - { - clientId: optionsOrClientId, - clientSecret, - redirectUri, - tokenUrl: authClientOpts.tokenUrl, - authBaseUrl: authClientOpts.authBaseUrl - }; + {clientId: optionsOrClientId, clientSecret, redirectUri}; this._clientId = opts.clientId; this._clientSecret = opts.clientSecret; this.redirectUri = opts.redirectUri; - this.authBaseUrl = opts.authBaseUrl; - this.tokenUrl = opts.tokenUrl; this.eagerRefreshThresholdMillis = opts.eagerRefreshThresholdMillis || 5 * 60 * 1000; } @@ -433,9 +414,7 @@ export class OAuth2Client extends AuthClient { if (opts.scope instanceof Array) { opts.scope = opts.scope.join(' '); } - const rootUrl = - this.authBaseUrl || OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_; - + const rootUrl = OAuth2Client.GOOGLE_OAUTH2_AUTH_BASE_URL_; return rootUrl + '?' + querystring.stringify(opts); } @@ -488,7 +467,7 @@ export class OAuth2Client extends AuthClient { private async getTokenAsync(options: GetTokenOptions): Promise { - const url = this.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; + const url = OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; const values = { code: options.code, client_id: options.client_id || this._clientId, @@ -544,7 +523,7 @@ export class OAuth2Client extends AuthClient { protected async refreshTokenNoCache(refreshToken?: string| null): Promise { - const url = this.tokenUrl || OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; + const url = OAuth2Client.GOOGLE_OAUTH2_TOKEN_URL_; const data = { refresh_token: refreshToken, client_id: this._clientId, diff --git a/test/test.compute.ts b/test/test.compute.ts index 7e2dec7b..053be019 100644 --- a/test/test.compute.ts +++ b/test/test.compute.ts @@ -16,8 +16,9 @@ import assert from 'assert'; import {AxiosError} from 'axios'; -import {BASE_PATH, HOST_ADDRESS} from 'gcp-metadata'; +import {BASE_PATH, HEADERS, HOST_ADDRESS} from 'gcp-metadata'; import nock from 'nock'; + import {Compute} from '../src'; nock.disableNetConnect(); @@ -26,10 +27,9 @@ const url = 'http://example.com'; const tokenPath = `${BASE_PATH}/instance/service-accounts/default/token`; function mockToken() { - return nock(HOST_ADDRESS).get(tokenPath).reply(200, { - access_token: 'abc123', - expires_in: 10000 - }); + return nock(HOST_ADDRESS) + .get(tokenPath, undefined, {reqheaders: HEADERS}) + .reply(200, {access_token: 'abc123', expires_in: 10000}, HEADERS); } function mockExample() { @@ -113,42 +113,6 @@ it('should not refresh if access token has not expired', async () => { scope.done(); }); -it('should retry calls to the metadata service if there are network errors', - async () => { - const scopes = [ - nock(HOST_ADDRESS) - .get(tokenPath) - .times(2) - .replyWithError({code: 'ENOTFOUND'}) - .get(tokenPath) - .reply(200, {access_token: 'abc123', expires_in: 10000}), - mockExample() - ]; - compute.credentials.access_token = 'initial-access-token'; - compute.credentials.expiry_date = (new Date()).getTime() - 10000; - await compute.request({url}); - assert.equal(compute.credentials.access_token, 'abc123'); - scopes.forEach(s => s.done()); - }); - -it('should retry calls to the metadata service if it returns non-200 errors', - async () => { - const scopes = [ - nock(HOST_ADDRESS) - .get(tokenPath) - .times(2) - .reply(500) - .get(tokenPath) - .reply(200, {access_token: 'abc123', expires_in: 10000}), - mockExample() - ]; - compute.credentials.access_token = 'initial-access-token'; - compute.credentials.expiry_date = (new Date()).getTime() - 10000; - await compute.request({url}); - assert.equal(compute.credentials.access_token, 'abc123'); - scopes.forEach(s => s.done()); - }); - it('should return false for createScopedRequired', () => { assert.equal(false, compute.createScopedRequired()); }); @@ -265,7 +229,7 @@ it('should accept a custom service account', async () => { nock(HOST_ADDRESS) .get(`${BASE_PATH}/instance/service-accounts/${ serviceAccountEmail}/token`) - .reply(200, {access_token: 'abc123', expires_in: 10000}) + .reply(200, {access_token: 'abc123', expires_in: 10000}, HEADERS) ]; await compute.request({url}); scopes.forEach(s => s.done()); diff --git a/test/test.googleauth.ts b/test/test.googleauth.ts index 56022fc1..ea474571 100644 --- a/test/test.googleauth.ts +++ b/test/test.googleauth.ts @@ -18,7 +18,7 @@ import assert from 'assert'; import child_process from 'child_process'; import crypto from 'crypto'; import * as fs from 'fs'; -import {BASE_PATH, HEADER_NAME, HOST_ADDRESS} from 'gcp-metadata'; +import {BASE_PATH, HEADERS, HOST_ADDRESS} from 'gcp-metadata'; import nock from 'nock'; import path from 'path'; import sinon from 'sinon'; @@ -64,9 +64,7 @@ afterEach(() => { }); function nockIsGCE() { - return nock(host).get(instancePath).reply(200, {}, { - 'metadata-flavor': 'Google' - }); + return nock(host).get(instancePath).reply(200, {}, HEADERS); } function nockNotGCE() { @@ -88,7 +86,7 @@ function nock404GCE() { function createGetProjectIdNock(projectId: string) { return nock(host) .get(`${BASE_PATH}/project/project-id`) - .reply(200, projectId, {'metadata-flavor': 'Google'}); + .reply(200, projectId, HEADERS); } // Creates a standard JSON auth object for testing. @@ -117,10 +115,10 @@ function mockGCE() { blockGoogleApplicationCredentialEnvironmentVariable(); const auth = new GoogleAuth(); auth._fileExists = () => false; - const scope2 = nock(HOST_ADDRESS).get(tokenPath).reply(200, { - access_token: 'abc123', - expires_in: 10000 - }); + const scope2 = + nock(HOST_ADDRESS) + .get(tokenPath) + .reply(200, {access_token: 'abc123', expires_in: 10000}, HEADERS); return {auth, scopes: [scope1, scope2]}; } @@ -1139,9 +1137,7 @@ it('getCredentials should get metadata from the server when running on GCE', } }; nock.cleanAll(); - const scope = nock(host).get(svcAccountPath).reply(200, response, { - 'Metadata-Flavor': 'Google' - }); + const scope = nock(host).get(svcAccountPath).reply(200, response, HEADERS); const body = await auth.getCredentials(); assert(body); assert.equal( @@ -1306,7 +1302,7 @@ it('should get the current environment if GKE', async () => { const {auth, scopes} = mockGCE(); const scope = nock(host) .get(`${instancePath}/attributes/cluster-name`) - .reply(200, {}, {[HEADER_NAME.toLowerCase()]: 'Google'}); + .reply(200, {}, HEADERS); const env = await auth.getEnv(); assert.equal(env, envDetect.GCPEnv.KUBERNETES_ENGINE); scope.done(); @@ -1364,9 +1360,7 @@ it('sign should hit the IAM endpoint if no private_key is available', nock(iamUri).post(iamPath).reply(200, {signature}), nock(host) .get(svcAccountPath) - .reply( - 200, {default: {email, private_key: privateKey}}, - {'Metadata-Flavor': 'Google'})); + .reply(200, {default: {email, private_key: privateKey}}, HEADERS)); const value = await auth.sign(data); scopes.forEach(x => x.done()); assert.equal(value, signature); diff --git a/test/test.oauth2.ts b/test/test.oauth2.ts index 109f6918..8137b575 100644 --- a/test/test.oauth2.ts +++ b/test/test.oauth2.ts @@ -1065,21 +1065,6 @@ it('should return expiry_date', done => { }); }); -it('should accept custom authBaseUrl and tokenUrl', async () => { - const authBaseUrl = 'http://authBaseUrl.com'; - const tokenUrl = 'http://tokenUrl.com'; - const client = new OAuth2Client( - CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, {authBaseUrl, tokenUrl}); - const authUrl = client.generateAuthUrl(); - const authUrlParts = url.parse(authUrl); - assert.equal( - authBaseUrl.toLowerCase(), - authUrlParts.protocol + '//' + authUrlParts.hostname); - const scope = nock(tokenUrl).post('/').reply(200, {}); - const result = await client.getToken('12345'); - scope.done(); -}); - it('should obtain token info', async () => { const accessToken = 'abc'; const tokenInfo = {