Skip to content
Snippets Groups Projects
Commit e752c1da authored by Sandro Weber's avatar Sandro Weber
Browse files

updated with newest changes form old frontend

parent 54019621
No related branches found
No related tags found
No related merge requests found
......@@ -28,6 +28,7 @@
<title>Neurorobotics Platform</title>
</head>
<body>
<script src="https://iam.ebrains.eu/auth/js/keycloak.js"></script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
......
import config from '../config.json';
/* global Keycloak */
let keycloakClient = undefined;
const INIT_CHECK_INTERVAL_MS = 100;
const INIT_CHECK_MAX_RETRIES = 10;
let _instance = null;
const SINGLETON_ENFORCER = Symbol();
......@@ -12,13 +19,13 @@ class AuthenticationService {
throw new Error('Use ' + this.constructor.name + '.instance');
}
this.CLIENT_ID = config.authV2.clientId;
this.CLIENT_SECRET = config.authV2.secret;
this.STORAGE_KEY = `tokens-${this.CLIENT_ID}@https://iam.ebrains.eu/auth/realms/hbp/protocol/openid-connect/auth`;
this.proxyURL = config.api.proxy.url;
this.oidcEnabled = config.auth.enableOIDC;
this.clientId = config.auth.clientId;
this.authURL = config.auth.url;
this.STORAGE_KEY = `tokens-${this.clientId}@https://iam.ebrains.eu/auth/realms/hbp`;
this.redirectToAuthPage = true;
this.checkForSessionStateAndAuthCode();
//this.checkForNewTokenToStore();
this.init();
}
static get instance() {
......@@ -29,120 +36,126 @@ class AuthenticationService {
return _instance;
}
/**
* Checks if the current page URL contains access tokens.
* This happens when the successfully logging in at the proxy login page and
* being redirected back with the token info.
* Will automatically remove additional access info and present a clean URL after being redirected.
*/
checkForNewTokenToStore() {
const path = window.location.href;
const accessTokenMatch = /&access_token=([^&]*)/.exec(path);
init() {
this.initialized = false;
if (this.oidcEnabled) {
this.authCollab().then(() => {
this.initialized = true;
});
}
else {
this.checkForNewLocalTokenToStore();
this.initialized = true;
}
if (!accessTokenMatch || !accessTokenMatch[1]) {
return;
this.promiseInitialized = new Promise((resolve, reject) => {
let numChecks = 0;
let checkInterval = setInterval(() => {
numChecks++;
if (numChecks > INIT_CHECK_MAX_RETRIES) {
clearInterval(checkInterval);
reject();
}
if (this.initialized) {
clearInterval(checkInterval);
resolve();
}
}, INIT_CHECK_INTERVAL_MS);
});
}
authenticate(config) {
if (this.oidcEnabled) {
this.authCollab(config);
}
else {
this.authLocal(config);
}
}
let accessToken = accessTokenMatch[1];
getToken() {
if (this.oidcEnabled) {
if (keycloakClient && keycloakClient.authenticated) {
keycloakClient
.updateToken(30)
.then(function() {})
.catch(function() {
console.error('Failed to refresh token');
});
return keycloakClient.token;
}
else {
console.error('getToken() - Client is not authenticated');
}
}
else {
return this.getStoredLocalToken();
}
}
localStorage.setItem(
this.STORAGE_KEY,
//eslint-disable-next-line camelcase
JSON.stringify([{ access_token: accessToken }])
);
const pathMinusAccessToken = path.substr(0, path.indexOf('&access_token='));
window.location.href = pathMinusAccessToken;
logout() {
if (this.oidcEnabled) {
if (keycloakClient && keycloakClient.authenticated) {
keycloakClient.logout();
keycloakClient.clearStoredLocalToken();
}
else {
console.error('Client is not authenticated');
}
}
else {
return this.clearStoredLocalToken();
}
}
/**
* Checks if the current page URL contains access tokens.
* This happens when the successfully logging in at the proxy login page and
* being redirected back with the token info.
* Will automatically remove additional access info and present a clean URL after being redirected.
*/
checkForSessionStateAndAuthCode() {
const path = window.location.href;
const sessionStateMatch = /session_state=([^&]*)/.exec(path);
const authCodeMatch = /code=([^&]*)/.exec(path);
if (!sessionStateMatch || !authCodeMatch) {
authLocal(config) {
if (this.authenticating) {
return;
}
this.authenticating = true;
this.redirectToAuthPage = false;
this.authURL = this.authURL || config.url;
this.clientId = this.clientId || config.clientId;
let sessionState = sessionStateMatch[1];
let authCode = authCodeMatch[1];
console.info('authCode = ' + authCode);
let absoluteUrl = /^https?:\/\//i;
if (!absoluteUrl.test(this.authURL)) {
this.authURL = `${this.proxyURL}${this.authURL}`;
}
this.getAccessToken(authCode);
this.clearStoredLocalToken();
window.location.href = `${this.authURL}&client_id=${this
.clientId}&redirect_uri=${encodeURIComponent(window.location.href)}`;
}
async getAccessToken(authorizationCode) {
console.info('getAccessToken - origin = ' + window.location.origin);
console.info('getAccessToken - authenticationCode = ' + authorizationCode);
let urlRequestAccessToken = 'https://iam.ebrains.eu/auth/realms/hbp/protocol/openid-connect/token';
let options = {
method: 'POST',
mode: 'cors', // no-cors, *cors, same-origin
//cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
//credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/x-www-form-urlencoded'//,
//'Access-Control-Allow-Origin': '*',
//Referer: window.location.origin
},
// redirect: manual, *follow, error
//redirect: 'follow',
// referrerPolicy: no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin,
// strict-origin, strict-origin-when-cross-origin, unsafe-url
referrerPolicy: 'no-referrer'
};
let formDetails = {
grant_type: 'authorization_code',
client_id: this.CLIENT_ID,
redirect_uri: window.location.origin,
client_secret: this.CLIENT_SECRET,
code: authorizationCode
};
const formBody = Object.entries(formDetails)
.map(([key, value]) => encodeURIComponent(key) + '=' + encodeURIComponent(value))
.join('&');
options.body = formBody;
const responseAccessTokenRequest = await fetch(urlRequestAccessToken, options);
const responseAccessTokenRequestJSON = await responseAccessTokenRequest.json();
console.info(responseAccessTokenRequest);
console.info(responseAccessTokenRequestJSON);
/*localStorage.setItem(
checkForNewLocalTokenToStore() {
const path = window.location.pathname;
const accessTokenMatch = /&access_token=([^&]*)/.exec(path);
if (!accessTokenMatch || !accessTokenMatch[1]) {
return;
}
let accessToken = accessTokenMatch[1];
localStorage.setItem(
this.STORAGE_KEY,
//eslint-disable-next-line camelcase
JSON.stringify([{ access_token: accessToken }])
);*/
//const pathMinusAccessToken = path.substr(0, path.indexOf('?'));
//window.location.href = pathMinusAccessToken;
);
// navigate to clean url
let cleanedPath = path.substr(0, path.indexOf('&'));
window.location = cleanedPath;
}
/**
* Clear currently stored access token.
*/
clearStoredToken() {
clearStoredLocalToken() {
localStorage.removeItem(this.STORAGE_KEY);
}
/**
* Get the stored access token.
*
* @return token The stored access token. Or strings identifying 'no-token' / 'malformed-token'.
*/
getStoredToken() {
getStoredLocalToken() {
let storedItem = localStorage.getItem(this.STORAGE_KEY);
if (!storedItem) {
// this token will be rejected by the server and the client will get a proper auth error
return AuthenticationService.CONSTANTS.NO_TOKEN;
return 'no-token';
}
try {
......@@ -151,38 +164,57 @@ class AuthenticationService {
}
catch (e) {
// this token will be rejected by the server and the client will get a proper auth error
return AuthenticationService.CONSTANTS.MALFORMED_TOKEN;
return 'malformed-token';
}
}
/**
* Opens the proxy's authentication page.
*
* @param {*} url The URL of the authentication page.
* If not an absolute URL it is assumed to be a subpage of the proxy.
*/
openAuthenticationPage(url = config.authV2.url) {
if (!this.redirectToAuthPage) {
authCollab(config) {
if (this.authenticating) {
return;
}
console.info('openAuthenticationPage - origin=' + window.location.origin);
this.clearStoredToken();
this.authenticating = true;
return new Promise(resolve => {
this.authURL = this.authURL || config.url;
this.initKeycloakClient().then(() => {
if (!keycloakClient.authenticated) {
// User is not authenticated, run login
keycloakClient
.login({ scope: 'openid profile email group' })
.then(() => {
resolve(true);
});
}
else {
keycloakClient.loadUserInfo().then(userInfo => {
this.userInfo = userInfo;
resolve(true);
});
}
});
});
}
let absoluteUrl = /^https?:\/\//i;
if (!absoluteUrl.test(url)) {
url = `https://${url}`;
}
/*window.location.href = `${url}
&client_id=${this.CLIENT_ID}
&redirect_uri=${encodeURIComponent(window.location.href)}`;*/
let testClientID = 'community-apps-tutorial';
console.info('redirect_uri=' + window.location.origin);
let testRedirectURI = window.location.origin; //'http://localhost:3000';
window.location.href = url +
'&client_id=' + testClientID +
'&redirect_uri=' + testRedirectURI;
initKeycloakClient() {
return new Promise(resolve => {
keycloakClient = Keycloak({
realm: 'hbp',
clientId: this.clientId,
//'public-client': true,
'confidential-port': 0,
url: this.authURL,
redirectUri: window.location.href // 'http://localhost:9001/#/esv-private' //
});
keycloakClient
.init({
flow: 'hybrid' /*, responseMode: 'fragment'*/
})
.then(() => {
resolve(keycloakClient);
});
});
}
}
......
......@@ -253,13 +253,11 @@ class ExperimentStorageService extends HttpService {
async setFile(directoryPath, filename, data, byname = true, contentType = 'text/plain') {
let directory = directoryPath.replaceAll('/', '%2F');
const url = new URL(`${config.api.proxy.url}${endpoints.proxy.storage.url}/${directory}/${filename}`);
//console.info(url);
url.searchParams.append('byname', byname);
let requestOptions = {
...this.POSTOptions, ...{ headers: { 'Content-Type': contentType } }
};
//console.info(requestOptions);
if (contentType === 'text/plain') {
return this.httpRequestPOST(url, data, requestOptions);
......
......@@ -44,7 +44,9 @@ export class HttpService extends EventEmitter {
*/
performRequest = async (url, options, data) => {
// Add authorization header
options.headers.Authorization = `Bearer ${AuthenticationService.instance.getStoredToken()}`;
await AuthenticationService.instance.promiseInitialized;
let token = AuthenticationService.instance.getToken();
options.headers.Authorization = 'Bearer ' + token;
if (data) {
options.body = data;
}
......@@ -54,10 +56,7 @@ export class HttpService extends EventEmitter {
// error handling
if (!response.ok) {
if (response.status === 477) {
const responseText = await response.text();
console.info('auth error');
console.info(responseText);
AuthenticationService.instance.openAuthenticationPage(/*responseText*/);
AuthenticationService.instance.authenticate();
}
else if (response.status === 478) {
//TODO: redirect to maintenance page
......
......@@ -62,7 +62,6 @@ class NrpUserService extends HttpService {
async getCurrentUser() {
if (!this.currentUser) {
let responseIdentity = await this.httpRequestGET(IDENTITY_ME_URL);
console.info(responseIdentity);
if (responseIdentity.ok) {
this.currentUser = await responseIdentity.json();
}
......
import * as ROSLIB from 'roslib';
import _ from 'lodash';
import AuthenticationService from './authentication-service.js';
import AuthenticationService from './authentication-service-v2';
let _instance = null;
const SINGLETON_ENFORCER = Symbol();
......@@ -32,7 +32,7 @@ class RoslibService {
*/
getConnection(url) {
if (!this.connections.has(url)) {
let urlWithAuth = url + '?token=' + AuthenticationService.instance.getStoredToken();
let urlWithAuth = url + '?token=' + AuthenticationService.instance.getToken();
this.connections.set(url, new ROSLIB.Ros({ url: urlWithAuth }));
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment