UNPKG

@mindconnect/mindconnect-nodejs

Version:

MindConnect Library for NodeJS (community based)

184 lines 7.96 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const debug = require("debug"); const jwt = require("jsonwebtoken"); const node_fetch_1 = require("node-fetch"); const mindconnect_base_1 = require("./mindconnect-base"); const utils_1 = require("./utils"); const log = debug("mindconnect-credentialauth"); class CredentialAuth extends mindconnect_base_1.MindConnectBase { /** * Creates an instance of CredentialAuth. * @param {string} _gateway * @param {string} _basicAuth * @param {string} _tenant * * @memberOf CredentialAuth */ constructor(_gateway, _basicAuth, _tenant) { super(); this._gateway = _gateway; this._basicAuth = _basicAuth; this._tenant = _tenant; if (!_basicAuth || !_basicAuth.startsWith("Basic")) { throw new Error("You have to pass the basic authentication header (Basic: <base64encoded login:password> in the constructor. Wrong Passkey in CLI?"); } if (!utils_1.isUrl(_gateway)) { throw new Error("the gateway must be an URL (e.g. https://gateway.eu1.mindsphere.io"); } if (!_tenant) { throw new Error("You have to provide a tenant"); } } AcquireToken() { return __awaiter(this, void 0, void 0, function* () { const headers = Object.assign(Object.assign({}, this._urlEncodedHeaders), { Authorization: this._basicAuth }); const url = `${utils_1.getPiamUrl(this._gateway, this._tenant)}oauth/token`; log(`AcquireToken Headers: ${JSON.stringify(headers)} Url: ${url}`); const body = "grant_type=client_credentials"; try { const response = yield node_fetch_1.default(url, { method: "POST", body: body, headers: headers, agent: this._proxyHttpAgent }); if (!response.ok) { throw new Error(`${response.statusText} ${yield response.text()}`); } if (response.status >= 200 && response.status <= 299) { const json = yield response.json(); log(`AcquireToken Response ${JSON.stringify(json)}`); this._accessToken = json; } else { throw new Error(`invalid response ${JSON.stringify(response)}`); } } catch (err) { log(err); throw new Error(`Network error occured ${err.message}`); } return true; }); } ValidateToken() { return __awaiter(this, void 0, void 0, function* () { yield utils_1.retry(5, () => this.AcquirePublicKey()); const fullToken = jwt.decode(this._accessToken.access_token, { complete: true }); const tokenkey = fullToken.header.kid; // console.log(tokenkey); let publicKey = this.getPublicKey(tokenkey); if (!publicKey) { this._oauthResponse = undefined; // maybe we have an old token and there was a key rotation yield utils_1.retry(5, () => this.AcquirePublicKey()); publicKey = this.getPublicKey(tokenkey); } if (!publicKey) { throw new Error(`Token validation error, can't find certificate for ${tokenkey}`); } if (!this._accessToken.access_token) throw new Error("Invalid access token"); const result = jwt.verify(this._accessToken.access_token, publicKey); log("Token validated, still good"); return result ? true : false; }); } getPublicKey(tokenkey) { let publicKey = undefined; for (const key of this._oauthResponse.keys) { if (key.kid === tokenkey) { publicKey = key.value; } break; } return publicKey; } AcquirePublicKey() { return __awaiter(this, void 0, void 0, function* () { if (!this._oauthResponse) { const headers = this._headers; const url = `${utils_1.getPiamUrl(this._gateway, this._tenant)}token_keys`; log(`AcquirePublicKey Headers: ${JSON.stringify(headers)} Url: ${url}`); try { const response = yield node_fetch_1.default(url, { method: "GET", headers: headers, agent: this._proxyHttpAgent }); if (!response.ok) { throw new Error(`${response.statusText} ${yield response.text()}`); } if (response.status >= 200 && response.status <= 299) { const json = yield response.json(); log(`OauthPublicKey Response ${JSON.stringify(json)}`); this._oauthResponse = json; } else { throw new Error(`invalid response ${JSON.stringify(response)}`); } } catch (err) { log(err); throw new Error(`Network error occured ${err.message}`); } } return true; }); } RenewToken() { return __awaiter(this, void 0, void 0, function* () { if (this._accessToken) { try { yield this.ValidateToken(); } catch (err) { log(`jwt exchange token expired - renewing : ${err}`); this._accessToken = undefined; if (err.name === "JsonWebTokenError" && err.message === "invalid signature") { log("invalid certificate - renewing"); this._oauthResponse = undefined; } } } if (!this._accessToken) { yield this.AcquireToken(); yield this.ValidateToken(); if (!this._accessToken) { throw new Error("Error aquiering the new token!"); } } return true; }); } /** * Returns the current agent token. * This token can be used in e.g. in Postman to call mindspher APIs. * * @returns {(Promise<string>)} * * @memberOf AgentAuth */ GetServiceToken() { return __awaiter(this, void 0, void 0, function* () { yield this.RenewToken(); if (!this._accessToken || !this._accessToken.access_token) throw new Error("Error getting the new token!"); return this._accessToken.access_token; }); } } exports.CredentialAuth = CredentialAuth; //# sourceMappingURL=credential-auth.js.map