🔀 Merge pull request #397 from leocov-dev/FEATURE/keycloak-user-data

 Adds Keycloak group and role based visibility
Credit to @leocov-dev
Closes #342
This commit is contained in:
Alicia Sykes 2022-01-02 03:19:27 +00:00 committed by GitHub
commit d4d8ea5a5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 255 additions and 58 deletions

View File

@ -143,9 +143,25 @@ appConfig:
realm: 'alicia-homelab' realm: 'alicia-homelab'
clientId: 'dashy' clientId: 'dashy'
``` ```
### 4. Add groups and roles (Optional)
Keycloak allows you to assign users roles and groups. You can use these values to configure who can access various sections in Dashy.
Keycloak server administration and configuration is a deep topic; please refer to the [server admin guide](https://www.keycloak.org/docs/latest/server_admin/index.html#assigning-permissions-and-access-using-roles-and-groups) to see details about creating and assigning roles and groups.
Once you have groups or roles assigned to users you can configure access under each sections `displayData.showForKeycloakUser` and `displayData.hideForKeycloakUser`.
Both show and hide configurations accept a list of `groups` and `roles` that limit access. If a users data matches one or more items in these lists they will be allowed or excluded as defined.
```yaml
sections:
- name: DeveloperResources
displayData:
showForKeycloakUsers:
roles: ['canViewDevResources']
hideForKeycloakUsers:
groups: ['ProductTeam']
```
Your app is now secured :) When you load Dashy, it will redirect to your Keycloak login page, and any user without valid credentials will be prevented from accessing your dashboard. Your app is now secured :) When you load Dashy, it will redirect to your Keycloak login page, and any user without valid credentials will be prevented from accessing your dashboard.
From within the Keycloak console, you can then configure things like user permissions, time outs, password policies, access, etc. You can also backup your full Keycloak config, and it is recommended to do this, along with your Dashy config. You can spin up both Dashy and Keycloak simultaneously and restore both applications configs using a `docker-compose.yml` file, and this is recommended. From within the Keycloak console, you can then configure things like time-outs, password policies, etc. You can also backup your full Keycloak config, and it is recommended to do this, along with your Dashy config. You can spin up both Dashy and Keycloak simultaneously and restore both applications configs using a `docker-compose.yml` file, and this is recommended.
--- ---

View File

@ -228,6 +228,8 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
**`hideForUsers`** | `string[]` | _Optional_ | Current section will be visible to all users, except for those specified in this list **`hideForUsers`** | `string[]` | _Optional_ | Current section will be visible to all users, except for those specified in this list
**`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list **`showForUsers`** | `string[]` | _Optional_ | Current section will be hidden from all users, except for those specified in this list
**`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false` **`hideForGuests`** | `boolean` | _Optional_ | Current section will be visible for logged in users, but not for guests (see `appConfig.enableGuestAccess`). Defaults to `false`
**`hideForKeycloakUsers`** | `object` | _Optional_ | Current section will be visible to all keycloak users, except for those configured via these groups and roles. See `hideForKeycloakUsers`
**`showForKeycloakUsers`** | `object` | _Optional_ | Current section will be hidden from all keyclaok users, except for those configured via these groups and roles. See `showForKeycloakUsers`
**[⬆️ Back to Top](#configuring)** **[⬆️ Back to Top](#configuring)**
@ -239,6 +241,15 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
**[⬆️ Back to Top](#configuring)** **[⬆️ Back to Top](#configuring)**
### `section.displayData.hideForKeycloakUsers` and `section.displayData.showForKeycloakUsers`
**Field** | **Type** | **Required**| **Description**
--- |------------| --- | ---
**`groups`** | `string[]` | _Optional_ | Current Section will be hidden or shown based on the user having any of the groups in this list
**`roles`** | `string[]` | _Optional_ | Current Section will be hidden or shown based on the user having any of the roles in this list
**[⬆️ Back to Top](#configuring)**
--- ---
## Notes ## Notes

View File

@ -285,6 +285,7 @@ Styleguides:
│ ├── InitServiceWorker.js # Initializes and manages service worker, if enabled │ ├── InitServiceWorker.js # Initializes and manages service worker, if enabled
│ ├── Search.js # Helper functions for searching/ filtering items in all views │ ├── Search.js # Helper functions for searching/ filtering items in all views
│ ├── JsonToYaml.js # Function that parses and converts raw JSON into valid YAML │ ├── JsonToYaml.js # Function that parses and converts raw JSON into valid YAML
│ ├── KeycloakAuth.js # Singleton class to manage Keycloak authentication
│ ├── languages.js # Handles fetching, switching and validating languages │ ├── languages.js # Handles fetching, switching and validating languages
│ ╰── ThemeHelper.js # Function that handles the fetching and setting of user themes │ ╰── ThemeHelper.js # Function that handles the fetching and setting of user themes
╰── views # Directory of available pages, corresponding to available routes ╰── views # Directory of available pages, corresponding to available routes

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<!-- If auth configured, show status text --> <!-- If auth configured, show status text -->
<span class="user-type-note">{{ makeText() }}</span> <span class="user-type-note">{{ makeUserGreeting() }}</span>
<div class="display-options"> <div class="display-options">
<!-- If user logged in, show logout button --> <!-- If user logged in, show logout button -->
<IconLogout <IconLogout
@ -17,6 +17,13 @@
v-tooltip="tooltip($t('settings.sign-in-tooltip'))" v-tooltip="tooltip($t('settings.sign-in-tooltip'))"
class="layout-icon" tabindex="-2" class="layout-icon" tabindex="-2"
/> />
<!-- If user logged in via keycloak, show keycloak logout button -->
<IconLogout
v-if="userType == userStateEnum.keycloakEnabled"
@click="keycloakLogout()"
v-tooltip="tooltip($t('settings.sign-out-tooltip'))"
class="layout-icon" tabindex="-2"
/>
</div> </div>
</div> </div>
</template> </template>
@ -24,6 +31,7 @@
<script> <script>
import router from '@/router'; import router from '@/router';
import { logout as registerLogout } from '@/utils/Auth'; import { logout as registerLogout } from '@/utils/Auth';
import { getKeycloakAuth } from '@/utils/KeycloakAuth';
import { localStorageKeys, userStateEnum } from '@/utils/defaults'; import { localStorageKeys, userStateEnum } from '@/utils/defaults';
import IconLogout from '@/assets/interface-icons/user-logout.svg'; import IconLogout from '@/assets/interface-icons/user-logout.svg';
@ -48,14 +56,22 @@ export default {
router.push({ path: '/login' }); router.push({ path: '/login' });
}, 500); }, 500);
}, },
keycloakLogout() {
const keycloak = getKeycloakAuth();
this.$toasted.show(this.$t('login.logout-message'));
setTimeout(() => {
keycloak.logout();
}, 500);
},
goToLogin() { goToLogin() {
router.push({ path: '/login' }); router.push({ path: '/login' });
}, },
tooltip(content) { tooltip(content) {
return { content, trigger: 'hover focus', delay: 250 }; return { content, trigger: 'hover focus', delay: 250 };
}, },
makeText() { makeUserGreeting() {
if (this.userType === userStateEnum.loggedIn) { if (this.userType === userStateEnum.loggedIn
|| this.userType === userStateEnum.keycloakEnabled) {
const username = localStorage[localStorageKeys.USERNAME]; const username = localStorage[localStorageKeys.USERNAME];
return username ? this.$t('settings.sign-in-welcome', { username }) : ''; return username ? this.$t('settings.sign-in-welcome', { username }) : '';
} }
@ -73,7 +89,6 @@ export default {
span.user-type-note { span.user-type-note {
color: var(--settings-text-color); color: var(--settings-text-color);
text-transform: capitalize;
margin-right: 0.5rem; margin-right: 0.5rem;
} }

View File

@ -10,7 +10,7 @@
<LayoutSelector :displayLayout="displayLayout" /> <LayoutSelector :displayLayout="displayLayout" />
<ItemSizeSelector :iconSize="iconSize" /> <ItemSizeSelector :iconSize="iconSize" />
<ConfigLauncher /> <ConfigLauncher />
<AuthButtons v-if="userState != 'noone'" :userType="userState" /> <AuthButtons v-if="userState !== 0" :userType="userState" />
</div> </div>
<div :class="`show-hide-container ${settingsVisible? 'hide-btn' : 'show-btn'}`"> <div :class="`show-hide-container ${settingsVisible? 'hide-btn' : 'show-btn'}`">
<button @click="toggleSettingsVisibility()" <button @click="toggleSettingsVisibility()"
@ -80,7 +80,7 @@ export default {
/** /**
* Determines which button should display, based on the user type * Determines which button should display, based on the user type
* 0 = Auth not configured, don't show anything * 0 = Auth not configured, don't show anything
* 1 = Auth condifured, and user logged in, show logout button * 1 = Auth configured, and user logged in, show logout button
* 2 = Auth configured, guest access enabled, and not logged in, show login * 2 = Auth configured, guest access enabled, and not logged in, show login
* Note that if auth is enabled, but not guest access, and user not logged in, * Note that if auth is enabled, but not guest access, and user not logged in,
* then they will never be able to view the homepage, so no button needed * then they will never be able to view the homepage, so no button needed

View File

@ -2,7 +2,6 @@
// Import core framework and essential utils // Import core framework and essential utils
import Vue from 'vue'; import Vue from 'vue';
import VueI18n from 'vue-i18n'; // i18n for localization import VueI18n from 'vue-i18n'; // i18n for localization
import Keycloak from 'keycloak-js';
// Import component Vue plugins, used throughout the app // Import component Vue plugins, used throughout the app
import VTooltip from 'v-tooltip'; // A Vue directive for Popper.js, tooltip component import VTooltip from 'v-tooltip'; // A Vue directive for Popper.js, tooltip component
@ -21,7 +20,7 @@ import clickOutside from '@/utils/ClickOutside'; // Directive for closing p
import { messages } from '@/utils/languages'; // Language texts import { messages } from '@/utils/languages'; // Language texts
import ErrorReporting from '@/utils/ErrorReporting'; // Error reporting initializer (off) import ErrorReporting from '@/utils/ErrorReporting'; // Error reporting initializer (off)
import { toastedOptions, tooltipOptions, language as defaultLanguage } from '@/utils/defaults'; import { toastedOptions, tooltipOptions, language as defaultLanguage } from '@/utils/defaults';
import { isKeycloakEnabled, getKeycloakConfig } from '@/utils/Auth'; // Keycloak auth config import { initKeycloakAuth, isKeycloakEnabled } from '@/utils/KeycloakAuth';
// Initialize global Vue components // Initialize global Vue components
Vue.use(VueI18n); Vue.use(VueI18n);
@ -63,18 +62,7 @@ const mount = () => new Vue({
if (!isKeycloakEnabled()) { if (!isKeycloakEnabled()) {
mount(); mount();
} else { // Keycloak is enabled, redirect to KC login page } else { // Keycloak is enabled, redirect to KC login page
const { serverUrl, realm, clientId } = getKeycloakConfig(); initKeycloakAuth()
const initOptions = { .then(() => mount())
url: `${serverUrl}/auth`, realm, clientId, onLoad: 'login-required', .catch(() => window.location.reload());
};
const keycloak = Keycloak(initOptions);
keycloak.init({ onLoad: initOptions.onLoad }).then((auth) => {
if (!auth) {
// Not authenticated, reload to Keycloak login page
window.location.reload();
} else {
// Yay - user successfully authenticated with Keycloak, render the app!
mount();
}
});
} }

View File

@ -2,6 +2,7 @@ import sha256 from 'crypto-js/sha256';
import ConfigAccumulator from '@/utils/ConfigAccumalator'; import ConfigAccumulator from '@/utils/ConfigAccumalator';
import ErrorHandler from '@/utils/ErrorHandler'; import ErrorHandler from '@/utils/ErrorHandler';
import { cookieKeys, localStorageKeys, userStateEnum } from '@/utils/defaults'; import { cookieKeys, localStorageKeys, userStateEnum } from '@/utils/defaults';
import { isKeycloakEnabled } from '@/utils/KeycloakAuth';
/* Uses config accumulator to get and return app config */ /* Uses config accumulator to get and return app config */
const getAppConfig = () => { const getAppConfig = () => {
@ -19,26 +20,6 @@ const printWarning = () => {
ErrorHandler('From V 1.6.5 onwards, the structure of the users object has changed.'); ErrorHandler('From V 1.6.5 onwards, the structure of the users object has changed.');
}; };
/* Returns true if keycloak is enabled */
export const isKeycloakEnabled = () => {
const appConfig = getAppConfig();
if (!appConfig.auth) return false;
return appConfig.auth.enableKeycloak || false;
};
/* Returns the users keycloak config */
export const getKeycloakConfig = () => {
const appConfig = getAppConfig();
if (!isKeycloakEnabled()) return false;
const { keycloak } = appConfig.auth;
const { serverUrl, realm, clientId } = keycloak;
if (!serverUrl || !realm || !clientId) {
ErrorHandler('Keycloak config missing- please ensure you specify: serverUrl, realm, clientId');
return false;
}
return keycloak;
};
/* Returns array of users from appConfig.auth, if available, else an empty array */ /* Returns array of users from appConfig.auth, if available, else an empty array */
const getUsers = () => { const getUsers = () => {
const appConfig = getAppConfig(); const appConfig = getAppConfig();
@ -65,7 +46,6 @@ const generateUserToken = (user) => {
/** /**
* Checks if the user is currently authenticated * Checks if the user is currently authenticated
* @param {Array[Object]} users An array of user objects pulled from the config
* @returns {Boolean} Will return true if the user is logged in, else false * @returns {Boolean} Will return true if the user is logged in, else false
*/ */
export const isLoggedIn = () => { export const isLoggedIn = () => {
@ -95,7 +75,7 @@ export const isAuthEnabled = () => {
/* Returns true if guest access is enabled */ /* Returns true if guest access is enabled */
export const isGuestAccessEnabled = () => { export const isGuestAccessEnabled = () => {
const appConfig = getAppConfig(); const appConfig = getAppConfig();
if (appConfig.auth && typeof appConfig.auth === 'object') { if (appConfig.auth && typeof appConfig.auth === 'object' && !isKeycloakEnabled()) {
return appConfig.auth.enableGuestAccess || false; return appConfig.auth.enableGuestAccess || false;
} }
return false; return false;
@ -108,6 +88,7 @@ export const isGuestAccessEnabled = () => {
* @param {String} username The username entered by the user * @param {String} username The username entered by the user
* @param {String} pass The password entered by the user * @param {String} pass The password entered by the user
* @param {String[]} users An array of valid user objects * @param {String[]} users An array of valid user objects
* @param {Object} messages A static message template object
* @returns {Object} An object containing a boolean result and a message * @returns {Object} An object containing a boolean result and a message
*/ */
export const checkCredentials = (username, pass, users, messages) => { export const checkCredentials = (username, pass, users, messages) => {
@ -146,7 +127,7 @@ export const login = (username, pass, timeout) => {
}; };
/** /**
* Removed the browsers cookie, causing user to be logged out * Removed the browsers' cookie, causing user to be logged out
*/ */
export const logout = () => { export const logout = () => {
document.cookie = 'authenticationToken=null'; document.cookie = 'authenticationToken=null';
@ -164,7 +145,7 @@ export const getCurrentUser = () => {
if (!username) return false; // No username if (!username) return false; // No username
let foundUserObject = false; // Value to return let foundUserObject = false; // Value to return
getUsers().forEach((user) => { getUsers().forEach((user) => {
// If current logged in user found, then return that user // If current logged-in user found, then return that user
if (user.user === username) foundUserObject = user; if (user.user === username) foundUserObject = user;
}); });
return foundUserObject; return foundUserObject;
@ -186,7 +167,6 @@ export const isLoggedInAsGuest = () => {
* But if auth is configured, then will verify user is correctly * But if auth is configured, then will verify user is correctly
* logged in and then check weather they are of type admin, and * logged in and then check weather they are of type admin, and
* return false if any conditions fail * return false if any conditions fail
* @param {String[]} - Array of users
* @returns {Boolean} - True if admin privileges * @returns {Boolean} - True if admin privileges
*/ */
export const isUserAdmin = () => { export const isUserAdmin = () => {
@ -212,7 +192,13 @@ export const isUserAdmin = () => {
* then they will never be able to view the homepage, so no button needed * then they will never be able to view the homepage, so no button needed
*/ */
export const getUserState = () => { export const getUserState = () => {
const { notConfigured, loggedIn, guestAccess } = userStateEnum; // Numeric enum options const {
notConfigured,
loggedIn,
guestAccess,
keycloakEnabled,
} = userStateEnum; // Numeric enum options
if (isKeycloakEnabled()) return keycloakEnabled; // Keycloak auth configured
if (!isAuthEnabled()) return notConfigured; // No auth enabled if (!isAuthEnabled()) return notConfigured; // No auth enabled
if (isLoggedIn()) return loggedIn; // User is logged in if (isLoggedIn()) return loggedIn; // User is logged in
if (isGuestAccessEnabled()) return guestAccess; // Guest is viewing if (isGuestAccessEnabled()) return guestAccess; // Guest is viewing

View File

@ -6,24 +6,32 @@
// Import helper functions from auth, to get current user, and check if guest // Import helper functions from auth, to get current user, and check if guest
import { getCurrentUser, isLoggedInAsGuest } from '@/utils/Auth'; import { getCurrentUser, isLoggedInAsGuest } from '@/utils/Auth';
import { localStorageKeys } from '@/utils/defaults';
/* Helper function, checks if a given username appears in a user array */ /* Helper function, checks if a given testValue is found in the visibility list */
const determineVisibility = (visibilityList, cUsername) => { const determineVisibility = (visibilityList, testValue) => {
let isFound = false; let isFound = false;
visibilityList.forEach((userInList) => { visibilityList.forEach((visibilityItem) => {
if (userInList.toLowerCase() === cUsername) isFound = true; if (visibilityItem.toLowerCase() === testValue.toLowerCase()) isFound = true;
}); });
return isFound; return isFound;
}; };
/* Helper function, determines if two arrays have any intersecting elements
(one or more items that are the same) */
const determineIntersection = (source = [], target = []) => {
const intersections = source.filter(item => target.indexOf(item) !== -1);
return intersections.length > 0;
};
/* Returns false if this section should not be rendered for the current user/ guest */ /* Returns false if this section should not be rendered for the current user/ guest */
const isSectionVisibleToUser = (displayData, currentUser, isGuest) => { const isSectionVisibleToUser = (displayData, currentUser, isGuest) => {
// Checks if user explicitly has access to a certain section // Checks if user explicitly has access to a certain section
const checkVisiblity = () => { const checkVisibility = () => {
if (!currentUser) return true; if (!currentUser) return true;
const hideFor = displayData.hideForUsers || []; const hideForUsers = displayData.hideForUsers || [];
const cUsername = currentUser.user.toLowerCase(); const cUsername = currentUser.user.toLowerCase();
return !determineVisibility(hideFor, cUsername); return !determineVisibility(hideForUsers, cUsername);
}; };
// Checks if user is explicitly prevented from viewing a certain section // Checks if user is explicitly prevented from viewing a certain section
const checkHiddenability = () => { const checkHiddenability = () => {
@ -33,12 +41,36 @@ const isSectionVisibleToUser = (displayData, currentUser, isGuest) => {
if (showForUsers.length < 1) return true; if (showForUsers.length < 1) return true;
return determineVisibility(showForUsers, cUsername); return determineVisibility(showForUsers, cUsername);
}; };
const checkKeycloakVisibility = () => {
if (!displayData.hideForKeycloakUsers) return true;
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
const hideForGroups = displayData.hideForKeycloakUsers.groups || [];
const hideForRoles = displayData.hideForKeycloakUsers.roles || [];
return !(determineIntersection(hideForRoles, roles)
|| determineIntersection(hideForGroups, groups));
};
const checkKeycloakHiddenability = () => {
if (!displayData.showForKeycloakUsers) return true;
const { groups, roles } = JSON.parse(localStorage.getItem(localStorageKeys.KEYCLOAK_INFO) || '{}');
const showForGroups = displayData.showForKeycloakUsers.groups || [];
const showForRoles = displayData.showForKeycloakUsers.roles || [];
return determineIntersection(showForRoles, roles)
|| determineIntersection(showForGroups, groups);
};
// Checks if the current user is a guest, and if section allows for guests // Checks if the current user is a guest, and if section allows for guests
const checkIfHideForGuest = () => { const checkIfHideForGuest = () => {
const hideForGuest = displayData.hideForGuests; const hideForGuest = displayData.hideForGuests;
return !(hideForGuest && isGuest); return !(hideForGuest && isGuest);
}; };
return checkVisiblity() && checkHiddenability() && checkIfHideForGuest(); return checkVisibility()
&& checkHiddenability()
&& checkIfHideForGuest()
&& checkKeycloakVisibility()
&& checkKeycloakHiddenability();
}; };
/* Putting it all together, the function to export */ /* Putting it all together, the function to export */

View File

@ -613,6 +613,60 @@
"type": "boolean", "type": "boolean",
"default": false, "default": false,
"description": "If set to true, section will be visible for logged in users, but not for guests" "description": "If set to true, section will be visible for logged in users, but not for guests"
},
"showForKeycloakUsers": {
"title": "Show for select Keycloak groups or roles",
"type": "object",
"description": "Configure the Keycloak groups or roles that will have access to this section",
"additionalProperties": false,
"properties": {
"groups": {
"title": "Show for Groups",
"type": "array",
"description": "Section will be hidden from all users except those with one or more of these groups",
"items": {
"type": "string",
"description": "Name of the group that will be able to view this section"
}
},
"roles": {
"title": "Show for Roles",
"type": "array",
"description": "Section will be hidden from all users except those with one or more of these roles",
"items": {
"type": "string",
"description": "Name of the role that will be able to view this section"
}
}
}
},
"hideForKeycloakUsers": {
"title": "Hide for select Keycloak groups or roles",
"type": "object",
"description": "Configure the Keycloak groups or roles that will not have access to this section",
"additionalProperties": false,
"properties": {
"groups": {
"title": "Hide for Groups",
"type": "array",
"description": "Section will be hidden from users with any of these groups",
"items": {
"type": "string",
"description": "name of the group that will not be able to view this section"
}
},
"roles": {
"title": "Hide for Roles",
"type": "array",
"description": "Section will be hidden from users with any of roles",
"items": {
"type": "string",
"description": "name of the role that will not be able to view this section"
}
}
}
} }
} }
}, },

92
src/utils/KeycloakAuth.js Normal file
View File

@ -0,0 +1,92 @@
import Keycloak from 'keycloak-js';
import ConfigAccumulator from '@/utils/ConfigAccumalator';
import { localStorageKeys } from '@/utils/defaults';
import ErrorHandler from '@/utils/ErrorHandler';
const getAppConfig = () => {
const Accumulator = new ConfigAccumulator();
const config = Accumulator.config();
return config.appConfig || {};
};
class KeycloakAuth {
constructor() {
const { auth } = getAppConfig();
const { serverUrl, realm, clientId } = auth.keycloak;
const initOptions = {
url: `${serverUrl}/auth`, realm, clientId, onLoad: 'login-required',
};
this.keycloakClient = Keycloak(initOptions);
}
login() {
return new Promise((resolve, reject) => {
this.keycloakClient.init({ onLoad: 'login-required' })
.then((auth) => {
if (auth) {
this.storeKeycloakInfo();
return resolve();
} else {
return reject(new Error('Not authenticated'));
}
})
.catch((reason) => reject(reason));
});
}
logout() {
localStorage.removeItem(localStorageKeys.USERNAME);
localStorage.removeItem(localStorageKeys.KEYCLOAK_INFO);
this.keycloakClient.logout();
}
storeKeycloakInfo() {
if (this.keycloakClient.tokenParsed && typeof this.keycloakClient.tokenParsed === 'object') {
const {
groups,
realm_access: realmAccess,
resource_access: resourceAccess,
azp: clientId,
preferred_username: preferredUsername,
} = this.keycloakClient.tokenParsed;
const realmRoles = realmAccess.roles || [];
let clientRoles = [];
if (Object.hasOwn(resourceAccess, clientId)) {
clientRoles = resourceAccess[clientId].roles || [];
}
const roles = [...realmRoles, ...clientRoles];
const info = {
groups,
roles,
};
localStorage.setItem(localStorageKeys.KEYCLOAK_INFO, JSON.stringify(info));
localStorage.setItem(localStorageKeys.USERNAME, preferredUsername);
}
}
}
export const isKeycloakEnabled = () => {
const { auth } = getAppConfig();
if (!auth) return false;
return auth.enableKeycloak || false;
};
let keycloak;
export const initKeycloakAuth = () => {
keycloak = new KeycloakAuth();
return keycloak.login();
};
export const getKeycloakAuth = () => {
if (!keycloak) {
ErrorHandler("Keycloak not initialized, can't get instance of class");
}
return keycloak;
};

View File

@ -124,6 +124,7 @@ module.exports = {
USERNAME: 'username', USERNAME: 'username',
MOST_USED: 'mostUsed', MOST_USED: 'mostUsed',
LAST_USED: 'lastUsed', LAST_USED: 'lastUsed',
KEYCLOAK_INFO: 'keycloakInfo',
}, },
/* Key names for cookie identifiers */ /* Key names for cookie identifiers */
cookieKeys: { cookieKeys: {
@ -278,6 +279,7 @@ module.exports = {
loggedIn: 1, loggedIn: 1,
guestAccess: 2, guestAccess: 2,
notLoggedIn: 3, notLoggedIn: 3,
keycloakEnabled: 4,
}, },
/* Progressive Web App settings, used by Vue Config */ /* Progressive Web App settings, used by Vue Config */
pwa: { pwa: {