@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
64 lines (63 loc) • 2.75 kB
JavaScript
import { authenticateFactory } from '../sync/streaming/AuthClient';
import { Backoff } from '../utils/Backoff';
import { LOG_PREFIX_SYNC_AUTH } from '../logger/constants';
import { TOKEN } from '../utils/constants';
var SKEW_SECONDS = 30;
function isExpired(credential) {
return Date.now() / 1000 + SKEW_SECONDS >= credential.decodedToken.exp;
}
/**
* Factory of AuthProvider, which provides JWT credentials for authenticated HTTP requests.
* Credentials are fetched lazily on demand, cached in memory, and retried with backoff on failure.
*/
export function authProviderFactory(settings, splitHttpClient, telemetryTracker) {
var urls = settings.urls, log = settings.log;
function fetchAuth() {
var url = "".concat(urls.auth, "/api/v3/auth?capabilities=config");
return splitHttpClient(url, undefined, telemetryTracker.trackHttp(TOKEN), false, true);
}
var authenticate = authenticateFactory(fetchAuth);
var backoff = new Backoff(fetchCredential);
var cachedCredential;
var inFlightPromise;
var stopped = false;
function fetchCredential() {
return authenticate().then(function (credential) {
log.info(LOG_PREFIX_SYNC_AUTH + 'credential fetched successfully');
cachedCredential = credential;
inFlightPromise = undefined;
backoff.reset();
return credential;
}).catch(function (error) {
// Avoid rejected promises and unnecessary retries after stop()
if (stopped)
return cachedCredential;
if (error.statusCode && error.statusCode >= 400 && error.statusCode < 500) {
log.error(LOG_PREFIX_SYNC_AUTH + 'non-retryable error fetching credential (status ' + error.statusCode + '): ' + error.message);
inFlightPromise = undefined;
throw error;
}
log.warn(LOG_PREFIX_SYNC_AUTH + 'credential fetch failed (attempt ' + (backoff.attempts + 1) + '). Error: ' + error.message);
return backoff.scheduleCallAsync();
});
}
return {
credential: function () {
if (cachedCredential && !isExpired(cachedCredential)) {
return Promise.resolve(cachedCredential);
}
if (cachedCredential)
log.debug(LOG_PREFIX_SYNC_AUTH + 'cached credential expired');
return inFlightPromise || (inFlightPromise = fetchCredential());
},
invalidate: function () {
cachedCredential = undefined;
},
stop: function () {
stopped = true;
cachedCredential = undefined;
inFlightPromise = undefined;
backoff.reset();
}
};
}