mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
Merge pull request #1829 from sbenmoussati/bugfix/SDA-4120-main
SDA-4120 Proxy authentication on Browser login flow (#1826)
This commit is contained in:
commit
b9ca1f6e8f
@ -72,6 +72,24 @@ const broadcastMessage = (method, data) => {
|
|||||||
const getBrowserLoginUrl = (pod: string) =>
|
const getBrowserLoginUrl = (pod: string) =>
|
||||||
`${pod}/login/sso/initsso?RelayState=${pod}/client-bff/device-login/index.html?callbackScheme=symphony&action=login`;
|
`${pod}/login/sso/initsso?RelayState=${pod}/client-bff/device-login/index.html?callbackScheme=symphony&action=login`;
|
||||||
const AUTH_STATUS_PATH = '/login/checkauth?type=user';
|
const AUTH_STATUS_PATH = '/login/checkauth?type=user';
|
||||||
|
interface IProxyDetails {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
hostname: string;
|
||||||
|
retries: number;
|
||||||
|
}
|
||||||
|
const proxyDetails: IProxyDetails = {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
hostname: '',
|
||||||
|
retries: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let loginUrl = '';
|
||||||
|
let formattedPodUrl = '';
|
||||||
|
let credentialsPromise;
|
||||||
|
const credentialsPromiseRefHolder: { [key: string]: any } = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle API related ipc messages from renderers. Only messages from windows
|
* Handle API related ipc messages from renderers. Only messages from windows
|
||||||
* we have created are allowed.
|
* we have created are allowed.
|
||||||
@ -368,7 +386,8 @@ ipcMain.on(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case apiCmds.unmaximizeMainWindow:
|
case apiCmds.unmaximizeMainWindow:
|
||||||
const mainWindow = windowHandler.getMainWindow();
|
const mainWindow =
|
||||||
|
windowHandler.getMainWindow() as ICustomBrowserWindow;
|
||||||
if (mainWindow && windowExists(mainWindow)) {
|
if (mainWindow && windowExists(mainWindow)) {
|
||||||
if (mainWindow.isFullScreen()) {
|
if (mainWindow.isFullScreen()) {
|
||||||
mainWindow.setFullScreen(false);
|
mainWindow.setFullScreen(false);
|
||||||
@ -402,38 +421,14 @@ ipcMain.on(
|
|||||||
? userConfigURL
|
? userConfigURL
|
||||||
: globalConfigURL;
|
: globalConfigURL;
|
||||||
const { subdomain, domain, tld } = whitelistHandler.parseDomain(podUrl);
|
const { subdomain, domain, tld } = whitelistHandler.parseDomain(podUrl);
|
||||||
const formattedPodUrl = `https://${subdomain}.${domain}${tld}`;
|
formattedPodUrl = `https://${subdomain}.${domain}${tld}`;
|
||||||
const loginUrl = getBrowserLoginUrl(formattedPodUrl);
|
loginUrl = getBrowserLoginUrl(formattedPodUrl);
|
||||||
logger.info(
|
logger.info(
|
||||||
'main-api-handler:',
|
'main-api-handler:',
|
||||||
'check if sso is enabled for the pod',
|
'check if sso is enabled for the pod',
|
||||||
formattedPodUrl,
|
formattedPodUrl,
|
||||||
);
|
);
|
||||||
const response = await fetch(`${formattedPodUrl}${AUTH_STATUS_PATH}`);
|
loadPodUrl();
|
||||||
const authResponse = (await response.json()) as IAuthResponse;
|
|
||||||
logger.info('main-api-handler:', 'check auth response', authResponse);
|
|
||||||
if (
|
|
||||||
arg.isBrowserLoginEnabled &&
|
|
||||||
authResponse.authenticationType === 'sso'
|
|
||||||
) {
|
|
||||||
logger.info(
|
|
||||||
'main-api-handler:',
|
|
||||||
'browser login is enabled - logging in',
|
|
||||||
loginUrl,
|
|
||||||
);
|
|
||||||
await shell.openExternal(loginUrl);
|
|
||||||
} else {
|
|
||||||
logger.info(
|
|
||||||
'main-api-handler:',
|
|
||||||
'browser login is not enabled - loading main window with',
|
|
||||||
formattedPodUrl,
|
|
||||||
);
|
|
||||||
const mainWebContents = windowHandler.getMainWebContents();
|
|
||||||
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
|
||||||
windowHandler.setMainWindowOrigin(formattedPodUrl);
|
|
||||||
mainWebContents.loadURL(formattedPodUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case apiCmds.setBroadcastMessage:
|
case apiCmds.setBroadcastMessage:
|
||||||
if (swiftSearchInstance) {
|
if (swiftSearchInstance) {
|
||||||
@ -650,3 +645,70 @@ const logApiCallParams = (arg: any) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadPodUrl = (proxyLogin = false) => {
|
||||||
|
logger.info('loading pod URL. Proxy: ', proxyLogin);
|
||||||
|
let onLogin = {};
|
||||||
|
if (proxyLogin) {
|
||||||
|
onLogin = {
|
||||||
|
async onLogin(authInfo) {
|
||||||
|
// this 'authInfo' is the one received by the 'login' event. See https://www.electronjs.org/docs/latest/api/client-request#event-login
|
||||||
|
proxyDetails.hostname = authInfo.host || authInfo.realm;
|
||||||
|
await credentialsPromise;
|
||||||
|
return Promise.resolve({
|
||||||
|
username: proxyDetails.username,
|
||||||
|
password: proxyDetails.password,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fetch(`${formattedPodUrl}${AUTH_STATUS_PATH}`, onLogin)
|
||||||
|
.then(async (response) => {
|
||||||
|
const authResponse = (await response.json()) as IAuthResponse;
|
||||||
|
logger.info('main-api-handler:', 'check auth response', authResponse);
|
||||||
|
if (authResponse.authenticationType === 'sso') {
|
||||||
|
logger.info(
|
||||||
|
'main-api-handler:',
|
||||||
|
'browser login is enabled - logging in',
|
||||||
|
loginUrl,
|
||||||
|
);
|
||||||
|
await shell.openExternal(loginUrl);
|
||||||
|
} else {
|
||||||
|
logger.info(
|
||||||
|
'main-api-handler:',
|
||||||
|
'browser login is not enabled - loading main window with',
|
||||||
|
formattedPodUrl,
|
||||||
|
);
|
||||||
|
const mainWebContents = windowHandler.getMainWebContents();
|
||||||
|
if (mainWebContents && !mainWebContents.isDestroyed()) {
|
||||||
|
windowHandler.setMainWindowOrigin(formattedPodUrl);
|
||||||
|
mainWebContents.loadURL(formattedPodUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(async (error) => {
|
||||||
|
if (
|
||||||
|
(error.type === 'proxy' && error.code === 'PROXY_AUTH_FAILED') ||
|
||||||
|
(error.code === 'ERR_TOO_MANY_RETRIES' && proxyLogin)
|
||||||
|
) {
|
||||||
|
credentialsPromise = new Promise((res, _rej) => {
|
||||||
|
credentialsPromiseRefHolder.resolutionCallback = res;
|
||||||
|
});
|
||||||
|
const welcomeWindow =
|
||||||
|
windowHandler.getMainWindow() as ICustomBrowserWindow;
|
||||||
|
windowHandler.createBasicAuthWindow(
|
||||||
|
welcomeWindow,
|
||||||
|
proxyDetails.hostname,
|
||||||
|
proxyDetails.retries === 0,
|
||||||
|
undefined,
|
||||||
|
(username, password) => {
|
||||||
|
proxyDetails.username = username;
|
||||||
|
proxyDetails.password = password;
|
||||||
|
credentialsPromiseRefHolder.resolutionCallback(true);
|
||||||
|
loadPodUrl(true);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
proxyDetails.retries += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -62,7 +62,7 @@ export default class BasicAuth extends React.Component<{}, IState> {
|
|||||||
BASIC_AUTH_NAMESPACE,
|
BASIC_AUTH_NAMESPACE,
|
||||||
)()}
|
)()}
|
||||||
</span>
|
</span>
|
||||||
<span className='hostname'>{hostname}</span>
|
{hostname && <span className='hostname'>{hostname}</span>}
|
||||||
<span id='credentialsError' className={shouldShowError}>
|
<span id='credentialsError' className={shouldShowError}>
|
||||||
{i18n.t('Invalid user name/password', BASIC_AUTH_NAMESPACE)()}
|
{i18n.t('Invalid user name/password', BASIC_AUTH_NAMESPACE)()}
|
||||||
</span>
|
</span>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@import "theme";
|
@import 'theme';
|
||||||
|
|
||||||
@color-red: red;
|
@color-red: red;
|
||||||
|
|
||||||
@ -10,16 +10,22 @@ html {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100%;
|
height: calc(100% - 40px);
|
||||||
|
margin: 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.components-window-root {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-family: @font-family;
|
font-family: @font-family;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 20px;
|
height: 100%;
|
||||||
|
justify-content: space-evenly;
|
||||||
}
|
}
|
||||||
|
|
||||||
.container:lang(ja-JP) {
|
.container:lang(ja-JP) {
|
||||||
@ -27,12 +33,11 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
padding-top: 10px;
|
|
||||||
text-align: start;
|
text-align: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hostname {
|
.hostname {
|
||||||
font-size: .9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.credentials-error {
|
.credentials-error {
|
||||||
@ -44,28 +49,40 @@ span {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
|
||||||
padding-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
table {
|
||||||
border-spacing: 5px;
|
border-spacing: 5px;
|
||||||
|
display: flex;
|
||||||
|
tbody {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
tr {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
text-align: left;
|
||||||
|
td:last-child {
|
||||||
|
margin-left: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
width: 200px;
|
width: calc(100% - 8px);
|
||||||
height: 20px;
|
height: 20px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
&:lang(fr-FR) {
|
||||||
|
max-width: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
width: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 25px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-container {
|
.button-container {
|
||||||
|
Loading…
Reference in New Issue
Block a user