@okta/okta-auth-js
Version:
The Okta Auth SDK
146 lines (142 loc) • 5.3 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.SyncStorageService = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _broadcastChannel = require("broadcast-channel");
var _features = require("../features");
var _types = require("../oidc/types");
var _errors = require("../errors");
/*!
* Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/
class SyncStorageService {
constructor(tokenManager, options = {}) {
(0, _defineProperty2.default)(this, "started", false);
(0, _defineProperty2.default)(this, "enablePostMessage", true);
this.tokenManager = tokenManager;
this.options = options;
this.onTokenAddedHandler = this.onTokenAddedHandler.bind(this);
this.onTokenRemovedHandler = this.onTokenRemovedHandler.bind(this);
this.onTokenRenewedHandler = this.onTokenRenewedHandler.bind(this);
this.onSetStorageHandler = this.onSetStorageHandler.bind(this);
this.onSyncMessageHandler = this.onSyncMessageHandler.bind(this);
}
requiresLeadership() {
return false;
}
isStarted() {
return this.started;
}
canStart() {
return !!this.options.syncStorage && (0, _features.isBrowser)() && !this.started;
}
async start() {
if (!this.canStart()) {
return;
}
const {
syncChannelName
} = this.options;
try {
// BroadcastChannel throws if no supported method can be found
this.channel = new _broadcastChannel.BroadcastChannel(syncChannelName);
} catch (err) {
throw new _errors.AuthSdkError('SyncStorageService is not supported in current browser.');
}
this.tokenManager.on(_types.EVENT_ADDED, this.onTokenAddedHandler);
this.tokenManager.on(_types.EVENT_REMOVED, this.onTokenRemovedHandler);
this.tokenManager.on(_types.EVENT_RENEWED, this.onTokenRenewedHandler);
this.tokenManager.on(_types.EVENT_SET_STORAGE, this.onSetStorageHandler);
this.channel.addEventListener('message', this.onSyncMessageHandler);
this.started = true;
}
async stop() {
if (this.started) {
this.tokenManager.off(_types.EVENT_ADDED, this.onTokenAddedHandler);
this.tokenManager.off(_types.EVENT_REMOVED, this.onTokenRemovedHandler);
this.tokenManager.off(_types.EVENT_RENEWED, this.onTokenRenewedHandler);
this.tokenManager.off(_types.EVENT_SET_STORAGE, this.onSetStorageHandler);
this.channel?.removeEventListener('message', this.onSyncMessageHandler);
await this.channel?.close();
this.channel = undefined;
this.started = false;
}
}
onTokenAddedHandler(key, token) {
if (!this.enablePostMessage) {
return;
}
this.channel?.postMessage({
type: _types.EVENT_ADDED,
key,
token
});
}
onTokenRemovedHandler(key, token) {
if (!this.enablePostMessage) {
return;
}
this.channel?.postMessage({
type: _types.EVENT_REMOVED,
key,
token
});
}
onTokenRenewedHandler(key, token, oldToken) {
if (!this.enablePostMessage) {
return;
}
this.channel?.postMessage({
type: _types.EVENT_RENEWED,
key,
token,
oldToken
});
}
onSetStorageHandler(storage) {
this.channel?.postMessage({
type: _types.EVENT_SET_STORAGE,
storage
});
}
/* eslint-disable complexity */
onSyncMessageHandler(msg) {
// Notes:
// 1. Using `enablePostMessage` flag here to prevent sync message loop.
// If this flag is on, tokenManager event handlers do not post sync message.
// 2. IE11 has known issue with synchronization of LocalStorage cross tabs.
// One workaround is to set empty event handler for `window.onstorage`.
// But it's not 100% working, sometimes you still get old value from LocalStorage.
// Better approch is to explicitly udpate LocalStorage with `setStorage`.
this.enablePostMessage = false;
switch (msg.type) {
case _types.EVENT_SET_STORAGE:
this.tokenManager.getStorage().setStorage(msg.storage);
break;
case _types.EVENT_ADDED:
this.tokenManager.emitAdded(msg.key, msg.token);
this.tokenManager.setExpireEventTimeout(msg.key, msg.token);
break;
case _types.EVENT_REMOVED:
this.tokenManager.clearExpireEventTimeout(msg.key);
this.tokenManager.emitRemoved(msg.key, msg.token);
break;
case _types.EVENT_RENEWED:
this.tokenManager.emitRenewed(msg.key, msg.token, msg.oldToken);
break;
default:
break;
}
this.enablePostMessage = true;
}
}
exports.SyncStorageService = SyncStorageService;
//# sourceMappingURL=SyncStorageService.js.map