Skip to content

Commit af11518

Browse files
authored
refactor: refactor validate method to be used across authenticators/token mangers (#49)
* add types for token manager properties in authenticators * add return type for `getAuthenticatorFromEnvironment` * return `Error` object in `checkCredentials` rather than a `string` * Make `authenticator` optional in the base service options
1 parent 529c66e commit af11518

12 files changed

+81
-61
lines changed

auth/authenticators/authenticator.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616

1717
import { OutgoingHttpHeaders } from 'http';
18-
import { getMissingParams } from '../../lib/helper';
19-
import { checkCredentials } from '../utils/helpers'; // just using '../utils' here leads to a test failure. need to open an issue against typescript
2018
import { AuthenticateCallback, AuthenticateOptions, AuthenticatorInterface } from './authenticator-interface';
2119

2220
export class Authenticator implements AuthenticatorInterface {
@@ -36,20 +34,4 @@ export class Authenticator implements AuthenticatorInterface {
3634
public authenticate(options: AuthenticateOptions, callback: AuthenticateCallback): void {
3735
throw new Error('Should be implemented by subclass!');
3836
}
39-
40-
protected validate(options: any, requiredOptions: string[]): void {
41-
// check for required params
42-
const missingParamsError = getMissingParams(options, requiredOptions);
43-
if (missingParamsError) {
44-
throw missingParamsError;
45-
}
46-
47-
// check certain credentials for common user errors: username, password, and apikey
48-
// note: will only apply to certain authenticators
49-
const credsToCheck = ['username', 'password', 'apikey']
50-
const credentialProblems = checkCredentials(options, credsToCheck);
51-
if (credentialProblems) {
52-
throw new Error(credentialProblems);
53-
}
54-
}
5537
}

auth/authenticators/basic-authenticator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import extend = require('extend');
18-
import { computeBasicAuthHeader } from '../utils';
18+
import { computeBasicAuthHeader, validateInput } from '../utils';
1919
import { Authenticator } from './authenticator';
2020
import { AuthenticateCallback, AuthenticateOptions, AuthenticatorInterface } from './authenticator-interface';
2121

@@ -42,7 +42,7 @@ export class BasicAuthenticator extends Authenticator implements AuthenticatorIn
4242
constructor(options: Options) {
4343
super();
4444

45-
this.validate(options, this.requiredOptions);
45+
validateInput(options, this.requiredOptions);
4646

4747
this.username = options.username;
4848
this.password = options.password;

auth/authenticators/bearer-token-authenticator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
import extend = require('extend');
18+
import { validateInput } from '../utils';
1819
import { Authenticator } from './authenticator';
1920
import { AuthenticateCallback, AuthenticateOptions, AuthenticatorInterface } from './authenticator-interface';
2021

@@ -38,7 +39,7 @@ export class BearerTokenAuthenticator extends Authenticator implements Authentic
3839
constructor(options: Options) {
3940
super();
4041

41-
this.validate(options, this.requiredOptions);
42+
validateInput(options, this.requiredOptions);
4243

4344
this.bearerToken = options.bearerToken;
4445
}

auth/authenticators/cloud-pak-for-data-authenticator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import { OutgoingHttpHeaders } from 'http';
1818
import { Cp4dTokenManager } from '../token-managers';
19+
import { validateInput } from '../utils';
1920
import { BaseOptions, TokenRequestBasedAuthenticator } from './token-request-based-authenticator';
2021

2122
export interface Options extends BaseOptions {
@@ -26,6 +27,7 @@ export interface Options extends BaseOptions {
2627

2728
export class CloudPakForDataAuthenticator extends TokenRequestBasedAuthenticator {
2829
protected requiredOptions = ['username', 'password', 'url'];
30+
protected tokenManager: Cp4dTokenManager;
2931
private username: string;
3032
private password: string;
3133

@@ -41,7 +43,7 @@ export class CloudPakForDataAuthenticator extends TokenRequestBasedAuthenticator
4143
constructor(options: Options) {
4244
super(options);
4345

44-
this.validate(options, this.requiredOptions);
46+
validateInput(options, this.requiredOptions);
4547

4648
this.username = options.username;
4749
this.password = options.password;

auth/authenticators/iam-authenticator.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import { OutgoingHttpHeaders } from 'http';
1818
import { IamTokenManager } from '../token-managers';
19+
import { validateInput } from '../utils';
1920
import { BaseOptions, TokenRequestBasedAuthenticator } from './token-request-based-authenticator';
2021

2122
export interface Options extends BaseOptions {
@@ -26,6 +27,7 @@ export interface Options extends BaseOptions {
2627

2728
export class IamAuthenticator extends TokenRequestBasedAuthenticator {
2829
protected requiredOptions = ['apikey'];
30+
protected tokenManager: IamTokenManager;
2931
private apikey: string;
3032
private clientId: string;
3133
private clientSecret: string;
@@ -41,7 +43,7 @@ export class IamAuthenticator extends TokenRequestBasedAuthenticator {
4143
constructor(options: Options) {
4244
super(options);
4345

44-
this.validate(options, this.requiredOptions);
46+
validateInput(options, this.requiredOptions);
4547

4648
this.apikey = options.apikey;
4749
this.clientId = options.clientId;

auth/authenticators/token-request-based-authenticator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export type BaseOptions = {
2929
}
3030

3131
export class TokenRequestBasedAuthenticator extends Authenticator implements AuthenticatorInterface {
32-
protected tokenManager: any;
32+
protected tokenManager: JwtTokenManager;
3333
protected url: string;
3434
protected headers: OutgoingHttpHeaders;
3535
protected disableSslVerification: boolean;
@@ -66,11 +66,11 @@ export class TokenRequestBasedAuthenticator extends Authenticator implements Aut
6666
// if they try to pass in a non-boolean value,
6767
// use the "truthy-ness" of the value
6868
this.disableSslVerification = Boolean(value);
69-
this.tokenManager.disableSslVerification = this.disableSslVerification; // could use a setter here
69+
this.tokenManager.setDisableSslVerification(this.disableSslVerification);
7070
}
7171

7272
/**
73-
* Set a completely new set of headers. Should we have a method to add/remove a single header?
73+
* Set a completely new set of headers.
7474
*
7575
* @param {OutgoingHttpHeaders} headers - the new set of headers as an object
7676
* @returns {void}
@@ -81,7 +81,7 @@ export class TokenRequestBasedAuthenticator extends Authenticator implements Aut
8181
return;
8282
}
8383
this.headers = headers;
84-
this.tokenManager.headers = this.headers;
84+
this.tokenManager.setHeaders(this.headers);
8585
}
8686

8787
public authenticate(options: AuthenticateOptions, callback: AuthenticateCallback): void {

auth/token-managers/cp4d-token-manager.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,13 @@
1616

1717
import extend = require('extend');
1818
import { getMissingParams } from '../../lib/helper';
19-
import { computeBasicAuthHeader } from '../utils';
20-
import { JwtTokenManager } from './jwt-token-manager';
19+
import { computeBasicAuthHeader, validateInput } from '../utils';
20+
import { JwtTokenManager, TokenManagerOptions } from './jwt-token-manager';
2121

22-
// we should make these options extend the ones from the base class
23-
export type Options = {
22+
interface Options extends TokenManagerOptions {
2423
url: string;
25-
username?: string;
26-
password?: string;
27-
disableSslVerification?: boolean;
28-
requestWrapper?: any;
24+
username: string;
25+
password: string;
2926
}
3027

3128
// this interface is a representation of the response
@@ -44,6 +41,7 @@ export interface CpdTokenData {
4441
}
4542

4643
export class Cp4dTokenManager extends JwtTokenManager {
44+
protected requiredOptions = ['username', 'password', 'url'];
4745
private username: string;
4846
private password: string;
4947

@@ -65,12 +63,7 @@ export class Cp4dTokenManager extends JwtTokenManager {
6563

6664
this.tokenName = 'accessToken';
6765

68-
// check for required params
69-
const requiredOptions = ['username', 'password', 'url'];
70-
const missingParamsError = getMissingParams(options, requiredOptions);
71-
if (missingParamsError) {
72-
throw missingParamsError;
73-
}
66+
validateInput(options, this.requiredOptions);
7467

7568
const tokenApiPath = '/v1/preauth/validateAuth';
7669

auth/token-managers/iam-token-manager.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import extend = require('extend');
1818
import { OutgoingHttpHeaders } from 'http';
1919
import { getMissingParams } from '../../lib/helper';
20-
import { computeBasicAuthHeader } from '../utils';
21-
import { JwtTokenManager } from './jwt-token-manager';
20+
import { computeBasicAuthHeader, validateInput } from '../utils';
21+
import { JwtTokenManager, TokenManagerOptions } from './jwt-token-manager';
2222

2323
/**
2424
* Check for only one of two elements being defined.
@@ -36,13 +36,10 @@ function onlyOne(a: any, b: any): boolean {
3636

3737
const CLIENT_ID_SECRET_WARNING = 'Warning: Client ID and Secret must BOTH be given, or the header will not be included.';
3838

39-
export type Options = {
39+
interface Options extends TokenManagerOptions {
4040
apikey: string;
41-
url?: string;
4241
clientId?: string;
4342
clientSecret?: string;
44-
disableSslVerification?: boolean;
45-
headers?: OutgoingHttpHeaders;
4643
}
4744

4845
// this interface is a representation of the response
@@ -57,6 +54,7 @@ export interface IamTokenData {
5754
}
5855

5956
export class IamTokenManager extends JwtTokenManager {
57+
protected requiredOptions = ['apikey'];
6058
private apikey: string;
6159
private clientId: string;
6260
private clientSecret: string;
@@ -75,12 +73,7 @@ export class IamTokenManager extends JwtTokenManager {
7573
constructor(options: Options) {
7674
super(options);
7775

78-
// check for required params
79-
const requiredOptions = ['apikey'];
80-
const missingParamsError = getMissingParams(options, requiredOptions);
81-
if (missingParamsError) {
82-
throw missingParamsError;
83-
}
76+
validateInput(options, this.requiredOptions);
8477

8578
this.apikey = options.apikey;
8679

auth/token-managers/jwt-token-manager.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ function getCurrentTime(): number {
2323
return Math.floor(Date.now() / 1000);
2424
}
2525

26-
export type Options = {
26+
export type TokenManagerOptions = {
2727
url?: string;
28+
headers?: OutgoingHttpHeaders;
29+
disableSslVerification?: boolean;
2830
/** Allow additional request config parameters */
2931
[propName: string]: any;
3032
}
@@ -48,9 +50,9 @@ export class JwtTokenManager {
4850
* @param {String} [options.accessToken] - user-managed access token
4951
* @constructor
5052
*/
51-
constructor(options: Options) {
53+
constructor(options: TokenManagerOptions) {
5254
// all parameters are optional
53-
options = options || {} as Options;
55+
options = options || {} as TokenManagerOptions;
5456

5557
this.tokenInfo = {};
5658
this.tokenName = 'access_token';
@@ -98,6 +100,32 @@ export class JwtTokenManager {
98100
}
99101
}
100102

103+
/**
104+
* Setter for the disableSslVerification property.
105+
*
106+
* @param {boolean} value - the new value for the disableSslVerification property
107+
* @returns {void}
108+
*/
109+
public setDisableSslVerification(value: boolean): void {
110+
// if they try to pass in a non-boolean value,
111+
// use the "truthy-ness" of the value
112+
this.disableSslVerification = Boolean(value);
113+
}
114+
115+
/**
116+
* Set a completely new set of headers.
117+
*
118+
* @param {OutgoingHttpHeaders} headers - the new set of headers as an object
119+
* @returns {void}
120+
*/
121+
public setHeaders(headers: OutgoingHttpHeaders): void {
122+
if (typeof headers !== 'object') {
123+
// do nothing, for now
124+
return;
125+
}
126+
this.headers = headers;
127+
}
128+
101129
/**
102130
* Request a JWT using an API key.
103131
*

auth/utils/get-authenticator-from-environment.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import camelcase = require('camelcase');
1818
import extend = require('extend');
1919

2020
import {
21+
Authenticator,
2122
BasicAuthenticator,
2223
BearerTokenAuthenticator,
2324
CloudPakForDataAuthenticator,
@@ -27,7 +28,7 @@ import {
2728

2829
import { readExternalSources } from './read-external-sources';
2930

30-
export function getAuthenticatorFromEnvironment(serviceName: string) {
31+
export function getAuthenticatorFromEnvironment(serviceName: string): Authenticator {
3132
if (!serviceName) {
3233
throw new Error('Service name is required.');
3334
}

0 commit comments

Comments
 (0)