Skip to content

Commit

Permalink
feat: add support for retrieving refresh tokens from iam-based authen…
Browse files Browse the repository at this point in the history
…ticators (#173)

This commit moves the refresh token retrieval functionality to the IAM "based"
token manager and authenticator, so that any subclasses can take advantage of.
With this, calling 'getRefreshToken' is now support for both the IAM and
Container authenticators.
  • Loading branch information
dpopp07 authored Oct 20, 2021
1 parent 313fdca commit e7f11fc
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 47 deletions.
16 changes: 8 additions & 8 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "package-lock.json|^.secrets.baseline$",
"lines": null
},
"generated_at": "2021-10-18T13:39:19Z",
"generated_at": "2021-10-20T21:45:37Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -224,23 +224,23 @@
"hashed_secret": "f84f793e0af9ade37c8b927bc5091e98f35bf821",
"is_secret": false,
"is_verified": false,
"line_number": 81,
"line_number": 83,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "45c43fe97e3a06ab078b0eeff6fbe622cc417a25",
"is_secret": false,
"is_verified": false,
"line_number": 118,
"line_number": 120,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "99833a8b234b57b886a9aef1dba187fdd7ceece8",
"is_secret": false,
"is_verified": false,
"line_number": 120,
"line_number": 122,
"type": "Secret Keyword",
"verified_result": null
}
Expand All @@ -250,23 +250,23 @@
"hashed_secret": "8f4bfc22c4fd7cb884f94ec175ff4a3284a174a1",
"is_secret": false,
"is_verified": false,
"line_number": 60,
"line_number": 58,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "0358c67856fb6a21c4767daf02fcb8fe4dc0a318",
"is_secret": false,
"is_verified": false,
"line_number": 63,
"line_number": 61,
"type": "Secret Keyword",
"verified_result": null
},
{
"hashed_secret": "dbb19b8ae3b78f908e1467721fe4c9f0b0529d9b",
"is_secret": false,
"is_verified": false,
"line_number": 64,
"line_number": 62,
"type": "Secret Keyword",
"verified_result": null
}
Expand Down Expand Up @@ -524,7 +524,7 @@
}
]
},
"version": "0.13.1+ibm.46.dss",
"version": "0.13.1+ibm.40.dss",
"word_list": {
"file": null,
"hash": null
Expand Down
10 changes: 0 additions & 10 deletions auth/authenticators/iam-authenticator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,6 @@ export class IamAuthenticator extends IamRequestBasedAuthenticator {
this.tokenManager = new IamTokenManager(options);
}

/**
* Return the most recently stored refresh token.
*
* @public
* @returns {string}
*/
public getRefreshToken(): string {
return this.tokenManager.getRefreshToken();
}

/**
* Returns the authenticator's type ('iam').
*
Expand Down
10 changes: 10 additions & 0 deletions auth/authenticators/iam-request-based-authenticator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,14 @@ export class IamRequestBasedAuthenticator extends TokenRequestBasedAuthenticator
// update properties in token manager
this.tokenManager.setScope(scope);
}

/**
* Return the most recently stored refresh token.
*
* @public
* @returns {string}
*/
public getRefreshToken(): string {
return this.tokenManager.getRefreshToken();
}
}
29 changes: 29 additions & 0 deletions auth/token-managers/iam-request-based-token-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export class IamRequestBasedTokenManager extends JwtTokenManager {

private scope: string;

protected refreshToken: string;

protected formData: any;

/**
Expand Down Expand Up @@ -124,6 +126,33 @@ export class IamRequestBasedTokenManager extends JwtTokenManager {
}
}

/**
* Return the most recently stored refresh token.
*
* @public
* @returns {string}
*/
public getRefreshToken(): string {
return this.refreshToken;
}

/**
* Extend this method from the parent class to extract the refresh token from
* the request and save it.
*
* @param tokenResponse - Response object from JWT service request
* @protected
* @returns {void}
*/
protected saveTokenInfo(tokenResponse): void {
super.saveTokenInfo(tokenResponse);

const responseBody = tokenResponse.result || {};
if (responseBody.refresh_token) {
this.refreshToken = responseBody.refresh_token;
}
}

/**
* Request an IAM token using an API key.
*
Expand Down
29 changes: 0 additions & 29 deletions auth/token-managers/iam-token-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ interface Options extends IamRequestOptions {
export class IamTokenManager extends IamRequestBasedTokenManager {
protected requiredOptions = ['apikey'];

protected refreshToken: string;

private apikey: string;

/**
Expand Down Expand Up @@ -64,31 +62,4 @@ export class IamTokenManager extends IamRequestBasedTokenManager {
this.formData.grant_type = 'urn:ibm:params:oauth:grant-type:apikey';
this.formData.response_type = 'cloud_iam';
}

/**
* Return the most recently stored refresh token.
*
* @public
* @returns {string}
*/
public getRefreshToken(): string {
return this.refreshToken;
}

/**
* Extend this method from the parent class to extract the refresh token from
* the request and save it.
*
* @param tokenResponse - Response object from JWT service request
* @protected
* @returns {void}
*/
protected saveTokenInfo(tokenResponse): void {
super.saveTokenInfo(tokenResponse);

const responseBody = tokenResponse.result || {};
if (responseBody.refresh_token) {
this.refreshToken = responseBody.refresh_token;
}
}
}
8 changes: 8 additions & 0 deletions test/unit/container-authenticator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,12 @@ describe('Container Authenticator', () => {
// verify that the original options are kept intact
expect(options.headers['X-Some-Header']).toBe('user-supplied header');
});

it('should return the refresh token stored in the token manager', () => {
const token = 'some-token';
const authenticator = new ContainerAuthenticator({ iamProfileName: config.iamProfileName });
expect(authenticator.tokenManager.refreshToken).toBeUndefined();
authenticator.tokenManager.refreshToken = token;
expect(authenticator.getRefreshToken()).toEqual(token);
});
});
8 changes: 8 additions & 0 deletions test/unit/iam-authenticator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,12 @@ describe('IAM Authenticator', () => {
// also, verify that the underlying token manager has been updated
expect(authenticator.tokenManager.scope).toEqual(newScope);
});

it('should return the refresh token stored in the token manager', () => {
const token = 'some-token';
const authenticator = new IamAuthenticator(config);
expect(authenticator.tokenManager.refreshToken).toBeUndefined();
authenticator.tokenManager.refreshToken = token;
expect(authenticator.getRefreshToken()).toEqual(token);
});
});
10 changes: 10 additions & 0 deletions test/unit/iam-request-based-authenticator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,14 @@ describe('IAM Request Based Authenticator', () => {
expect(authenticator.tokenManager.clientSecret).toEqual(CLIENT_SECRET);
});
});

describe('getRefreshToken', () => {
it('should return the refresh token stored in the token manager', () => {
const token = 'some-token';
const authenticator = new IamRequestBasedAuthenticator();
expect(authenticator.tokenManager.refreshToken).toBeUndefined();
authenticator.tokenManager.refreshToken = token;
expect(authenticator.getRefreshToken()).toEqual(token);
});
});
});
10 changes: 10 additions & 0 deletions test/unit/iam-request-based-token-manager.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ describe('IAM Request Based Token Manager', () => {
});
});

describe('getRefreshToken', () => {
it('should return the stored refresh token with the getter', () => {
const token = 'some-token';
const instance = new IamRequestBasedTokenManager();
expect(instance.refreshToken).toBeUndefined();
instance.refreshToken = token;
expect(instance.getRefreshToken()).toEqual(token);
});
});

describe('request token', () => {
it('should set required headers by default', async () => {
const instance = new IamRequestBasedTokenManager();
Expand Down

0 comments on commit e7f11fc

Please sign in to comment.