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

cleanup old auth service, console output

parent e752c1da
No related branches found
No related tags found
No related merge requests found
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();
/**
* Service taking care of OIDC/FS authentication for NRP accounts
*/
class AuthenticationService {
constructor(enforcer) {
if (enforcer !== SINGLETON_ENFORCER) {
throw new Error('Use ' + this.constructor.name + '.instance');
}
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.init();
}
static get instance() {
if (_instance == null) {
_instance = new AuthenticationService(SINGLETON_ENFORCER);
}
return _instance;
}
init() {
this.initialized = false;
if (this.oidcEnabled) {
this.authCollab().then(() => {
this.initialized = true;
});
}
else {
this.checkForNewLocalTokenToStore();
this.initialized = true;
}
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);
}
}
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();
}
}
logout() {
if (this.oidcEnabled) {
if (keycloakClient && keycloakClient.authenticated) {
keycloakClient.logout();
keycloakClient.clearStoredLocalToken();
}
else {
console.error('Client is not authenticated');
}
}
else {
return this.clearStoredLocalToken();
}
}
authLocal(config) {
if (this.authenticating) {
return;
}
this.authenticating = true;
this.authURL = this.authURL || config.url;
this.clientId = this.clientId || config.clientId;
let absoluteUrl = /^https?:\/\//i;
if (!absoluteUrl.test(this.authURL)) {
this.authURL = `${this.proxyURL}${this.authURL}`;
}
this.clearStoredLocalToken();
window.location.href = `${this.authURL}&client_id=${this
.clientId}&redirect_uri=${encodeURIComponent(window.location.href)}`;
}
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 }])
);
// navigate to clean url
let cleanedPath = path.substr(0, path.indexOf('&'));
window.location = cleanedPath;
}
clearStoredLocalToken() {
localStorage.removeItem(this.STORAGE_KEY);
}
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 'no-token';
}
try {
let tokens = JSON.parse(storedItem);
return tokens.length ? tokens[tokens.length - 1].access_token : null;
}
catch (e) {
// this token will be rejected by the server and the client will get a proper auth error
return 'malformed-token';
}
}
authCollab(config) {
if (this.authenticating) {
return;
}
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);
});
}
});
});
}
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);
});
});
}
}
AuthenticationService.CONSTANTS = Object.freeze({
MALFORMED_TOKEN: 'malformed-token',
NO_TOKEN: 'no-token'
});
export default AuthenticationService;
import config from '../config.json'; 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; let _instance = null;
const SINGLETON_ENFORCER = Symbol(); const SINGLETON_ENFORCER = Symbol();
...@@ -12,11 +19,13 @@ class AuthenticationService { ...@@ -12,11 +19,13 @@ class AuthenticationService {
throw new Error('Use ' + this.constructor.name + '.instance'); throw new Error('Use ' + this.constructor.name + '.instance');
} }
this.CLIENT_ID = config.auth.clientId; this.proxyURL = config.api.proxy.url;
this.STORAGE_KEY = `tokens-${this.CLIENT_ID}@https://services.humanbrainproject.eu/oidc`; this.oidcEnabled = config.auth.enableOIDC;
this.PROXY_URL = config.api.proxy.url; this.clientId = config.auth.clientId;
this.authURL = config.auth.url;
this.STORAGE_KEY = `tokens-${this.clientId}@https://iam.ebrains.eu/auth/realms/hbp`;
this.checkForNewTokenToStore(); this.init();
} }
static get instance() { static get instance() {
...@@ -27,44 +36,122 @@ class AuthenticationService { ...@@ -27,44 +36,122 @@ class AuthenticationService {
return _instance; return _instance;
} }
/** init() {
* Checks if the current page URL contains access tokens. this.initialized = false;
* This happens when the successfully logging in at the proxy login page and if (this.oidcEnabled) {
* being redirected back with the token info. this.authCollab().then(() => {
* Will automatically remove additional access info and present a clean URL after being redirected. this.initialized = true;
*/ });
checkForNewTokenToStore() { }
const path = window.location.href; else {
const accessTokenMatch = /&access_token=([^&]*)/.exec(path); this.checkForNewLocalTokenToStore();
this.initialized = true;
}
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);
}
}
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();
}
}
logout() {
if (this.oidcEnabled) {
if (keycloakClient && keycloakClient.authenticated) {
keycloakClient.logout();
keycloakClient.clearStoredLocalToken();
}
else {
console.error('Client is not authenticated');
}
}
else {
return this.clearStoredLocalToken();
}
}
authLocal(config) {
if (this.authenticating) {
return;
}
this.authenticating = true;
this.authURL = this.authURL || config.url;
this.clientId = this.clientId || config.clientId;
let absoluteUrl = /^https?:\/\//i;
if (!absoluteUrl.test(this.authURL)) {
this.authURL = `${this.proxyURL}${this.authURL}`;
}
this.clearStoredLocalToken();
window.location.href = `${this.authURL}&client_id=${this
.clientId}&redirect_uri=${encodeURIComponent(window.location.href)}`;
}
checkForNewLocalTokenToStore() {
const path = window.location.pathname;
const accessTokenMatch = /&access_token=([^&]*)/.exec(path);
if (!accessTokenMatch || !accessTokenMatch[1]) { if (!accessTokenMatch || !accessTokenMatch[1]) {
return; return;
} }
let accessToken = accessTokenMatch[1]; let accessToken = accessTokenMatch[1];
localStorage.setItem( localStorage.setItem(
this.STORAGE_KEY, this.STORAGE_KEY,
//eslint-disable-next-line camelcase //eslint-disable-next-line camelcase
JSON.stringify([{ access_token: accessToken }]) JSON.stringify([{ access_token: accessToken }])
); );
const pathMinusAccessToken = path.substr(0, path.indexOf('&access_token='));
window.location.href = pathMinusAccessToken; // navigate to clean url
let cleanedPath = path.substr(0, path.indexOf('&'));
window.location = cleanedPath;
} }
/** clearStoredLocalToken() {
* Clear currently stored access token.
*/
clearStoredToken() {
localStorage.removeItem(this.STORAGE_KEY); localStorage.removeItem(this.STORAGE_KEY);
} }
/** getStoredLocalToken() {
* Get the stored access token.
*
* @return token The stored access token. Or strings identifying 'no-token' / 'malformed-token'.
*/
getStoredToken() {
let storedItem = localStorage.getItem(this.STORAGE_KEY); let storedItem = localStorage.getItem(this.STORAGE_KEY);
if (!storedItem) { if (!storedItem) {
// this token will be rejected by the server and the client will get a proper auth error // this token will be rejected by the server and the client will get a proper auth error
...@@ -77,31 +164,63 @@ class AuthenticationService { ...@@ -77,31 +164,63 @@ class AuthenticationService {
} }
catch (e) { catch (e) {
// this token will be rejected by the server and the client will get a proper auth error // 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';
} }
} }
/** authCollab(config) {
* Opens the proxy's authentication page. if (this.authenticating) {
* return;
* @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) {
this.clearStoredToken();
let absoluteUrl = /^https?:\/\//i;
if (!absoluteUrl.test(url)) {
url = `${this.PROXY_URL}${url}`;
} }
window.location.href = `${url}&client_id=${ this.authenticating = true;
this.CLIENT_ID
}&redirect_uri=${encodeURIComponent(window.location.href)}`; 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);
});
}
});
});
}
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);
});
});
} }
} }
AuthenticationService.CONSTANTS = Object.freeze({ AuthenticationService.CONSTANTS = Object.freeze({
MALFORMED_TOKEN: 'malformed-token' MALFORMED_TOKEN: 'malformed-token',
NO_TOKEN: 'no-token'
}); });
export default AuthenticationService; export default AuthenticationService;
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import AuthenticationService from './authentication-service-v2.js'; import AuthenticationService from './authentication-service';
/** /**
* Base class that performs http requests with default request options. * Base class that performs http requests with default request options.
......
import * as ROSLIB from 'roslib'; import * as ROSLIB from 'roslib';
import _ from 'lodash'; import _ from 'lodash';
import AuthenticationService from './authentication-service-v2'; import AuthenticationService from './authentication-service';
let _instance = null; let _instance = null;
const SINGLETON_ENFORCER = Symbol(); const SINGLETON_ENFORCER = Symbol();
......
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