Skip to content

Commit

Permalink
Merge pull request #1009 from neo4j-labs/fix/sso-standalone-params
Browse files Browse the repository at this point in the history
fixing strange param behaviour with sso
  • Loading branch information
alfredorubin96 authored Feb 10, 2025
2 parents 7fea3eb + 563a1d6 commit f3ae774
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
29 changes: 20 additions & 9 deletions src/application/ApplicationThunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ export const handleSharedDashboardsThunk = () => (dispatch: any) => {
if (skipConfirmation === true) {
dispatch(onConfirmLoadSharedDashboardThunk());
}

window.history.pushState({}, document.title, window.location.pathname);
} else {
dispatch(setConnectionModalOpen(false));
Expand Down Expand Up @@ -358,7 +357,6 @@ export const onConfirmLoadSharedDashboardThunk = () => (dispatch: any, getState:
}
if (shareDetails.standalone == true) {
dispatch(setStandaloneMode(true));
localStorage.setItem('standaloneShared', 'true'); // EDGE CASE: redirect SSO removes the shareDetails when redirecting
}
dispatch(resetShareDetails());
} catch (e) {
Expand Down Expand Up @@ -410,29 +408,33 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:

try {
// Parse the URL parameters to see if there's any deep linking of parameters.
const state = getState();
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
if (state.application.waitForSSO) {
const paramsBeforeSSO = JSON.parse(sessionStorage.getItem('SSO_PARAMS_BEFORE_REDIRECT') || '{}');
Object.entries(paramsBeforeSSO).forEach(([key, value]) => {
urlParams.set(key, value);
});
}
const paramsToSetAfterConnecting = {};
Array.from(urlParams.entries()).forEach(([key, value]) => {
if (key.startsWith('neodash_')) {
paramsToSetAfterConnecting[key] = value;
}
});

sessionStorage.getItem('SSO_PARAMS_BEFORE_REDIRECT');
const page = urlParams.get('page');
if (page !== '' && page !== null) {
if (!isNaN(page)) {
dispatch(setPageNumberThunk(parseInt(page)));
}
}
const state = getState();
dispatch(setSSOEnabled(config.ssoEnabled, state.application.cachedSSODiscoveryUrl));
dispatch(setSSOProviders(config.ssoProviders));

// Check if we are in standalone mode
// const standaloneShared = localStorage.getItem('standaloneShared') == 'true'; // EDGE case: from url param it could happen that we lose the value due to SSO redirect
const { standalone } = config;
// || standaloneShared;
const standalone = config.standalone || urlParams.get('standalone') == 'Yes';

// if a dashboard database was previously set, remember to use it.
const dashboardDatabase = state.application.standaloneDashboardDatabase;
Expand All @@ -455,7 +457,6 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
config.standaloneDatabaseList
)
);
localStorage.removeItem('standaloneShared');

dispatch(setLoggingMode(config.loggingMode));
dispatch(setLoggingDatabase(config.loggingDatabase));
Expand Down Expand Up @@ -530,14 +531,18 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
}

if (standalone) {
if (config.standaloneDashboardURL !== undefined && config.standaloneDashboardURL.length > 0) {
if (urlParams.get('id')) {
dispatch(setDashboardToLoadAfterConnecting(urlParams.get('id')));
} else if (config.standaloneDashboardURL !== undefined && config.standaloneDashboardURL.length > 0) {
dispatch(setDashboardToLoadAfterConnecting(config.standaloneDashboardURL));
} else {
dispatch(setDashboardToLoadAfterConnecting(`name:${config.standaloneDashboardName}`));
}
dispatch(setParametersToLoadAfterConnecting(paramsToSetAfterConnecting));
}
sessionStorage.removeItem('SSO_PARAMS_BEFORE_REDIRECT');
});

dispatch(setWaitForSSO(false));
if (!success) {
alert('Unable to connect using SSO. See the browser console for more details.');
Expand All @@ -550,6 +555,12 @@ export const loadApplicationConfigThunk = () => async (dispatch: any, getState:
} else {
return;
}
} else if (state.application.ssoEnabled && !state.application.waitForSSO && urlParams) {
let paramsToStore = {};
urlParams.forEach((value, key) => {
paramsToStore[key] = value;
});
sessionStorage.setItem('SSO_PARAMS_BEFORE_REDIRECT', JSON.stringify(paramsToStore));
}

if (standalone) {
Expand Down
13 changes: 10 additions & 3 deletions src/component/sso/SSOLoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Button, IconButton } from '@neo4j-ndl/react';

export const SSOLoginButton = ({ discoveryAPIUrl, hostname, port, onSSOAttempt, onClick, providers }) => {
const [savedSSOProviders, setSSOProviders] = useState([]);
const [discoveryUrlValidated, setDiscoveryUrlValidated] = useState(undefined);
const [discoveryUrlValidated, setDiscoveryUrlValidated] = useState<string | undefined>(undefined);

const filterByProvidersList = (discoveredProviders, validProviders) => {
return validProviders == null || validProviders.length == 0
Expand All @@ -15,19 +15,26 @@ export const SSOLoginButton = ({ discoveryAPIUrl, hostname, port, onSSOAttempt,
};
const attemptManualSSOProviderRetrieval = () => {
// Do an extra check to see if the hostname provides some SSO provider configuration.
getDiscoveryDataInfo(`https://${hostname}:${port}`)
const protocol = isLocalhost(hostname) ? 'http' : 'https';
const discoveryUrl = `${protocol}://${hostname}:${port}`;
getDiscoveryDataInfo(discoveryUrl)
.then((mergedSSOProviders) => {
setSSOProviders(filterByProvidersList(mergedSSOProviders, providers));
if (mergedSSOProviders.length == 0) {
setDiscoveryUrlValidated(undefined);
} else {
setDiscoveryUrlValidated(`https://${hostname}:${port}`);
setDiscoveryUrlValidated(discoveryUrl);
}
})
// eslint-disable-next-line no-console
.catch((err) => console.error('Error in getDiscoveryDataInfo of Login component', err));
};

function isLocalhost(hostname) {
const localhostNames = ['localhost', '127.0.0.1', '::1'];
return localhostNames.includes(hostname);
}

useEffect(() => {
// First, try to get the SSO discovery URL from the config.json configuration file and see if it contains anything.
getDiscoveryDataInfo(discoveryAPIUrl)
Expand Down

0 comments on commit f3ae774

Please sign in to comment.