diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3abcd8ee..8ad710bc0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -136,7 +136,7 @@ importers: devDependencies: vitepress: specifier: ^1.6.3 - version: 1.6.3(@algolia/client-search@5.23.2)(@types/node@22.14.0)(axios@1.8.4)(postcss@8.5.3)(typescript@5.8.3) + version: 1.6.3(@algolia/client-search@5.23.2)(@types/node@22.14.0)(axios@1.8.4)(jwt-decode@4.0.0)(postcss@8.5.3)(typescript@5.8.3) src: dependencies: @@ -197,6 +197,9 @@ importers: jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 languages4translatewiki: specifier: 0.1.3 version: 0.1.3 @@ -3515,6 +3518,10 @@ packages: jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + kebab-case@1.0.2: resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} @@ -6713,7 +6720,7 @@ snapshots: transitivePeerDependencies: - typescript - '@vueuse/integrations@12.8.2(axios@1.8.4)(focus-trap@7.6.4)(typescript@5.8.3)': + '@vueuse/integrations@12.8.2(axios@1.8.4)(focus-trap@7.6.4)(jwt-decode@4.0.0)(typescript@5.8.3)': dependencies: '@vueuse/core': 12.8.2(typescript@5.8.3) '@vueuse/shared': 12.8.2(typescript@5.8.3) @@ -6721,6 +6728,7 @@ snapshots: optionalDependencies: axios: 1.8.4 focus-trap: 7.6.4 + jwt-decode: 4.0.0 transitivePeerDependencies: - typescript @@ -7502,7 +7510,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@9.24.0))(eslint@9.24.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -7542,7 +7550,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.24.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@9.24.0))(eslint@9.24.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -8445,6 +8453,8 @@ snapshots: jwa: 1.4.1 safe-buffer: 5.2.1 + jwt-decode@4.0.0: {} + kebab-case@1.0.2: {} keygrip@1.1.0: @@ -9964,7 +9974,7 @@ snapshots: fsevents: 2.3.3 tsx: 4.19.3 - vitepress@1.6.3(@algolia/client-search@5.23.2)(@types/node@22.14.0)(axios@1.8.4)(postcss@8.5.3)(typescript@5.8.3): + vitepress@1.6.3(@algolia/client-search@5.23.2)(@types/node@22.14.0)(axios@1.8.4)(jwt-decode@4.0.0)(postcss@8.5.3)(typescript@5.8.3): dependencies: '@docsearch/css': 3.8.2 '@docsearch/js': 3.8.2(@algolia/client-search@5.23.2) @@ -9977,7 +9987,7 @@ snapshots: '@vue/devtools-api': 7.7.2 '@vue/shared': 3.5.13 '@vueuse/core': 12.8.2(typescript@5.8.3) - '@vueuse/integrations': 12.8.2(axios@1.8.4)(focus-trap@7.6.4)(typescript@5.8.3) + '@vueuse/integrations': 12.8.2(axios@1.8.4)(focus-trap@7.6.4)(jwt-decode@4.0.0)(typescript@5.8.3) focus-trap: 7.6.4 mark.js: 8.11.1 minisearch: 7.1.2 diff --git a/src/node/handler/APIHandler.ts b/src/node/handler/APIHandler.ts index b108f50f0..7886d0b46 100644 --- a/src/node/handler/APIHandler.ts +++ b/src/node/handler/APIHandler.ts @@ -20,9 +20,10 @@ */ import {MapArrayType} from "../types/MapType"; - +import { jwtDecode } from "jwt-decode"; const api = require('../db/API'); const padManager = require('../db/PadManager'); +const settings = require('../utils/Settings'); import createHTTPError from 'http-errors'; import {Http2ServerRequest} from "node:http2"; import {publicKeyExported} from "../security/OAuth2Provider"; @@ -182,8 +183,17 @@ exports.handle = async function (apiVersion: string, functionName: string, field throw new createHTTPError.Unauthorized('no or wrong API Key'); } try { - await jwtVerify(req.headers.authorization!.replace("Bearer ", ""), publicKeyExported!, {algorithms: ['RS256'], - requiredClaims: ["admin"]}) + const clientIds: string[] = settings.sso.clients?.map((client: {client_id: string}) => client.client_id); + const jwtToCheck = req.headers.authorization.replace("Bearer ", "") + const payload = jwtDecode(jwtToCheck) + // client_credentials + if (clientIds.includes(payload.sub)) { + await jwtVerify(jwtToCheck, publicKeyExported!, {algorithms: ['RS256']}) + } else { + // authorization_code + await jwtVerify(jwtToCheck, publicKeyExported!, {algorithms: ['RS256'], + requiredClaims: ["admin"]}) + } } catch (e) { throw new createHTTPError.Unauthorized('no or wrong OAuth token'); } diff --git a/src/node/security/OAuth2Provider.ts b/src/node/security/OAuth2Provider.ts index 76e7ed4b8..b4abd3249 100644 --- a/src/node/security/OAuth2Provider.ts +++ b/src/node/security/OAuth2Provider.ts @@ -30,7 +30,7 @@ const configuration: Configuration = { if(account === undefined) { return undefined } - if (account.is_admin) { + if (account.is_admin ) { return { accountId: id, claims: () => ({ diff --git a/src/package.json b/src/package.json index 9f24fa644..db3d181a2 100644 --- a/src/package.json +++ b/src/package.json @@ -70,6 +70,7 @@ "socket.io-client": "^4.8.1", "superagent": "10.2.0", "swagger-ui-express": "^5.0.1", + "jwt-decode": "^4.0.0", "tinycon": "0.6.8", "tsx": "4.19.3", "ueberdb2": "^5.0.6",