Track OpenID automatic permissions by (widgetLocation, widgetUrl)
This commit is contained in:
parent
21d52a8311
commit
2dcb40f1be
5 changed files with 41 additions and 7 deletions
|
@ -26,6 +26,7 @@ import Modal from "./Modal";
|
||||||
import MatrixClientPeg from "./MatrixClientPeg";
|
import MatrixClientPeg from "./MatrixClientPeg";
|
||||||
import SettingsStore from "./settings/SettingsStore";
|
import SettingsStore from "./settings/SettingsStore";
|
||||||
import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog";
|
import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog";
|
||||||
|
import WidgetUtils from "./utils/WidgetUtils";
|
||||||
|
|
||||||
if (!global.mxFromWidgetMessaging) {
|
if (!global.mxFromWidgetMessaging) {
|
||||||
global.mxFromWidgetMessaging = new FromWidgetPostMessageApi();
|
global.mxFromWidgetMessaging = new FromWidgetPostMessageApi();
|
||||||
|
@ -39,9 +40,10 @@ if (!global.mxToWidgetMessaging) {
|
||||||
const OUTBOUND_API_NAME = 'toWidget';
|
const OUTBOUND_API_NAME = 'toWidget';
|
||||||
|
|
||||||
export default class WidgetMessaging {
|
export default class WidgetMessaging {
|
||||||
constructor(widgetId, widgetUrl, target) {
|
constructor(widgetId, widgetUrl, isUserWidget, target) {
|
||||||
this.widgetId = widgetId;
|
this.widgetId = widgetId;
|
||||||
this.widgetUrl = widgetUrl;
|
this.widgetUrl = widgetUrl;
|
||||||
|
this.isUserWidget = isUserWidget;
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.fromWidget = global.mxFromWidgetMessaging;
|
this.fromWidget = global.mxFromWidgetMessaging;
|
||||||
this.toWidget = global.mxToWidgetMessaging;
|
this.toWidget = global.mxToWidgetMessaging;
|
||||||
|
@ -126,12 +128,14 @@ export default class WidgetMessaging {
|
||||||
async _onOpenIdRequest(ev, rawEv) {
|
async _onOpenIdRequest(ev, rawEv) {
|
||||||
if (ev.widgetId !== this.widgetId) return; // not interesting
|
if (ev.widgetId !== this.widgetId) return; // not interesting
|
||||||
|
|
||||||
|
const widgetSecurityKey = WidgetUtils.getWidgetSecurityKey(this.widgetId, this.widgetUrl, this.isUserWidget);
|
||||||
|
|
||||||
const settings = SettingsStore.getValue("widgetOpenIDPermissions");
|
const settings = SettingsStore.getValue("widgetOpenIDPermissions");
|
||||||
if (settings.blacklist && settings.blacklist.includes(this.widgetId)) {
|
if (settings.blacklist && settings.blacklist.includes(widgetSecurityKey)) {
|
||||||
this.fromWidget.sendResponse(rawEv, {state: "blocked"});
|
this.fromWidget.sendResponse(rawEv, {state: "blocked"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (settings.whitelist && settings.whitelist.includes(this.widgetId)) {
|
if (settings.whitelist && settings.whitelist.includes(widgetSecurityKey)) {
|
||||||
const responseBody = {state: "allowed"};
|
const responseBody = {state: "allowed"};
|
||||||
const credentials = await MatrixClientPeg.get().getOpenIdToken();
|
const credentials = await MatrixClientPeg.get().getOpenIdToken();
|
||||||
Object.assign(responseBody, credentials);
|
Object.assign(responseBody, credentials);
|
||||||
|
@ -147,6 +151,7 @@ export default class WidgetMessaging {
|
||||||
WidgetOpenIDPermissionsDialog, {
|
WidgetOpenIDPermissionsDialog, {
|
||||||
widgetUrl: this.widgetUrl,
|
widgetUrl: this.widgetUrl,
|
||||||
widgetId: this.widgetId,
|
widgetId: this.widgetId,
|
||||||
|
isUserWidget: this.isUserWidget,
|
||||||
|
|
||||||
onFinished: async (confirm) => {
|
onFinished: async (confirm) => {
|
||||||
const responseBody = {success: confirm};
|
const responseBody = {success: confirm};
|
||||||
|
|
|
@ -20,12 +20,14 @@ import {_t} from "../../../languageHandler";
|
||||||
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
import SettingsStore, {SettingLevel} from "../../../settings/SettingsStore";
|
||||||
import sdk from "../../../index";
|
import sdk from "../../../index";
|
||||||
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
|
||||||
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||||
|
|
||||||
export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onFinished: PropTypes.func.isRequired,
|
onFinished: PropTypes.func.isRequired,
|
||||||
widgetUrl: PropTypes.string.isRequired,
|
widgetUrl: PropTypes.string.isRequired,
|
||||||
widgetId: PropTypes.string.isRequired,
|
widgetId: PropTypes.string.isRequired,
|
||||||
|
isUserWidget: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -52,7 +54,11 @@ export default class WidgetOpenIDPermissionsDialog extends React.Component {
|
||||||
if (!currentValues.whitelist) currentValues.whitelist = [];
|
if (!currentValues.whitelist) currentValues.whitelist = [];
|
||||||
if (!currentValues.blacklist) currentValues.blacklist = [];
|
if (!currentValues.blacklist) currentValues.blacklist = [];
|
||||||
|
|
||||||
(allowed ? currentValues.whitelist : currentValues.blacklist).push(this.props.widgetId);
|
const securityKey = WidgetUtils.getWidgetSecurityKey(
|
||||||
|
this.props.widgetId,
|
||||||
|
this.props.widgetUrl,
|
||||||
|
this.props.isUserWidget);
|
||||||
|
(allowed ? currentValues.whitelist : currentValues.blacklist).push(securityKey);
|
||||||
SettingsStore.setValue("widgetOpenIDPermissions", null, SettingLevel.DEVICE, currentValues);
|
SettingsStore.setValue("widgetOpenIDPermissions", null, SettingLevel.DEVICE, currentValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,7 +351,7 @@ export default class AppTile extends React.Component {
|
||||||
_setupWidgetMessaging() {
|
_setupWidgetMessaging() {
|
||||||
// FIXME: There's probably no reason to do this here: it should probably be done entirely
|
// FIXME: There's probably no reason to do this here: it should probably be done entirely
|
||||||
// in ActiveWidgetStore.
|
// in ActiveWidgetStore.
|
||||||
const widgetMessaging = new WidgetMessaging(this.props.id, this.props.url, this.refs.appFrame.contentWindow);
|
const widgetMessaging = new WidgetMessaging(this.props.id, this.props.url, this.props.userWidget, this.refs.appFrame.contentWindow);
|
||||||
ActiveWidgetStore.setWidgetMessaging(this.props.id, widgetMessaging);
|
ActiveWidgetStore.setWidgetMessaging(this.props.id, widgetMessaging);
|
||||||
widgetMessaging.getCapabilities().then((requestedCapabilities) => {
|
widgetMessaging.getCapabilities().then((requestedCapabilities) => {
|
||||||
console.log(`Widget ${this.props.id} requested capabilities: ` + requestedCapabilities);
|
console.log(`Widget ${this.props.id} requested capabilities: ` + requestedCapabilities);
|
||||||
|
|
|
@ -343,8 +343,8 @@ export const SETTINGS = {
|
||||||
"widgetOpenIDPermissions": {
|
"widgetOpenIDPermissions": {
|
||||||
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS,
|
||||||
default: {
|
default: {
|
||||||
whitelisted: [],
|
whitelist: [],
|
||||||
blacklisted: [],
|
blacklist: [],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"RoomList.orderByImportance": {
|
"RoomList.orderByImportance": {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 Vector Creations Ltd
|
Copyright 2017 Vector Creations Ltd
|
||||||
Copyright 2018 New Vector Ltd
|
Copyright 2018 New Vector Ltd
|
||||||
|
Copyright 2019 Travis Ralston
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -25,6 +26,7 @@ import WidgetEchoStore from '../stores/WidgetEchoStore';
|
||||||
// before waitFor[Room/User]Widget rejects its promise
|
// before waitFor[Room/User]Widget rejects its promise
|
||||||
const WIDGET_WAIT_TIME = 20000;
|
const WIDGET_WAIT_TIME = 20000;
|
||||||
import SettingsStore from "../settings/SettingsStore";
|
import SettingsStore from "../settings/SettingsStore";
|
||||||
|
import ActiveWidgetStore from "../stores/ActiveWidgetStore";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a URI according to a set of template variables. Variables will be
|
* Encodes a URI according to a set of template variables. Variables will be
|
||||||
|
@ -396,4 +398,25 @@ export default class WidgetUtils {
|
||||||
|
|
||||||
return capWhitelist;
|
return capWhitelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getWidgetSecurityKey(widgetId, widgetUrl, isUserWidget) {
|
||||||
|
let widgetLocation = ActiveWidgetStore.getRoomId(widgetId);
|
||||||
|
|
||||||
|
if (isUserWidget) {
|
||||||
|
const userWidget = WidgetUtils.getUserWidgetsArray()
|
||||||
|
.find((w) => w.id === widgetId && w.content && w.content.url === widgetUrl);
|
||||||
|
|
||||||
|
if (!userWidget) {
|
||||||
|
throw new Error("No matching user widget to form security key");
|
||||||
|
}
|
||||||
|
|
||||||
|
widgetLocation = userWidget.sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!widgetLocation) {
|
||||||
|
throw new Error("Failed to locate where the widget resides");
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodeURIComponent(`${widgetLocation}::${widgetUrl}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue