Skip to content

Commit

Permalink
added trusted origin to login message for security
Browse files Browse the repository at this point in the history
  • Loading branch information
jvigliotta committed Aug 20, 2024
1 parent 872d521 commit d208dcd
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 98 deletions.
2 changes: 1 addition & 1 deletion src/AMMOSPlugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ define([
});
openmct.install(RealtimeIndicatorPlugin.default(vistaTime));

const identityPlugin = new IdentityPlugin(options);
const identityPlugin = new IdentityPlugin.default(options);
openmct.install(identityPlugin);

mcwsClient.default.configure(options, identityPlugin.login);
Expand Down
157 changes: 75 additions & 82 deletions src/identity/LoginService.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,85 @@
/*global define*/
define(
[],
function () {
export default class LoginService {
/**
* LoginService provides a simple interface for logging in a user.
*
* @param camUrl the url to use for logging in a user.
*/
constructor(camUrl) {
this.camUrl = camUrl;
this.overlay = undefined;
this.whenLoggedIn = undefined;
window.addEventListener('message', this.onMessage.bind(this));
}

/**
* @private
*/
onMessage(event) {
const message = event.data;
const trustedOrigin = new URL(this.camUrl).origin;

/**
* LoginService provides a simple interface for logging in a user.
*
* @param camUrl the url to use for logging in a user.
*/
function LoginService(camUrl) {
this.camUrl = camUrl;
this.overlay = undefined;
this.whenLoggedIn = undefined;
window.addEventListener('message', this.onMessage.bind(this));
if (event.origin === trustedOrigin && message.name === 'login:complete') {

Check failure

Code scanning / CodeQL

User-controlled bypass of security check High

This condition guards a sensitive
action
, but a
user-provided value
controls it.
this.completeLogin();
}
}

/**
* @private
*/
LoginService.prototype.onMessage = function (event) {
var message = event.data;
if (message.name === 'login:complete') {
this.completeLogin();
}
};

/**
* Return the login url, with a parameter to redirect to a local url
* after the login completes.
* @private
*/
LoginService.prototype.getLoginUrl = function () {
return this.camUrl + "?goto=" +
encodeURIComponent(
window.location.origin +
window.location.pathname +
'src/identity/close.html'
);
};
/**
* Return the login url, with a parameter to redirect to a local url
* after the login completes.
* @private
*/
getLoginUrl() {
return this.camUrl + "?goto=" +
encodeURIComponent(
window.location.origin +
window.location.pathname +
'src/identity/close.html'
);
}

/**
* @private
*/
LoginService.prototype.show = function () {
this.overlay = document.createElement('div');
this.overlay.classList.add('u-contents');
const iframe = document.createElement('iframe');
iframe.classList.add('c-login-overlay');
iframe.src = this.getLoginUrl();
/**
* @private
*/
show() {
this.overlay = document.createElement('div');
this.overlay.classList.add('u-contents');

const iframe = document.createElement('iframe');
iframe.classList.add('c-login-overlay');
iframe.src = this.getLoginUrl();

this.overlay.appendChild(iframe);
document.body.appendChild(this.overlay);
};
this.overlay.appendChild(iframe);
document.body.appendChild(this.overlay);
}

/**
* Signal login as complete, dismiss the visible dialog, and resolve
* the login promise.
* @private
*/
LoginService.prototype.completeLogin = function () {
this.overlay.remove();
this.resolve();
delete this.overlay;
delete this.resolve;
delete this.reject;
};
/**
* Signal login as complete, dismiss the visible dialog, and resolve
* the login promise.
* @private
*/
completeLogin() {
this.overlay.remove();
this.resolve();
delete this.overlay;
delete this.resolve;
delete this.reject;
}

/**
* Log in a user. Displays a login dialog in an iFrame.
*
* @returns Promise a promise that is resolved when a user is logged in,
* or rejected if they choose not to log in.
*/
LoginService.prototype.login = function () {
if (this.whenLoggedIn) {
return this.whenLoggedIn;
}
this.show();
this.whenLoggedIn = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this))
/**
* Log in a user. Displays a login dialog in an iFrame.
*
* @returns Promise a promise that is resolved when a user is logged in,
* or rejected if they choose not to log in.
*/
login() {
if (this.whenLoggedIn) {
return this.whenLoggedIn;
};

return LoginService;

}
this.show();
this.whenLoggedIn = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
return this.whenLoggedIn;
}
);
}
27 changes: 12 additions & 15 deletions src/identity/plugin.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
define([
'./LoginService'
], function (
LoginService
) {
import LoginService from './LoginService';

function IdentityPlugin(options) {
class IdentityPlugin {
constructor(options) {
this.options = options;
}

return function install(openmct) {
if (options.proxyUrl) {
options.camUrl = options.proxyUrl + 'cam/UI/Login';
}
var loginService = new LoginService(options.camUrl);
install.login = loginService.login.bind(loginService);
install(openmct) {
if (this.options.proxyUrl) {
this.options.camUrl = this.options.proxyUrl + 'cam/UI/Login';
}
const loginService = new LoginService(this.options.camUrl);
this.install.login = loginService.login.bind(loginService);
}
}

return IdentityPlugin;

});
export default IdentityPlugin;

0 comments on commit d208dcd

Please sign in to comment.