UNPKG

@livechat/customer-auth

Version:

Authorization library for connecting to LiveChat as a customer.

259 lines (245 loc) 8.31 kB
'use strict'; 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;