@livechat/customer-auth
Advanced tools
Comparing version 0.4.0-alpha.1 to 0.4.0-alpha.2
@@ -11,42 +11,16 @@ 'use strict'; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
// this is the same as "https://accounts.livechatinc.com" | ||
// it's hardcoded here because chat.io has its own ACCOUNTS_URL | ||
// but this variable has to have the same value for both LiveChat and chat.io | ||
var POST_MESSAGE_ORIGIN = 'https://accounts.livechatinc.com'; // as const | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
var CUSTOMER_AUTH_FOOTPRINT = '@livechat/customer-auth'; // as const | ||
return target; | ||
}; | ||
var ACCOUNTS_URL = "https://accounts.livechatinc.com"; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
if (source == null) return {}; | ||
var target = {}; | ||
var sourceKeys = Object.keys(source); | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
key = sourceKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
target[key] = source[key]; | ||
} | ||
return target; | ||
} | ||
var buildParams = function buildParams(_ref) { | ||
var buildParams = function buildParams(_ref, redirectUri) { | ||
var clientId = _ref.clientId, | ||
license = _ref.license, | ||
redirectUri = _ref.redirectUri, | ||
state = _ref.state; | ||
var params = { | ||
license_id: license, | ||
license = _ref.license; | ||
return { | ||
license_id: String(license), | ||
flow: 'button', | ||
@@ -56,10 +30,5 @@ response_type: 'token', | ||
redirect_uri: redirectUri, | ||
post_message_uri: redirectUri | ||
post_message_uri: redirectUri, | ||
state: CUSTOMER_AUTH_FOOTPRINT | ||
}; | ||
if (state) { | ||
params.state = state; | ||
} | ||
return params; | ||
}; | ||
@@ -74,42 +43,20 @@ | ||
var buildSrc = (function (config, state, env) { | ||
var url = env === 'production' ? "https://accounts.livechatinc.com" : "https://accounts.livechatinc.com".replace('accounts.', "accounts." + env + "."); | ||
var buildSrc = function buildSrc(config, redirectUri, env) { | ||
var url = env === 'production' ? ACCOUNTS_URL : ACCOUNTS_URL.replace('accounts.', "accounts." + env + "."); | ||
var path = buildPath(config); | ||
var query = urlUtils.buildQueryString(buildParams(_extends({}, config, { | ||
state: state | ||
}))); | ||
var query = urlUtils.buildQueryString(buildParams(config, redirectUri)); | ||
return "" + url + path + "?" + query; | ||
}); | ||
var ok = function ok(value) { | ||
return { | ||
type: 'ok', | ||
value: value | ||
}; | ||
}; | ||
var error = function error(err) { | ||
return { | ||
type: 'error', | ||
error: err | ||
}; | ||
}; | ||
var fold = function fold(foldErr, foldValue, result) { | ||
return result.type === 'ok' ? foldValue(result.value) : foldErr(result.error); | ||
}; | ||
var parseTokenResponse = function parseTokenResponse(tokenResponse, _ref) { | ||
var license = _ref.license; | ||
return { | ||
accessToken: tokenResponse.access_token, | ||
entityId: tokenResponse.entity_id, | ||
expiresIn: tokenResponse.expires_in * 1000, | ||
tokenType: tokenResponse.token_type, | ||
creationDate: Date.now(), | ||
license: license | ||
}; | ||
var createError = function createError(_ref) { | ||
var code = _ref.code, | ||
message = _ref.message; | ||
var err = new Error(message); | ||
err.code = code; | ||
return err; | ||
}; | ||
var parseToken = (function (token, extraData) { | ||
if (token.identity_exception) { | ||
return error({ | ||
var parseTokenResponse = function parseTokenResponse(token, license) { | ||
if ('identity_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_IDENTITY_EXCEPTION', | ||
@@ -120,4 +67,4 @@ message: token.identity_exception | ||
if (token.oauth_exception) { | ||
return error({ | ||
if ('oauth_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_OAUTH_EXCEPTION', | ||
@@ -128,10 +75,12 @@ message: token.oauth_exception | ||
return ok(parseTokenResponse(token, extraData)); | ||
}); | ||
return { | ||
accessToken: token.access_token, | ||
entityId: token.entity_id, | ||
expiresIn: token.expires_in * 1000, | ||
tokenType: token.token_type, | ||
creationDate: Date.now(), | ||
license: license | ||
}; | ||
}; | ||
// it's hardcoded here because chat.io has its own ACCOUNTS_URL | ||
// but this variable has to have the same value for both LiveChat and chat.io | ||
var POST_MESSAGE_ORIGIN = 'https://accounts.livechatinc.com'; | ||
var getPostMessageOrigin = function getPostMessageOrigin(env) { | ||
@@ -141,43 +90,23 @@ return env === 'production' ? POST_MESSAGE_ORIGIN : POST_MESSAGE_ORIGIN.replace('accounts.', "accounts." + env + "."); | ||
var CUSTOMER_AUTH_FOOTPRINT = '@livechat/customer-auth'; | ||
var buildIframe = function buildIframe(config, env) { | ||
var iframe = document.createElement('iframe'); | ||
iframe.style.display = 'none'; | ||
iframe.setAttribute('src', buildSrc(_extends({}, config, { | ||
redirectUri: urlUtils.getOrigin(String(location)) + location.pathname | ||
}), CUSTOMER_AUTH_FOOTPRINT, env)); | ||
iframe.setAttribute('src', buildSrc(config, urlUtils.getOrigin(String(window.location)) + window.location.pathname, env)); | ||
return iframe; | ||
}; | ||
var removeNode = function removeNode(node) { | ||
if (!node.parentNode) { | ||
return; | ||
} | ||
node.parentNode.removeChild(node); | ||
var isTokenResponse = function isTokenResponse(data) { | ||
return data && data.state === CUSTOMER_AUTH_FOOTPRINT; | ||
}; | ||
var createError = function createError(_ref) { | ||
var code = _ref.code, | ||
message = _ref.message; | ||
var err = new Error(message); | ||
err.code = code; | ||
return err; | ||
}; | ||
var fetchToken = (function (config, env) { | ||
var fetchToken = function fetchToken(config, env) { | ||
var license = config.license; | ||
var postMessageOrigin = getPostMessageOrigin(env); | ||
return new Promise(function (resolve, reject) { | ||
var _window2; | ||
var iframe = buildIframe(config, env); | ||
var cleanup = function cleanup() { | ||
var _window; | ||
domUtils.removeNode(iframe); // eslint-disable-next-line no-use-before-define | ||
removeNode(iframe); // eslint-disable-next-line no-use-before-define | ||
(_window = window).removeEventListener.apply(_window, listener); | ||
window.removeEventListener('message', listener, false); | ||
}; | ||
@@ -192,6 +121,7 @@ | ||
}, 15 * 1000); | ||
var listener = ['message', function (_ref2) { | ||
var origin = _ref2.origin, | ||
data = _ref2.data; | ||
var listener = function listener(_ref) { | ||
var origin = _ref.origin, | ||
data = _ref.data; | ||
if (origin !== postMessageOrigin) { | ||
@@ -201,3 +131,3 @@ return; | ||
if (!data || data.state !== CUSTOMER_AUTH_FOOTPRINT) { | ||
if (!isTokenResponse(data)) { | ||
return; | ||
@@ -208,11 +138,11 @@ } | ||
cleanup(); | ||
fold(function (err) { | ||
return reject(createError(err)); | ||
}, resolve, parseToken(data, { | ||
license: license | ||
})); | ||
}, false]; | ||
(_window2 = window).addEventListener.apply(_window2, listener); | ||
try { | ||
resolve(parseTokenResponse(data, license)); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}; | ||
window.addEventListener('message', listener, false); | ||
domUtils.getRoot().then(function (body) { | ||
@@ -222,5 +152,5 @@ body.appendChild(iframe); | ||
}); | ||
}); | ||
}; | ||
var validateConfig = (function (_ref) { | ||
var validateConfig = function validateConfig(_ref) { | ||
var license = _ref.license, | ||
@@ -232,24 +162,15 @@ clientId = _ref.clientId; | ||
} | ||
}); | ||
var isExpiredToken = function isExpiredToken(token) { | ||
return Date.now() >= token.creationDate + token.expiresIn; | ||
}; | ||
var withDefaults = function withDefaults(_ref) { | ||
var _ref$uniqueGroups = _ref.uniqueGroups, | ||
uniqueGroups = _ref$uniqueGroups === void 0 ? false : _ref$uniqueGroups, | ||
rest = _objectWithoutPropertiesLoose(_ref, ["uniqueGroups"]); | ||
return _extends({ | ||
uniqueGroups: uniqueGroups | ||
}, rest); | ||
var isExpiredToken = function isExpiredToken(_ref) { | ||
var creationDate = _ref.creationDate, | ||
expiresIn = _ref.expiresIn; | ||
return Date.now() >= creationDate + expiresIn; | ||
}; | ||
var auth = (function (inputConfig, env) { | ||
validateConfig(inputConfig); | ||
var config = withDefaults(inputConfig); | ||
var pendingTokenRequest; | ||
var cachedToken; | ||
var createAuth = function createAuth(config, env) { | ||
validateConfig(config); | ||
var cacheKey = "@@lc_auth_token:" + config.license + (config.uniqueGroups ? ":" + config.group : ''); | ||
var pendingTokenRequest = null; | ||
var cachedToken = null; | ||
var retrievingToken = storage.getItem(cacheKey).then(function (token) { | ||
@@ -268,41 +189,56 @@ if (retrievingToken === null) { | ||
}); | ||
var auth = Object.freeze({ | ||
getFreshToken: function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}).catch(function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
var getFreshToken = function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}, function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
return pendingTokenRequest; | ||
}; | ||
var getToken = function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
}, | ||
getToken: function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
} | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(auth.getToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(getToken); | ||
} | ||
return auth.getFreshToken(); | ||
}, | ||
invalidate: function invalidate() { | ||
storage.removeItem(cacheKey); | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return getFreshToken(); | ||
}; | ||
var hasToken = function hasToken() { | ||
if (retrievingToken) { | ||
return retrievingToken.then(hasToken); | ||
} | ||
}); | ||
return auth; | ||
}); | ||
exports.default = auth; | ||
return Promise.resolve(!!cachedToken); | ||
}; | ||
var invalidate = function invalidate() { | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return storage.removeItem(cacheKey); | ||
}; | ||
return { | ||
getFreshToken: getFreshToken, | ||
getToken: getToken, | ||
hasToken: hasToken, | ||
invalidate: invalidate | ||
}; | ||
}; | ||
exports.default = createAuth; | ||
exports.isExpiredToken = isExpiredToken; | ||
exports.validateConfig = validateConfig; |
import { buildQueryString, getOrigin } from '@livechat/url-utils'; | ||
import { getRoot } from '@livechat/dom-utils'; | ||
import { getRoot, removeNode } from '@livechat/dom-utils'; | ||
import storage from '@livechat/isomorphic-storage'; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
// this is the same as "https://accounts.livechatinc.com" | ||
// it's hardcoded here because chat.io has its own ACCOUNTS_URL | ||
// but this variable has to have the same value for both LiveChat and chat.io | ||
var POST_MESSAGE_ORIGIN = 'https://accounts.livechatinc.com'; // as const | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
var CUSTOMER_AUTH_FOOTPRINT = '@livechat/customer-auth'; // as const | ||
return target; | ||
}; | ||
var ACCOUNTS_URL = "https://accounts.livechatinc.com"; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
if (source == null) return {}; | ||
var target = {}; | ||
var sourceKeys = Object.keys(source); | ||
var key, i; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
key = sourceKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
target[key] = source[key]; | ||
} | ||
return target; | ||
} | ||
var buildParams = function buildParams(_ref) { | ||
var buildParams = function buildParams(_ref, redirectUri) { | ||
var clientId = _ref.clientId, | ||
license = _ref.license, | ||
redirectUri = _ref.redirectUri, | ||
state = _ref.state; | ||
var params = { | ||
license_id: license, | ||
license = _ref.license; | ||
return { | ||
license_id: String(license), | ||
flow: 'button', | ||
@@ -49,10 +23,5 @@ response_type: 'token', | ||
redirect_uri: redirectUri, | ||
post_message_uri: redirectUri | ||
post_message_uri: redirectUri, | ||
state: CUSTOMER_AUTH_FOOTPRINT | ||
}; | ||
if (state) { | ||
params.state = state; | ||
} | ||
return params; | ||
}; | ||
@@ -67,42 +36,20 @@ | ||
var buildSrc = (function (config, state, env) { | ||
var url = env === 'production' ? "https://accounts.livechatinc.com" : "https://accounts.livechatinc.com".replace('accounts.', "accounts." + env + "."); | ||
var buildSrc = function buildSrc(config, redirectUri, env) { | ||
var url = env === 'production' ? ACCOUNTS_URL : ACCOUNTS_URL.replace('accounts.', "accounts." + env + "."); | ||
var path = buildPath(config); | ||
var query = buildQueryString(buildParams(_extends({}, config, { | ||
state: state | ||
}))); | ||
var query = buildQueryString(buildParams(config, redirectUri)); | ||
return "" + url + path + "?" + query; | ||
}); | ||
var ok = function ok(value) { | ||
return { | ||
type: 'ok', | ||
value: value | ||
}; | ||
}; | ||
var error = function error(err) { | ||
return { | ||
type: 'error', | ||
error: err | ||
}; | ||
}; | ||
var fold = function fold(foldErr, foldValue, result) { | ||
return result.type === 'ok' ? foldValue(result.value) : foldErr(result.error); | ||
}; | ||
var parseTokenResponse = function parseTokenResponse(tokenResponse, _ref) { | ||
var license = _ref.license; | ||
return { | ||
accessToken: tokenResponse.access_token, | ||
entityId: tokenResponse.entity_id, | ||
expiresIn: tokenResponse.expires_in * 1000, | ||
tokenType: tokenResponse.token_type, | ||
creationDate: Date.now(), | ||
license: license | ||
}; | ||
var createError = function createError(_ref) { | ||
var code = _ref.code, | ||
message = _ref.message; | ||
var err = new Error(message); | ||
err.code = code; | ||
return err; | ||
}; | ||
var parseToken = (function (token, extraData) { | ||
if (token.identity_exception) { | ||
return error({ | ||
var parseTokenResponse = function parseTokenResponse(token, license) { | ||
if ('identity_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_IDENTITY_EXCEPTION', | ||
@@ -113,4 +60,4 @@ message: token.identity_exception | ||
if (token.oauth_exception) { | ||
return error({ | ||
if ('oauth_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_OAUTH_EXCEPTION', | ||
@@ -121,10 +68,12 @@ message: token.oauth_exception | ||
return ok(parseTokenResponse(token, extraData)); | ||
}); | ||
return { | ||
accessToken: token.access_token, | ||
entityId: token.entity_id, | ||
expiresIn: token.expires_in * 1000, | ||
tokenType: token.token_type, | ||
creationDate: Date.now(), | ||
license: license | ||
}; | ||
}; | ||
// it's hardcoded here because chat.io has its own ACCOUNTS_URL | ||
// but this variable has to have the same value for both LiveChat and chat.io | ||
var POST_MESSAGE_ORIGIN = 'https://accounts.livechatinc.com'; | ||
var getPostMessageOrigin = function getPostMessageOrigin(env) { | ||
@@ -134,43 +83,23 @@ return env === 'production' ? POST_MESSAGE_ORIGIN : POST_MESSAGE_ORIGIN.replace('accounts.', "accounts." + env + "."); | ||
var CUSTOMER_AUTH_FOOTPRINT = '@livechat/customer-auth'; | ||
var buildIframe = function buildIframe(config, env) { | ||
var iframe = document.createElement('iframe'); | ||
iframe.style.display = 'none'; | ||
iframe.setAttribute('src', buildSrc(_extends({}, config, { | ||
redirectUri: getOrigin(String(location)) + location.pathname | ||
}), CUSTOMER_AUTH_FOOTPRINT, env)); | ||
iframe.setAttribute('src', buildSrc(config, getOrigin(String(window.location)) + window.location.pathname, env)); | ||
return iframe; | ||
}; | ||
var removeNode = function removeNode(node) { | ||
if (!node.parentNode) { | ||
return; | ||
} | ||
node.parentNode.removeChild(node); | ||
var isTokenResponse = function isTokenResponse(data) { | ||
return data && data.state === CUSTOMER_AUTH_FOOTPRINT; | ||
}; | ||
var createError = function createError(_ref) { | ||
var code = _ref.code, | ||
message = _ref.message; | ||
var err = new Error(message); | ||
err.code = code; | ||
return err; | ||
}; | ||
var fetchToken = (function (config, env) { | ||
var fetchToken = function fetchToken(config, env) { | ||
var license = config.license; | ||
var postMessageOrigin = getPostMessageOrigin(env); | ||
return new Promise(function (resolve, reject) { | ||
var _window2; | ||
var iframe = buildIframe(config, env); | ||
var cleanup = function cleanup() { | ||
var _window; | ||
removeNode(iframe); // eslint-disable-next-line no-use-before-define | ||
(_window = window).removeEventListener.apply(_window, listener); | ||
window.removeEventListener('message', listener, false); | ||
}; | ||
@@ -185,6 +114,7 @@ | ||
}, 15 * 1000); | ||
var listener = ['message', function (_ref2) { | ||
var origin = _ref2.origin, | ||
data = _ref2.data; | ||
var listener = function listener(_ref) { | ||
var origin = _ref.origin, | ||
data = _ref.data; | ||
if (origin !== postMessageOrigin) { | ||
@@ -194,3 +124,3 @@ return; | ||
if (!data || data.state !== CUSTOMER_AUTH_FOOTPRINT) { | ||
if (!isTokenResponse(data)) { | ||
return; | ||
@@ -201,11 +131,11 @@ } | ||
cleanup(); | ||
fold(function (err) { | ||
return reject(createError(err)); | ||
}, resolve, parseToken(data, { | ||
license: license | ||
})); | ||
}, false]; | ||
(_window2 = window).addEventListener.apply(_window2, listener); | ||
try { | ||
resolve(parseTokenResponse(data, license)); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}; | ||
window.addEventListener('message', listener, false); | ||
getRoot().then(function (body) { | ||
@@ -215,5 +145,5 @@ body.appendChild(iframe); | ||
}); | ||
}); | ||
}; | ||
var validateConfig = (function (_ref) { | ||
var validateConfig = function validateConfig(_ref) { | ||
var license = _ref.license, | ||
@@ -225,24 +155,15 @@ clientId = _ref.clientId; | ||
} | ||
}); | ||
var isExpiredToken = function isExpiredToken(token) { | ||
return Date.now() >= token.creationDate + token.expiresIn; | ||
}; | ||
var withDefaults = function withDefaults(_ref) { | ||
var _ref$uniqueGroups = _ref.uniqueGroups, | ||
uniqueGroups = _ref$uniqueGroups === void 0 ? false : _ref$uniqueGroups, | ||
rest = _objectWithoutPropertiesLoose(_ref, ["uniqueGroups"]); | ||
return _extends({ | ||
uniqueGroups: uniqueGroups | ||
}, rest); | ||
var isExpiredToken = function isExpiredToken(_ref) { | ||
var creationDate = _ref.creationDate, | ||
expiresIn = _ref.expiresIn; | ||
return Date.now() >= creationDate + expiresIn; | ||
}; | ||
var auth = (function (inputConfig, env) { | ||
validateConfig(inputConfig); | ||
var config = withDefaults(inputConfig); | ||
var pendingTokenRequest; | ||
var cachedToken; | ||
var createAuth = function createAuth(config, env) { | ||
validateConfig(config); | ||
var cacheKey = "@@lc_auth_token:" + config.license + (config.uniqueGroups ? ":" + config.group : ''); | ||
var pendingTokenRequest = null; | ||
var cachedToken = null; | ||
var retrievingToken = storage.getItem(cacheKey).then(function (token) { | ||
@@ -261,40 +182,55 @@ if (retrievingToken === null) { | ||
}); | ||
var auth = Object.freeze({ | ||
getFreshToken: function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}).catch(function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
var getFreshToken = function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}, function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
return pendingTokenRequest; | ||
}; | ||
var getToken = function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
}, | ||
getToken: function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
} | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(auth.getToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(getToken); | ||
} | ||
return auth.getFreshToken(); | ||
}, | ||
invalidate: function invalidate() { | ||
storage.removeItem(cacheKey); | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return getFreshToken(); | ||
}; | ||
var hasToken = function hasToken() { | ||
if (retrievingToken) { | ||
return retrievingToken.then(hasToken); | ||
} | ||
}); | ||
return auth; | ||
}); | ||
export default auth; | ||
return Promise.resolve(!!cachedToken); | ||
}; | ||
var invalidate = function invalidate() { | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return storage.removeItem(cacheKey); | ||
}; | ||
return { | ||
getFreshToken: getFreshToken, | ||
getToken: getToken, | ||
hasToken: hasToken, | ||
invalidate: invalidate | ||
}; | ||
}; | ||
export default createAuth; | ||
export { isExpiredToken, validateConfig }; |
@@ -12,20 +12,2 @@ 'use strict'; | ||
function _extends() { | ||
_extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
return _extends.apply(this, arguments); | ||
} | ||
function _inheritsLoose(subClass, superClass) { | ||
@@ -37,48 +19,30 @@ subClass.prototype = Object.create(superClass.prototype); | ||
function _objectWithoutPropertiesLoose(source, excluded) { | ||
if (source == null) return {}; | ||
var target = {}; | ||
var sourceKeys = Object.keys(source); | ||
var key, i; | ||
var createError = function createError(_ref) { | ||
var code = _ref.code, | ||
message = _ref.message; | ||
var err = new Error(message); | ||
err.code = code; | ||
return err; | ||
}; | ||
for (i = 0; i < sourceKeys.length; i++) { | ||
key = sourceKeys[i]; | ||
if (excluded.indexOf(key) >= 0) continue; | ||
target[key] = source[key]; | ||
var parseTokenResponse = function parseTokenResponse(token, license) { | ||
if ('identity_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_IDENTITY_EXCEPTION', | ||
message: token.identity_exception | ||
}); | ||
} | ||
return target; | ||
} | ||
function _assertThisInitialized(self) { | ||
if (self === void 0) { | ||
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); | ||
if ('oauth_exception' in token) { | ||
throw createError({ | ||
code: 'SSO_OAUTH_EXCEPTION', | ||
message: token.oauth_exception | ||
}); | ||
} | ||
return self; | ||
} | ||
var ok = function ok(value) { | ||
return { | ||
type: 'ok', | ||
value: value | ||
}; | ||
}; | ||
var error = function error(err) { | ||
return { | ||
type: 'error', | ||
error: err | ||
}; | ||
}; | ||
var fold = function fold(foldErr, foldValue, result) { | ||
return result.type === 'ok' ? foldValue(result.value) : foldErr(result.error); | ||
}; | ||
var parseTokenResponse = function parseTokenResponse(tokenResponse, _ref) { | ||
var license = _ref.license; | ||
return { | ||
accessToken: tokenResponse.access_token, | ||
entityId: tokenResponse.entity_id, | ||
expiresIn: tokenResponse.expires_in * 1000, | ||
tokenType: tokenResponse.token_type, | ||
accessToken: token.access_token, | ||
entityId: token.entity_id, | ||
expiresIn: token.expires_in * 1000, | ||
tokenType: token.token_type, | ||
creationDate: Date.now(), | ||
@@ -89,27 +53,13 @@ license: license | ||
var parseToken = (function (token, extraData) { | ||
if (token.identity_exception) { | ||
return error({ | ||
code: 'SSO_IDENTITY_EXCEPTION', | ||
message: token.identity_exception | ||
}); | ||
} | ||
// this is the same as "https://accounts.livechatinc.com" | ||
if (token.oauth_exception) { | ||
return error({ | ||
code: 'SSO_OAUTH_EXCEPTION', | ||
message: token.oauth_exception | ||
}); | ||
} | ||
var CUSTOMER_AUTH_FOOTPRINT = '@livechat/customer-auth'; // as const | ||
return ok(parseTokenResponse(token, extraData)); | ||
}); | ||
var ACCOUNTS_URL = "https://accounts.livechatinc.com"; | ||
var buildParams = function buildParams(_ref) { | ||
var buildParams = function buildParams(_ref, redirectUri) { | ||
var clientId = _ref.clientId, | ||
license = _ref.license, | ||
redirectUri = _ref.redirectUri, | ||
state = _ref.state; | ||
var params = { | ||
license_id: license, | ||
license = _ref.license; | ||
return { | ||
license_id: String(license), | ||
flow: 'button', | ||
@@ -119,10 +69,5 @@ response_type: 'token', | ||
redirect_uri: redirectUri, | ||
post_message_uri: redirectUri | ||
post_message_uri: redirectUri, | ||
state: CUSTOMER_AUTH_FOOTPRINT | ||
}; | ||
if (state) { | ||
params.state = state; | ||
} | ||
return params; | ||
}; | ||
@@ -137,18 +82,17 @@ | ||
var buildSrc = (function (config, state, env) { | ||
var url = env === 'production' ? "https://accounts.livechatinc.com" : "https://accounts.livechatinc.com".replace('accounts.', "accounts." + env + "."); | ||
var buildSrc = function buildSrc(config, redirectUri, env) { | ||
var url = env === 'production' ? ACCOUNTS_URL : ACCOUNTS_URL.replace('accounts.', "accounts." + env + "."); | ||
var path = buildPath(config); | ||
var query = urlUtils.buildQueryString(buildParams(_extends({}, config, { | ||
state: state | ||
}))); | ||
var query = urlUtils.buildQueryString(buildParams(config, redirectUri)); | ||
return "" + url + path + "?" + query; | ||
}); | ||
}; | ||
var authWebView; | ||
var injectWebView = function injectWebView(webView) { | ||
return authWebView = webView; | ||
var registerRequest = null; | ||
var injectRegisterRequest = function injectRegisterRequest(_registerRequest) { | ||
return registerRequest = _registerRequest; | ||
}; | ||
var fetchToken = (function (config, env) { | ||
var fetchToken = function fetchToken(config, env) { | ||
return new Promise(function (resolve, reject) { | ||
if (!authWebView) { | ||
if (!registerRequest) { | ||
reject(new Error("You should render { AuthWebView } from '@livechat/customer-auth' first.")); | ||
@@ -158,11 +102,13 @@ return; | ||
authWebView.registerRequest(buildSrc(config, null, env), function (data) { | ||
return fold(reject, resolve, parseToken(data, { | ||
license: config.license | ||
})); | ||
registerRequest(buildSrc(config, config.redirectUri, env), function (token) { | ||
try { | ||
resolve(parseTokenResponse(token, config.license)); | ||
} catch (err) { | ||
reject(err); | ||
} | ||
}); | ||
}); | ||
}); | ||
}; | ||
var validateConfig = (function (_ref) { | ||
var validateConfig = function validateConfig(_ref) { | ||
var license = _ref.license, | ||
@@ -175,24 +121,15 @@ clientId = _ref.clientId, | ||
} | ||
}); | ||
var isExpiredToken = function isExpiredToken(token) { | ||
return Date.now() >= token.creationDate + token.expiresIn; | ||
}; | ||
var withDefaults = function withDefaults(_ref) { | ||
var _ref$uniqueGroups = _ref.uniqueGroups, | ||
uniqueGroups = _ref$uniqueGroups === void 0 ? false : _ref$uniqueGroups, | ||
rest = _objectWithoutPropertiesLoose(_ref, ["uniqueGroups"]); | ||
return _extends({ | ||
uniqueGroups: uniqueGroups | ||
}, rest); | ||
var isExpiredToken = function isExpiredToken(_ref) { | ||
var creationDate = _ref.creationDate, | ||
expiresIn = _ref.expiresIn; | ||
return Date.now() >= creationDate + expiresIn; | ||
}; | ||
var auth = (function (inputConfig, env) { | ||
validateConfig(inputConfig); | ||
var config = withDefaults(inputConfig); | ||
var pendingTokenRequest; | ||
var cachedToken; | ||
var createAuth = function createAuth(config, env) { | ||
validateConfig(config); | ||
var cacheKey = "@@lc_auth_token:" + config.license + (config.uniqueGroups ? ":" + config.group : ''); | ||
var pendingTokenRequest = null; | ||
var cachedToken = null; | ||
var retrievingToken = storage.getItem(cacheKey).then(function (token) { | ||
@@ -211,39 +148,54 @@ if (retrievingToken === null) { | ||
}); | ||
var auth = Object.freeze({ | ||
getFreshToken: function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}).catch(function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
var getFreshToken = function getFreshToken() { | ||
pendingTokenRequest = fetchToken(config, env).then(function (token) { | ||
pendingTokenRequest = null; | ||
storage.setItem(cacheKey, JSON.stringify(token)); | ||
cachedToken = token; | ||
return token; | ||
}, function (err) { | ||
pendingTokenRequest = null; | ||
throw err; | ||
}); | ||
return pendingTokenRequest; | ||
}; | ||
var getToken = function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
}, | ||
getToken: function getToken() { | ||
if (pendingTokenRequest) { | ||
return pendingTokenRequest; | ||
} | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (cachedToken && !isExpiredToken(cachedToken)) { | ||
return Promise.resolve(cachedToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(auth.getToken); | ||
} | ||
if (retrievingToken) { | ||
return retrievingToken.then(getToken); | ||
} | ||
return auth.getFreshToken(); | ||
}, | ||
invalidate: function invalidate() { | ||
storage.removeItem(cacheKey); | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return getFreshToken(); | ||
}; | ||
var hasToken = function hasToken() { | ||
if (retrievingToken) { | ||
return retrievingToken.then(hasToken); | ||
} | ||
}); | ||
return auth; | ||
}); | ||
return Promise.resolve(!!cachedToken); | ||
}; | ||
var invalidate = function invalidate() { | ||
cachedToken = null; | ||
retrievingToken = null; | ||
return storage.removeItem(cacheKey); | ||
}; | ||
return { | ||
getFreshToken: getFreshToken, | ||
getToken: getToken, | ||
hasToken: hasToken, | ||
invalidate: invalidate | ||
}; | ||
}; | ||
var target = reactNative.Platform.select({ | ||
@@ -253,2 +205,3 @@ ios: 'parent', | ||
}); | ||
var WebView = reactNative.WebView; | ||
var AuthWebView = | ||
@@ -259,10 +212,13 @@ /*#__PURE__*/ | ||
function AuthWebView(props) { | ||
function AuthWebView() { | ||
var _this; | ||
_this = _React$Component.call(this, props) || 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 = { | ||
renderWebView: false, | ||
uri: null | ||
@@ -279,4 +235,4 @@ }; | ||
var _this$requestQueue$sh = _this.requestQueue.shift(), | ||
callback = _this$requestQueue$sh.callback; | ||
var _ref = _this.requestQueue.shift(), | ||
callback = _ref.callback; | ||
@@ -292,3 +248,2 @@ callback(tokenResponse); | ||
injectWebView(_assertThisInitialized(_assertThisInitialized(_this))); | ||
return _this; | ||
@@ -299,39 +254,37 @@ } | ||
_proto.makeRequest = function makeRequest() { | ||
this.requesting = true; | ||
var requestUri = this.requestQueue[0].requestUri; | ||
_proto.componentDidMount = function componentDidMount() { | ||
var _this2 = this; | ||
if (!this.state.renderWebView) { | ||
this.setState({ | ||
renderWebView: true, | ||
uri: requestUri | ||
var registerRequest = function registerRequest(uri, callback) { | ||
_this2.requestQueue.push({ | ||
uri: uri, | ||
callback: callback | ||
}); | ||
return; | ||
} | ||
if (this.state.uri === requestUri) { | ||
this.webViewRef.reload(); | ||
return; | ||
} | ||
if (_this2.requesting) { | ||
return; | ||
} | ||
this.setState({ | ||
uri: requestUri | ||
}); | ||
_this2.makeRequest(); | ||
}; | ||
injectRegisterRequest(registerRequest); | ||
}; | ||
_proto.registerRequest = function registerRequest(requestUri, callback) { | ||
this.requestQueue.push({ | ||
requestUri: requestUri, | ||
callback: callback | ||
}); | ||
_proto.makeRequest = function makeRequest() { | ||
this.requesting = true; | ||
var uri = this.requestQueue[0].uri; | ||
if (this.requesting) { | ||
if (this.state.uri === uri) { | ||
this.webViewRef.reload(); | ||
return; | ||
} | ||
this.makeRequest(); | ||
this.setState({ | ||
uri: uri | ||
}); | ||
}; | ||
_proto.render = function render() { | ||
return this.state.renderWebView ? React.createElement(reactNative.WebView, { | ||
return this.state.uri ? React.createElement(WebView, { | ||
injectedJavaScript: target + ".postMessage(location.hash || location.search)", | ||
@@ -350,4 +303,4 @@ onMessage: this.onMessage, | ||
exports.AuthWebView = AuthWebView; | ||
exports.default = auth; | ||
exports.default = createAuth; | ||
exports.isExpiredToken = isExpiredToken; | ||
exports.validateConfig = validateConfig; |
{ | ||
"name": "@livechat/customer-auth", | ||
"version": "0.4.0-alpha.1", | ||
"version": "0.4.0-alpha.2", | ||
"description": "Authorization library for connecting to LiveChat as a customer.", | ||
@@ -16,15 +16,14 @@ "contributors": [ | ||
"dependencies": { | ||
"@livechat/dom-utils": "^0.1.0", | ||
"@livechat/dom-utils": "^0.2.0", | ||
"@livechat/isomorphic-storage": "^0.1.0", | ||
"@livechat/mitt": "^0.1.2", | ||
"@livechat/url-utils": "^0.1.2", | ||
"memory-web-storage": "^0.1.0" | ||
"@livechat/url-utils": "^0.1.3" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.0.0", | ||
"@babel/plugin-proposal-class-properties": "^7.0.0", | ||
"@babel/core": "^7.4.0", | ||
"@babel/plugin-proposal-class-properties": "^7.4.0", | ||
"@babel/plugin-syntax-dynamic-import": "^7.0.0", | ||
"@babel/preset-env": "^7.0.0", | ||
"@babel/preset-env": "^7.4.2", | ||
"@babel/preset-react": "^7.0.0", | ||
"@babel/preset-typescript": "^7.1.0", | ||
"@babel/preset-typescript": "^7.3.3", | ||
"lerna-alias": "3.0.3-0", | ||
@@ -39,3 +38,4 @@ "rimraf": "^2.6.1", | ||
"rollup-plugin-replace": "^1.1.1", | ||
"rollup-plugin-uglify": "^2.0.1" | ||
"rollup-plugin-uglify": "^2.0.1", | ||
"typescript": "^3.6.4" | ||
}, | ||
@@ -42,0 +42,0 @@ "scripts": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
4
21648
17
5
611
2
+ Added@livechat/dom-utils@0.2.6(transitive)
+ Addedcsstype@2.6.21(transitive)
+ Addedtabbable@5.3.3(transitive)
- Removedmemory-web-storage@^0.1.0
- Removed@livechat/dom-utils@0.1.0(transitive)
Updated@livechat/dom-utils@^0.2.0
Updated@livechat/url-utils@^0.1.3