oidc-client-rx
Version:
ReactiveX enhanced OIDC and OAuth2 protocol support for browser-based JavaScript applications
128 lines (127 loc) • 5.62 kB
JavaScript
import { Injectable, inject } from "injection-js";
import { Subject } from "rxjs";
import { DOCUMENT } from "../../dom/index.js";
import { LoggerService } from "../../logging/logger.service.js";
import { StoragePersistenceService } from "../../storage/storage-persistence.service.js";
function _ts_decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : null === desc ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if ("object" == typeof Reflect && "function" == typeof Reflect.decorate) r = Reflect.decorate(decorators, target, key, desc);
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
class PopUpService {
get result$() {
return this.resultInternal$.asObservable();
}
get windowInternal() {
return this.document.defaultView;
}
isCurrentlyInPopup(config) {
if (this.canAccessSessionStorage()) {
const popup = this.storagePersistenceService.read(this.STORAGE_IDENTIFIER, config);
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return false;
return Boolean(windowIdentifier.opener) && windowIdentifier.opener !== windowIdentifier && Boolean(popup);
}
return false;
}
openPopUp(url, popupOptions, config) {
const optionsToPass = this.getOptions(popupOptions);
this.storagePersistenceService.write(this.STORAGE_IDENTIFIER, "true", config);
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return;
if (!url) return void this.loggerService.logError(config, "Could not open popup, url is empty");
this.popUp = windowIdentifier.open(url, "_blank", optionsToPass);
if (!this.popUp) {
this.storagePersistenceService.remove(this.STORAGE_IDENTIFIER, config);
this.loggerService.logError(config, "Could not open popup");
return;
}
this.loggerService.logDebug(config, `Opened popup with url ${url}`);
const listener = (event)=>{
if (!event?.data || "string" != typeof event.data) {
if (config.disableCleaningPopupOnInvalidMessage) return;
this.cleanUp(listener, config);
return;
}
this.loggerService.logDebug(config, `Received message from popup with url ${event.data}`);
this.resultInternal$.next({
userClosed: false,
receivedUrl: event.data
});
this.cleanUp(listener, config);
};
windowIdentifier.addEventListener("message", listener, false);
this.handle = windowIdentifier.setInterval(()=>{
if (this.popUp?.closed) {
this.resultInternal$.next({
userClosed: true,
receivedUrl: ""
});
this.cleanUp(listener, config);
}
}, 200);
}
sendMessageToMainWindow(url, config) {
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return;
if (windowIdentifier.opener) {
const href = windowIdentifier.location.href;
this.sendMessage(url, href, config);
}
}
cleanUp(listener, config) {
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return;
windowIdentifier.removeEventListener("message", listener, false);
windowIdentifier.clearInterval(this.handle);
if (this.popUp) {
this.storagePersistenceService.remove(this.STORAGE_IDENTIFIER, config);
this.popUp.close();
this.popUp = null;
}
}
sendMessage(url, href, config) {
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return;
if (!url) return void this.loggerService.logDebug(config, `Can not send message to parent, no url: '${url}'`);
windowIdentifier.opener.postMessage(url, href);
}
getOptions(popupOptions) {
const popupDefaultOptions = {
width: 500,
height: 500,
left: 50,
top: 50
};
const options = {
...popupDefaultOptions,
...popupOptions || {}
};
const windowIdentifier = this.windowInternal;
if (!windowIdentifier) return "";
const width = options.width || popupDefaultOptions.width;
const height = options.height || popupDefaultOptions.height;
const left = windowIdentifier.screenLeft + (windowIdentifier.outerWidth - width) / 2;
const top = windowIdentifier.screenTop + (windowIdentifier.outerHeight - height) / 2;
options.left = left;
options.top = top;
return Object.entries(options).map(([key, value])=>`${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join(",");
}
canAccessSessionStorage() {
return "u" > typeof navigator && navigator.cookieEnabled && "u" > typeof Storage;
}
constructor(){
this.loggerService = inject(LoggerService);
this.storagePersistenceService = inject(StoragePersistenceService);
this.document = inject(DOCUMENT);
this.STORAGE_IDENTIFIER = "popupauth";
this.popUp = null;
this.handle = -1;
this.resultInternal$ = new Subject();
}
}
PopUpService = _ts_decorate([
Injectable()
], PopUpService);
export { PopUpService };