deep-security
Version:
DEEP Security Library
389 lines (306 loc) • 9.97 kB
JavaScript
/**
* Created by mgoria on 11/6/15.
*/
/* eslint-disable no-unused-vars */
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TokenManager = undefined;
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _awsSdk = require('aws-sdk');
var _awsSdk2 = _interopRequireDefault(_awsSdk);
var _deepCore = require('deep-core');
var _deepCore2 = _interopRequireDefault(_deepCore);
var _amazonCognitoJs = require('amazon-cognito-js');
var _amazonCognitoJs2 = _interopRequireDefault(_amazonCognitoJs);
var _CreateCognitoDatasetException = require('./Exception/CreateCognitoDatasetException');
var _PutCognitoRecordException = require('./Exception/PutCognitoRecordException');
var _SynchronizeCognitoDatasetException = require('./Exception/SynchronizeCognitoDatasetException');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
let TokenManager = exports.TokenManager = function () {
_createClass(TokenManager, null, [{
key: 'DATASET_NAME',
/**
* @returns {String}
*/
get: function get() {
return 'deep_session';
}
/**
* @returns {String}
*/
}, {
key: 'RECORD_NAME',
get: function get() {
return 'session_creds';
}
/**
* @param {String} identityPoolId
* @param {Object|null} cognitoSyncClient
*/
}]);
function TokenManager(identityPoolId) {
let cognitoSyncClient = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
_classCallCheck(this, TokenManager);
this._identityPoolId = identityPoolId;
this._cognitoSyncClient = cognitoSyncClient;
this._lastSyncedEntry = null;
this._syncInProgress = false;
}
/**
* @returns {Object}
*/
_createClass(TokenManager, [{
key: 'saveToken',
/**
* @param {Token} token
* @returns {Promise}
*/
value: function saveToken(token) {
return new Promise((resolve, reject) => {
this._createOrGetDataset((error, dataset) => {
if (error) {
return reject(error);
}
let encodedToken = this._encodeToken(token);
if (this._lastSyncedEntry === encodedToken || this._syncInProgress) {
return resolve();
}
this._syncInProgress = true;
this._lastSyncedEntry = encodedToken;
dataset.put(TokenManager.RECORD_NAME, this._encodeToken(token), (error /*, record*/) => {
if (error) {
return reject(new _PutCognitoRecordException.PutCognitoRecordException(TokenManager.DATASET_NAME, TokenManager.RECORD_NAME, error));
}
this._synchronizeDataset(dataset, (error, savedRecords) => {
this._syncInProgress = false;
if (error) {
return reject(new _SynchronizeCognitoDatasetException.SynchronizeCognitoDatasetException(dataset, error));
}
resolve(savedRecords);
});
});
});
});
}
/**
* @param {String} identityId
* @returns {Promise}
*/
}, {
key: 'loadBackendToken',
value: function loadBackendToken(identityId) {
let cognitosync = new _awsSdk2.default.CognitoSync({
credentials: _deepCore2.default.AWS.ENV_CREDENTIALS
});
let params = {
DatasetName: TokenManager.DATASET_NAME,
IdentityId: identityId,
IdentityPoolId: this._identityPoolId
};
return cognitosync.listRecords(params).promise().then(data => {
let token = null;
data.Records.forEach(record => {
if (record.Key === TokenManager.RECORD_NAME) {
token = this._decodeToken(record.Value);
return token;
}
});
return token;
});
}
/**
* @returns {Promise}
*/
}, {
key: 'loadFrontendToken',
value: function loadFrontendToken() {
return new Promise((resolve, reject) => {
this._createOrGetDataset((error, dataset) => {
if (error) {
return reject(error);
}
dataset.get(TokenManager.RECORD_NAME, (error, rawToken) => {
if (error) {
return reject(error);
}
resolve(this._decodeToken(rawToken));
});
});
});
}
/**
* @returns {String}
*/
}, {
key: 'deleteToken',
/**
* Deletes cached Token from local storage
*
* @returns {TokenManager}
*/
value: function deleteToken() {
this.cognitoSyncClient.wipeData();
return this;
}
/**
* @param {Function} callback
* @private
*/
}, {
key: '_createOrGetDataset',
value: function _createOrGetDataset(callback) {
this.cognitoSyncClient.openOrCreateDataset(TokenManager.DATASET_NAME, (error, dataset) => {
if (error) {
callback(new _CreateCognitoDatasetException.CreateCognitoDatasetException(TokenManager.DATASET_NAME, error), null);
return;
}
callback(null, dataset);
});
}
/**
* @param {Object} dataset
* @param {Function} callback
* @private
*/
}, {
key: '_synchronizeDataset',
value: function _synchronizeDataset(dataset, callback) {
dataset.synchronize({
onSuccess: (dataset, newRecords) => {
callback(null, newRecords);
},
onFailure: error => {
callback(error, null);
},
onConflict: (dataset, conflicts, cb) => {
let resolved = [];
for (let i = 0; i < conflicts.length; i++) {
// take local version. @todo: implement custom merge logic to take latest changes
resolved.push(conflicts[i].resolveWithLocalRecord());
}
dataset.resolve(resolved, () => {
return cb(true);
});
},
onDatasetDeleted: (dataset, datasetName, cb) => {
return cb(true);
},
onDatasetMerged: (dataset, datasetNames, cb) => {
return cb(true);
}
});
}
/**
* @todo: implement an encoding method
*
* @param {Token} token
* @returns {String}
*/
}, {
key: '_encodeToken',
value: function _encodeToken(token) {
return JSON.stringify(token.toJSON());
}
/**
* @todo: implement a decoding method
*
* @param {String} rawToken
* @returns {Object}
*/
}, {
key: '_decodeToken',
value: function _decodeToken(rawToken) {
if (rawToken && typeof rawToken === 'string') {
try {
let tokenObj = JSON.parse(rawToken);
tokenObj.credentials = this._decodeCredentials(tokenObj.credentials);
tokenObj.credentials.params = {
IdentityId: tokenObj.identityId,
IdentityPoolId: this._identityPoolId
};
for (let key in tokenObj.rolesCredentials) {
if (tokenObj.rolesCredentials.hasOwnProperty(key)) {
tokenObj.rolesCredentials[key] = this._decodeCredentials(tokenObj.rolesCredentials[key]);
}
}
return tokenObj;
} catch (e) {
return null;
}
}
return null;
}
/**
* @todo: implement a decoding method
*
* @param {Object} credentials
* @returns {Object}
*/
}, {
key: '_decodeCredentials',
value: function _decodeCredentials(credentials) {
let expireTime = credentials.expireTime;
credentials = new _awsSdk2.default.Credentials(credentials);
// restore expireTime because AWS.Credentials resets it to null
credentials.expireTime = expireTime;
// set secretAccessKey property enumerable:true to allow storing it into Cognito datastore
credentials = this._makeKeyEnumerable(credentials, 'secretAccessKey');
return credentials;
}
/**
* @param {Object} obj
* @param {String} key
* @returns {Object}
* @private
*/
}, {
key: '_makeKeyEnumerable',
value: function _makeKeyEnumerable(obj, key) {
obj = Object.defineProperty(obj, key, {
enumerable: true,
writable: true,
configurable: true
});
return obj;
}
/**
* @returns {Boolean}
* @private
*/
}, {
key: '_isLocalStorageAvailable',
value: function _isLocalStorageAvailable() {
try {
if (window && window.localStorage) {
window.localStorage.setItem('key', 'value');
window.localStorage.removeItem('key');
return true;
}
return false;
} catch (e) {
return false;
}
}
}, {
key: 'cognitoSyncClient',
get: function get() {
if (!this._cognitoSyncClient) {
let options = {};
if (!this._isLocalStorageAvailable()) {
options.DataStore = _awsSdk2.default.CognitoSyncManager.StoreInMemory;
}
this._cognitoSyncClient = new _awsSdk2.default.CognitoSyncManager(options);
}
return this._cognitoSyncClient;
}
}, {
key: 'identityId',
get: function get() {
return this.cognitoSyncClient.getIdentityId();
}
}]);
return TokenManager;
}();