@livechat/customer-auth
Version:
Authorization library for connecting to LiveChat as a customer.
259 lines (245 loc) • 8.31 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
var reactNativeWebview = require('react-native-webview');
var urlUtils = require('@livechat/url-utils');
var storage = require('@livechat/isomorphic-storage');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var storage__default = /*#__PURE__*/_interopDefaultLegacy(storage);
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
_setPrototypeOf(subClass, superClass);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
var createError = function createError(_ref) {
var code = _ref.code,
message = _ref.message;
var err = new Error(message);
err.code = code;
return err;
};
var parseTokenResponse = function parseTokenResponse(token, organizationId) {
if ('identity_exception' in token) {
throw createError({
code: 'SSO_IDENTITY_EXCEPTION',
message: token.identity_exception
});
}
if ('oauth_exception' in token) {
throw createError({
code: 'SSO_OAUTH_EXCEPTION',
message: token.oauth_exception
});
}
return {
accessToken: token.access_token,
entityId: token.entity_id,
expiresIn: token.expires_in * 1000,
tokenType: token.token_type,
creationDate: Date.now(),
organizationId: organizationId
};
};
var ACCOUNTS_URL = "https://accounts.livechatinc.com";
var buildPath = function buildPath(_ref) {
var uniqueGroups = _ref.uniqueGroups,
organizationId = _ref.organizationId,
groupId = _ref.groupId;
return "" + (uniqueGroups ? "/v2/customer/" + organizationId + "/" + groupId + "/token" : '/v2/customer/token');
};
var buildRequestUrl = function buildRequestUrl(config, env) {
var url = env === 'production' ? ACCOUNTS_URL : ACCOUNTS_URL.replace('accounts.', "accounts." + env + ".");
var path = buildPath(config);
return "" + url + path;
};
var registerRequest = null;
var injectRegisterRequest = function injectRegisterRequest(_registerRequest) {
return registerRequest = _registerRequest;
};
var fetchToken = function fetchToken(config, env) {
return new Promise(function (resolve, reject) {
if (!registerRequest) {
reject(new Error("You should render { AuthWebView } from '@livechat/customer-auth' first."));
return;
}
var url = buildRequestUrl(config, env);
var query = {
response_type: 'token',
flow: 'button',
client_id: config.clientId,
organization_id: config.organizationId,
redirect_uri: config.redirectUri,
post_message_uri: config.redirectUri
};
registerRequest(url + "?" + urlUtils.buildQueryString(query), function (token) {
try {
resolve(parseTokenResponse(token, config.organizationId));
} catch (err) {
reject(err);
}
});
});
};
var validateConfig = function validateConfig(_ref) {
var organizationId = _ref.organizationId,
clientId = _ref.clientId,
redirectUri = _ref.redirectUri;
if (typeof organizationId !== 'string' || typeof clientId !== 'string' || typeof redirectUri !== 'string') {
throw new Error('You need to pass valid configuration object: { organizationId, clientId, redirectUri }.');
}
};
var isExpiredToken = function isExpiredToken(_ref) {
var creationDate = _ref.creationDate,
expiresIn = _ref.expiresIn;
return Date.now() >= creationDate + expiresIn;
};
var createAuth = function createAuth(config, licenseId, env) {
validateConfig(config);
var tokenStoragePrefix = config.tokenStoragePrefix || "@@lc_auth_token:";
var oldCacheKey = "" + tokenStoragePrefix + licenseId + (config.uniqueGroups ? ":" + config.groupId : '');
var newCacheKey = "" + tokenStoragePrefix + config.organizationId + (config.uniqueGroups ? ":" + config.groupId : '');
var pendingTokenRequest = null;
var cachedToken = null;
var retrievingToken = storage__default['default'].getItem(oldCacheKey).then(function (token) {
if (retrievingToken === null) {
return;
}
retrievingToken = null;
if (!token) {
storage__default['default'].removeItem(oldCacheKey).then(function () {
return storage__default['default'].getItem(newCacheKey).then(function (newKeyToken) {
if (!newKeyToken) {
return;
}
cachedToken = JSON.parse(newKeyToken);
});
});
return;
}
storage__default['default'].setItem(newCacheKey, token).then(function () {
storage__default['default'].removeItem(oldCacheKey).then(function () {
cachedToken = JSON.parse(token);
});
});
});
var getFreshToken = function getFreshToken() {
pendingTokenRequest = fetchToken(config, env).then(function (token) {
pendingTokenRequest = null;
storage__default['default'].setItem(newCacheKey, JSON.stringify(token));
cachedToken = token;
return token;
}, function (err) {
pendingTokenRequest = null;
throw err;
});
return pendingTokenRequest;
};
var getToken = function getToken() {
if (pendingTokenRequest) {
return pendingTokenRequest;
}
if (cachedToken && !isExpiredToken(cachedToken)) {
return Promise.resolve(cachedToken);
}
if (retrievingToken) {
return retrievingToken.then(getToken);
}
return getFreshToken();
};
var hasToken = function hasToken() {
if (retrievingToken) {
return retrievingToken.then(hasToken);
}
return Promise.resolve(!!cachedToken);
};
var invalidate = function invalidate() {
cachedToken = null;
retrievingToken = null;
return storage__default['default'].removeItem(newCacheKey);
};
return {
getFreshToken: getFreshToken,
getToken: getToken,
hasToken: hasToken,
invalidate: invalidate
};
};
var AuthWebView = /*#__PURE__*/function (_React$Component) {
_inheritsLoose(AuthWebView, _React$Component);
function AuthWebView() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
_this.requesting = false;
_this.requestQueue = [];
_this.state = {
uri: null
};
_this.webViewRef = null;
_this.storeWebViewRef = function (ref) {
return _this.webViewRef = ref;
};
_this.onMessage = function (event) {
var tokenResponse = urlUtils.decodeQueryString(event.nativeEvent.data.replace(/^(\?|#)/, ''));
var _ref = _this.requestQueue.shift(),
callback = _ref.callback;
callback(tokenResponse);
if (_this.requestQueue.length === 0) {
_this.requesting = false;
} else {
_this.makeRequest();
}
};
return _this;
}
var _proto = AuthWebView.prototype;
_proto.componentDidMount = function componentDidMount() {
var _this2 = this;
var registerRequest = function registerRequest(uri, callback) {
_this2.requestQueue.push({
uri: uri,
callback: callback
});
if (_this2.requesting) {
return;
}
_this2.makeRequest();
};
injectRegisterRequest(registerRequest);
};
_proto.makeRequest = function makeRequest() {
this.requesting = true;
var uri = this.requestQueue[0].uri;
if (this.state.uri === uri) {
this.webViewRef.reload();
return;
}
this.setState({
uri: uri
});
};
_proto.render = function render() {
return this.state.uri ? /*#__PURE__*/React.createElement(reactNativeWebview.WebView, {
injectedJavaScript: "window.ReactNativeWebView.postMessage(location.hash || location.search)",
onMessage: this.onMessage,
ref: this.storeWebViewRef,
source: {
uri: this.state.uri
}
}) : null;
};
return AuthWebView;
}(React.Component);
exports.AuthWebView = AuthWebView;
exports.default = createAuth;
exports.isExpiredToken = isExpiredToken;
exports.validateConfig = validateConfig;