Skip to content

Commit 9777a50

Browse files
committed
1 parent bcfa6cb commit 9777a50

File tree

5 files changed

+130
-136
lines changed

5 files changed

+130
-136
lines changed

apps/model_catalog/package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/model_catalog/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"eslint-plugin-react-hooks": "^4.2.0",
1616
"filesize": "^6.1.0",
1717
"humanparser": "^1.11.0",
18-
"keycloak-js": "^8.0.1",
18+
"keycloak-js": "^12.0.2",
1919
"lodash": "^4.17.20",
2020
"material-ui-chip-input": "^2.0.0-beta.2",
2121
"moment": "^2.29.1",

apps/model_catalog/src/Introduction.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ import "./App.css";
2727

2828
const ResponsiveEllipsis = responsiveHOC()(LinesEllipsis);
2929

30-
// const openInNewTab = (url) => {
31-
// const newWindow = window.open(url, "_blank", "noopener,noreferrer");
32-
// if (newWindow) newWindow.opener = null;
33-
// };
3430

3531
const styles = (theme) => ({
3632
header: {

apps/model_catalog/src/auth.js

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import Keycloak from 'keycloak-js';
2+
3+
4+
// We start by configuring the Keycloak javascript client
5+
// It needs to know your app id in order to authenticate users for it
6+
const keycloak = Keycloak({
7+
url: 'https://iam.ebrains.eu/auth',
8+
realm: 'hbp',
9+
clientId: 'model-catalog',
10+
'public-client': true,
11+
'confidential-port': 0,
12+
});
13+
const YOUR_APP_SCOPES = 'team email profile'; // full list at https://iam.ebrains.eu/auth/realms/hbp/.well-known/openid-configuration
14+
15+
16+
export default function initAuth(main) {
17+
console.log('DOM content is loaded, initialising Keycloak client...');
18+
keycloak
19+
.init({ flow: 'standard', pkceMethod: 'S256' })
20+
.then(() => checkAuth(main))
21+
.catch(console.log);
22+
}
23+
24+
function checkAuth(main) {
25+
console.log('Keycloak client is initialised, verifying authentication...');
26+
27+
// Is the user anonymous or authenticated?
28+
const isAuthenticated = keycloak.authenticated;
29+
const isAnonymous = !keycloak.authenticated;
30+
// Is this app a standalone app, a framed app or a delegate?
31+
const isParent = (window.opener == null);
32+
const isIframe = (window !== window.parent);
33+
const isMainFrame = (window === window.parent);
34+
const isStandaloneApp = isMainFrame && isParent;
35+
const isFramedApp = isIframe && isParent;
36+
const isDelegate = (window.opener != null);
37+
// Posting and listening to messages
38+
const postMessageToParentTab = (message, parentTabOrigin) => window.opener.postMessage(message, parentTabOrigin);
39+
const listenToMessage = (callback) => window.addEventListener('message', callback);
40+
const AUTH_MESSAGE = 'clb.authenticated';
41+
const myAppOrigin = window.location.origin;
42+
// Manipulating URLs and tabs
43+
const openTab = (url) => window.open(url);
44+
const getCurrentURL = () => new URL(window.location);
45+
const closeCurrentTab = () => window.close();
46+
47+
const login = (scopes) => keycloak.login({ scope: scopes });
48+
49+
// A standalone app should simply login if the user is not authenticated
50+
// and do its business logic otherwise
51+
if (isStandaloneApp) {
52+
console.log('This is a standalone app...');
53+
if (isAnonymous) {
54+
console.log('...which is not authenticated, starting login...');
55+
return login(YOUR_APP_SCOPES);
56+
}
57+
if (isAuthenticated) {
58+
console.log('...which is authenticated, starting business logic...');
59+
return main(keycloak);
60+
}
61+
}
62+
63+
// A framed app should open a delegate to do the authentication for it and listen to its messages and verify them
64+
// If the user is authenticated, it should do its business logic
65+
if (isFramedApp) {
66+
console.log('This is a framed app...');
67+
if (isAnonymous) {
68+
console.log('...which is not authenticated, delegating to new tab...');
69+
listenToMessage(verifyMessage);
70+
return openTab(getCurrentURL());
71+
}
72+
if (isAuthenticated) {
73+
console.log('...which is authenticated, starting business logic...');
74+
return main(keycloak);
75+
}
76+
}
77+
78+
// A delegate should login if the user is not authenticated
79+
// Otherwise, it should inform its opener that the user is authenticated and close itself
80+
if (isDelegate) {
81+
console.log('This is a delegate tab...');
82+
if (isAnonymous) {
83+
console.log('...which is not authenticated, starting login...');
84+
return login(YOUR_APP_SCOPES);
85+
}
86+
if (isAuthenticated) {
87+
console.log('...which is authenticated, warn parent and close...');
88+
postMessageToParentTab(AUTH_MESSAGE, myAppOrigin);
89+
return closeCurrentTab();
90+
}
91+
}
92+
}
93+
94+
function verifyMessage(event) {
95+
console.log('Message receveived, verifying it...');
96+
97+
const AUTH_MESSAGE = 'clb.authenticated';
98+
const receivedMessage = event.data;
99+
const messageOrigin = event.origin;
100+
const myAppOrigin = window.location.origin;
101+
// const reload = () => window.location.reload(); // TODO: remove?
102+
const login = (scopes) => keycloak.login({ scope: scopes });
103+
104+
105+
// Stop if the message is not the auth message
106+
if (receivedMessage !== AUTH_MESSAGE) return;
107+
108+
// Stop if the message is not coming from our app origin
109+
if (messageOrigin !== myAppOrigin) return;
110+
111+
// Login otherwise
112+
return login(YOUR_APP_SCOPES);
113+
}

apps/model_catalog/src/index.js

Lines changed: 9 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,21 @@
1-
import Keycloak from "keycloak-js";
2-
import React from "react";
3-
import ReactDOM from "react-dom";
4-
5-
import { SnackbarProvider } from "notistack";
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import initAuth from './auth';
64
import { datastore } from "./datastore";
75
import { ContextMainProvider } from "./ContextMain";
6+
import { SnackbarProvider } from "notistack";
87
import ValidationFramework from "./ValidationFramework";
98

10-
// We start by configuring the Keycloak javascript client
11-
// It needs to know your app id in order to authenticate users for it
12-
const keycloak = Keycloak({
13-
url: "https://iam.ebrains.eu/auth",
14-
realm: "hbp",
15-
clientId: "model-catalog", // TODO: change clientID to validation-framework, once client is registered
16-
});
17-
const YOUR_APP_SCOPES = "team email profile"; // full list at https://iam.ebrains.eu/auth/realms/hbp/.well-known/openid-configuration
18-
19-
// When ready, we initialise the keycloak client
20-
// Once done, it will call our `checkAuth` function
21-
window.addEventListener("DOMContentLoaded", initKeycloak);
22-
23-
function initKeycloak() {
24-
console.log("DOM content is loaded, initialising Keycloak client...");
25-
keycloak.init({ flow: "implicit" }).success(checkAuth).error(console.log);
26-
}
27-
28-
function checkAuth() {
29-
console.log("Keycloak client is initialised, verifying authentication...");
30-
31-
// Is the user anonymous or authenticated?
32-
const isAuthenticated = keycloak.authenticated;
33-
const isAnonymous = !keycloak.authenticated;
34-
// Is this app a standalone app, a framed app or a delegate?
35-
const isParent = window.opener == null;
36-
const isIframe = window !== window.parent;
37-
const isMainFrame = window === window.parent;
38-
const isStandaloneApp = isMainFrame && isParent;
39-
const isFramedApp = isIframe && isParent;
40-
const isDelegate = window.opener != null;
41-
// Posting and listening to messages
42-
const postMessageToParentTab = (message, parentTabOrigin) =>
43-
window.opener.postMessage(message, parentTabOrigin);
44-
const listenToMessage = (callback) =>
45-
window.addEventListener("message", callback);
46-
const AUTH_MESSAGE = "clb.authenticated";
47-
const myAppOrigin = window.location.origin;
48-
// Manipulating URLs and tabs
49-
const openTab = (url) => window.open(url);
50-
const getCurrentURL = () => new URL(window.location);
51-
const closeCurrentTab = () => window.close();
52-
53-
const login = (scopes) => keycloak.login({ scope: scopes });
54-
55-
// A standalone app should simply login if the user is not authenticated
56-
// and do its business logic otherwise
57-
if (isStandaloneApp) {
58-
console.log("This is a standalone app...");
59-
if (isAnonymous) {
60-
console.log("...which is not authenticated, starting login...");
61-
return login(YOUR_APP_SCOPES);
62-
}
63-
if (isAuthenticated) {
64-
console.log(
65-
"...which is authenticated, starting business logic..."
66-
);
67-
return doBusinessLogic(keycloak);
68-
}
69-
}
70-
71-
// A framed app should open a delegate to do the authentication for it and listen to its messages and verify them
72-
// If the user is authenticated, it should do its business logic
73-
if (isFramedApp) {
74-
console.log("This is a framed app...");
75-
if (isAnonymous) {
76-
console.log(
77-
"...which is not authenticated, delegating to new tab..."
78-
);
79-
listenToMessage(verifyMessage);
80-
return openTab(getCurrentURL());
81-
}
82-
if (isAuthenticated) {
83-
console.log(
84-
"...which is authenticated, starting business logic..."
85-
);
86-
return doBusinessLogic(keycloak);
87-
}
88-
}
89-
90-
// A delegate should login if the user is not authenticated
91-
// Otherwise, it should inform its opener that the user is authenticated and close itself
92-
if (isDelegate) {
93-
console.log("This is a delegate tab...");
94-
if (isAnonymous) {
95-
console.log("...which is not authenticated, starting login...");
96-
return login(YOUR_APP_SCOPES);
97-
}
98-
if (isAuthenticated) {
99-
console.log("...which is authenticated, warn parent and close...");
100-
postMessageToParentTab(AUTH_MESSAGE, myAppOrigin);
101-
return closeCurrentTab();
102-
}
103-
}
104-
}
105-
106-
function verifyMessage(event) {
107-
console.log("Message receveived, verifying it...");
108-
109-
const AUTH_MESSAGE = "clb.authenticated";
110-
const receivedMessage = event.data;
111-
const messageOrigin = event.origin;
112-
const myAppOrigin = window.location.origin;
113-
// const reload = () => window.location.reload(); // TODO: remove?
114-
const login = (scopes) => keycloak.login({ scope: scopes });
115-
116-
// Stop if the message is not the auth message
117-
if (receivedMessage !== AUTH_MESSAGE) return;
118-
119-
// Stop if the message is not coming from our app origin
120-
if (messageOrigin !== myAppOrigin) return;
121-
122-
// Login otherwise
123-
return login(YOUR_APP_SCOPES);
124-
}
125-
126-
function doBusinessLogic(auth) {
9+
function renderApp(auth) {
12710
datastore.auth = auth;
12811
ReactDOM.render(
12912
<ContextMainProvider>
13013
<SnackbarProvider maxSnack={3}>
13114
<ValidationFramework auth={auth} />
13215
</SnackbarProvider>
13316
</ContextMainProvider>,
134-
document.getElementById("root")
17+
document.getElementById('root')
13518
);
136-
}
19+
};
20+
21+
window.addEventListener('DOMContentLoaded', () => initAuth(renderApp));

0 commit comments

Comments
 (0)