mirror of https://github.com/Lissy93/dashy.git
WIP: Attempt at adding header auth. Ignore Settings #981
This commit is contained in:
parent
4813d49e42
commit
4aa34f66dc
10
server.js
10
server.js
|
@ -27,6 +27,7 @@ const rebuild = require('./services/rebuild-app'); // A script to programmatical
|
||||||
const systemInfo = require('./services/system-info'); // Basic system info, for resource widget
|
const systemInfo = require('./services/system-info'); // Basic system info, for resource widget
|
||||||
const sslServer = require('./services/ssl-server'); // TLS-enabled web server
|
const sslServer = require('./services/ssl-server'); // TLS-enabled web server
|
||||||
const corsProxy = require('./services/cors-proxy'); // Enables API requests to CORS-blocked services
|
const corsProxy = require('./services/cors-proxy'); // Enables API requests to CORS-blocked services
|
||||||
|
const getUser = require('./services/get-user'); // Enables server side user lookup
|
||||||
|
|
||||||
/* Helper functions, and default config */
|
/* Helper functions, and default config */
|
||||||
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
|
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
|
||||||
|
@ -124,6 +125,15 @@ const app = express()
|
||||||
res.end(JSON.stringify({ success: false, message: e }));
|
res.end(JSON.stringify({ success: false, message: e }));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// GET endpoint to return user info
|
||||||
|
.use(ENDPOINTS.getUser, (req, res) => {
|
||||||
|
try {
|
||||||
|
const user = getUser(req);
|
||||||
|
res.end(JSON.stringify(user));
|
||||||
|
} catch (e) {
|
||||||
|
res.end(JSON.stringify({ success: false, message: e }));
|
||||||
|
}
|
||||||
|
})
|
||||||
// GET fallback endpoint
|
// GET fallback endpoint
|
||||||
.get('*', (req, res) => res.sendFile(path.join(__dirname, 'dist', 'index.html')));
|
.get('*', (req, res) => res.sendFile(path.join(__dirname, 'dist', 'index.html')));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = (req) => {
|
||||||
|
const userHeader = "Remote-User";
|
||||||
|
console.log("Running Server Side", req.headers[userHeader.toLowerCase()]); // eslint-disable-line no-console
|
||||||
|
return { "success": true, "user": req.headers[userHeader.toLowerCase()] };
|
||||||
|
};
|
19
src/main.js
19
src/main.js
|
@ -21,6 +21,7 @@ import ErrorReporting from '@/utils/ErrorReporting'; // Error reporting initial
|
||||||
import clickOutside from '@/directives/ClickOutside'; // Directive for closing popups, modals, etc
|
import clickOutside from '@/directives/ClickOutside'; // Directive for closing popups, modals, etc
|
||||||
import { toastedOptions, tooltipOptions, language as defaultLanguage } from '@/utils/defaults';
|
import { toastedOptions, tooltipOptions, language as defaultLanguage } from '@/utils/defaults';
|
||||||
import { initKeycloakAuth, isKeycloakEnabled } from '@/utils/KeycloakAuth';
|
import { initKeycloakAuth, isKeycloakEnabled } from '@/utils/KeycloakAuth';
|
||||||
|
import { initHeaderAuth, isHeaderAuthEnabled } from '@/utils/HeaderAuth';
|
||||||
import Keys from '@/utils/StoreMutations';
|
import Keys from '@/utils/StoreMutations';
|
||||||
|
|
||||||
// Initialize global Vue components
|
// Initialize global Vue components
|
||||||
|
@ -54,18 +55,24 @@ ErrorReporting(Vue, router);
|
||||||
// Render function
|
// Render function
|
||||||
const render = (awesome) => awesome(Dashy);
|
const render = (awesome) => awesome(Dashy);
|
||||||
|
|
||||||
store.dispatch(Keys.INITIALIZE_CONFIG).then((thing) => console.log('main', thing));
|
|
||||||
|
|
||||||
// Mount the app, with router, store i18n and render func
|
// Mount the app, with router, store i18n and render func
|
||||||
const mount = () => new Vue({
|
const mount = () => new Vue({
|
||||||
store, router, render, i18n,
|
store, router, render, i18n,
|
||||||
}).$mount('#app');
|
}).$mount('#app');
|
||||||
|
|
||||||
// If Keycloak not enabled, then proceed straight to the app
|
store.dispatch(Keys.INITIALIZE_CONFIG).then((thing) => {
|
||||||
if (!isKeycloakEnabled()) {
|
console.log('main', thing);
|
||||||
mount();
|
|
||||||
} else { // Keycloak is enabled, redirect to KC login page
|
// Keycloak is enabled, redirect to KC login page
|
||||||
|
if (isKeycloakEnabled()) {
|
||||||
initKeycloakAuth()
|
initKeycloakAuth()
|
||||||
.then(() => mount())
|
.then(() => mount())
|
||||||
.catch(() => window.location.reload());
|
.catch(() => window.location.reload());
|
||||||
|
} else if (isHeaderAuthEnabled()) {
|
||||||
|
initHeaderAuth()
|
||||||
|
.then(() => mount())
|
||||||
|
.catch(() => window.location.reload());
|
||||||
|
} else { // If Keycloak not enabled, then proceed straight to the app
|
||||||
|
mount();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
|
@ -450,6 +450,37 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enableHeaderAuth": {
|
||||||
|
"title": "Enable HeaderAuth?",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "If set to true, enable Header Authentication. See appConfig.auth.headerAuth"
|
||||||
|
},
|
||||||
|
"headerAuth": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Configuration for headerAuth",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"proxyWhitelist"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"userHeader": {
|
||||||
|
"title": "User Header",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Header name which contains username",
|
||||||
|
"default": "REMOTE_USER"
|
||||||
|
},
|
||||||
|
"proxyWhitelist": {
|
||||||
|
"title": "Upstream Proxy Auth Trust",
|
||||||
|
"type": "array",
|
||||||
|
"description": "Upstream proxy servers to expect authenticated requests from",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "IPs of upstream proxies that will be trusted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"enableKeycloak": {
|
"enableKeycloak": {
|
||||||
"title": "Enable Keycloak?",
|
"title": "Enable Keycloak?",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import sha256 from 'crypto-js/sha256';
|
||||||
|
import ConfigAccumulator from '@/utils/ConfigAccumalator';
|
||||||
|
import { cookieKeys, localStorageKeys, serviceEndpoints } from '@/utils/defaults';
|
||||||
|
import { InfoHandler, ErrorHandler, InfoKeys } from '@/utils/ErrorHandler';
|
||||||
|
import { logout, getUserState } from '@/utils/Auth';
|
||||||
|
|
||||||
|
const getAppConfig = () => {
|
||||||
|
const Accumulator = new ConfigAccumulator();
|
||||||
|
const config = Accumulator.config();
|
||||||
|
return config.appConfig || {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class HeaderAuth {
|
||||||
|
constructor() {
|
||||||
|
const { auth } = getAppConfig();
|
||||||
|
const {
|
||||||
|
userHeader, proxyWhitelist,
|
||||||
|
} = auth.headerAuth;
|
||||||
|
this.userHeader = userHeader;
|
||||||
|
this.proxyWhitelist = proxyWhitelist;
|
||||||
|
this.users = auth.users;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable class-methods-use-this */
|
||||||
|
login() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
|
||||||
|
axios.get(`${baseUrl}${serviceEndpoints.getUser}`).then((response) => {
|
||||||
|
if (!response.data || response.data.errorMsg) {
|
||||||
|
reject(response.data.errorMsg || 'Error');
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.users.forEach((user) => {
|
||||||
|
if (user.user.toLowerCase() === response.data.user.toLowerCase()) { // User found
|
||||||
|
const strAndUpper = (input) => input.toString().toUpperCase();
|
||||||
|
const sha = strAndUpper(sha256(strAndUpper(user.user) + strAndUpper(user.hash)));
|
||||||
|
document.cookie = `${cookieKeys.AUTH_TOKEN}=${sha};`;
|
||||||
|
localStorage.setItem(localStorageKeys.USERNAME, user.user);
|
||||||
|
InfoHandler(`Succesfully signed in as ${response.data.user}`, InfoKeys.AUTH);
|
||||||
|
console.log('I think we\'re good', getUserState());
|
||||||
|
resolve(response.data.user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
logout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isHeaderAuthEnabled = () => {
|
||||||
|
const { auth } = getAppConfig();
|
||||||
|
if (!auth) return false;
|
||||||
|
return auth.enableHeaderAuth || false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let headerAuth;
|
||||||
|
|
||||||
|
export const initHeaderAuth = () => {
|
||||||
|
headerAuth = new HeaderAuth();
|
||||||
|
return headerAuth.login();
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Find where this is implemented
|
||||||
|
export const getHeaderAuth = () => {
|
||||||
|
if (!headerAuth) {
|
||||||
|
ErrorHandler("HeaderAuth not initialized, can't get instance of class");
|
||||||
|
}
|
||||||
|
return headerAuth;
|
||||||
|
};
|
|
@ -44,6 +44,7 @@ module.exports = {
|
||||||
rebuild: '/config-manager/rebuild',
|
rebuild: '/config-manager/rebuild',
|
||||||
systemInfo: '/system-info',
|
systemInfo: '/system-info',
|
||||||
corsProxy: '/cors-proxy',
|
corsProxy: '/cors-proxy',
|
||||||
|
getUser: '/get-user',
|
||||||
},
|
},
|
||||||
/* List of built-in themes, to be displayed within the theme-switcher dropdown */
|
/* List of built-in themes, to be displayed within the theme-switcher dropdown */
|
||||||
builtInThemes: [
|
builtInThemes: [
|
||||||
|
|
Loading…
Reference in New Issue