@ambassify/ambassify-client
Advanced tools
Comparing version 4.1.0 to 5.0.0
@@ -14,2 +14,13 @@ # Changelog | ||
## 5.0.0 | ||
#### :boom: Breaking Change | ||
- Target [ambassify-approved browsers](https://github.com/ambassify/browserslist-config) during build | ||
#### :nail_care: Polish | ||
- Switch to `@babel/polyfills` for polyfilling. This replaces the `@babel/runtime-corejs3` peer dependency with `@babel/runtime` and `core-js-pure` peer dependencies. It makes sure only polyfills required for the `targets` config are added during build. | ||
- Update `@ambassify/fetch-api` to version that matches this new build strategy | ||
## 4.1.0 | ||
@@ -100,1 +111,11 @@ | ||
412
lib/index.js
"use strict"; | ||
var _Reflect$construct = require("@babel/runtime-corejs3/core-js-stable/reflect/construct"); | ||
const _get = require('lodash/get'); | ||
var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys"); | ||
const _set = require('lodash/set'); | ||
var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"); | ||
const serializeFields = require('@ambassify/aql-serializer').fields; | ||
var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter"); | ||
const FetchApi = require('@ambassify/fetch-api'); | ||
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"); | ||
const AmbassifyError = require('@ambassify/error'); | ||
var _forEachInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/for-each"); | ||
const jwt = require('./jwt'); | ||
var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"); | ||
const { | ||
isRefreshEnabled, | ||
doRefreshToken, | ||
doCachedRefreshToken | ||
} = require('./refresh-token'); | ||
var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties"); | ||
FetchApi.defineContentType('JSON', require('@ambassify/fetch-api/lib/content-type/json')); | ||
var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); | ||
class AmbassifyApi extends FetchApi { | ||
static impersonate() { | ||
let guardianConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
let tokenOptions = arguments.length > 1 ? arguments[1] : undefined; | ||
let clientOptions = arguments.length > 2 ? arguments[2] : undefined; | ||
const { | ||
baseUrl = '', | ||
clientId, | ||
clientSecret, | ||
guestToken | ||
} = guardianConfig; | ||
const guardian = new AmbassifyApi({ | ||
baseUrl, | ||
tokenType: 'Bearer', | ||
token: guestToken | ||
}); | ||
tokenOptions = { | ||
include_refresh: true, | ||
...tokenOptions, | ||
grant_type: 'ambassify:impersonate', | ||
client_id: clientId, | ||
client_secret: clientSecret | ||
}; | ||
return guardian.post('/token', tokenOptions).then(res => { | ||
if (!res.ok) { | ||
throw AmbassifyError.fromExternal({ | ||
message: 'Failed to retrieve token', | ||
response: { | ||
status: res.status, | ||
statusText: res.statusText, | ||
body: res.body, | ||
text: JSON.stringify(res.body) | ||
} | ||
}); | ||
} | ||
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); | ||
const { | ||
access_token, | ||
refresh_token | ||
} = res.body; | ||
const tokenData = jwt.decode(access_token); | ||
return new this({ | ||
tokenType: 'Bearer', | ||
token: access_token, | ||
refreshToken: refresh_token, | ||
clientId, | ||
clientSecret, | ||
tokenEndpoint: baseUrl.replace(/\/*$/, '') + '/token', | ||
tokenAuthorization: guestToken ? `Bearer ${guestToken}` : undefined, | ||
organization: tokenData && tokenData.oid, | ||
...clientOptions | ||
}); | ||
}); | ||
} | ||
var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); | ||
static addAuthenticationOptions(options) { | ||
// If no token is set we don't need to update any options | ||
if (!options.token) return options; | ||
let { | ||
tokenType = 'Bearer', | ||
headers, | ||
fetchOptions | ||
} = options; | ||
/** | ||
* If `tokenType` is set to `Cookie` we must set the `credentials` | ||
* option for Fetch requests to add and accept cookies on requests. | ||
* | ||
* Cookie-auth also means that the actual token type is a Basic token. | ||
*/ | ||
var _now = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/date/now")); | ||
if (tokenType.toLowerCase() == 'cookie') { | ||
tokenType = 'Basic'; | ||
fetchOptions = { | ||
credentials: 'include', | ||
...fetchOptions | ||
}; | ||
} | ||
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify")); | ||
headers = { | ||
authorization: `${tokenType} ${options.token}`, | ||
...headers | ||
}; | ||
return { ...options, | ||
headers, | ||
fetchOptions | ||
}; | ||
} | ||
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/objectWithoutProperties")); | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray")); | ||
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); | ||
var _get3 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/get")); | ||
var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inherits")); | ||
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/possibleConstructorReturn")); | ||
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/getPrototypeOf")); | ||
function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); if (enumerableOnly) symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { var _context3; _forEachInstanceProperty(_context3 = ownKeys(Object(source), true)).call(_context3, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (_Object$getOwnPropertyDescriptors) { _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)); } else { var _context4; _forEachInstanceProperty(_context4 = ownKeys(Object(source))).call(_context4, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } | ||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } | ||
var _get = require('lodash/get'); | ||
var _set = require('lodash/set'); | ||
var serializeFields = require('@ambassify/aql-serializer').fields; | ||
var FetchApi = require('@ambassify/fetch-api'); | ||
var AmbassifyError = require('@ambassify/error'); | ||
var jwt = require('./jwt'); | ||
var _require = require('./refresh-token'), | ||
isRefreshEnabled = _require.isRefreshEnabled, | ||
doRefreshToken = _require.doRefreshToken, | ||
doCachedRefreshToken = _require.doCachedRefreshToken; | ||
FetchApi.defineContentType('JSON', require('@ambassify/fetch-api/lib/content-type/json')); | ||
var AmbassifyApi = /*#__PURE__*/function (_FetchApi) { | ||
(0, _inherits2["default"])(AmbassifyApi, _FetchApi); | ||
var _super = _createSuper(AmbassifyApi); | ||
function AmbassifyApi() { | ||
var _this; | ||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
(0, _classCallCheck2["default"])(this, AmbassifyApi); | ||
constructor() { | ||
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
options = AmbassifyApi.addAuthenticationOptions(options); | ||
var retry = options.retry; | ||
let retry = options.retry; | ||
if (typeof retry === 'number') retry = { | ||
@@ -91,201 +120,94 @@ retries: options.retry | ||
if (retry !== false) { | ||
retry = _objectSpread({ | ||
retry = { | ||
retries: 3, | ||
delay: 100 | ||
}, retry); | ||
delay: 100, | ||
...retry | ||
}; | ||
} | ||
_this = _super.call(this, _objectSpread(_objectSpread({}, options), {}, { | ||
super({ ...options, | ||
contentType: options.contentType || FetchApi.ContentTypes.JSON, | ||
retry: retry | ||
})); | ||
_this.options = options; | ||
return _this; | ||
retry | ||
}); | ||
this.options = options; | ||
} | ||
(0, _createClass2["default"])(AmbassifyApi, [{ | ||
key: "_stringifyFields", | ||
value: function _stringifyFields(fields) { | ||
return serializeFields(fields); | ||
} | ||
}, { | ||
key: "_getResources", | ||
value: function _getResources(resourceName, response) { | ||
var resources = _get(response, 'body._embedded', {}); | ||
_stringifyFields(fields) { | ||
return serializeFields(fields); | ||
} | ||
return resources[resourceName] || []; | ||
} | ||
}, { | ||
key: "_getNextUrl", | ||
value: function _getNextUrl(url, response) { | ||
return _get(response, 'body._links.next.href'); | ||
} | ||
}, { | ||
key: "refreshTokenEnabled", | ||
value: function refreshTokenEnabled() { | ||
return isRefreshEnabled(this.options); | ||
} | ||
}, { | ||
key: "refreshToken", | ||
value: function refreshToken() { | ||
var _this2 = this; | ||
_getResources(resourceName, response) { | ||
const resources = _get(response, 'body._embedded', {}); | ||
return doRefreshToken(this.fetch, this.options).then(function (res) { | ||
return _this2._updateAuthentication(res); | ||
}); | ||
} | ||
}, { | ||
key: "_updateAuthentication", | ||
value: function _updateAuthentication(options) { | ||
var _context; | ||
return resources[resourceName] || []; | ||
} | ||
var token = options.token, | ||
tokenType = options.tokenType, | ||
refreshToken = options.refreshToken; | ||
if (refreshToken) this.options.refreshToken = refreshToken; | ||
this.headers['authorization'] = (0, _concat["default"])(_context = "".concat(tokenType, " ")).call(_context, token); | ||
} | ||
}, { | ||
key: "_request", | ||
value: function _request(url, options) { | ||
var _this3 = this; | ||
_getNextUrl(url, response) { | ||
return _get(response, 'body._links.next.href'); | ||
} | ||
if (!this.refreshTokenEnabled()) return (0, _get3["default"])((0, _getPrototypeOf2["default"])(AmbassifyApi.prototype), "_request", this).call(this, url, options); | ||
refreshTokenEnabled() { | ||
return isRefreshEnabled(this.options); | ||
} | ||
var authorization = _get(options, 'headers.authorization', ''); | ||
refreshToken() { | ||
return doRefreshToken(this.fetch, this.options).then(res => this._updateAuthentication(res)); | ||
} | ||
var _ref = /^Bearer\s+(.*)/i.exec(authorization) || [], | ||
_ref2 = (0, _slicedToArray2["default"])(_ref, 2), | ||
token = _ref2[1]; | ||
_updateAuthentication(options) { | ||
const { | ||
token, | ||
tokenType, | ||
refreshToken | ||
} = options; | ||
if (refreshToken) this.options.refreshToken = refreshToken; | ||
this.headers['authorization'] = `${tokenType} ${token}`; | ||
} | ||
if (!token) return (0, _get3["default"])((0, _getPrototypeOf2["default"])(AmbassifyApi.prototype), "_request", this).call(this, url, options); | ||
var data = jwt.decode(token); | ||
var now = Math.floor((0, _now["default"])() / 1000); | ||
if (!data || !data.exp || data.exp > now + 60) return (0, _get3["default"])((0, _getPrototypeOf2["default"])(AmbassifyApi.prototype), "_request", this).call(this, url, options); | ||
return doCachedRefreshToken(this.fetch, _objectSpread(_objectSpread({}, this.options), {}, { | ||
token: token | ||
})).then(function (res) { | ||
_this3._updateAuthentication(res); | ||
_request(url, options) { | ||
if (!this.refreshTokenEnabled()) return super._request(url, options); | ||
_set(options, 'headers.authorization', 'Bearer ' + res.token); | ||
const authorization = _get(options, 'headers.authorization', ''); | ||
return (0, _get3["default"])((0, _getPrototypeOf2["default"])(AmbassifyApi.prototype), "_request", _this3).call(_this3, url, options); | ||
}); | ||
} | ||
}, { | ||
key: "request", | ||
value: function request(method, url, query, body) { | ||
var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
const [, token] = /^Bearer\s+(.*)/i.exec(authorization) || []; | ||
if (!token) return super._request(url, options); | ||
const data = jwt.decode(token); | ||
const now = Math.floor(Date.now() / 1000); | ||
if (!data || !data.exp || data.exp > now + 60) return super._request(url, options); | ||
return doCachedRefreshToken(this.fetch, { ...this.options, | ||
token | ||
}).then(res => { | ||
this._updateAuthentication(res); | ||
if (options.fields) { | ||
var _options = options, | ||
fields = _options.fields, | ||
rest = (0, _objectWithoutProperties2["default"])(_options, ["fields"]); | ||
query = _objectSpread(_objectSpread({}, query), {}, { | ||
fields: this._stringifyFields(fields) | ||
}); | ||
options = rest; | ||
} | ||
_set(options, 'headers.authorization', 'Bearer ' + res.token); | ||
var promise = (0, _get3["default"])((0, _getPrototypeOf2["default"])(AmbassifyApi.prototype), "request", this).call(this, method, url, query, body, options); | ||
promise.hal = { | ||
embedded: function embedded(resourceName) { | ||
return promise.then(function (res) { | ||
return _get(res.body, "_embedded.".concat(resourceName)) || []; | ||
}); | ||
} | ||
}; | ||
return promise; | ||
} | ||
}], [{ | ||
key: "impersonate", | ||
value: function impersonate() { | ||
var _this4 = this; | ||
return super._request(url, options); | ||
}); | ||
} | ||
var guardianConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
var tokenOptions = arguments.length > 1 ? arguments[1] : undefined; | ||
var clientOptions = arguments.length > 2 ? arguments[2] : undefined; | ||
var _guardianConfig$baseU = guardianConfig.baseUrl, | ||
baseUrl = _guardianConfig$baseU === void 0 ? '' : _guardianConfig$baseU, | ||
clientId = guardianConfig.clientId, | ||
clientSecret = guardianConfig.clientSecret, | ||
guestToken = guardianConfig.guestToken; | ||
var guardian = new AmbassifyApi({ | ||
baseUrl: baseUrl, | ||
tokenType: 'Bearer', | ||
token: guestToken | ||
}); | ||
tokenOptions = _objectSpread(_objectSpread({ | ||
include_refresh: true | ||
}, tokenOptions), {}, { | ||
grant_type: 'ambassify:impersonate', | ||
client_id: clientId, | ||
client_secret: clientSecret | ||
}); | ||
return guardian.post('/token', tokenOptions).then(function (res) { | ||
if (!res.ok) { | ||
throw AmbassifyError.fromExternal({ | ||
message: 'Failed to retrieve token', | ||
response: { | ||
status: res.status, | ||
statusText: res.statusText, | ||
body: res.body, | ||
text: (0, _stringify["default"])(res.body) | ||
} | ||
}); | ||
} | ||
request(method, url, query, body) { | ||
let options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; | ||
var _res$body = res.body, | ||
access_token = _res$body.access_token, | ||
refresh_token = _res$body.refresh_token; | ||
var tokenData = jwt.decode(access_token); | ||
return new _this4(_objectSpread({ | ||
tokenType: 'Bearer', | ||
token: access_token, | ||
refreshToken: refresh_token, | ||
clientId: clientId, | ||
clientSecret: clientSecret, | ||
tokenEndpoint: baseUrl.replace(/\/*$/, '') + '/token', | ||
tokenAuthorization: guestToken ? "Bearer ".concat(guestToken) : undefined, | ||
organization: tokenData && tokenData.oid | ||
}, clientOptions)); | ||
}); | ||
if (options.fields) { | ||
const { | ||
fields, | ||
...rest | ||
} = options; | ||
query = { ...query, | ||
fields: this._stringifyFields(fields) | ||
}; | ||
options = rest; | ||
} | ||
}, { | ||
key: "addAuthenticationOptions", | ||
value: function addAuthenticationOptions(options) { | ||
var _context2; | ||
// If no token is set we don't need to update any options | ||
if (!options.token) return options; | ||
var _options$tokenType = options.tokenType, | ||
tokenType = _options$tokenType === void 0 ? 'Bearer' : _options$tokenType, | ||
headers = options.headers, | ||
fetchOptions = options.fetchOptions; | ||
/** | ||
* If `tokenType` is set to `Cookie` we must set the `credentials` | ||
* option for Fetch requests to add and accept cookies on requests. | ||
* | ||
* Cookie-auth also means that the actual token type is a Basic token. | ||
*/ | ||
const promise = super.request(method, url, query, body, options); | ||
promise.hal = { | ||
embedded: resourceName => promise.then(res => { | ||
return _get(res.body, `_embedded.${resourceName}`) || []; | ||
}) | ||
}; | ||
return promise; | ||
} | ||
if (tokenType.toLowerCase() == 'cookie') { | ||
tokenType = 'Basic'; | ||
fetchOptions = _objectSpread({ | ||
credentials: 'include' | ||
}, fetchOptions); | ||
} | ||
} | ||
headers = _objectSpread({ | ||
authorization: (0, _concat["default"])(_context2 = "".concat(tokenType, " ")).call(_context2, options.token) | ||
}, headers); | ||
return _objectSpread(_objectSpread({}, options), {}, { | ||
headers: headers, | ||
fetchOptions: fetchOptions | ||
}); | ||
} | ||
}]); | ||
return AmbassifyApi; | ||
}(FetchApi); | ||
module.exports = AmbassifyApi; |
"use strict"; | ||
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray")); | ||
var decodeBase64 = require('compact-base64').decode; | ||
const decodeBase64 = require('compact-base64').decode; | ||
/** | ||
@@ -15,9 +11,6 @@ * As long as we only need to decode, we can use this small utility that does | ||
module.exports = { | ||
decode: function decode(jwt) { | ||
decode(jwt) { | ||
try { | ||
var _jwt$split = jwt.split('.'), | ||
_jwt$split2 = (0, _slicedToArray2["default"])(_jwt$split, 2), | ||
encoded = _jwt$split2[1]; | ||
var json = decodeBase64(encoded); | ||
const [, encoded] = jwt.split('.'); | ||
const json = decodeBase64(encoded); | ||
return JSON.parse(json); | ||
@@ -28,2 +21,3 @@ } catch (e) { | ||
} | ||
}; |
"use strict"; | ||
var _Reflect$construct = require("@babel/runtime-corejs3/core-js-stable/reflect/construct"); | ||
const safeJson = require('@ambassify/json-parse-safe'); | ||
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); | ||
const AmbassifyError = require('@ambassify/error'); | ||
var _stringify = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/json/stringify")); | ||
const throttle = require('@ambassify/throttle'); | ||
var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise")); | ||
const jwt = require('./jwt'); | ||
var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter")); | ||
class TokenRefreshFailed extends AmbassifyError { | ||
static code() { | ||
return 'TokenRefreshFailed'; | ||
} | ||
var _now = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/date/now")); | ||
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray")); | ||
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck")); | ||
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/createClass")); | ||
var _inherits2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/inherits")); | ||
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/possibleConstructorReturn")); | ||
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/getPrototypeOf")); | ||
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2["default"])(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2["default"])(this).constructor; result = _Reflect$construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2["default"])(this, result); }; } | ||
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !_Reflect$construct) return false; if (_Reflect$construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } | ||
var safeJson = require('@ambassify/json-parse-safe'); | ||
var AmbassifyError = require('@ambassify/error'); | ||
var throttle = require('@ambassify/throttle'); | ||
var jwt = require('./jwt'); | ||
var TokenRefreshFailed = /*#__PURE__*/function (_AmbassifyError) { | ||
(0, _inherits2["default"])(TokenRefreshFailed, _AmbassifyError); | ||
var _super = _createSuper(TokenRefreshFailed); | ||
function TokenRefreshFailed() { | ||
(0, _classCallCheck2["default"])(this, TokenRefreshFailed); | ||
return _super.apply(this, arguments); | ||
[AmbassifyError.getHttpResponse]() { | ||
return { | ||
statusCode: 403, | ||
body: { | ||
message: 'Failed to refresh access token' | ||
} | ||
}; | ||
} | ||
(0, _createClass2["default"])(TokenRefreshFailed, [{ | ||
key: AmbassifyError.getHttpResponse, | ||
value: function value() { | ||
return { | ||
statusCode: 403, | ||
body: { | ||
message: 'Failed to refresh access token' | ||
} | ||
}; | ||
} | ||
}], [{ | ||
key: "code", | ||
value: function code() { | ||
return 'TokenRefreshFailed'; | ||
} | ||
}]); | ||
return TokenRefreshFailed; | ||
}(AmbassifyError); | ||
} | ||
function isRefreshEnabled(options) { | ||
var clientId = options.clientId, | ||
tokenEndpoint = options.tokenEndpoint, | ||
refreshToken = options.refreshToken; | ||
const { | ||
clientId, | ||
tokenEndpoint, | ||
refreshToken | ||
} = options; | ||
return !!(clientId && tokenEndpoint && refreshToken); | ||
@@ -76,7 +37,7 @@ } | ||
function strHash(str) { | ||
var hash = 0; | ||
let hash = 0; | ||
if (this.length == 0) return hash; | ||
for (var i = 0; i < str.length; i++) { | ||
var c = str.charCodeAt(i); | ||
for (let i = 0; i < str.length; i++) { | ||
const c = str.charCodeAt(i); | ||
hash = (hash << 5) - hash + c; | ||
@@ -90,8 +51,10 @@ hash = hash & hash; // Convert to 32bit integer | ||
function doExternalRefresh(fetch, options) { | ||
var clientId = options.clientId, | ||
clientSecret = options.clientSecret, | ||
refreshToken = options.refreshToken, | ||
tokenEndpoint = options.tokenEndpoint, | ||
tokenAuthorization = options.tokenAuthorization; | ||
var reqOptions = { | ||
const { | ||
clientId, | ||
clientSecret, | ||
refreshToken, | ||
tokenEndpoint, | ||
tokenAuthorization | ||
} = options; | ||
const reqOptions = { | ||
method: 'POST', | ||
@@ -101,3 +64,3 @@ headers: { | ||
}, | ||
body: (0, _stringify["default"])({ | ||
body: JSON.stringify({ | ||
grant_type: 'refresh_token', | ||
@@ -114,8 +77,10 @@ client_id: clientId, | ||
function doInternalRefresh(fetch, options) { | ||
var clientId = options.clientId, | ||
clientSecret = options.clientSecret, | ||
refreshToken = options.refreshToken, | ||
tokenEndpoint = options.tokenEndpoint, | ||
tokenAuthorization = options.tokenAuthorization; | ||
var reqOptions = { | ||
const { | ||
clientId, | ||
clientSecret, | ||
refreshToken, | ||
tokenEndpoint, | ||
tokenAuthorization | ||
} = options; | ||
const reqOptions = { | ||
method: 'POST', | ||
@@ -125,3 +90,3 @@ headers: { | ||
}, | ||
body: (0, _stringify["default"])({ | ||
body: JSON.stringify({ | ||
grant_type: 'ambassify:refresh_token/internal', | ||
@@ -138,28 +103,18 @@ client_id: clientId, | ||
function doRefreshToken(fetch, options) { | ||
if (!isRefreshEnabled(options)) return _promise["default"].reject(new TokenRefreshFailed('Refresh token is not enabled')); | ||
var _options$tokenType = options.tokenType, | ||
tokenType = _options$tokenType === void 0 ? 'Bearer' : _options$tokenType; | ||
return _promise["default"].all([doInternalRefresh(fetch, options)["catch"](function () { | ||
return null; | ||
}), doExternalRefresh(fetch, options)["catch"](function () { | ||
return null; | ||
})]).then(function (results) { | ||
results = (0, _filter["default"])(results).call(results, Boolean); | ||
var res = (0, _filter["default"])(results).call(results, function (r) { | ||
return r.ok; | ||
}).pop() || results.pop(); | ||
if (!isRefreshEnabled(options)) return Promise.reject(new TokenRefreshFailed('Refresh token is not enabled')); | ||
const { | ||
tokenType = 'Bearer' | ||
} = options; | ||
return Promise.all([doInternalRefresh(fetch, options).catch(() => null), doExternalRefresh(fetch, options).catch(() => null)]).then(results => { | ||
results = results.filter(Boolean); | ||
const res = results.filter(r => r.ok).pop() || results.pop(); | ||
if (!res) throw new TokenRefreshFailed({}); | ||
return res; | ||
}).then(function (res) { | ||
return _promise["default"].all([res, res.text()]); | ||
}).then(function (_ref) { | ||
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2), | ||
res = _ref2[0], | ||
text = _ref2[1]; | ||
}).then(res => Promise.all([res, res.text()])).then(_ref => { | ||
let [res, text] = _ref; | ||
const json = safeJson(text); | ||
var json = safeJson(text); | ||
if (res.ok && json) { | ||
return { | ||
tokenType: tokenType, | ||
tokenType, | ||
token: json.access_token, | ||
@@ -186,32 +141,33 @@ refreshToken: json.refresh_token | ||
var MAX_TTL = 59 * 60 * 1000; // 59 minutes (tokens are usually valid for an hour) | ||
const MAX_TTL = 59 * 60 * 1000; // 59 minutes (tokens are usually valid for an hour) | ||
var doCachedRefreshToken = throttle(doRefreshToken, MAX_TTL, { | ||
const doCachedRefreshToken = throttle(doRefreshToken, MAX_TTL, { | ||
rejectFailedPromise: true, | ||
resolver: function resolver(f, _ref3) { | ||
var token = _ref3.token, | ||
refreshToken = _ref3.refreshToken, | ||
clientId = _ref3.clientId, | ||
tokenEndpoint = _ref3.tokenEndpoint, | ||
tokenAuthorization = _ref3.tokenAuthorization; | ||
resolver: (f, _ref2) => { | ||
let { | ||
token, | ||
refreshToken, | ||
clientId, | ||
tokenEndpoint, | ||
tokenAuthorization | ||
} = _ref2; | ||
return clientId + strHash(token + refreshToken + tokenEndpoint + tokenAuthorization); | ||
}, | ||
onCached: function onCached(item) { | ||
return item.value.then(function (_ref4) { | ||
var token = _ref4.token; | ||
var _ref5 = jwt.decode(token) || {}, | ||
exp = _ref5.exp; | ||
if (!exp) return; | ||
var ttl = (exp - 60) * 1000 - (0, _now["default"])(); | ||
ttl = Math.max(0, Math.min(MAX_TTL, ttl)); | ||
item.ttl(ttl); | ||
})["catch"](function () {}); | ||
} | ||
onCached: item => item.value.then(_ref3 => { | ||
let { | ||
token | ||
} = _ref3; | ||
const { | ||
exp | ||
} = jwt.decode(token) || {}; | ||
if (!exp) return; | ||
let ttl = (exp - 60) * 1000 - Date.now(); | ||
ttl = Math.max(0, Math.min(MAX_TTL, ttl)); | ||
item.ttl(ttl); | ||
}).catch(() => {}) | ||
}); | ||
module.exports = { | ||
isRefreshEnabled: isRefreshEnabled, | ||
doRefreshToken: doRefreshToken, | ||
doCachedRefreshToken: doCachedRefreshToken | ||
isRefreshEnabled, | ||
doRefreshToken, | ||
doCachedRefreshToken | ||
}; |
{ | ||
"name": "@ambassify/ambassify-client", | ||
"version": "4.1.0", | ||
"version": "5.0.0", | ||
"description": "Base API client library for all Ambassify clients", | ||
@@ -23,3 +23,3 @@ "engines": { | ||
"@ambassify/error": "^1.0.1", | ||
"@ambassify/fetch-api": "^3.3.0", | ||
"@ambassify/fetch-api": "^4.0.0", | ||
"@ambassify/json-parse-safe": "^1.1.0", | ||
@@ -31,2 +31,3 @@ "@ambassify/throttle": "^0.1.8", | ||
"devDependencies": { | ||
"@ambassify/browserslist-config": "^1.0.1", | ||
"@babel/cli": "^7.12.16", | ||
@@ -36,2 +37,3 @@ "@babel/core": "^7.12.16", | ||
"@babel/preset-env": "^7.12.16", | ||
"babel-plugin-polyfill-corejs3": "^0.3.0", | ||
"eslint": "^7.20.0", | ||
@@ -46,5 +48,2 @@ "eslint-config-ambassify": "^2.0.2", | ||
}, | ||
"peerDependencies": { | ||
"@babel/runtime-corejs3": ">=7" | ||
}, | ||
"publishConfig": { | ||
@@ -61,3 +60,7 @@ "access": "public" | ||
"homepage": "https://github.com/ambassify/api-clients#readme", | ||
"gitHead": "a05866fc9f60257ad978e7186ee1c4f53e5eaf43" | ||
"peerDependencies": { | ||
"@babel/runtime": ">=7", | ||
"core-js-pure": ">=3" | ||
}, | ||
"gitHead": "fda8c8966b07932dce62f44438c420020ce521fe" | ||
} |
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
SPDX disjunction
LicenseSPDX disjunction for an artifact's license information
Found 1 instance in 1 package
40718
9
14
1079
+ Added@babel/runtime@7.24.7(transitive)
- Removed@babel/runtime-corejs3@7.24.7(transitive)
Updated@ambassify/fetch-api@^4.0.0