🔀 Merge pull request #1894 from Alexis-BX/Fix-Oidc-user-islogin-and-admin

Fix OIDC getUser and added admin role and group
This commit is contained in:
Alicia Sykes 2025-08-03 14:05:27 +01:00 committed by GitHub
commit 4e00947322
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 4 deletions

View File

@ -286,6 +286,7 @@ appConfig:
clientId: [registered client id] clientId: [registered client id]
endpoint: [OIDC endpoint] endpoint: [OIDC endpoint]
scope: [The scope(s) to request from the OIDC provider] scope: [The scope(s) to request from the OIDC provider]
adminGroup: admin
``` ```
Because Dashy is a SPA, a [public client](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1) registration with PKCE is needed. Because Dashy is a SPA, a [public client](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1) registration with PKCE is needed.

View File

@ -204,6 +204,8 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
--- | --- | --- | --- --- | --- | --- | ---
**`clientId`** | `string` | Required | The client id registered in the OIDC server **`clientId`** | `string` | Required | The client id registered in the OIDC server
**`endpoint`** | `string` | Required | The URL of the OIDC server that should be used. **`endpoint`** | `string` | Required | The URL of the OIDC server that should be used.
**`adminRole`** | `string` | _Optional_ | The role that will be considered as admin.
**`adminGroup`** | `string` | _Optional_ | The group that will be considered as admin.
**`scope`** | `string` | Required | The scope(s) to request from the OIDC provider **`scope`** | `string` | Required | The scope(s) to request from the OIDC provider
**[⬆️ Back to Top](#configuring)** **[⬆️ Back to Top](#configuring)**

View File

@ -31,7 +31,19 @@ const getUsers = () => {
return []; // Support for old data structure now removed return []; // Support for old data structure now removed
} }
// Otherwise, return the users array, if available // Otherwise, return the users array, if available
return auth.users || [];
const users = auth.users || [];
if (isOidcEnabled()) {
if (localStorage[localStorageKeys.USERNAME]) {
const user = {
user: localStorage[localStorageKeys.USERNAME],
type: localStorage[localStorageKeys.ISADMIN] === 'true' ? 'admin' : 'normal',
};
users.push(user);
}
}
return users;
}; };
/** /**
@ -80,6 +92,17 @@ export const makeBasicAuthHeaders = () => {
export const isLoggedIn = () => { export const isLoggedIn = () => {
const users = getUsers(); const users = getUsers();
const cookieToken = getCookieToken(); const cookieToken = getCookieToken();
if (isOidcEnabled()) {
const username = localStorage[localStorageKeys.USERNAME]; // Get username
if (!username) return false; // No username
return users.some((user) => {
if (user.user === username || generateUserToken(user) === cookieToken) {
return true;
} else return false;
});
}
return users.some((user) => { return users.some((user) => {
if (generateUserToken(user) === cookieToken) { if (generateUserToken(user) === cookieToken) {
localStorage.setItem(localStorageKeys.USERNAME, user.user); localStorage.setItem(localStorageKeys.USERNAME, user.user);

View File

@ -566,6 +566,18 @@
"type": "string", "type": "string",
"description": "ClientId from OIDC provider" "description": "ClientId from OIDC provider"
}, },
"adminRole" : {
"title": "Admin Role",
"type": "string",
"default": false,
"description": "The role that will be considered as admin. If not set, no roles will be considered as admin"
},
"adminGroup" : {
"title": "Admin Group",
"type": "string",
"default": false,
"description": "The group that will be considered as admin. If not set, no groups will be considered as admin"
},
"scope" : { "scope" : {
"title": "OIDC Scope", "title": "OIDC Scope",
"type": "string", "type": "string",

View File

@ -13,7 +13,13 @@ const getAppConfig = () => {
class OidcAuth { class OidcAuth {
constructor() { constructor() {
const { auth } = getAppConfig(); const { auth } = getAppConfig();
const { clientId, endpoint, scope } = auth.oidc; const {
clientId,
endpoint,
scope,
adminGroup,
adminRole,
} = auth.oidc;
const settings = { const settings = {
userStore: new WebStorageStateStore({ store: window.localStorage }), userStore: new WebStorageStateStore({ store: window.localStorage }),
authority: endpoint, authority: endpoint,
@ -25,6 +31,8 @@ class OidcAuth {
filterProtocolClaims: true, filterProtocolClaims: true,
}; };
this.adminGroup = adminGroup;
this.adminRole = adminRole;
this.userManager = new UserManager(settings); this.userManager = new UserManager(settings);
} }
@ -43,22 +51,27 @@ class OidcAuth {
if (user === null) { if (user === null) {
await this.userManager.signinRedirect(); await this.userManager.signinRedirect();
} else { } else {
const { roles, groups } = user.profile; const { roles = [], groups = [] } = user.profile;
const info = { const info = {
groups, groups,
roles, roles,
}; };
const isAdmin = (Array.isArray(groups) && groups.includes(this.adminGroup))
|| (Array.isArray(roles) && roles.includes(this.adminRole))
|| false;
statusMsg(`user: ${user.profile.preferred_username}`, JSON.stringify(info)); statusMsg(`user: ${user.profile.preferred_username} admin: ${isAdmin}`, JSON.stringify(info));
localStorage.setItem(localStorageKeys.KEYCLOAK_INFO, JSON.stringify(info)); localStorage.setItem(localStorageKeys.KEYCLOAK_INFO, JSON.stringify(info));
localStorage.setItem(localStorageKeys.USERNAME, user.profile.preferred_username); localStorage.setItem(localStorageKeys.USERNAME, user.profile.preferred_username);
localStorage.setItem(localStorageKeys.ISADMIN, isAdmin);
} }
} }
async logout() { async logout() {
localStorage.removeItem(localStorageKeys.USERNAME); localStorage.removeItem(localStorageKeys.USERNAME);
localStorage.removeItem(localStorageKeys.KEYCLOAK_INFO); localStorage.removeItem(localStorageKeys.KEYCLOAK_INFO);
localStorage.removeItem(localStorageKeys.ISADMIN);
try { try {
await this.userManager.signoutRedirect(); await this.userManager.signoutRedirect();

View File

@ -137,6 +137,7 @@ module.exports = {
MOST_USED: 'mostUsed', MOST_USED: 'mostUsed',
LAST_USED: 'lastUsed', LAST_USED: 'lastUsed',
KEYCLOAK_INFO: 'keycloakInfo', KEYCLOAK_INFO: 'keycloakInfo',
ISADMIN: 'isAdmin',
DISABLE_CRITICAL_WARNING: 'disableCriticalWarning', DISABLE_CRITICAL_WARNING: 'disableCriticalWarning',
}, },
/* Key names for cookie identifiers */ /* Key names for cookie identifiers */