-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add new token manager for ICP4D (#26)
feat: add new token manager for ICP4D
- Loading branch information
Showing
19 changed files
with
1,284 additions
and
473 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,6 @@ node_modules/ | |
**/*v*.js | ||
!test/**/*.js | ||
lib/*.js | ||
auth/*.js | ||
index.js | ||
scripts/typedoc/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ doc/ | |
.env | ||
.eslintcache | ||
lib/*.js | ||
auth/*.js | ||
iam-token-manager/*.js | ||
index.js | ||
.nyc_output | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/** | ||
* Copyright 2019 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import extend = require('extend'); | ||
import { JwtTokenManagerV1 } from './jwt-token-manager-v1'; | ||
import { computeBasicAuthHeader } from './utils'; | ||
|
||
/** | ||
* Check for only one of two elements being defined. | ||
* Returns true if a is defined and b is undefined, | ||
* or vice versa. Returns false if both are defined | ||
* or both are undefined. | ||
* | ||
* @param {any} a - The first object | ||
* @param {any} b - The second object | ||
* @returns {boolean} | ||
*/ | ||
function onlyOne(a: any, b: any): boolean { | ||
return Boolean((a && !b) || (b && !a)); | ||
} | ||
|
||
const CLIENT_ID_SECRET_WARNING = 'Warning: Client ID and Secret must BOTH be given, or the defaults will be used.'; | ||
|
||
export type Options = { | ||
url?: string; | ||
iamUrl?: string; | ||
iamApikey?: string; | ||
accessToken?: string; | ||
iamAccessToken?: string; | ||
iamClientId?: string; | ||
iamClientSecret?: string; | ||
} | ||
|
||
// this interface is a representation of the response | ||
// object from the IAM service, hence the snake_case | ||
// parameter names | ||
export interface IamTokenData { | ||
access_token: string; | ||
refresh_token: string; | ||
token_type: string; | ||
expires_in: number; | ||
expiration: number; | ||
} | ||
|
||
export class IamTokenManagerV1 extends JwtTokenManagerV1 { | ||
private iamApikey: string; | ||
private iamClientId: string; | ||
private iamClientSecret: string; | ||
|
||
/** | ||
* IAM Token Manager Service | ||
* | ||
* Retreives and stores IAM access tokens. | ||
* | ||
* @param {Object} options | ||
* @param {String} options.iamApikey | ||
* @param {String} options.iamAccessToken | ||
* @param {String} options.iamUrl - url of the iam api to retrieve tokens from | ||
* @constructor | ||
*/ | ||
constructor(options: Options) { | ||
super(options); | ||
|
||
this.url = this.url || options.iamUrl || 'https://iam.cloud.ibm.com/identity/token'; | ||
|
||
if (options.iamApikey) { | ||
this.iamApikey = options.iamApikey; | ||
} | ||
if (options.iamAccessToken) { | ||
this.userAccessToken = options.iamAccessToken; | ||
} | ||
if (options.iamClientId) { | ||
this.iamClientId = options.iamClientId; | ||
} | ||
if (options.iamClientSecret) { | ||
this.iamClientSecret = options.iamClientSecret; | ||
} | ||
if (onlyOne(options.iamClientId, options.iamClientSecret)) { | ||
// tslint:disable-next-line | ||
console.log(CLIENT_ID_SECRET_WARNING); | ||
} | ||
} | ||
|
||
/** | ||
* Set the IAM 'client_id' and 'client_secret' values. | ||
* These values are used to compute the Authorization header used | ||
* when retrieving the IAM access token. | ||
* If these values are not set, then a default Authorization header | ||
* will be used when interacting with the IAM token server. | ||
* | ||
* @param {string} iamClientId - The client id | ||
* @param {string} iamClientSecret - The client secret | ||
* @returns {void} | ||
*/ | ||
public setIamAuthorizationInfo(iamClientId: string, iamClientSecret: string): void { | ||
this.iamClientId = iamClientId; | ||
this.iamClientSecret = iamClientSecret; | ||
if (onlyOne(iamClientId, iamClientSecret)) { | ||
// tslint:disable-next-line | ||
console.log(CLIENT_ID_SECRET_WARNING); | ||
} | ||
} | ||
|
||
/** | ||
* Callback for handling response. | ||
* | ||
* @callback requestTokenCallback | ||
* @param {Error} An error if there is one, null otherwise | ||
* @param {Object} The response if request is successful, null otherwise | ||
*/ | ||
/** | ||
* Request an IAM token using an API key. | ||
* | ||
* @param {requestTokenCallback} callback - The callback that handles the response. | ||
* @returns {void} | ||
*/ | ||
protected requestToken(callback: Function): void { | ||
// Use bx:bx as default auth header creds. | ||
let clientId = 'bx'; | ||
let clientSecret = 'bx'; | ||
|
||
// If both the clientId and secret were specified by the user, then use them. | ||
if (this.iamClientId && this.iamClientSecret) { | ||
clientId = this.iamClientId; | ||
clientSecret = this.iamClientSecret; | ||
} | ||
|
||
const parameters = { | ||
options: { | ||
url: this.url, | ||
method: 'POST', | ||
headers: { | ||
'Content-type': 'application/x-www-form-urlencoded', | ||
Authorization: computeBasicAuthHeader(clientId, clientSecret), | ||
}, | ||
form: { | ||
grant_type: 'urn:ibm:params:oauth:grant-type:apikey', | ||
apikey: this.iamApikey, | ||
response_type: 'cloud_iam' | ||
}, | ||
} | ||
}; | ||
this.requestWrapperInstance.sendRequest(parameters, callback); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/** | ||
* Copyright 2019 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import extend = require('extend'); | ||
import { JwtTokenManagerV1 } from './jwt-token-manager-v1'; | ||
import { computeBasicAuthHeader } from './utils'; | ||
|
||
export type Options = { | ||
url: string; | ||
accessToken?: string; | ||
username?: string; | ||
password?: string; | ||
disableSslVerification?: boolean; | ||
} | ||
|
||
// this interface is a representation of the response | ||
// object from the ICP4D authentication service | ||
export interface IcpTokenData { | ||
username: string; | ||
role: string; | ||
permissions: string[]; | ||
sub: string; | ||
iss: string; | ||
aud: string; | ||
uid: string; | ||
_messageCode_: string; | ||
message: string; | ||
accessToken: string; | ||
} | ||
|
||
export class Icp4dTokenManagerV1 extends JwtTokenManagerV1 { | ||
private username: string; | ||
private password: string; | ||
|
||
/** | ||
* ICP Token Manager Service | ||
* | ||
* Retreives and stores ICP access tokens. | ||
* | ||
* @param {Object} options | ||
* @param {String} options.username | ||
* @param {String} options.password | ||
* @param {String} options.accessToken - user-managed access token | ||
* @param {String} options.url - URL for the ICP4D cluster | ||
* @param {Boolean} options.disableSslVerification - disable SSL verification for token request | ||
* @constructor | ||
*/ | ||
constructor(options: Options) { | ||
super(options); | ||
|
||
this.tokenName = 'accessToken'; | ||
|
||
if (this.url) { | ||
this.url = this.url + '/v1/preauth/validateAuth'; | ||
} else if (!this.userAccessToken) { | ||
// url is not needed if the user specifies their own access token | ||
throw new Error('`url` is a required parameter for Icp4dTokenManagerV1'); | ||
} | ||
|
||
if (options.username) { | ||
this.username = options.username; | ||
} | ||
if (options.password) { | ||
this.password = options.password; | ||
} | ||
// username and password are required too, unless there's access token | ||
this.rejectUnauthorized = !options.disableSslVerification; | ||
} | ||
|
||
/** | ||
* Callback for handling response. | ||
* | ||
* @callback requestTokenCallback | ||
* @param {Error} An error if there is one, null otherwise | ||
* @param {Object} The response if request is successful, null otherwise | ||
*/ | ||
/** | ||
* Request an ICP token using a basic auth header. | ||
* | ||
* @param {requestTokenCallback} callback - The callback that handles the response. | ||
* @returns {void} | ||
*/ | ||
protected requestToken(callback: Function): void { | ||
const parameters = { | ||
options: { | ||
url: this.url, | ||
method: 'GET', | ||
headers: { | ||
Authorization: computeBasicAuthHeader(this.username, this.password), | ||
}, | ||
rejectUnauthorized: this.rejectUnauthorized, | ||
} | ||
}; | ||
this.requestWrapperInstance.sendRequest(parameters, callback); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Copyright 2019 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
export { IamTokenManagerV1 } from './iam-token-manager-v1'; | ||
export { Icp4dTokenManagerV1 } from './icp4d-token-manager-v1'; | ||
export { JwtTokenManagerV1 } from './jwt-token-manager-v1'; | ||
export * from './utils'; |
Oops, something went wrong.