diff --git a/apps/model_catalog/package-lock.json b/apps/model_catalog/package-lock.json
index 916e558..772e6c1 100644
--- a/apps/model_catalog/package-lock.json
+++ b/apps/model_catalog/package-lock.json
@@ -20,7 +20,7 @@
"eslint-plugin-react-hooks": "^4.2.0",
"filesize": "^6.1.0",
"humanparser": "^1.11.0",
- "keycloak-js": "^8.0.1",
+ "keycloak-js": "^12.0.2",
"lodash": "^4.17.20",
"material-ui-chip-input": "^2.0.0-beta.2",
"moment": "^2.29.1",
@@ -16284,9 +16284,9 @@
"integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
},
"node_modules/keycloak-js": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-8.0.2.tgz",
- "integrity": "sha512-5Jy5rHx0oURTtj2T6LSMLiqyHzDzPr6ZnaY1fwCBlMsiMx7RVsIBeysYZ5yy29ojH9IMzNJzlZvuLKbEOCmgDQ==",
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-12.0.4.tgz",
+ "integrity": "sha512-O/BHtyiDrZrUnKBrVF8POojqd3gmhuiDw4FiI+FbnB14nu7G5jKFrKYZa9Q0JYKIZXHJOBzSaKQcMp2WUI+zmA==",
"dependencies": {
"base64-js": "1.3.1",
"js-sha256": "0.9.0"
@@ -40495,9 +40495,9 @@
"integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
},
"keycloak-js": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-8.0.2.tgz",
- "integrity": "sha512-5Jy5rHx0oURTtj2T6LSMLiqyHzDzPr6ZnaY1fwCBlMsiMx7RVsIBeysYZ5yy29ojH9IMzNJzlZvuLKbEOCmgDQ==",
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-12.0.4.tgz",
+ "integrity": "sha512-O/BHtyiDrZrUnKBrVF8POojqd3gmhuiDw4FiI+FbnB14nu7G5jKFrKYZa9Q0JYKIZXHJOBzSaKQcMp2WUI+zmA==",
"requires": {
"base64-js": "1.3.1",
"js-sha256": "0.9.0"
diff --git a/apps/model_catalog/package.json b/apps/model_catalog/package.json
index 61d8a3a..fdc2b31 100644
--- a/apps/model_catalog/package.json
+++ b/apps/model_catalog/package.json
@@ -15,7 +15,7 @@
"eslint-plugin-react-hooks": "^4.2.0",
"filesize": "^6.1.0",
"humanparser": "^1.11.0",
- "keycloak-js": "^8.0.1",
+ "keycloak-js": "^12.0.2",
"lodash": "^4.17.20",
"material-ui-chip-input": "^2.0.0-beta.2",
"moment": "^2.29.1",
diff --git a/apps/model_catalog/src/AuthWidget.js b/apps/model_catalog/src/AuthWidget.js
new file mode 100644
index 0000000..892072a
--- /dev/null
+++ b/apps/model_catalog/src/AuthWidget.js
@@ -0,0 +1,45 @@
+import React from "react";
+import Button from "@material-ui/core/Button";
+import IconButton from "@material-ui/core/IconButton";
+import PersonIcon from '@material-ui/icons/Person';
+import Tooltip from "@material-ui/core/Tooltip";
+import ContextMain from "./ContextMain";
+
+
+function AuthWidget(props) {
+
+ const context = React.useContext(ContextMain);
+ const [auth] = context.auth;
+
+ if (auth.authenticated || props.currentUser) {
+
+ if (!props.currentUser) {
+ auth.loadUserInfo().then((userInfo) => {
+ console.log(userInfo);
+ props.setCurrentUser(userInfo.preferred_username);
+ });
+ };
+
+ return (
+
+
+
+
+
+ );
+ } else {
+ return (
+
+ );
+ }
+}
+
+export default AuthWidget;
\ No newline at end of file
diff --git a/apps/model_catalog/src/Introduction.js b/apps/model_catalog/src/Introduction.js
index d03a9d4..981e646 100644
--- a/apps/model_catalog/src/Introduction.js
+++ b/apps/model_catalog/src/Introduction.js
@@ -27,10 +27,6 @@ import "./App.css";
const ResponsiveEllipsis = responsiveHOC()(LinesEllipsis);
-// const openInNewTab = (url) => {
-// const newWindow = window.open(url, "_blank", "noopener,noreferrer");
-// if (newWindow) newWindow.opener = null;
-// };
const styles = (theme) => ({
header: {
diff --git a/apps/model_catalog/src/ValidationFramework.js b/apps/model_catalog/src/ValidationFramework.js
index be2f955..4a7def2 100644
--- a/apps/model_catalog/src/ValidationFramework.js
+++ b/apps/model_catalog/src/ValidationFramework.js
@@ -48,6 +48,7 @@ import ContextMain from "./ContextMain";
import Theme from "./theme";
import { withSnackbar } from "notistack";
import WarningBox from "./WarningBox";
+import AuthWidget from "./AuthWidget";
// if working on the appearance/layout set globals.DevMode=true
// to avoid loading the models and tests over the network every time;
@@ -129,6 +130,7 @@ class ValidationFramework extends React.Component {
this.state = {
modelData: [],
testData: [],
+ currentUser: null,
currentModel: null,
currentTest: null,
currentResult: null,
@@ -1174,6 +1176,10 @@ class ValidationFramework extends React.Component {
+ this.setState({currentUser: user})}
+ />
diff --git a/apps/model_catalog/src/auth.js b/apps/model_catalog/src/auth.js
new file mode 100644
index 0000000..c4331a1
--- /dev/null
+++ b/apps/model_catalog/src/auth.js
@@ -0,0 +1,114 @@
+import Keycloak from 'keycloak-js';
+
+
+// We start by configuring the Keycloak javascript client
+// It needs to know your app id in order to authenticate users for it
+const keycloak = Keycloak({
+ url: 'https://iam.ebrains.eu/auth',
+ realm: 'hbp',
+ clientId: 'model-catalog',
+ 'public-client': true,
+ 'confidential-port': 0,
+});
+const YOUR_APP_SCOPES = 'team email profile'; // full list at https://iam.ebrains.eu/auth/realms/hbp/.well-known/openid-configuration
+
+
+export default function initAuth(main) {
+ console.log('DOM content is loaded, initialising Keycloak client...');
+ keycloak
+ //.init({ flow: 'standard', pkceMethod: 'S256' })
+ .init({ flow: 'implicit' })
+ .then(() => checkAuth(main))
+ .catch(console.log);
+}
+
+function checkAuth(main) {
+ console.log('Keycloak client is initialised, verifying authentication...');
+
+ // Is the user anonymous or authenticated?
+ const isAuthenticated = keycloak.authenticated;
+ const isAnonymous = !keycloak.authenticated;
+ // Is this app a standalone app, a framed app or a delegate?
+ const isParent = (window.opener == null);
+ const isIframe = (window !== window.parent);
+ const isMainFrame = (window === window.parent);
+ const isStandaloneApp = isMainFrame && isParent;
+ const isFramedApp = isIframe && isParent;
+ const isDelegate = (window.opener != null);
+ // Posting and listening to messages
+ const postMessageToParentTab = (message, parentTabOrigin) => window.opener.postMessage(message, parentTabOrigin);
+ const listenToMessage = (callback) => window.addEventListener('message', callback);
+ const AUTH_MESSAGE = 'clb.authenticated';
+ const myAppOrigin = window.location.origin;
+ // Manipulating URLs and tabs
+ const openTab = (url) => window.open(url);
+ const getCurrentURL = () => new URL(window.location);
+ const closeCurrentTab = () => window.close();
+
+ const login = (scopes) => keycloak.login({ scope: scopes });
+
+ // A standalone app should simply login if the user is not authenticated
+ // and do its business logic otherwise
+ if (isStandaloneApp) {
+ console.log('This is a standalone app...');
+ if (isAnonymous) {
+ console.log('...which is not authenticated, starting app without authentication')
+ return main(keycloak);
+ }
+ if (isAuthenticated) {
+ console.log('...which is authenticated, starting app with authentication');
+ return main(keycloak);
+ }
+ }
+
+ // A framed app should open a delegate to do the authentication for it and listen to its messages and verify them
+ // If the user is authenticated, it should do its business logic
+ if (isFramedApp) {
+ console.log('This is a framed app...');
+ if (isAnonymous) {
+ console.log('...which is not authenticated, delegating to new tab...');
+ listenToMessage(verifyMessage);
+ return openTab(getCurrentURL());
+ }
+ if (isAuthenticated) {
+ console.log('...which is authenticated, starting business logic...');
+ return main(keycloak);
+ }
+ }
+
+ // A delegate should login if the user is not authenticated
+ // Otherwise, it should inform its opener that the user is authenticated and close itself
+ if (isDelegate) {
+ console.log('This is a delegate tab...');
+ if (isAnonymous) {
+ console.log('...which is not authenticated, starting login...');
+ return login(YOUR_APP_SCOPES);
+ }
+ if (isAuthenticated) {
+ console.log('...which is authenticated, warn parent and close...');
+ postMessageToParentTab(AUTH_MESSAGE, myAppOrigin);
+ return closeCurrentTab();
+ }
+ }
+}
+
+function verifyMessage(event) {
+ console.log('Message receveived, verifying it...');
+
+ const AUTH_MESSAGE = 'clb.authenticated';
+ const receivedMessage = event.data;
+ const messageOrigin = event.origin;
+ const myAppOrigin = window.location.origin;
+ // const reload = () => window.location.reload(); // TODO: remove?
+ const login = (scopes) => keycloak.login({ scope: scopes });
+
+
+ // Stop if the message is not the auth message
+ if (receivedMessage !== AUTH_MESSAGE) return;
+
+ // Stop if the message is not coming from our app origin
+ if (messageOrigin !== myAppOrigin) return;
+
+ // Login otherwise
+ return login(YOUR_APP_SCOPES);
+}
diff --git a/apps/model_catalog/src/index.js b/apps/model_catalog/src/index.js
index 949c607..1d7bcd1 100644
--- a/apps/model_catalog/src/index.js
+++ b/apps/model_catalog/src/index.js
@@ -1,129 +1,12 @@
-import Keycloak from "keycloak-js";
-import React from "react";
-import ReactDOM from "react-dom";
-
-import { SnackbarProvider } from "notistack";
+import React from 'react';
+import ReactDOM from 'react-dom';
+import initAuth from './auth';
import { datastore } from "./datastore";
import { ContextMainProvider } from "./ContextMain";
+import { SnackbarProvider } from "notistack";
import ValidationFramework from "./ValidationFramework";
-// We start by configuring the Keycloak javascript client
-// It needs to know your app id in order to authenticate users for it
-const keycloak = Keycloak({
- url: "https://iam.ebrains.eu/auth",
- realm: "hbp",
- clientId: "model-catalog", // TODO: change clientID to validation-framework, once client is registered
-});
-const YOUR_APP_SCOPES = "team email profile"; // full list at https://iam.ebrains.eu/auth/realms/hbp/.well-known/openid-configuration
-
-// When ready, we initialise the keycloak client
-// Once done, it will call our `checkAuth` function
-window.addEventListener("DOMContentLoaded", initKeycloak);
-
-function initKeycloak() {
- console.log("DOM content is loaded, initialising Keycloak client...");
- keycloak.init({ flow: "implicit" }).success(checkAuth).error(console.log);
-}
-
-function checkAuth() {
- console.log("Keycloak client is initialised, verifying authentication...");
-
- // Is the user anonymous or authenticated?
- const isAuthenticated = keycloak.authenticated;
- const isAnonymous = !keycloak.authenticated;
- // Is this app a standalone app, a framed app or a delegate?
- const isParent = window.opener == null;
- const isIframe = window !== window.parent;
- const isMainFrame = window === window.parent;
- const isStandaloneApp = isMainFrame && isParent;
- const isFramedApp = isIframe && isParent;
- const isDelegate = window.opener != null;
- // Posting and listening to messages
- const postMessageToParentTab = (message, parentTabOrigin) =>
- window.opener.postMessage(message, parentTabOrigin);
- const listenToMessage = (callback) =>
- window.addEventListener("message", callback);
- const AUTH_MESSAGE = "clb.authenticated";
- const myAppOrigin = window.location.origin;
- // Manipulating URLs and tabs
- const openTab = (url) => window.open(url);
- const getCurrentURL = () => new URL(window.location);
- const closeCurrentTab = () => window.close();
-
- const login = (scopes) => keycloak.login({ scope: scopes });
-
- // A standalone app should simply login if the user is not authenticated
- // and do its business logic otherwise
- if (isStandaloneApp) {
- console.log("This is a standalone app...");
- if (isAnonymous) {
- console.log("...which is not authenticated, starting login...");
- return login(YOUR_APP_SCOPES);
- }
- if (isAuthenticated) {
- console.log(
- "...which is authenticated, starting business logic..."
- );
- return doBusinessLogic(keycloak);
- }
- }
-
- // A framed app should open a delegate to do the authentication for it and listen to its messages and verify them
- // If the user is authenticated, it should do its business logic
- if (isFramedApp) {
- console.log("This is a framed app...");
- if (isAnonymous) {
- console.log(
- "...which is not authenticated, delegating to new tab..."
- );
- listenToMessage(verifyMessage);
- return openTab(getCurrentURL());
- }
- if (isAuthenticated) {
- console.log(
- "...which is authenticated, starting business logic..."
- );
- return doBusinessLogic(keycloak);
- }
- }
-
- // A delegate should login if the user is not authenticated
- // Otherwise, it should inform its opener that the user is authenticated and close itself
- if (isDelegate) {
- console.log("This is a delegate tab...");
- if (isAnonymous) {
- console.log("...which is not authenticated, starting login...");
- return login(YOUR_APP_SCOPES);
- }
- if (isAuthenticated) {
- console.log("...which is authenticated, warn parent and close...");
- postMessageToParentTab(AUTH_MESSAGE, myAppOrigin);
- return closeCurrentTab();
- }
- }
-}
-
-function verifyMessage(event) {
- console.log("Message receveived, verifying it...");
-
- const AUTH_MESSAGE = "clb.authenticated";
- const receivedMessage = event.data;
- const messageOrigin = event.origin;
- const myAppOrigin = window.location.origin;
- // const reload = () => window.location.reload(); // TODO: remove?
- const login = (scopes) => keycloak.login({ scope: scopes });
-
- // Stop if the message is not the auth message
- if (receivedMessage !== AUTH_MESSAGE) return;
-
- // Stop if the message is not coming from our app origin
- if (messageOrigin !== myAppOrigin) return;
-
- // Login otherwise
- return login(YOUR_APP_SCOPES);
-}
-
-function doBusinessLogic(auth) {
+function renderApp(auth) {
datastore.auth = auth;
ReactDOM.render(
@@ -131,6 +14,8 @@ function doBusinessLogic(auth) {
,
- document.getElementById("root")
+ document.getElementById('root')
);
-}
+};
+
+window.addEventListener('DOMContentLoaded', () => initAuth(renderApp));