@shoutem/fetch-token-intercept
Advanced tools
Comparing version 0.2.2 to 0.3.0
@@ -47,3 +47,3 @@ "use strict"; | ||
/** | ||
* Renews current access token with provided refresh token | ||
* Configures access token provider | ||
*/ | ||
@@ -53,2 +53,12 @@ | ||
_createClass(AccessTokenProvider, [{ | ||
key: "configure", | ||
value: function configure(config) { | ||
this.config = _extends({}, this.config, config); | ||
} | ||
/** | ||
* Renews current access token with provided refresh token | ||
*/ | ||
}, { | ||
key: "renew", | ||
@@ -55,0 +65,0 @@ value: function renew() { |
@@ -13,2 +13,6 @@ 'use strict'; | ||
var _isFunction = require('lodash/isFunction'); | ||
var _isFunction2 = _interopRequireDefault(_isFunction); | ||
var _const = require('./const'); | ||
@@ -32,6 +36,6 @@ | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
@@ -42,5 +46,65 @@ | ||
/** | ||
* Prepares signed request object which can be used for renewing access token | ||
* | ||
* @callback createAccessTokenRequest | ||
* @param {string} refreshToken Refresh token used to sign the request | ||
* @returns {Request} Signed request object which can be used to get access token | ||
*/ | ||
/** | ||
* Parses access token from access token response object | ||
* | ||
* @callback parseAccessToken | ||
* @param {Response} response Response object with access token | ||
* @returns {string} Access token parsed from response | ||
*/ | ||
/** | ||
* Checks whether interceptor will intercept this request or just let it pass through | ||
* | ||
* @callback shouldIntercept | ||
* @param {Request} request Request object | ||
* @returns {bool} A value indicating whether this request should be intercepted | ||
*/ | ||
/** | ||
* Checks whether provided response invalidates current access token | ||
* | ||
* @callback shouldInvalidateAccessToken | ||
* @param {Response} response Response object | ||
* @returns {bool} A value indicating whether token should be invalidated | ||
*/ | ||
/** | ||
* Adds authorization for intercepted requests | ||
* | ||
* @callback authorizeRequest | ||
* @param {Request} request Request object being intercepted | ||
* @param {string} accessToken Current access token | ||
* @returns {Request} Authorized request object | ||
*/ | ||
var getDefaultConfig = function getDefaultConfig() { | ||
return { | ||
fetchRetryCount: 1, | ||
createAccessTokenRequest: null, | ||
shouldIntercept: function shouldIntercept() { | ||
return false; | ||
}, | ||
shouldInvalidateAccessToken: function shouldInvalidateAccessToken() { | ||
return false; | ||
}, | ||
isResponseUnauthorized: http.isResponseUnauthorized, | ||
parseAccessToken: null, | ||
authorizeRequest: null, | ||
onAccessTokenChange: null, | ||
onResponse: null | ||
}; | ||
}; | ||
/** | ||
* Provides a default implementation for intercepting fetch requests. It will try to resolve | ||
* unauthorized responses by renewing the access token and repeating the initial request. | ||
*/ | ||
var FetchInterceptor = function () { | ||
@@ -52,18 +116,5 @@ function FetchInterceptor(fetch) { | ||
this.fetch = fetch; | ||
this.accessTokenProvider = new _AccessTokenProvider2.default(this.fetch); | ||
this.config = { | ||
fetchRetryCount: 1, | ||
createAccessTokenRequest: null, | ||
shouldIntercept: function shouldIntercept() { | ||
return true; | ||
}, | ||
shouldInvalidateAccessToken: function shouldInvalidateAccessToken() { | ||
return false; | ||
}, | ||
isResponseUnauthorized: http.isResponseUnauthorized, | ||
parseAccessToken: null, | ||
authorizeRequest: null, | ||
onAccessTokenChange: null, | ||
onResponse: null | ||
}; | ||
this.config = getDefaultConfig(); | ||
@@ -91,33 +142,24 @@ this.intercept = this.intercept.bind(this); | ||
* | ||
* @param config | ||
* | ||
* (Required) Prepare fetch request for renewing new access token | ||
* createAccessTokenRequest: (refreshToken) => request, | ||
* | ||
* (Required) Parses access token from access token response | ||
* parseAccessToken: (response) => accessToken, | ||
* | ||
* (Required) Defines whether interceptor will intercept this request or just let it pass through | ||
* shouldIntercept: (request) => boolean, | ||
* | ||
* (Required) Defines whether access token will be invalidated after this response | ||
* shouldInvalidateAccessToken: (response) => boolean, | ||
* | ||
* (Required) Adds authorization for intercepted requests | ||
* authorizeRequest: (request, accessToken) => authorizedRequest, | ||
* | ||
* Checks if response should be considered unauthorized (by default only 401 responses are | ||
* considered unauthorized. Override this method if you need to trigger token renewal for | ||
* other response statuses. | ||
* isResponseUnauthorized: (response) => boolean, | ||
* | ||
* Number of retries after initial request was unauthorized | ||
* fetchRetryCount: 1, | ||
* | ||
* Event invoked when access token has changed | ||
* onAccessTokenChange: null, | ||
* | ||
* Event invoked when response is resolved | ||
* onResponse: null, | ||
* | ||
* @param {object} config | ||
* @param {createAccessTokenRequest} config.createAccessTokenRequest | ||
* Prepare fetch request for renewing new access token | ||
* @param {parseAccessToken} config.parseAccessToken | ||
* Parses access token from access token response | ||
* @param {shouldIntercept} config.shouldIntercept | ||
* Defines whether interceptor will intercept this request or just let it pass through | ||
* @param {shouldInvalidateAccessToken} config.shouldInvalidateAccessToken | ||
* Defines whether access token will be invalidated after this response | ||
* @param {authorizeRequest} config.authorizeRequest | ||
* Adds authorization for intercepted requests | ||
* @param {function} [config.isResponseUnauthorized=null] | ||
* Checks if response should be considered unauthorized (by default only 401 responses are | ||
* considered unauthorized. Override this method if you need to trigger token renewal for | ||
* other response statuses. | ||
* @param {number} [config.fetchRetryCount=1] | ||
* Number of retries after initial request was unauthorized | ||
* @param {number} [config.onAccessTokenChange=null] | ||
* Event invoked when access token has changed | ||
* @param {number} [config.onResponse=null] | ||
* Event invoked when response is resolved | ||
* </pre> | ||
*/ | ||
@@ -135,3 +177,3 @@ | ||
this.accessTokenProvider = new _AccessTokenProvider2.default(this.fetch, this.config); | ||
this.accessTokenProvider.configure(this.config); | ||
} | ||
@@ -141,4 +183,4 @@ | ||
* Authorizes fetch interceptor with given refresh token | ||
* @param refreshToken | ||
* @param accessToken | ||
* @param {string} refreshToken Refresh token | ||
* @param {string} accessToken Access token | ||
*/ | ||
@@ -174,2 +216,14 @@ | ||
/** | ||
* Clears current authorization and restores default configuration, e.g. interceptor | ||
* will stop intercepting requests. | ||
*/ | ||
}, { | ||
key: 'unload', | ||
value: function unload() { | ||
this.clear(); | ||
this.config = getDefaultConfig(); | ||
} | ||
/** | ||
* Main intercept method, you should chain this inside wrapped fetch call | ||
@@ -196,3 +250,3 @@ * @param args Args initially provided to fetch method | ||
value: function isConfigValid() { | ||
return this.config.shouldIntercept && this.config.authorizeRequest && this.config.createAccessTokenRequest && this.config.parseAccessToken; | ||
return this.config.shouldIntercept && (0, _isFunction2.default)(this.config.shouldIntercept) && this.config.authorizeRequest && (0, _isFunction2.default)(this.config.authorizeRequest) && this.config.isResponseUnauthorized && (0, _isFunction2.default)(this.config.isResponseUnauthorized) && this.config.createAccessTokenRequest && (0, _isFunction2.default)(this.config.createAccessTokenRequest) && this.config.parseAccessToken && (0, _isFunction2.default)(this.config.parseAccessToken); | ||
} | ||
@@ -199,0 +253,0 @@ }, { |
@@ -12,2 +12,4 @@ 'use strict'; | ||
exports.clear = clear; | ||
exports.isActive = isActive; | ||
exports.unload = unload; | ||
@@ -25,2 +27,3 @@ var _environment = require('./services/environment'); | ||
var interceptor = null; | ||
var environment = null; | ||
@@ -52,20 +55,29 @@ function attach(env) { | ||
function init() { | ||
if ((0, _environment.isReactNative)()) { | ||
attach(global); | ||
} else if ((0, _environment.isWorker)()) { | ||
attach(self); | ||
} else if ((0, _environment.isWeb)()) { | ||
attach(window); | ||
} else if ((0, _environment.isNode)()) { | ||
attach(global); | ||
} else { | ||
function initialize() { | ||
environment = (0, _environment.resolveEnvironment)(); | ||
if (!environment) { | ||
throw new Error('Unsupported environment for fetch-token-intercept'); | ||
} | ||
attach(environment); | ||
} | ||
/** | ||
* Initializes and configures interceptor | ||
* @param config Configuration object | ||
* @see FetchInterceptor#configure | ||
*/ | ||
function configure(config) { | ||
if (!interceptor) { | ||
initialize(); | ||
} | ||
interceptor.configure(config); | ||
} | ||
/** | ||
* Initializes tokens which will be used by interceptor | ||
* @param args | ||
* @see FetchInterceptor#authorize | ||
*/ | ||
function authorize() { | ||
@@ -77,2 +89,6 @@ var _interceptor2; | ||
/** | ||
* Returns current set of tokens used by interceptor | ||
* @returns {{accessToken: string, refreshToken: string}|*} | ||
*/ | ||
function getAuthorization() { | ||
@@ -82,2 +98,5 @@ return interceptor.getAuthorization(); | ||
/** | ||
* Clears authorization tokens from interceptor | ||
*/ | ||
function clear() { | ||
@@ -87,5 +106,22 @@ return interceptor.clear(); | ||
/** | ||
* Gets a value indicating whether interceptor is currently active | ||
* @returns {boolean} | ||
*/ | ||
function isActive() { | ||
return !!interceptor; | ||
} | ||
/** | ||
* Removes interceptor and restores default behaviour | ||
*/ | ||
function unload() { | ||
if (interceptor) { | ||
interceptor.unload(); | ||
} | ||
} | ||
exports.isResponseUnauthorized = _http.isResponseUnauthorized; | ||
init(); | ||
initialize(); |
@@ -13,2 +13,3 @@ 'use strict'; | ||
exports.isWorker = isWorker; | ||
exports.resolveEnvironment = resolveEnvironment; | ||
// Uses Emscripten stategy for determining environment | ||
@@ -29,2 +30,19 @@ function isReactNative() { | ||
return typeof importScripts === 'function'; | ||
} | ||
function resolveEnvironment() { | ||
if (isReactNative()) { | ||
return global; | ||
} | ||
if (isWorker()) { | ||
return self; | ||
} | ||
if (isWeb()) { | ||
return window; | ||
} | ||
if (isNode()) { | ||
return global; | ||
} | ||
return null; | ||
} |
@@ -11,2 +11,8 @@ "use strict"; | ||
/** | ||
* Checks if response status matches the provided status | ||
* @param response Response object | ||
* @param status Query status | ||
* @returns {boolean} Value indicating whether response status matches query status | ||
*/ | ||
function isResponseStatus(response, status) { | ||
@@ -13,0 +19,0 @@ if (!response) { |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -50,3 +50,3 @@ Object.defineProperty(exports, "__esModule", { | ||
// Use V8's native method if available, otherwise fallback | ||
if ("captureStackTrace" in Error) { | ||
if ('captureStackTrace' in Error) { | ||
Error.captureStackTrace(_this, RetryCountExceededException); | ||
@@ -53,0 +53,0 @@ } else { |
@@ -1,2 +0,2 @@ | ||
"use strict"; | ||
'use strict'; | ||
@@ -50,3 +50,3 @@ Object.defineProperty(exports, "__esModule", { | ||
// Use V8's native method if available, otherwise fallback | ||
if ("captureStackTrace" in Error) { | ||
if ('captureStackTrace' in Error) { | ||
Error.captureStackTrace(_this, TokenExpiredException); | ||
@@ -53,0 +53,0 @@ } else { |
{ | ||
"name": "@shoutem/fetch-token-intercept", | ||
"version": "0.2.2", | ||
"version": "0.3.0", | ||
"description": "Fetch interceptor for managing refresh token flow.", | ||
@@ -60,3 +60,5 @@ "main": "lib/index.js", | ||
}, | ||
"dependencies": {} | ||
"dependencies": { | ||
"lodash": "^4.17.4" | ||
} | ||
} |
@@ -72,4 +72,4 @@ [![CircleCI](https://img.shields.io/circleci/project/github/shoutem/fetch-token-intercept.svg)](https://github.com/shoutem/fetch-token-intercept) | ||
All required methods return a promise to enable reading of request or response body. | ||
You should avoid reading the body directly on provided requests and responses and instead clone | ||
them first. The library does not clone objects to avoid unnecessary overhead in cases where | ||
You should avoid reading the body directly on provided requests and responses and instead **clone | ||
them first.** The library does not clone objects to avoid unnecessary overhead in cases where | ||
reading a body is not required to provide data. | ||
@@ -121,2 +121,6 @@ | ||
`unload()` | ||
Completely unloads the library and restores initial state. | ||
`isResponseUnauthorized(response)` | ||
@@ -123,0 +127,0 @@ |
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
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
43825
834
141
1
+ Addedlodash@^4.17.4
+ Addedlodash@4.17.21(transitive)