Skip to content

Commit

Permalink
Fix auth with OIDC (#63)
Browse files Browse the repository at this point in the history
* resolve merge

* merge

* feat: oidc auth with oidc-spa lib

* fix: build option for node >16, remove auto admin mode

* fix: bump react-script

* fix: resolve build warnings

* fix: userRoles is an array

* fix: missing user_roles in localStorage

* fix: add debug log

* fix: split user roles

* fix: more debug

* fix: pick roles in token roles -_-

* fix: unify roles check

* chore: remove console log

* ci: open-ssl-legacy-provider option is handled in package scripts
  • Loading branch information
SimonDmz authored Dec 11, 2024
1 parent 116bca3 commit 4655dcf
Show file tree
Hide file tree
Showing 26 changed files with 4,283 additions and 6,822 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/develop-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
with:
node-version: 18
- run: yarn
- run: yarn --openssl-legacy-provider build
- run: yarn build
- name: Upload build
uses: actions/upload-artifact@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
with:
node-version: 18
- run: yarn
- run: yarn --openssl-legacy-provider build
- run: yarn build
- name: Upload build
uses: actions/upload-artifact@v4
with:
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*

#IDE
.idea/
.idea
.vscode
12 changes: 6 additions & 6 deletions jsconfig.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": ["src/*"]
}
"compilerOptions": {
"baseUrl": "src",
"paths": {
"*": ["src/*"]
}
}
}
}
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "massive-attack",
"version": "2.3.2",
"version": "2.4.0",
"private": true,
"dependencies": {
"@material-ui/core": "^4.11.4",
Expand All @@ -13,19 +13,19 @@
"date-fns": "^2.25.0",
"i18next": "^23.5.1",
"i18next-browser-languagedetector": "^7.1.0",
"keycloak-js": "^14.0.0",
"oidc-spa": "^5.6.1",
"papaparse": "^5.4.1",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^13.2.2",
"react-router-dom": "^5.2.1",
"react-scripts": "4.0.3",
"react-scripts": "5.0.1",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"start": "react-scripts --openssl-legacy-provider start",
"build": "react-scripts --openssl-legacy-provider build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Expand Down Expand Up @@ -89,6 +89,7 @@
]
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@types/react": "^16.9.23",
"@types/react-router-dom": "^5.1.3",
"copy-and-watch": "^0.1.4",
Expand Down
11 changes: 6 additions & 5 deletions public/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
"AUTHENTICATION_MODE": "${AUTHENTICATION_MODE}",
"_AUTHENTICATION_MODE_COMMENT": "The mode of authentication. ['anonymous','keycloak' ]",

"PLATEFORM":"${PLATEFORM}",
"_PLATEFORM_COMMENT":"The API may be connected to multiple environnements. [PRODUCTION, TRAINING]",

"ADMIN_ROLE":"${ADMIN_ROLE}",
"USER_ROLES":"${USER_ROLES}"
"ISSUER_URI": "${ISSUER_URI}",
"OIDC_CLIENT_ID": "${OIDC_CLIENT_ID}",

"PLATEFORM": "${PLATEFORM}",
"_PLATEFORM_COMMENT": "Just a label in the header",

"ADMIN_ROLE": "${ADMIN_ROLE}",
"USER_ROLES": "${USER_ROLES}"
}
8 changes: 0 additions & 8 deletions public/keycloak.json

This file was deleted.

14 changes: 14 additions & 0 deletions public/silent-sso.htm
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">

<head>
<title>Massive-Attack authentication</title>
</head>

<body>
<script>
parent.postMessage(location.href, location.origin);
</script>
</body>

</html>
27 changes: 12 additions & 15 deletions src/components/app/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,19 @@ import { I18nextProvider } from 'react-i18next';
import i18n from '../../utils/i18n/i18n';
import Header from '../header';
import Navigation from '../navigation';
import OrganisationUnitsVue from '../orgaUnitsVue';
import Preloader from '../common/Preloader';
import Requester from '../requester';
import TrainingCourses from '../trainingCourses';
import { getConfiguration } from '../../utils/configuration';
import { getUserOrganisationalUnit } from '../../utils/api/massive-attack-api';
import { getUser } from '../../utils/userInfo';
import { useAuth } from '../../utils/hook/auth';
import { LOC_STOR_API_URL_KEY, LOC_STOR_USER_KEY } from 'utils/constants';
import { OrganisationUnitsVue } from 'components/orgaUnitsVue';

export const AppContext = React.createContext();

const App = () => {
const { authenticated, isAdmin, pending } = useAuth();
const { authenticated, isAdmin, pending, tokens } = useAuth();
const [organisationalUnit, setOrganisationalUnit] = useState();
const [pf, setPf] = useState('');
const [dateReference, setDateReference] = useState(new Date().getTime());
const [campaignLabel, setCampaignLabel] = useState('');
const [campaignId, setCampaignId] = useState('');
Expand All @@ -28,20 +26,19 @@ const App = () => {
const [error, setError] = useState(undefined);
const [organisationalUnits, setOrganisationalUnits] = useState([]);
const [availableSessions, setAvailableSessions] = useState(undefined);
const [user, setUser] = useState({ firstName: 'John', lastName: 'Doe' });

useEffect(() => {
const fetchUserOrgaUnit = async () => {
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
const orgaUnitResponse = await getUserOrganisationalUnit(
MASSIVE_ATTACK_API_URL,
AUTHENTICATION_MODE,
PLATEFORM
);
const apiUrl = window.localStorage.getItem(LOC_STOR_API_URL_KEY);
const orgaUnitResponse = await getUserOrganisationalUnit(apiUrl, tokens);
setOrganisationalUnit(await orgaUnitResponse.data);
setPf(PLATEFORM);
};
if (authenticated) fetchUserOrgaUnit();
}, [authenticated]);
if (authenticated) {
fetchUserOrgaUnit();
setUser(JSON.parse(window.localStorage.getItem(LOC_STOR_USER_KEY)));
}
}, [authenticated, tokens]);

const context = {
organisationalUnit,
Expand Down Expand Up @@ -75,7 +72,7 @@ const App = () => {
)}
{authenticated && (
<>
<Header user={getUser()} pf={pf} />
<Header user={user} />
<BrowserRouter>
<I18nextProvider i18n={i18n}>
<AppContext.Provider value={context}>
Expand Down
9 changes: 6 additions & 3 deletions src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import PropTypes from 'prop-types';
import React from 'react';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core';
import { version } from '../../../package.json';
import packagejson from '../../../package.json';
import { LOC_STOR_PLATFORM_KEY } from 'utils/constants';

const appVersion = packagejson.version;
const useStyles = makeStyles(() => ({
row: {
display: 'flex',
Expand All @@ -23,15 +25,16 @@ const useStyles = makeStyles(() => ({
},
}));

const Header = ({ user = { firstName: 'John', lastName: 'Doe' }, pf }) => {
const Header = ({ user = { firstName: 'John', lastName: 'Doe' } }) => {
const classes = useStyles();
const { firstName, lastName } = user;
const pf = window.localStorage.getItem(LOC_STOR_PLATFORM_KEY);
return (
<AppBar className={classes.row} position="static">
<div className={classes.textBlock}>
<Typography variant="h4">MASSIVE ATTACK</Typography>
<Typography className={classes.marginLeft} variant="h6" color="error">
{version}
{appVersion}
</Typography>
</div>
<Typography variant="h4">{`==> ${pf}`}</Typography>
Expand Down
22 changes: 8 additions & 14 deletions src/components/orgaUnitsVue/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import { deleteCampaign, getCampaigns } from '../../utils/api/massive-attack-api
import { AppContext } from '../app/App';
import DeleteIcon from '@material-ui/icons/Delete';
import Preloader from '../common/Preloader';
import { getConfiguration } from '../../utils/configuration/index';
import { useTranslation } from 'react-i18next';
import { useIsAuthenticated } from 'utils/authentication/useAuth';
import { LOC_STOR_API_URL_KEY } from 'utils/constants';

const useStyles = makeStyles(theme => ({
row: {
Expand All @@ -42,9 +43,10 @@ const useStyles = makeStyles(theme => ({
},
}));

const OrganisationUnitsVue = () => {
export const OrganisationUnitsVue = () => {
const { t } = useTranslation();
const classes = useStyles();
const { tokens } = useIsAuthenticated();

const { isAdmin = false } = useContext(AppContext);
const [campaigns, setCampaigns] = useState([]);
Expand All @@ -53,24 +55,19 @@ const OrganisationUnitsVue = () => {
const [sessionToDelete, setSessionToDelete] = useState();
const [filteredCamps, setFilteredCamps] = useState([]);
const [waiting, setWaiting] = useState(false);
const MASSIVE_ATTACK_API_URL = window.localStorage.getItem(LOC_STOR_API_URL_KEY);

useEffect(() => {
setFilteredCamps(campaigns.filter(({ id }) => id.includes('_')));
}, [campaigns, isAdmin]);

useEffect(() => {
const fetchCampaigns = async () => {
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
const camps = await getCampaigns(
MASSIVE_ATTACK_API_URL,
AUTHENTICATION_MODE,
PLATEFORM,
isAdmin
);
const camps = await getCampaigns(MASSIVE_ATTACK_API_URL, tokens, isAdmin);
setCampaigns(await camps.data);
};
fetchCampaigns();
}, [isAdmin]);
}, [MASSIVE_ATTACK_API_URL, isAdmin, tokens]);

useEffect(() => {
const getOrganisationalUnit = id => id.split('_')[2];
Expand Down Expand Up @@ -108,8 +105,7 @@ const OrganisationUnitsVue = () => {
}, [filteredCamps]);

const deleteCampaignById = async id => {
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
return deleteCampaign(MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM)(id);
return deleteCampaign(MASSIVE_ATTACK_API_URL, tokens)(id);
};

const deleteCampaignsBySession = session => {
Expand Down Expand Up @@ -189,5 +185,3 @@ const OrganisationUnitsVue = () => {
</>
);
};

export default OrganisationUnitsVue;
34 changes: 9 additions & 25 deletions src/components/requester/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ import Button from '@material-ui/core/Button';
import DeleteIcon from '@material-ui/icons/Delete';
import Preloader from '../common/Preloader';
import Select from '@material-ui/core/Select';
import { getConfiguration } from '../../utils/configuration';
import { useIsAuthenticated } from 'utils/authentication/useAuth';
import { LOC_STOR_API_URL_KEY } from 'utils/constants';

const useStyles = makeStyles(theme => ({
importCsv: {
Expand Down Expand Up @@ -113,6 +114,7 @@ const useStyles = makeStyles(theme => ({
const Requester = () => {
const { t } = useTranslation();
const classes = useStyles();
const { tokens } = useIsAuthenticated();

const defaultValue = { id: 'default', ou: { id: 'unknown', label: 'Select...' } };
const {
Expand All @@ -130,7 +132,6 @@ const Requester = () => {
setInterviewers,
sessionType,
setSessionType,
error,
setError,
organisationalUnits,
setOrganisationalUnits,
Expand All @@ -141,8 +142,8 @@ const Requester = () => {
const [waiting, setWaiting] = useState(false);
const [invalidValues, setInvalidValues] = useState([]);
// eslint-disable-next-line no-unused-vars
const [successMessage, setSuccessMessage] = useState('');
const [alerts, setAlerts] = useState([]);
const MASSIVE_ATTACK_API_URL = window.localStorage.getItem(LOC_STOR_API_URL_KEY);

const showAlert = (message, severity) => {
const newAlert = { message, severity };
Expand All @@ -161,20 +162,15 @@ const Requester = () => {

useEffect(() => {
const getSessions = async () => {
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
let tempError;
const sessions = await getTrainingSessions(
MASSIVE_ATTACK_API_URL,
AUTHENTICATION_MODE,
PLATEFORM
).catch(() => {
const sessions = await getTrainingSessions(MASSIVE_ATTACK_API_URL, tokens).catch(() => {
tempError = true;
setError(true);
});
setAvailableSessions(tempError ? undefined : await sessions.data);
};
getSessions();
}, [setError, setAvailableSessions]);
}, [setError, setAvailableSessions, tokens, MASSIVE_ATTACK_API_URL]);

useEffect(() => {
if (!organisationalUnit) {
Expand Down Expand Up @@ -216,45 +212,33 @@ const Requester = () => {
const call = async () => {
setDateReference(dateReference + 1);
setWaiting(true);
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
const parametrizedUrl =
MASSIVE_ATTACK_API_URL + '/massive-attack/api/training-course' + constructParamsURL();
const callResponse = await postTrainingSession(
parametrizedUrl,
AUTHENTICATION_MODE,
PLATEFORM
).catch(e => {
const callResponse = await postTrainingSession(parametrizedUrl, tokens).catch(e => {
setError(true);
showAlert(t('ContactSupport'), 'error');
console.error(error);
console.error(invalidValues);
console.log(e);
});
setWaiting(false);
setResponse(await callResponse?.data.campaign);
// to prevent sending another session with the same timestamp
console.error(successMessage);
showAlert(t('TrainingSessionSuccess'), 'success');
setCampaignId('default');
setInterviewers([{ id: '', index: 0 }]);
};

useEffect(() => {
const getOUs = async () => {
const { MASSIVE_ATTACK_API_URL, AUTHENTICATION_MODE, PLATEFORM } = await getConfiguration();
let tempError;
const ous = await getOrganisationUnits(
MASSIVE_ATTACK_API_URL,
AUTHENTICATION_MODE,
PLATEFORM
).catch(() => {
const ous = await getOrganisationUnits(MASSIVE_ATTACK_API_URL, tokens).catch(() => {
tempError = true;
setError(true);
});
setOrganisationalUnits(tempError ? undefined : await ous.data);
};
getOUs();
}, [setError, setOrganisationalUnits]);
}, [setError, setOrganisationalUnits, tokens, MASSIVE_ATTACK_API_URL]);

const updateDateReference = stringDate => {
let newDate = new Date(stringDate);
Expand Down
Loading

0 comments on commit 4655dcf

Please sign in to comment.