UNPKG

@axway/amplify-sdk

Version:

Axway Amplify SDK for Node.js

117 lines (103 loc) 3.25 kB
import crypto from 'crypto'; import errors from '../errors.js'; import FileStore from './file-store.js'; import path from 'path'; import snooplogg from 'snooplogg'; import keytar from 'keytar'; import 'fs-extra'; import './token-store.js'; import 'pluralize'; import '@axway/amplify-utils'; /* eslint-disable security/detect-non-literal-require */ const { log, warn } = snooplogg('amplify-sdk:auth:secure-store'); /** * A operating-specific secure token store. */ class SecureStore extends FileStore { /** * The name of the token store file. * @type {String} */ filename = '.tokenstore.secure.v2'; /** * Loads the `keytar` library and initializes the token file. * * @param {Object} opts - Various options. * @param {String} opts.homeDir - The path to the home directory containing the `lib` * directory where `keytar` is located. * @param {Object} [opts.requestOptions] - HTTP client options. * @param {String} [opts.secureServiceName="Axway AMPLIFY Auth"] - The name of the consumer * using this library. * @access public */ constructor(opts = {}) { if (!opts || typeof opts !== 'object') { throw errors.INVALID_ARGUMENT('Expected opts to be an object'); } const { homeDir } = opts; if (!homeDir || typeof homeDir !== 'string') { throw errors.INVALID_PARAMETER('Secure store requires the home directory to be specified'); } super(opts); this.keytar = keytar; this.serviceName = opts.secureServiceName || 'Axway AMPLIFY Auth'; this.tokenStoreFile = path.join(this.tokenStoreDir, this.filename); } /** * Decodes the supplied string into an object. * * @param {String} str - The string to decode into an object. * @returns {Array} * @access private */ async decode(str) { try { return await super.decode(str); } catch (e) { if (e.amplifyCode === 'ERR_BAD_KEY') { await this.keytar.deletePassword(this.serviceName, this.serviceName); } throw e; } } /** * Gets the decipher key or generates a new one if it doesn't exist. * * @returns {String} * @access private */ async getKey() { if (!this._key) { let key; try { key = await this.keytar.getPassword(this.serviceName, this.serviceName); } catch (err) { if (process.platform === 'linux') { // this is likely due to d-bus daemon not running (i.e. "Connection refused") or // running in a non-desktop (headless) environment (i.e. "Cannot autolaunch D-Bus without X11") warn(err.message); throw new Error([ 'Unable to get the secure token store key.', '', 'On Linux, the secure token store requires a desktop environment.', 'SSH sessions and headless environments are not supported.', '', 'To use the insecure token store, run the following:', '', ' axway config set auth.tokenStoreType file' ].join('\n')); } throw err; } if (!key) { log('Generating new key...'); key = crypto.randomBytes(16).toString('hex'); await this.keytar.setPassword(this.serviceName, this.serviceName, key); } Object.defineProperty(this, '_key', { value: Buffer.from(key, 'hex') }); } return this._key; } } export { SecureStore as default }; //# sourceMappingURL=secure-store.js.map