From 789c2fb2b9f6f5e3217adb43af76f4e1d16499d2 Mon Sep 17 00:00:00 2001 From: mwinkens <104770531+mwinkens@users.noreply.github.com> Date: Wed, 16 Sep 2026 11:27:55 +0200 Subject: [PATCH 01/20] Allow JSON-Encoded group object Some upstream servers return each group object as a JSON-encoded string, e.g. "{\"gid\":\"group1\",\"displayName\":\"Group 1\"}". Decode these so the 'gid' and 'displayName' can be read correctly instead of being passed through verbatim. Signed-off-by: mwinkens <104770531+mwinkens@users.noreply.github.com> --- lib/Service/ProvisioningService.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Service/ProvisioningService.php b/lib/Service/ProvisioningService.php index 20ab7f4f..ebe970ff 100644 --- a/lib/Service/ProvisioningService.php +++ b/lib/Service/ProvisioningService.php @@ -620,7 +620,21 @@ public function getSyncGroupsOfToken(int $providerId, object $idTokenPayload): ? $group = $v; } elseif (is_string($v)) { // Handle array of strings, e.g. ["group1", "group2", ...] - $group = (object)['gid' => $v, 'displayName' => $v]; + // Some upstream servers return each group object as a JSON-encoded string, + // e.g. "{\"gid\":\"group1\",\"displayName\":\"Group 1\"}". Decode these so the + // gid and displayName can be read correctly instead of being passed through verbatim. + $decoded = json_decode($v, true); + if (is_array($decoded) && isset($decoded['gid'])) { + if (empty($decoded['gid']) && $decoded['gid'] !== '0' && $decoded['gid'] !== 0) { + continue; + } + $group = (object)[ + 'gid' => $decoded['gid'], + 'displayName' => $decoded['displayName'] ?? $decoded['gid'], + ]; + } else { + $group = (object)['gid' => $v, 'displayName' => $v]; + } } else { continue; } From 027eeae2355c40b176e2a2b0c4f5c21c3355300d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 01:03:25 +0000 Subject: [PATCH 02/20] Chore(deps): Bump @nextcloud/vue from 9.11.0 to 9.12.0 Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 9.11.0 to 9.12.0. - [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases) - [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/main/CHANGELOG.md) - [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v9.11.0...v9.12.0) --- updated-dependencies: - dependency-name: "@nextcloud/vue" dependency-version: 9.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 346 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 173 insertions(+), 175 deletions(-) diff --git a/package-lock.json b/package-lock.json index ece1eb10..0968e42c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.11.0", + "@nextcloud/vue": "^9.12.0", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" @@ -2844,6 +2844,66 @@ "node": "^20 || ^22 || ^24" } }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", + "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", + "license": "AGPL-3.0-or-later", + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.2", + "webdav": "^5.9.0" + }, + "engines": { + "node": "^24.0.0" + } + }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files/node_modules/@nextcloud/files": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", + "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "cancelable-promise": "^4.3.1", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.1", + "webdav": "^5.8.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files/node_modules/@nextcloud/sharing": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", + "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", + "license": "GPL-3.0-or-later", + "dependencies": { + "@nextcloud/initial-state": "^3.0.0", + "is-svg": "^6.1.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + }, + "optionalDependencies": { + "@nextcloud/files": "^3.12.0" + } + }, "node_modules/@nextcloud/eslint-config": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/@nextcloud/eslint-config/-/eslint-config-8.4.2.tgz", @@ -2930,66 +2990,6 @@ "node": ">=10" } }, - "node_modules/@nextcloud/files": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", - "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", - "license": "AGPL-3.0-or-later", - "dependencies": { - "@nextcloud/auth": "^2.5.3", - "@nextcloud/capabilities": "^1.2.1", - "@nextcloud/l10n": "^3.4.1", - "@nextcloud/logger": "^3.0.3", - "@nextcloud/paths": "^3.0.0", - "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "is-svg": "^6.1.0", - "typescript-event-target": "^1.1.2", - "webdav": "^5.9.0" - }, - "engines": { - "node": "^24.0.0" - } - }, - "node_modules/@nextcloud/files/node_modules/@nextcloud/files": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", - "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", - "license": "AGPL-3.0-or-later", - "optional": true, - "dependencies": { - "@nextcloud/auth": "^2.5.3", - "@nextcloud/capabilities": "^1.2.1", - "@nextcloud/l10n": "^3.4.1", - "@nextcloud/logger": "^3.0.3", - "@nextcloud/paths": "^3.0.0", - "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "cancelable-promise": "^4.3.1", - "is-svg": "^6.1.0", - "typescript-event-target": "^1.1.1", - "webdav": "^5.8.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/files/node_modules/@nextcloud/sharing": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", - "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", - "license": "GPL-3.0-or-later", - "dependencies": { - "@nextcloud/initial-state": "^3.0.0", - "is-svg": "^6.1.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - }, - "optionalDependencies": { - "@nextcloud/files": "^3.12.0" - } - }, "node_modules/@nextcloud/initial-state": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@nextcloud/initial-state/-/initial-state-3.0.0.tgz", @@ -3082,6 +3082,68 @@ "@nextcloud/files": "^3.12.2 || ^4.0.0" } }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/files": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", + "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.2", + "webdav": "^5.9.0" + }, + "engines": { + "node": "^24.0.0" + } + }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/sharing": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", + "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", + "license": "GPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/initial-state": "^3.0.0", + "is-svg": "^6.1.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + }, + "optionalDependencies": { + "@nextcloud/files": "^3.12.0" + } + }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/sharing/node_modules/@nextcloud/files": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", + "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "cancelable-promise": "^4.3.1", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.1", + "webdav": "^5.8.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, "node_modules/@nextcloud/stylelint-config": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@nextcloud/stylelint-config/-/stylelint-config-3.2.2.tgz", @@ -3113,9 +3175,9 @@ } }, "node_modules/@nextcloud/vue": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.11.0.tgz", - "integrity": "sha512-LRsyU9Mxs0b2xWqbxygps8O7/i1z4QhNQD9/QDni+VqFY3V0N95mAgmKJm6vfoFuxTAMXERp9bjqFn3UV542gw==", + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.12.0.tgz", + "integrity": "sha512-NuBj7wVKjUaEc9mNHSbnLl6NvLoVqUlHXV/pzn1NED1BtLb6iGwKh1KQX/BnOzGFOCkbFwTGMVgynH6i0ndjDQ==", "license": "AGPL-3.0-or-later", "dependencies": { "@ckpack/vue-color": "^1.6.0", @@ -3137,7 +3199,7 @@ "blurhash": "^2.0.5", "clone": "^2.1.2", "debounce": "^3.0.0", - "dompurify": "^3.4.14", + "dompurify": "^3.4.15", "emoji-mart-vue-fast": "^15.0.5", "escape-html": "^1.0.3", "floating-vue": "^5.2.2", @@ -3161,10 +3223,22 @@ "unist-builder": "^4.0.0", "unist-util-visit-parents": "^6.0.2", "vue": "^3.5.18", - "vue-router": "^5.2.0" + "vue-router": "^5.3.1" }, "engines": { "node": "^20.11.0 || ^22 || ^24" + }, + "peerDependencies": { + "@nextcloud/dialogs": "^7.4.0", + "@nextcloud/files": "^4.1.0-beta.2" + }, + "peerDependenciesMeta": { + "@nextcloud/dialogs": { + "optional": true + }, + "@nextcloud/files": { + "optional": true + } } }, "node_modules/@nextcloud/vue-select": { @@ -4011,12 +4085,6 @@ "@types/sizzle": "*" } }, - "node_modules/@types/jsesc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@types/jsesc/-/jsesc-2.5.1.tgz", - "integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==", - "license": "MIT" - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -7445,9 +7513,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz", - "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.15.tgz", + "integrity": "sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -10928,7 +10996,9 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, "license": "MIT", + "peer": true, "bin": { "jsesc": "bin/jsesc" }, @@ -10972,7 +11042,9 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "license": "MIT", + "peer": true, "bin": { "json5": "lib/cli.js" }, @@ -12999,16 +13071,22 @@ } }, "node_modules/pkg-types": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", - "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.3.tgz", + "integrity": "sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==", "license": "MIT", "dependencies": { - "confbox": "^0.2.4", - "exsolve": "^1.0.8", + "confbox": "^0.3.1", + "exsolve": "^1.1.1", "pathe": "^2.0.3" } }, + "node_modules/pkg-types/node_modules/confbox": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.3.1.tgz", + "integrity": "sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==", + "license": "MIT" + }, "node_modules/pkijs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", @@ -16629,9 +16707,9 @@ } }, "node_modules/unplugin-utils/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -16641,9 +16719,9 @@ } }, "node_modules/unplugin/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -16987,17 +17065,16 @@ } }, "node_modules/vue-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.2.0.tgz", - "integrity": "sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.3.1.tgz", + "integrity": "sha512-GDBZzgmILxA/kFnkFbJjQZdZ2QQbngnIMMuoUcjhZIfH1RGMaPjPwX5ASnV38qamuA9uhO0RDjSBHTDNG2uXyQ==", "license": "MIT", "dependencies": { - "@babel/generator": "^8.0.0", "@vue-macros/common": "^3.1.3", "@vue/devtools-api": "^8.1.5", "ast-walker-scope": "^0.9.0", "chokidar": "^5.0.0", - "json5": "^2.2.3", + "confbox": "^0.2.4", "local-pkg": "^1.2.1", "magic-string": "^0.30.21", "mlly": "^1.8.2", @@ -17008,8 +17085,7 @@ "scule": "^1.3.0", "tinyglobby": "^0.2.17", "unplugin": "^3.3.0", - "unplugin-utils": "^0.3.2", - "yaml": "^2.9.0" + "unplugin-utils": "^0.3.2" }, "funding": { "url": "https://github.com/sponsors/posva" @@ -17036,69 +17112,6 @@ } } }, - "node_modules/vue-router/node_modules/@babel/generator": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0.tgz", - "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^8.0.0", - "@babel/types": "^8.0.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "@types/jsesc": "^2.5.0", - "jsesc": "^3.0.2" - }, - "engines": { - "node": "^22.18.0 || >=24.11.0" - } - }, - "node_modules/vue-router/node_modules/@babel/helper-string-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz", - "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==", - "license": "MIT", - "engines": { - "node": "^22.18.0 || >=24.11.0" - } - }, - "node_modules/vue-router/node_modules/@babel/helper-validator-identifier": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz", - "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==", - "license": "MIT", - "engines": { - "node": "^22.18.0 || >=24.11.0" - } - }, - "node_modules/vue-router/node_modules/@babel/parser": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz", - "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==", - "license": "MIT", - "dependencies": { - "@babel/types": "^8.0.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": "^22.18.0 || >=24.11.0" - } - }, - "node_modules/vue-router/node_modules/@babel/types": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz", - "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^8.0.0", - "@babel/helper-validator-identifier": "^8.0.4" - }, - "engines": { - "node": "^22.18.0 || >=24.11.0" - } - }, "node_modules/vue-router/node_modules/chokidar": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", @@ -17115,9 +17128,9 @@ } }, "node_modules/vue-router/node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -17789,21 +17802,6 @@ "license": "ISC", "peer": true }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 265d7349..b3368ad4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.11.0", + "@nextcloud/vue": "^9.12.0", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" From 0aa1e05647c27930e1d6d42f7e03aae86de8b66a Mon Sep 17 00:00:00 2001 From: Git'Fellow <12234510+solracsf@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:18:46 +0200 Subject: [PATCH 03/20] fix(login): create the session token as remembered createSessionToken() defaulted to DO_NOT_REMEMBER while createRememberMeToken() right after it sets 15 day remember-me cookies. TokenCleanupJob deletes DO_NOT_REMEMBER tokens after session_lifetime (24h by default), so any user away for a day gets a cookie pointing at a deleted token and every request logs "Could not find the session token to renew" (nextcloud/server#43214). Signed-off-by: Git'Fellow <12234510+solracsf@users.noreply.github.com> --- lib/Controller/LoginController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Controller/LoginController.php b/lib/Controller/LoginController.php index 6edf9ea0..99970b93 100644 --- a/lib/Controller/LoginController.php +++ b/lib/Controller/LoginController.php @@ -697,7 +697,7 @@ public function code(string $state = '', string $code = '', string $scope = '', $this->eventDispatcher->dispatchTyped(new BeforeUserLoggedInEvent($userId, null, \OCP\Server::get(Backend::class))); $this->userSession->completeLogin($user, ['loginName' => $userId, 'password' => '']); - $this->userSession->createSessionToken($this->request, $userId, $userId); + $this->userSession->createSessionToken($this->request, $userId, $userId, remember: IToken::REMEMBER); $this->userSession->createRememberMeToken($user); // prevent password confirmation From bd3343f2a00a415cae206fe85cef155a076e8893 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 03:18:32 +0000 Subject: [PATCH 04/20] Chore(deps): Bump firebase/php-jwt from 7.1.0 to 7.1.1 Bumps [firebase/php-jwt](https://github.com/googleapis/php-jwt) from 7.1.0 to 7.1.1. - [Release notes](https://github.com/googleapis/php-jwt/releases) - [Changelog](https://github.com/googleapis/php-jwt/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/php-jwt/compare/v7.1.0...v7.1.1) --- updated-dependencies: - dependency-name: firebase/php-jwt dependency-version: 7.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index c2f5c1dd..0302d381 100644 --- a/composer.lock +++ b/composer.lock @@ -65,23 +65,23 @@ }, { "name": "firebase/php-jwt", - "version": "v7.1.0", + "version": "v7.1.1", "source": { "type": "git", "url": "https://github.com/googleapis/php-jwt.git", - "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0" + "reference": "9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/b374a5d1a4f1f67fadc2165cdb284645945e2fc0", - "reference": "b374a5d1a4f1f67fadc2165cdb284645945e2fc0", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a", + "reference": "9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a", "shasum": "" }, "require": { "php": "^8.0" }, "require-dev": { - "guzzlehttp/guzzle": "^7.4", + "guzzlehttp/guzzle": "^7.4||^8.0", "phpfastcache/phpfastcache": "^9.2", "phpseclib/phpseclib": "~3.0", "phpspec/prophecy-phpunit": "^2.0", @@ -125,9 +125,9 @@ ], "support": { "issues": "https://github.com/googleapis/php-jwt/issues", - "source": "https://github.com/googleapis/php-jwt/tree/v7.1.0" + "source": "https://github.com/googleapis/php-jwt/tree/v7.1.1" }, - "time": "2026-06-11T17:54:14+00:00" + "time": "2026-09-14T17:48:47+00:00" }, { "name": "id4me/id4me-rp", From 834d7d13897562310ec7dcc02b57d8b9528d0c46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 03:45:53 +0000 Subject: [PATCH 05/20] Chore(deps-dev): Bump @babel/core from 7.28.5 to 7.29.7 Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.28.5 to 7.29.7. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.7/packages/babel-core) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 7.29.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 56 +++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0968e42c..8903ac87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,9 +52,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "peer": true, @@ -63,22 +63,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -147,15 +147,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -381,9 +381,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "peer": true, @@ -408,15 +408,15 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" From 3182fc25813189a96dd3030899d7ec202f49e563 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 01:03:05 +0000 Subject: [PATCH 06/20] Chore(deps): Bump @nextcloud/vue from 9.12.0 to 9.13.0 Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 9.12.0 to 9.13.0. - [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases) - [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/main/CHANGELOG.md) - [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v9.12.0...v9.13.0) --- updated-dependencies: - dependency-name: "@nextcloud/vue" dependency-version: 9.13.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8903ac87..5bd0bf4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.12.0", + "@nextcloud/vue": "^9.13.0", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" @@ -3055,9 +3055,9 @@ } }, "node_modules/@nextcloud/router": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.1.0.tgz", - "integrity": "sha512-e4dkIaxRSwdZJlZFpn9x03QgBn/Sa2hN1hp/BA7+AbzykmSAlKuWfdmX8j/8ewrLpQwYmZR23IZO9XwpJXq2Uw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-3.2.0.tgz", + "integrity": "sha512-an4gJ7mlDZGtYq8zTxp4Sg+iLlKKGvQ9ZH3Dp6ga/IlDNAP7VeMVGphsY798ORjncAp9+sEf370L5zpsnuxgng==", "license": "GPL-3.0-or-later", "dependencies": { "@nextcloud/typings": "^1.10.0" @@ -3175,9 +3175,9 @@ } }, "node_modules/@nextcloud/vue": { - "version": "9.12.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.12.0.tgz", - "integrity": "sha512-NuBj7wVKjUaEc9mNHSbnLl6NvLoVqUlHXV/pzn1NED1BtLb6iGwKh1KQX/BnOzGFOCkbFwTGMVgynH6i0ndjDQ==", + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.13.0.tgz", + "integrity": "sha512-XiG34Od/hMlt4VgDmHlcUXhAj2KD/4LeorsVD5sc9Vix0wqa6e3aSHjPWghll/ZD+8JnKkId6zLoexM4VqQngQ==", "license": "AGPL-3.0-or-later", "dependencies": { "@ckpack/vue-color": "^1.6.0", @@ -3190,7 +3190,7 @@ "@nextcloud/initial-state": "^3.0.0", "@nextcloud/l10n": "^3.4.1", "@nextcloud/logger": "^3.0.3", - "@nextcloud/router": "^3.1.0", + "@nextcloud/router": "^3.2.0", "@nextcloud/sharing": "^0.4.0", "@nextcloud/vue-select": "^4.1.0", "@vuepic/vue-datepicker": "^11.0.3", @@ -3230,7 +3230,7 @@ }, "peerDependencies": { "@nextcloud/dialogs": "^7.4.0", - "@nextcloud/files": "^4.1.0-beta.2" + "@nextcloud/files": "^4.1.0" }, "peerDependenciesMeta": { "@nextcloud/dialogs": { diff --git a/package.json b/package.json index b3368ad4..8a463187 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.12.0", + "@nextcloud/vue": "^9.13.0", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" From a546814ae55b4a4dd566e7d2213e80f55e963f78 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 29 Sep 2026 12:17:28 +0200 Subject: [PATCH 07/20] fix: honor allowselfsigned for discovery and ID4me token requests SettingsController::isDiscoveryEndpointValid() and the ID4me code callback used IClientService directly, so the user_oidc 'httpclient.allowselfsigned' system config (and debug mode) was ignored and requests to IdPs with self-signed certificates failed with cURL error 60. Route both requests through HttpClientHelper so they apply the same SSL verification rules as the rest of the app. Signed-off-by: Jonas Assisted-by: ClaudeCode:claude-opus-5.5 --- lib/Controller/Id4meController.php | 27 +++++++++++---------------- lib/Controller/SettingsController.php | 11 ++++------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/lib/Controller/Id4meController.php b/lib/Controller/Id4meController.php index 8a76c8e5..7e448ff0 100644 --- a/lib/Controller/Id4meController.php +++ b/lib/Controller/Id4meController.php @@ -33,7 +33,6 @@ use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Utility\ITimeFactory; -use OCP\Http\Client\IClientService; use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; @@ -60,12 +59,11 @@ public function __construct( private IConfig $config, private IL10N $l10n, private ITimeFactory $timeFactory, - private IClientService $clientService, private IURLGenerator $urlGenerator, private UserMapper $userMapper, private IUserSession $userSession, private IUserManager $userManager, - HttpClientHelper $clientHelper, + private HttpClientHelper $clientHelper, private Id4MeMapper $id4MeMapper, private ID4MeService $id4MeService, private LoggerInterface $logger, @@ -222,24 +220,21 @@ public function code(string $state = '', string $code = '', string $scope = '') return $this->buildErrorTemplateResponse($message, Http::STATUS_BAD_REQUEST, [], false); } - $client = $this->clientService->newClient(); - $result = $client->post( + $body = $this->clientHelper->post( $openIdConfig->getTokenEndpoint(), [ - 'headers' => [ - 'Authorization' => 'Basic ' . base64_encode($id4Me->getClientId() . ':' . $id4meClientSecret) - ], - 'body' => [ - 'code' => $code, - 'client_id' => $id4Me->getClientId(), - 'client_secret' => $id4meClientSecret, - 'redirect_uri' => $this->urlGenerator->linkToRouteAbsolute(Application::APP_ID . '.id4me.code'), - 'grant_type' => 'authorization_code', - ], + 'code' => $code, + 'client_id' => $id4Me->getClientId(), + 'client_secret' => $id4meClientSecret, + 'redirect_uri' => $this->urlGenerator->linkToRouteAbsolute(Application::APP_ID . '.id4me.code'), + 'grant_type' => 'authorization_code', + ], + [ + 'Authorization' => 'Basic ' . base64_encode($id4Me->getClientId() . ':' . $id4meClientSecret), ] ); - $data = json_decode($result->getBody(), true); + $data = json_decode($body, true); // documentation about token validation: // https://gitlab.com/ID4me/documentation/blob/master/id4ME%20Relying%20Party%20Implementation%20Guide.pdf diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index ce50f3b6..80084391 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -12,6 +12,7 @@ use OCA\UserOIDC\AppInfo\Application; use OCA\UserOIDC\Db\Provider; use OCA\UserOIDC\Db\ProviderMapper; +use OCA\UserOIDC\Helper\HttpClientHelper; use OCA\UserOIDC\ResponseDefinitions; use OCA\UserOIDC\Service\ID4MeService; use OCA\UserOIDC\Service\ProviderService; @@ -22,7 +23,6 @@ use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; -use OCP\Http\Client\IClientService; use OCP\IAppConfig; use OCP\IRequest; use OCP\Security\ICrypto; @@ -40,7 +40,7 @@ public function __construct( private ID4MeService $id4meService, private ProviderService $providerService, private ICrypto $crypto, - private IClientService $clientService, + private HttpClientHelper $httpClientHelper, private LoggerInterface $logger, ) { parent::__construct(Application::APP_ID, $request); @@ -53,13 +53,10 @@ private function isDiscoveryEndpointValid($url) { ]; try { - $client = $this->clientService->newClient(); - $response = $client->get($url); - $httpCode = $response->getStatusCode(); - $body = $response->getBody(); + $body = $this->httpClientHelper->get($url); // Check if the request was successful - if ($httpCode === Http::STATUS_OK && !empty($body)) { + if (!empty($body)) { $result['isReachable'] = true; $data = json_decode($body, true); From 3f86a1dc03eb0572cc5fe1c8b58b18b5ba2ca092 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2026 07:10:55 +0000 Subject: [PATCH 08/20] Chore(deps-dev): Bump webpack-dev-middleware from 8.1.1 to 8.3.0 Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 8.1.1 to 8.3.0. - [Release notes](https://github.com/webpack/webpack-dev-middleware/releases) - [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/main/CHANGELOG.md) - [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v8.1.1...v8.3.0) --- updated-dependencies: - dependency-name: webpack-dev-middleware dependency-version: 8.3.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 125 +++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 62 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5bd0bf4c..bee7a387 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2306,15 +2306,15 @@ } }, "node_modules/@jsonjoy.com/fs-core": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.68.1.tgz", - "integrity": "sha512-V5oZ4Gt9WJKyQef0n9cAd0N9qjSkIBm3E4MYsgNIWBk5aINCDPKxMPo1i29rBxqiT4Ixf1epklqV9VJMKIxwlw==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.80.0.tgz", + "integrity": "sha512-qMKWshnyjbyhm+NbzqGE3w5y1mckFFEMj0aDPU2/JBNh1BzIjVy9esq9lBmRnNVmhMEkxwDzLZ8Gqh5G1P5Dag==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "@jsonjoy.com/fs-node-utils": "4.68.1", + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "@jsonjoy.com/fs-node-utils": "4.80.0", "thingies": "^2.5.0" }, "engines": { @@ -2329,16 +2329,16 @@ } }, "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.68.1.tgz", - "integrity": "sha512-HCG72UioncuO7Gw09XNVG+S85e3cq2hrUC/mexBrsWsa3mI7eePkkqWie3uVYbtsb64OR9YGQs5SqaufDRYBcg==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.80.0.tgz", + "integrity": "sha512-ZBEKl7J6dbkRCfmrFV48Re211A/FHqniTUhsWCsaRteNSOqMgkX3qF1UreVgwB9oSPm81JLAwhIi6Lb/NH/PoA==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-core": "4.68.1", - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "@jsonjoy.com/fs-node-utils": "4.68.1", + "@jsonjoy.com/fs-core": "4.80.0", + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "@jsonjoy.com/fs-node-utils": "4.80.0", "thingies": "^2.5.0" }, "engines": { @@ -2353,19 +2353,19 @@ } }, "node_modules/@jsonjoy.com/fs-node": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.68.1.tgz", - "integrity": "sha512-R5D9mWtqdURzcOWj1vdXr3APCwX0xchtFT+kmW7fXLNDifWdDrnh26jSID8pdnUfFBxTyfHtFtTL/NWKzIH7kQ==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.80.0.tgz", + "integrity": "sha512-yiBlUfkMMRFFGy8CD/h2zd5rPnrM6bjlF+nx2LRAxNV6hOSiuObQIUEE7m7y2VTMisjxCRtzINH94bFGySWL7g==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-core": "4.68.1", - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "@jsonjoy.com/fs-node-utils": "4.68.1", - "@jsonjoy.com/fs-print": "4.68.1", - "@jsonjoy.com/fs-snapshot": "4.68.1", - "glob-to-regex.js": "^1.0.0", + "@jsonjoy.com/fs-core": "4.80.0", + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "@jsonjoy.com/fs-node-utils": "4.80.0", + "@jsonjoy.com/fs-print": "4.80.0", + "@jsonjoy.com/fs-snapshot": "4.80.0", + "glob-to-regex.js": "^1.3.1", "thingies": "^2.5.0" }, "engines": { @@ -2380,9 +2380,9 @@ } }, "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.68.1.tgz", - "integrity": "sha512-HK1BTksysokNZxNspqDH0yPaqN9YgR/AYIlYiIaU2Ys4BOk5CdybI7r6BgiZuiiPiV8n4sK/kZdice7Znpy2Kw==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.80.0.tgz", + "integrity": "sha512-OIOIhqaWiwUySFMny4epIAoviXsyMaQQ63PTc3zH+5HEOvarl5hpUmZIhp2m5+OfyKAh5ylxXnQIgew1OgJDVw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -2398,16 +2398,16 @@ } }, "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.68.1.tgz", - "integrity": "sha512-lpKmU4X9e/oh8GIuAI7EXaS5QiLNM3KD15CkdhfS6PYmrGvoJqKQcyEfnLgnnaGslh/PFUMYSIZBCf2ejJGw8g==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.80.0.tgz", + "integrity": "sha512-ljeaR5xwtX1EyRmB0wvXANUMQZ3mjKcm7z8s2N8D8SLQ04CcAGtUhHFRZQXFb9mhgFyEVMydQGQtSOFS7pcrFQ==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-fsa": "4.68.1", - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "@jsonjoy.com/fs-node-utils": "4.68.1" + "@jsonjoy.com/fs-fsa": "4.80.0", + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "@jsonjoy.com/fs-node-utils": "4.80.0" }, "engines": { "node": ">=10.0" @@ -2421,15 +2421,15 @@ } }, "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.68.1.tgz", - "integrity": "sha512-/GxfW1DWm9SCdkfbvqevLO/P5duobQfmKkHXxdMIDbcZMQeAgooAstIfZhkXpATzq9QbCQsnoWFM/dGHdZfndw==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.80.0.tgz", + "integrity": "sha512-xwHeVVi3f+Khg/Fmb8i5qoYVmQ08QznE5TWhQokUmIZjz4KBPzU+zt/+bahBI6G1ghtqajt27lWuAciIxApuzA==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "glob-to-regex.js": "^1.0.1" + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "glob-to-regex.js": "^1.3.1" }, "engines": { "node": ">=10.0" @@ -2443,14 +2443,14 @@ } }, "node_modules/@jsonjoy.com/fs-print": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.68.1.tgz", - "integrity": "sha512-oGeZOGPYKK9v1CgeVeEDsLomH1lCnslSpqUN5GmPzrmAVGQlsmsdcXNA2O4lV8Y4xkuSuynx2ITBkUHJVaTbow==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.80.0.tgz", + "integrity": "sha512-1ocZLJw/m/xlq0moaIHO7HV9nHRVBUvdc2zMzhsJGkFOrqfwWvexfCv5cYCPPLRhP+9p3yunoi4Ep5YhRORC9Q==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.68.1", + "@jsonjoy.com/fs-node-utils": "4.80.0", "tree-dump": "^1.1.0" }, "engines": { @@ -2465,15 +2465,15 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.68.1.tgz", - "integrity": "sha512-XZfP0FDZN32bbc4t2bZN2qRrYHg5AktJnzk22HRoKGK4BprrbNRH2k5ceSNS/kupKYcofCs+O841+xaAbjnxwQ==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.80.0.tgz", + "integrity": "sha512-3AV23Q1H228KTtJKTUE0nNq8FCtxSvtENOLrEat80wkAJCKHuqQEv8yjhpS8Bei2OEFJAnluGXp9Ri2SWBlROw==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.68.1", + "@jsonjoy.com/fs-node-utils": "4.80.0", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, @@ -9313,9 +9313,9 @@ } }, "node_modules/glob-to-regex.js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", - "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.3.1.tgz", + "integrity": "sha512-zhWhMRsgnOym+1txhUmYJGD6eUsbUdrZv55gCYKuJX8t2p3+M8My23PD09bEIsreGUs5pnSa/idmcfp2/IlqGg==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -11546,24 +11546,24 @@ } }, "node_modules/memfs": { - "version": "4.68.1", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.68.1.tgz", - "integrity": "sha512-OD+IDRUvIxu3QHL+nFm9gdyugInD27FDJ+sl4B5QgomPHXMlbw+GP918P8VNKu2FkNlVeqBkpzkwROpamVifRw==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.80.0.tgz", + "integrity": "sha512-N70W2isi44XdGn7uPo9NJ4zRukcdkwSFHlnYx42SWOH/+hzqNc8P7+tVoA2up4z7faHvNi1RSNCFjxoYQ71VPQ==", "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { - "@jsonjoy.com/fs-core": "4.68.1", - "@jsonjoy.com/fs-fsa": "4.68.1", - "@jsonjoy.com/fs-node": "4.68.1", - "@jsonjoy.com/fs-node-builtins": "4.68.1", - "@jsonjoy.com/fs-node-to-fsa": "4.68.1", - "@jsonjoy.com/fs-node-utils": "4.68.1", - "@jsonjoy.com/fs-print": "4.68.1", - "@jsonjoy.com/fs-snapshot": "4.68.1", + "@jsonjoy.com/fs-core": "4.80.0", + "@jsonjoy.com/fs-fsa": "4.80.0", + "@jsonjoy.com/fs-node": "4.80.0", + "@jsonjoy.com/fs-node-builtins": "4.80.0", + "@jsonjoy.com/fs-node-to-fsa": "4.80.0", + "@jsonjoy.com/fs-node-utils": "4.80.0", + "@jsonjoy.com/fs-print": "4.80.0", + "@jsonjoy.com/fs-snapshot": "4.80.0", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", - "glob-to-regex.js": "^1.0.1", + "glob-to-regex.js": "^1.3.1", "thingies": "^2.5.0", "tree-dump": "^1.0.3", "tslib": "^2.0.0" @@ -17362,16 +17362,17 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-8.1.1.tgz", - "integrity": "sha512-JrxAE/HwNmEnTkzkUGHFItHpGalzuEIUDifXhjAkIEHZzHK/ZJFVoTQF5ubZQlgeRireqLdr2lZttrrmOH61IA==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-8.3.0.tgz", + "integrity": "sha512-jFNNMB29ugmkEUFW9cpWNqcWFQNwuMTMVoRpKVAiz/5nh3gA4x9x6DRPhNHGc/SLre7pEP9yrAPDAmCvdCblKg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "memfs": "^4.56.10", + "ansi-html-community": "^0.0.8", + "memfs": "^4.68.2", "mime-types": "^3.0.2", - "range-parser": "^1.2.1", + "range-parser": "^1.3.0", "schema-utils": "^4.3.3" }, "engines": { From 300576bba60ddcad0457253a628c9f63960d2b05 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Sep 2026 07:14:01 +0000 Subject: [PATCH 09/20] Chore(deps-dev): Bump brace-expansion from 1.1.18 to 1.1.21 Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 1.1.18 to 1.1.21. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v1.1.18...v1.1.21) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 1.1.21 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 49 +++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/package-lock.json b/package-lock.json index bee7a387..ced5136c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2029,10 +2029,11 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -2116,10 +2117,11 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -5983,9 +5985,10 @@ "peer": true }, "node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -8159,10 +8162,11 @@ } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -8277,10 +8281,11 @@ } }, "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -8422,10 +8427,11 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -9331,10 +9337,11 @@ } }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", From cac17ea060c5494a74f831fc12eb9e94d2518872 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Mon, 5 May 2025 17:03:52 +0200 Subject: [PATCH 10/20] feat(userinfo): accept signed JWT userinfo responses Some IdPs, e.g. ProConnect, return userinfo as a signed JWT instead of JSON. If the body isn't JSON, verify it against the provider's JWKS and use its claims. Signed-off-by: Julien Veyssier Signed-off-by: Peter Ringelmann --- lib/Service/OIDCService.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/Service/OIDCService.php b/lib/Service/OIDCService.php index 3b5bddad..3d94c353 100644 --- a/lib/Service/OIDCService.php +++ b/lib/Service/OIDCService.php @@ -11,6 +11,7 @@ use OCA\UserOIDC\Db\Provider; use OCA\UserOIDC\Helper\HttpClientHelper; +use OCA\UserOIDC\Vendor\Firebase\JWT\JWT; use OCP\Security\ICrypto; use Psr\Log\LoggerInterface; use Throwable; @@ -37,12 +38,31 @@ public function userinfo(Provider $provider, string $accessToken): array { 'Authorization' => 'Bearer ' . $accessToken, ], ]; + try { - return json_decode($this->clientService->get($url, [], $options), true); + $userInfoResponse = $this->clientService->get($url, [], $options); } catch (Throwable $e) { $this->logger->warning('[UserInfo] Failed to fetch user info endpoint', ['exception' => $e]); return []; } + + try { + return json_decode($userInfoResponse, true, 512, JSON_THROW_ON_ERROR); + } catch (Throwable) { + $this->logger->debug('[UserInfo] The response is not JSON'); + } + + JWT::$leeway = 60; + try { + $jwks = $this->discoveryService->obtainJWK($provider, $userInfoResponse); + $payload = JWT::decode($userInfoResponse, $jwks); + $arrayPayload = json_decode(json_encode($payload), true); + $this->logger->debug('[UserInfo] Decoded the JWT response', ['decoded_userinfo_response' => $arrayPayload]); + return $arrayPayload; + } catch (Throwable $e) { + $this->logger->warning('[UserInfo] Failed to decode the response as a JWT', ['exception' => $e]); + return []; + } } public function introspection(Provider $provider, string $accessToken): array { From 9d77998e41b3e900a00b637df8a24b784a16a639 Mon Sep 17 00:00:00 2001 From: Peter Ringelmann Date: Wed, 30 Sep 2026 12:51:22 +0200 Subject: [PATCH 11/20] test(userinfo): cover JSON and signed JWT responses Signed-off-by: Peter Ringelmann --- tests/unit/Service/OIDCServiceTest.php | 88 ++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/unit/Service/OIDCServiceTest.php diff --git a/tests/unit/Service/OIDCServiceTest.php b/tests/unit/Service/OIDCServiceTest.php new file mode 100644 index 00000000..512d6e56 --- /dev/null +++ b/tests/unit/Service/OIDCServiceTest.php @@ -0,0 +1,88 @@ +discoveryService = $this->createMock(DiscoveryService::class); + $this->clientHelper = $this->createMock(HttpClientHelper::class); + $this->provider = $this->createMock(Provider::class); + $this->oidcService = new OIDCService( + $this->discoveryService, + $this->createMock(LoggerInterface::class), + $this->clientHelper, + $this->createMock(ICrypto::class), + ); + + $this->discoveryService->method('obtainDiscovery') + ->willReturn(['userinfo_endpoint' => 'https://idp.example.org/userinfo']); + } + + private static function createRsaKeyPair(): array { + $key = openssl_pkey_new(['private_key_bits' => 2048, 'private_key_type' => OPENSSL_KEYTYPE_RSA]); + openssl_pkey_export($key, $privateKey); + return [$privateKey, openssl_pkey_get_details($key)['key']]; + } + + public function testUserinfoJsonResponse(): void { + $this->clientHelper->method('get') + ->willReturn(json_encode(['sub' => 'alice', 'email' => 'alice@example.org'])); + $this->discoveryService->expects($this->never())->method('obtainJWK'); + + $this->assertSame( + ['sub' => 'alice', 'email' => 'alice@example.org'], + $this->oidcService->userinfo($this->provider, 'access-token'), + ); + } + + public function testUserinfoSignedJwtResponse(): void { + [$privateKey, $publicKey] = self::createRsaKeyPair(); + $jwt = JWT::encode(['sub' => 'alice', 'email' => 'alice@example.org'], $privateKey, 'RS256', 'key1'); + + $this->clientHelper->method('get')->willReturn($jwt); + $this->discoveryService->expects($this->once()) + ->method('obtainJWK') + ->with($this->provider, $jwt) + ->willReturn(['key1' => new Key($publicKey, 'RS256')]); + + $this->assertSame( + ['sub' => 'alice', 'email' => 'alice@example.org'], + $this->oidcService->userinfo($this->provider, 'access-token'), + ); + } + + public function testUserinfoJwtWithInvalidSignature(): void { + [, $publicKey] = self::createRsaKeyPair(); + [$otherPrivateKey] = self::createRsaKeyPair(); + $jwt = JWT::encode(['sub' => 'mallory'], $otherPrivateKey, 'RS256', 'key1'); + + $this->clientHelper->method('get')->willReturn($jwt); + $this->discoveryService->method('obtainJWK') + ->willReturn(['key1' => new Key($publicKey, 'RS256')]); + + $this->assertSame([], $this->oidcService->userinfo($this->provider, 'access-token')); + } +} From dd0b93ee43afac0c7aa78f101a3b29a76a1a8d34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 01:03:38 +0000 Subject: [PATCH 12/20] Chore(deps): Bump firebase/php-jwt from 7.1.1 to 7.2.0 Bumps [firebase/php-jwt](https://github.com/googleapis/php-jwt) from 7.1.1 to 7.2.0. - [Release notes](https://github.com/googleapis/php-jwt/releases) - [Changelog](https://github.com/googleapis/php-jwt/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/php-jwt/compare/v7.1.1...v7.2.0) --- updated-dependencies: - dependency-name: firebase/php-jwt dependency-version: 7.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- composer.lock | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 0302d381..50f046a4 100644 --- a/composer.lock +++ b/composer.lock @@ -65,16 +65,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.1.1", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/googleapis/php-jwt.git", - "reference": "9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a" + "reference": "f502cdbf279cd7532060b041f7c22a05208c0b93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a", - "reference": "9bc93bd7e3ee5bead4cd23c365ec12f3c1fb0a6a", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/f502cdbf279cd7532060b041f7c22a05208c0b93", + "reference": "f502cdbf279cd7532060b041f7c22a05208c0b93", "shasum": "" }, "require": { @@ -84,7 +84,7 @@ "guzzlehttp/guzzle": "^7.4||^8.0", "phpfastcache/phpfastcache": "^9.2", "phpseclib/phpseclib": "~3.0", - "phpspec/prophecy-phpunit": "^2.0", + "phpspec/prophecy-phpunit": "^2.2", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", "psr/http-client": "^1.0", @@ -96,6 +96,14 @@ "phpseclib/phpseclib": "Support PS256 (RSASSA-PSS) signatures" }, "type": "library", + "extra": { + "component": { + "id": "jwt", + "path": "Jwt", + "entry": "README.md", + "target": "googleapis/php-jwt.git" + } + }, "autoload": { "psr-4": { "Firebase\\JWT\\": "src" @@ -125,9 +133,9 @@ ], "support": { "issues": "https://github.com/googleapis/php-jwt/issues", - "source": "https://github.com/googleapis/php-jwt/tree/v7.1.1" + "source": "https://github.com/googleapis/php-jwt/tree/v7.2.0" }, - "time": "2026-09-14T17:48:47+00:00" + "time": "2026-09-21T19:29:58+00:00" }, { "name": "id4me/id4me-rp", From b917c816c0cfcb4be65bf40b3713a85fba01ddad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 01:06:49 +0000 Subject: [PATCH 13/20] Chore(deps): Bump axios from 1.19.0 to 1.20.0 Bumps [axios](https://github.com/axios/axios) from 1.19.0 to 1.20.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.19.0...v1.20.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.20.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ced5136c..c6e31e8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5761,9 +5761,9 @@ } }, "node_modules/axios": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", - "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", From d0fe43ef3755ece44b25e7bf51378000263ba681 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 01:06:50 +0000 Subject: [PATCH 14/20] Chore(deps): Bump dompurify from 3.4.15 to 3.4.16 Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.4.15 to 3.4.16. - [Release notes](https://github.com/cure53/DOMPurify/releases) - [Commits](https://github.com/cure53/DOMPurify/compare/3.4.15...3.4.16) --- updated-dependencies: - dependency-name: dompurify dependency-version: 3.4.16 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index ced5136c..88ea1bb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7516,9 +7516,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.15", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.15.tgz", - "integrity": "sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==", + "version": "3.4.16", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.16.tgz", + "integrity": "sha512-sqo+pNp3qRhCIpbgRi1y8Tgk27Bo2Ry7w0dC1NBeNTdZChWjz9Xb/KOoZbRP/R6pQZ80Qw8YhXw13hWWBbMRnQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" From e29af78cacca9a66ae1ad611f3759f770e5090a4 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Fri, 2 Oct 2026 02:59:14 +0000 Subject: [PATCH 15/20] fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- l10n/sk.js | 2 +- l10n/sk.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n/sk.js b/l10n/sk.js index be3db699..087bb4db 100644 --- a/l10n/sk.js +++ b/l10n/sk.js @@ -45,7 +45,7 @@ OC.L10N.register( "Registered Providers" : "Preferovaní poskytovatelia", "Register new provider" : "Registrovať nového poskytovateľa", "Register a new provider" : "Registrovať nového poskytovateľa", - "Configure your provider to redirect back to {url}" : "Nastavte vášho poskytovateľa pre presmerovanie na {url}", + "Configure your provider to redirect back to {url}" : "Nastavte svojho poskytovateľa tak, aby presmeroval späť na {url}.", "No providers registered." : "Neboli zaregistrovaný žiadny poskytovatelia.", "Client ID" : "Client ID", "Discovery endpoint" : "Koncový bod discovery", diff --git a/l10n/sk.json b/l10n/sk.json index d087a14c..eb1e8b2e 100644 --- a/l10n/sk.json +++ b/l10n/sk.json @@ -43,7 +43,7 @@ "Registered Providers" : "Preferovaní poskytovatelia", "Register new provider" : "Registrovať nového poskytovateľa", "Register a new provider" : "Registrovať nového poskytovateľa", - "Configure your provider to redirect back to {url}" : "Nastavte vášho poskytovateľa pre presmerovanie na {url}", + "Configure your provider to redirect back to {url}" : "Nastavte svojho poskytovateľa tak, aby presmeroval späť na {url}.", "No providers registered." : "Neboli zaregistrovaný žiadny poskytovatelia.", "Client ID" : "Client ID", "Discovery endpoint" : "Koncový bod discovery", From 21a687798a323d8a1191d2f271a1e9c35cab89d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 01:03:32 +0000 Subject: [PATCH 16/20] Chore(deps): Bump @nextcloud/vue from 9.13.0 to 9.13.1 Bumps [@nextcloud/vue](https://github.com/nextcloud-libraries/nextcloud-vue) from 9.13.0 to 9.13.1. - [Release notes](https://github.com/nextcloud-libraries/nextcloud-vue/releases) - [Changelog](https://github.com/nextcloud-libraries/nextcloud-vue/blob/main/CHANGELOG.md) - [Commits](https://github.com/nextcloud-libraries/nextcloud-vue/compare/v9.13.0...v9.13.1) --- updated-dependencies: - dependency-name: "@nextcloud/vue" dependency-version: 9.13.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 20dc62d3..35203c7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.13.0", + "@nextcloud/vue": "^9.13.1", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" @@ -3177,9 +3177,9 @@ } }, "node_modules/@nextcloud/vue": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.13.0.tgz", - "integrity": "sha512-XiG34Od/hMlt4VgDmHlcUXhAj2KD/4LeorsVD5sc9Vix0wqa6e3aSHjPWghll/ZD+8JnKkId6zLoexM4VqQngQ==", + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.13.1.tgz", + "integrity": "sha512-6ZeHm+coHJ6wsavulll4CVl3tk5ehjh7p6pW9GU1BgfDkOsbx5Pv4U8/uVk7yOTn4oAo695XTHhFN17pyI1peQ==", "license": "AGPL-3.0-or-later", "dependencies": { "@ckpack/vue-color": "^1.6.0", diff --git a/package.json b/package.json index 8a463187..2032fb19 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@nextcloud/logger": "^3.0.2", "@nextcloud/password-confirmation": "^6.1.0", "@nextcloud/router": "^3.0.1", - "@nextcloud/vue": "^9.13.0", + "@nextcloud/vue": "^9.13.1", "jstz": "^2.1.1", "vue": "^3.5.17", "vue-material-design-icons": "^5.3.1" From 458cedc0f23173e3d6912816317cfe331a271fe2 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Mon, 5 Oct 2026 03:07:01 +0000 Subject: [PATCH 17/20] fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- l10n/da.js | 13 +++++++++++++ l10n/da.json | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/l10n/da.js b/l10n/da.js index d681f14a..051fac7d 100644 --- a/l10n/da.js +++ b/l10n/da.js @@ -11,6 +11,7 @@ OC.L10N.register( "The received state does not match the expected value." : "Den modtagne tilstand matcher ikke den forventede værdi.", "Authority not found" : "Autoritet ikke fundet", "Failed to decrypt the ID4ME provider client secret" : "Kunne ikke dekryptere ID4ME leverandør klient hemmeligheden", + "Failed to authenticate" : "Godkendelsen mislykkedes", "The received token is expired." : "Det modtagne token er udløbet.", "The audience does not match ours" : "Publikum matcher ikke vores", "The authorized party does not match ours" : "Den godkendte part matcher ikke vores", @@ -19,6 +20,8 @@ OC.L10N.register( "You must access Nextcloud with HTTPS to use OpenID Connect." : "Du skal tilgå Nextcloud via HTTPS for at anvende OpenID Connect.", "There is no such OpenID Connect provider." : "Der er ingen sådan OpenID Connect udbyder.", "Could not reach the OpenID Connect provider." : "Kunne ikke kontakte OpenID Connect leverandøren", + "The identity provider failed to authenticate the user." : "Identitetsudbyderen kunne ikke godkende brugeren.", + "The received state has expired." : "Den modtagne tilstand er udløbet.", "Failed to decrypt the OIDC provider client secret" : "Kunne ikke dekryptere OIDC leverandør klient hemmeligheden", "Failed to contact the OIDC provider token endpoint" : "Kunne ikke kontakte OIDC leverandør token slutpunktet", "The issuer does not match the one from the discovery endpoint" : "Udstederen matcher ikke den fra opdagelses slutpunktet", @@ -29,6 +32,7 @@ OC.L10N.register( "OpenID Connect user backend" : "OpenID Connect bruger backend", "Use an OpenID Connect backend to login to your Nextcloud" : "Anvend en OpenID Connect backend for at logge på din Nextcloud", "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC server som Nextcloud log på bruger backend.", + "Are you sure you want to delete the provider \"{providerName}\"?" : "Er du sikker på, at du vil slette udbyderen \"{providerName}\"?", "Could not save ID4me state: {msg}" : "Kunne ikke gemme ID4me tilstand: {msg}", "Could not save storeLoginToken state: {msg}" : "Kunne ikke gemme storeLoginToken tilstand: {msg}", "Could not update the provider:" : "Kunne ikke opdatere udbyderen:", @@ -37,6 +41,7 @@ OC.L10N.register( "Allows users to authenticate via OpenID Connect providers." : "Giver brugerne mulighed for at autentificere via OpenID Connect udbydere.", "Enable ID4me" : "Aktivér ID4me", "Store login tokens" : "Gem login nøgler", + "\"Store login tokens\" is needed if you are using other apps that want to use user_oidc's token exchange or simply get the login token" : "\"Gem login-tokens\" er nødvendig, hvis du bruger andre apps, der vil bruge user_oidc's tokenudveksling eller blot hente login-tokenet", "Registered Providers" : "Registrerede Udbydere", "Register new provider" : "Registrér ny udbyder", "Register a new provider" : "Registrér en ny udbyder", @@ -61,6 +66,7 @@ OC.L10N.register( "Leave empty to keep existing" : "Lad være tom for at beholde eksisterende", "Warning, if the protocol of the URLs in the discovery content is HTTP, the ID token will be delivered through an insecure connection." : "Advarsel, hvis protokollen for URL'er i opdagelsesindholdet er HTTP, så vil ID token blive leveret gennem en usikker forbindelse.", "Custom end session endpoint" : "Brugerdefineret slut session endepunkt", + "Post logout URI" : "URI efter logud", "Scope" : "Anvendelsesområde", "Extra claims" : "Ekstra claims", "Attribute mapping" : "Attribut tilknytning", @@ -70,10 +76,13 @@ OC.L10N.register( "Groups mapping" : "Gruppe tilknytning", "Extra attributes mapping" : "Ekstra attributter tilknytning", "Display name mapping" : "Vis navne tilknytning", + "Birth date mapping" : "Tilknytning af fødselsdato", + "Pronouns mapping" : "Tilknytning af pronominer", "Gender mapping" : "Køn tilknytning", "Email mapping" : "Mail tilknytning", "Phone mapping" : "Telefon tilknytning", "Language mapping" : "Sprog tilknytning", + "Locale mapping" : "Tilknytning af lokalitet", "Role/Title mapping" : "Rolle/titel tilknytning", "Street mapping" : "Gade tilknytning", "Postal code mapping" : "Postnummer tilknytning", @@ -90,6 +99,7 @@ OC.L10N.register( "Authentication and Access Control Settings" : "Indstillinger for godkendelse og adgangskontrol", "Use unique user ID" : "Brug unikt Bruger ID", "By default every user will get a unique user ID that is a hashed value of the provider and user ID. This can be turned off but uniqueness of users accross multiple user backends and providers is no longer preserved then." : "Som standard vil hver bruger få et unikt bruger ID, der er en hashed værdi af udbyderen og bruger ID. Dette kan deaktiveres, men unikheden af brugerne på tværs af flere bruger backends og udbydere vil så ikke længere være bevaret.", + "Keep in mind that disabling \"Unique user IDs\" means that this provider can produce user IDs that are identical to user IDs from other providers (and from other user backends if you are in non-auto-provisioning mode). This means this provider can be potentially used to authenticate as users from other providers/backends. This might be what you want to achieve. In any case, please make sure you trust this provider." : "Vær opmærksom på, at hvis du deaktiverer \"Unikke bruger-id'er\", kan denne udbyder oprette bruger-id'er, der er identiske med bruger-id'er fra andre udbydere (og fra andre brugerbackends, hvis du ikke bruger automatisk oprettelse). Det betyder, at denne udbyder potentielt kan bruges til at godkende sig som brugere fra andre udbydere eller backends. Det kan være det, du vil opnå. Under alle omstændigheder skal du sikre dig, at du har tillid til denne udbyder.", "Use provider identifier as prefix for IDs" : "Brug udbyderens id som præfiks for ID'er", "To keep IDs in plain text, but also preserve uniqueness of them across multiple providers, a prefix with the providers name is added." : "For at holde ID'er i almindelig tekst, men også bevare unikke af dem på tværs af flere udbydere, et præfiks med udbyderens navn tilføjes.", "Use group provisioning." : "Brug gruppeprovisionering", @@ -97,10 +107,13 @@ OC.L10N.register( "Restrict login for users that are not in any whitelisted group" : "Begræns login for brugere, der ikke er i nogen hvidlistet gruppe", "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er en del af nogen hvidlistet gruppe bliver ikke oprettet og kan ikke logge på", "Check Bearer token on API and WebDAV requests" : "Tjek Bearer token på API og WebDAV anmodninger", + "Do you want to allow API calls and WebDAV requests that are authenticated with an OIDC ID token or access token?" : "Vil du tillade API-kald og WebDAV-anmodninger, der er godkendt med et OIDC-id-token eller et adgangstoken?", "Auto provision user when accessing API and WebDAV with Bearer token" : "Automatisk provisionering af bruger når API og WebDAV tilgås med Bearer token", "This automatically provisions the user, when sending API and WebDAV requests with a Bearer token. Auto provisioning and Bearer token check have to be activated for this to work." : "Dette provisionerer automatisk brugeren, når der sendes API og WebDAV anmodninger med en Bearer token. Auto provisionering og Bearer token kontrol skal aktiveres for at dette virker.", "Send ID token hint on logout" : "Send ID token hint om log af", "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider." : "Skal ID token inkluderes som id_token_hint GET-parameteren i OpenID logud URL? Brugere omdirigeres til denne URL når de logger ud. Aktivering af denne indstilling eksponerer OIDC ID token til bruger-agenten, som måske ikke er nødvendig afhængigt af OIDC udbyder.", + "Enrich login ID token with userinfo" : "Berig login-id-tokenet med userinfo", + "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled." : "Hent yderligere oplysninger, som ikke findes i login-id-tokenet, fra userinfo-endpointet. Indstillingen overskrives, hvis den globale indstilling enrich_login_id_token_with_userinfo er slået til.", "Only groups matching the whitelist regex will be created, updated and deleted by the group claim. For example: {regex} allows all groups which ID starts with {substr}" : "Kun grupper der matcher hvidlistningens regex vil blive oprettet, opdateret og slettet af gruppe krav. For eksempel: {regex} tillader alle grupper hvis ID starter med {substr}", "This will create and update the users groups depending on the groups claim in the ID token. The Format of the groups claim value should be {sample1}, {sample2} or {sample3}" : "Dette vil oprette og opdatere brugernes grupper afhængigt af gruppernes krav i ID token. Formatet for gruppernes værdi skal være {sample1}, {sample2} eller {sample3}", "Back to %s" : "Tilbage til %s", diff --git a/l10n/da.json b/l10n/da.json index cefec050..7ba25c3c 100644 --- a/l10n/da.json +++ b/l10n/da.json @@ -9,6 +9,7 @@ "The received state does not match the expected value." : "Den modtagne tilstand matcher ikke den forventede værdi.", "Authority not found" : "Autoritet ikke fundet", "Failed to decrypt the ID4ME provider client secret" : "Kunne ikke dekryptere ID4ME leverandør klient hemmeligheden", + "Failed to authenticate" : "Godkendelsen mislykkedes", "The received token is expired." : "Det modtagne token er udløbet.", "The audience does not match ours" : "Publikum matcher ikke vores", "The authorized party does not match ours" : "Den godkendte part matcher ikke vores", @@ -17,6 +18,8 @@ "You must access Nextcloud with HTTPS to use OpenID Connect." : "Du skal tilgå Nextcloud via HTTPS for at anvende OpenID Connect.", "There is no such OpenID Connect provider." : "Der er ingen sådan OpenID Connect udbyder.", "Could not reach the OpenID Connect provider." : "Kunne ikke kontakte OpenID Connect leverandøren", + "The identity provider failed to authenticate the user." : "Identitetsudbyderen kunne ikke godkende brugeren.", + "The received state has expired." : "Den modtagne tilstand er udløbet.", "Failed to decrypt the OIDC provider client secret" : "Kunne ikke dekryptere OIDC leverandør klient hemmeligheden", "Failed to contact the OIDC provider token endpoint" : "Kunne ikke kontakte OIDC leverandør token slutpunktet", "The issuer does not match the one from the discovery endpoint" : "Udstederen matcher ikke den fra opdagelses slutpunktet", @@ -27,6 +30,7 @@ "OpenID Connect user backend" : "OpenID Connect bruger backend", "Use an OpenID Connect backend to login to your Nextcloud" : "Anvend en OpenID Connect backend for at logge på din Nextcloud", "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC server som Nextcloud log på bruger backend.", + "Are you sure you want to delete the provider \"{providerName}\"?" : "Er du sikker på, at du vil slette udbyderen \"{providerName}\"?", "Could not save ID4me state: {msg}" : "Kunne ikke gemme ID4me tilstand: {msg}", "Could not save storeLoginToken state: {msg}" : "Kunne ikke gemme storeLoginToken tilstand: {msg}", "Could not update the provider:" : "Kunne ikke opdatere udbyderen:", @@ -35,6 +39,7 @@ "Allows users to authenticate via OpenID Connect providers." : "Giver brugerne mulighed for at autentificere via OpenID Connect udbydere.", "Enable ID4me" : "Aktivér ID4me", "Store login tokens" : "Gem login nøgler", + "\"Store login tokens\" is needed if you are using other apps that want to use user_oidc's token exchange or simply get the login token" : "\"Gem login-tokens\" er nødvendig, hvis du bruger andre apps, der vil bruge user_oidc's tokenudveksling eller blot hente login-tokenet", "Registered Providers" : "Registrerede Udbydere", "Register new provider" : "Registrér ny udbyder", "Register a new provider" : "Registrér en ny udbyder", @@ -59,6 +64,7 @@ "Leave empty to keep existing" : "Lad være tom for at beholde eksisterende", "Warning, if the protocol of the URLs in the discovery content is HTTP, the ID token will be delivered through an insecure connection." : "Advarsel, hvis protokollen for URL'er i opdagelsesindholdet er HTTP, så vil ID token blive leveret gennem en usikker forbindelse.", "Custom end session endpoint" : "Brugerdefineret slut session endepunkt", + "Post logout URI" : "URI efter logud", "Scope" : "Anvendelsesområde", "Extra claims" : "Ekstra claims", "Attribute mapping" : "Attribut tilknytning", @@ -68,10 +74,13 @@ "Groups mapping" : "Gruppe tilknytning", "Extra attributes mapping" : "Ekstra attributter tilknytning", "Display name mapping" : "Vis navne tilknytning", + "Birth date mapping" : "Tilknytning af fødselsdato", + "Pronouns mapping" : "Tilknytning af pronominer", "Gender mapping" : "Køn tilknytning", "Email mapping" : "Mail tilknytning", "Phone mapping" : "Telefon tilknytning", "Language mapping" : "Sprog tilknytning", + "Locale mapping" : "Tilknytning af lokalitet", "Role/Title mapping" : "Rolle/titel tilknytning", "Street mapping" : "Gade tilknytning", "Postal code mapping" : "Postnummer tilknytning", @@ -88,6 +97,7 @@ "Authentication and Access Control Settings" : "Indstillinger for godkendelse og adgangskontrol", "Use unique user ID" : "Brug unikt Bruger ID", "By default every user will get a unique user ID that is a hashed value of the provider and user ID. This can be turned off but uniqueness of users accross multiple user backends and providers is no longer preserved then." : "Som standard vil hver bruger få et unikt bruger ID, der er en hashed værdi af udbyderen og bruger ID. Dette kan deaktiveres, men unikheden af brugerne på tværs af flere bruger backends og udbydere vil så ikke længere være bevaret.", + "Keep in mind that disabling \"Unique user IDs\" means that this provider can produce user IDs that are identical to user IDs from other providers (and from other user backends if you are in non-auto-provisioning mode). This means this provider can be potentially used to authenticate as users from other providers/backends. This might be what you want to achieve. In any case, please make sure you trust this provider." : "Vær opmærksom på, at hvis du deaktiverer \"Unikke bruger-id'er\", kan denne udbyder oprette bruger-id'er, der er identiske med bruger-id'er fra andre udbydere (og fra andre brugerbackends, hvis du ikke bruger automatisk oprettelse). Det betyder, at denne udbyder potentielt kan bruges til at godkende sig som brugere fra andre udbydere eller backends. Det kan være det, du vil opnå. Under alle omstændigheder skal du sikre dig, at du har tillid til denne udbyder.", "Use provider identifier as prefix for IDs" : "Brug udbyderens id som præfiks for ID'er", "To keep IDs in plain text, but also preserve uniqueness of them across multiple providers, a prefix with the providers name is added." : "For at holde ID'er i almindelig tekst, men også bevare unikke af dem på tværs af flere udbydere, et præfiks med udbyderens navn tilføjes.", "Use group provisioning." : "Brug gruppeprovisionering", @@ -95,10 +105,13 @@ "Restrict login for users that are not in any whitelisted group" : "Begræns login for brugere, der ikke er i nogen hvidlistet gruppe", "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er en del af nogen hvidlistet gruppe bliver ikke oprettet og kan ikke logge på", "Check Bearer token on API and WebDAV requests" : "Tjek Bearer token på API og WebDAV anmodninger", + "Do you want to allow API calls and WebDAV requests that are authenticated with an OIDC ID token or access token?" : "Vil du tillade API-kald og WebDAV-anmodninger, der er godkendt med et OIDC-id-token eller et adgangstoken?", "Auto provision user when accessing API and WebDAV with Bearer token" : "Automatisk provisionering af bruger når API og WebDAV tilgås med Bearer token", "This automatically provisions the user, when sending API and WebDAV requests with a Bearer token. Auto provisioning and Bearer token check have to be activated for this to work." : "Dette provisionerer automatisk brugeren, når der sendes API og WebDAV anmodninger med en Bearer token. Auto provisionering og Bearer token kontrol skal aktiveres for at dette virker.", "Send ID token hint on logout" : "Send ID token hint om log af", "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider." : "Skal ID token inkluderes som id_token_hint GET-parameteren i OpenID logud URL? Brugere omdirigeres til denne URL når de logger ud. Aktivering af denne indstilling eksponerer OIDC ID token til bruger-agenten, som måske ikke er nødvendig afhængigt af OIDC udbyder.", + "Enrich login ID token with userinfo" : "Berig login-id-tokenet med userinfo", + "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled." : "Hent yderligere oplysninger, som ikke findes i login-id-tokenet, fra userinfo-endpointet. Indstillingen overskrives, hvis den globale indstilling enrich_login_id_token_with_userinfo er slået til.", "Only groups matching the whitelist regex will be created, updated and deleted by the group claim. For example: {regex} allows all groups which ID starts with {substr}" : "Kun grupper der matcher hvidlistningens regex vil blive oprettet, opdateret og slettet af gruppe krav. For eksempel: {regex} tillader alle grupper hvis ID starter med {substr}", "This will create and update the users groups depending on the groups claim in the ID token. The Format of the groups claim value should be {sample1}, {sample2} or {sample3}" : "Dette vil oprette og opdatere brugernes grupper afhængigt af gruppernes krav i ID token. Formatet for gruppernes værdi skal være {sample1}, {sample2} eller {sample3}", "Back to %s" : "Tilbage til %s", From 84aa807a178b18b78b6d9825c10c84fc96b80741 Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Tue, 6 Oct 2026 02:46:34 +0000 Subject: [PATCH 18/20] fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- l10n/sk.js | 2 +- l10n/sk.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/l10n/sk.js b/l10n/sk.js index 087bb4db..f237043f 100644 --- a/l10n/sk.js +++ b/l10n/sk.js @@ -38,7 +38,7 @@ OC.L10N.register( "Could not update the provider:" : "Poskytovateľa sa nepodarilo aktualizovať:", "Could not remove provider: {msg}" : "Nepodarilo sa odstrániť poskytovateľa: {msg}", "Could not register provider:" : "Nepodarilo sa zaregistrovať poskytovateľa:", - "Allows users to authenticate via OpenID Connect providers." : "Povoliť užívateľom autentifikáciu cez OpenID Connect poskytovateľov.", + "Allows users to authenticate via OpenID Connect providers." : "Povoliť používateľom autentifikáciu cez OpenID Connect poskytovateľov.", "Enable ID4me" : "Povoliť ID4me", "Store login tokens" : "Uložiť prihlasovacie tokeny", "\"Store login tokens\" is needed if you are using other apps that want to use user_oidc's token exchange or simply get the login token" : "Nastavenie \"Ukladať prihlasovacie tokeny\" je potrebné, ak používate iné aplikácie, ktoré chcú používať výmenu tokenov aplikácie user_oidc alebo jednoducho získať prihlasovací token", diff --git a/l10n/sk.json b/l10n/sk.json index eb1e8b2e..951cfbed 100644 --- a/l10n/sk.json +++ b/l10n/sk.json @@ -36,7 +36,7 @@ "Could not update the provider:" : "Poskytovateľa sa nepodarilo aktualizovať:", "Could not remove provider: {msg}" : "Nepodarilo sa odstrániť poskytovateľa: {msg}", "Could not register provider:" : "Nepodarilo sa zaregistrovať poskytovateľa:", - "Allows users to authenticate via OpenID Connect providers." : "Povoliť užívateľom autentifikáciu cez OpenID Connect poskytovateľov.", + "Allows users to authenticate via OpenID Connect providers." : "Povoliť používateľom autentifikáciu cez OpenID Connect poskytovateľov.", "Enable ID4me" : "Povoliť ID4me", "Store login tokens" : "Uložiť prihlasovacie tokeny", "\"Store login tokens\" is needed if you are using other apps that want to use user_oidc's token exchange or simply get the login token" : "Nastavenie \"Ukladať prihlasovacie tokeny\" je potrebné, ak používate iné aplikácie, ktoré chcú používať výmenu tokenov aplikácie user_oidc alebo jednoducho získať prihlasovací token", From 6b398760b1a294ce8cbb95a408b227004a94638d Mon Sep 17 00:00:00 2001 From: Nextcloud bot Date: Thu, 8 Oct 2026 02:52:10 +0000 Subject: [PATCH 19/20] fix(l10n): Update translations from Transifex Signed-off-by: Nextcloud bot --- l10n/da.js | 14 +++++++------- l10n/da.json | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/l10n/da.js b/l10n/da.js index 051fac7d..5c28e166 100644 --- a/l10n/da.js +++ b/l10n/da.js @@ -1,7 +1,7 @@ OC.L10N.register( "user_oidc", { - "Login with %1s" : "Log på med %1s", + "Login with %1s" : "Log ind med %1s", "Error" : "Fejl", "Access forbidden" : "Adgang forbudt", "ID4Me is disabled" : "ID4Me er deaktiveret", @@ -26,12 +26,12 @@ OC.L10N.register( "Failed to contact the OIDC provider token endpoint" : "Kunne ikke kontakte OIDC leverandør token slutpunktet", "The issuer does not match the one from the discovery endpoint" : "Udstederen matcher ikke den fra opdagelses slutpunktet", "Failed to provision the user" : "Kunne ikke provisionere brugeren", - "You do not have permission to log in to this instance. If you think this is an error, please contact an administrator." : "Du har ikke tilladelse til at logge på denne instans. Hvis du mener at det er en fejl, så kontakt venligst en administrator.", + "You do not have permission to log in to this instance. If you think this is an error, please contact an administrator." : "Du har ikke tilladelse til at logge ind på denne instans. Hvis du mener, at det er en fejl, så kontakt en administrator.", "User conflict" : "Brugerkonfliktconflict", "OpenID Connect" : "OpenID Connect", "OpenID Connect user backend" : "OpenID Connect bruger backend", - "Use an OpenID Connect backend to login to your Nextcloud" : "Anvend en OpenID Connect backend for at logge på din Nextcloud", - "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC server som Nextcloud log på bruger backend.", + "Use an OpenID Connect backend to login to your Nextcloud" : "Brug en OpenID Connect-backend til at logge ind på din Nextcloud", + "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC-server som login-backend for brugere i Nextcloud.", "Are you sure you want to delete the provider \"{providerName}\"?" : "Er du sikker på, at du vil slette udbyderen \"{providerName}\"?", "Could not save ID4me state: {msg}" : "Kunne ikke gemme ID4me tilstand: {msg}", "Could not save storeLoginToken state: {msg}" : "Kunne ikke gemme storeLoginToken tilstand: {msg}", @@ -49,7 +49,7 @@ OC.L10N.register( "No providers registered." : "Ingen udbydere registeret.", "Client ID" : "Klient ID", "Discovery endpoint" : "Discovery endpoint", - "Backchannel Logout URL" : "Backchannel log af URL", + "Backchannel Logout URL" : "Backchannel Logout-URL", "Redirect URI (to be authorized in the provider client configuration)" : "Omdirigér URI (for godkendelse i udbyderens klient konfiguration)", "Update" : "Opdatér", "Remove" : "Fjern", @@ -105,12 +105,12 @@ OC.L10N.register( "Use group provisioning." : "Brug gruppeprovisionering", "Group whitelist regex" : "Gruppe hvidlistet regex", "Restrict login for users that are not in any whitelisted group" : "Begræns login for brugere, der ikke er i nogen hvidlistet gruppe", - "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er en del af nogen hvidlistet gruppe bliver ikke oprettet og kan ikke logge på", + "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er med i en gruppe på tilladelseslisten, bliver ikke oprettet og kan ikke logge ind", "Check Bearer token on API and WebDAV requests" : "Tjek Bearer token på API og WebDAV anmodninger", "Do you want to allow API calls and WebDAV requests that are authenticated with an OIDC ID token or access token?" : "Vil du tillade API-kald og WebDAV-anmodninger, der er godkendt med et OIDC-id-token eller et adgangstoken?", "Auto provision user when accessing API and WebDAV with Bearer token" : "Automatisk provisionering af bruger når API og WebDAV tilgås med Bearer token", "This automatically provisions the user, when sending API and WebDAV requests with a Bearer token. Auto provisioning and Bearer token check have to be activated for this to work." : "Dette provisionerer automatisk brugeren, når der sendes API og WebDAV anmodninger med en Bearer token. Auto provisionering og Bearer token kontrol skal aktiveres for at dette virker.", - "Send ID token hint on logout" : "Send ID token hint om log af", + "Send ID token hint on logout" : "Send ID-token-hint ved logout", "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider." : "Skal ID token inkluderes som id_token_hint GET-parameteren i OpenID logud URL? Brugere omdirigeres til denne URL når de logger ud. Aktivering af denne indstilling eksponerer OIDC ID token til bruger-agenten, som måske ikke er nødvendig afhængigt af OIDC udbyder.", "Enrich login ID token with userinfo" : "Berig login-id-tokenet med userinfo", "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled." : "Hent yderligere oplysninger, som ikke findes i login-id-tokenet, fra userinfo-endpointet. Indstillingen overskrives, hvis den globale indstilling enrich_login_id_token_with_userinfo er slået til.", diff --git a/l10n/da.json b/l10n/da.json index 7ba25c3c..4255df88 100644 --- a/l10n/da.json +++ b/l10n/da.json @@ -1,5 +1,5 @@ { "translations": { - "Login with %1s" : "Log på med %1s", + "Login with %1s" : "Log ind med %1s", "Error" : "Fejl", "Access forbidden" : "Adgang forbudt", "ID4Me is disabled" : "ID4Me er deaktiveret", @@ -24,12 +24,12 @@ "Failed to contact the OIDC provider token endpoint" : "Kunne ikke kontakte OIDC leverandør token slutpunktet", "The issuer does not match the one from the discovery endpoint" : "Udstederen matcher ikke den fra opdagelses slutpunktet", "Failed to provision the user" : "Kunne ikke provisionere brugeren", - "You do not have permission to log in to this instance. If you think this is an error, please contact an administrator." : "Du har ikke tilladelse til at logge på denne instans. Hvis du mener at det er en fejl, så kontakt venligst en administrator.", + "You do not have permission to log in to this instance. If you think this is an error, please contact an administrator." : "Du har ikke tilladelse til at logge ind på denne instans. Hvis du mener, at det er en fejl, så kontakt en administrator.", "User conflict" : "Brugerkonfliktconflict", "OpenID Connect" : "OpenID Connect", "OpenID Connect user backend" : "OpenID Connect bruger backend", - "Use an OpenID Connect backend to login to your Nextcloud" : "Anvend en OpenID Connect backend for at logge på din Nextcloud", - "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC server som Nextcloud log på bruger backend.", + "Use an OpenID Connect backend to login to your Nextcloud" : "Brug en OpenID Connect-backend til at logge ind på din Nextcloud", + "Allows flexible configuration of an OIDC server as Nextcloud login user backend." : "Giver mulighed for fleksibel konfiguration af en OIDC-server som login-backend for brugere i Nextcloud.", "Are you sure you want to delete the provider \"{providerName}\"?" : "Er du sikker på, at du vil slette udbyderen \"{providerName}\"?", "Could not save ID4me state: {msg}" : "Kunne ikke gemme ID4me tilstand: {msg}", "Could not save storeLoginToken state: {msg}" : "Kunne ikke gemme storeLoginToken tilstand: {msg}", @@ -47,7 +47,7 @@ "No providers registered." : "Ingen udbydere registeret.", "Client ID" : "Klient ID", "Discovery endpoint" : "Discovery endpoint", - "Backchannel Logout URL" : "Backchannel log af URL", + "Backchannel Logout URL" : "Backchannel Logout-URL", "Redirect URI (to be authorized in the provider client configuration)" : "Omdirigér URI (for godkendelse i udbyderens klient konfiguration)", "Update" : "Opdatér", "Remove" : "Fjern", @@ -103,12 +103,12 @@ "Use group provisioning." : "Brug gruppeprovisionering", "Group whitelist regex" : "Gruppe hvidlistet regex", "Restrict login for users that are not in any whitelisted group" : "Begræns login for brugere, der ikke er i nogen hvidlistet gruppe", - "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er en del af nogen hvidlistet gruppe bliver ikke oprettet og kan ikke logge på", + "Users that are not part of any whitelisted group are not created and can not login" : "Brugere, der ikke er med i en gruppe på tilladelseslisten, bliver ikke oprettet og kan ikke logge ind", "Check Bearer token on API and WebDAV requests" : "Tjek Bearer token på API og WebDAV anmodninger", "Do you want to allow API calls and WebDAV requests that are authenticated with an OIDC ID token or access token?" : "Vil du tillade API-kald og WebDAV-anmodninger, der er godkendt med et OIDC-id-token eller et adgangstoken?", "Auto provision user when accessing API and WebDAV with Bearer token" : "Automatisk provisionering af bruger når API og WebDAV tilgås med Bearer token", "This automatically provisions the user, when sending API and WebDAV requests with a Bearer token. Auto provisioning and Bearer token check have to be activated for this to work." : "Dette provisionerer automatisk brugeren, når der sendes API og WebDAV anmodninger med en Bearer token. Auto provisionering og Bearer token kontrol skal aktiveres for at dette virker.", - "Send ID token hint on logout" : "Send ID token hint om log af", + "Send ID token hint on logout" : "Send ID-token-hint ved logout", "Should the ID token be included as the id_token_hint GET parameter in the OpenID logout URL? Users are redirected to this URL after logging out of Nextcloud. Enabling this setting exposes the OIDC ID token to the user agent, which may not be necessary depending on the OIDC provider." : "Skal ID token inkluderes som id_token_hint GET-parameteren i OpenID logud URL? Brugere omdirigeres til denne URL når de logger ud. Aktivering af denne indstilling eksponerer OIDC ID token til bruger-agenten, som måske ikke er nødvendig afhængigt af OIDC udbyder.", "Enrich login ID token with userinfo" : "Berig login-id-tokenet med userinfo", "Fetch additional information not found in the login ID token from the userinfo endpoint. This setting is overwritten if the global enrich_login_id_token_with_userinfo option is enabled." : "Hent yderligere oplysninger, som ikke findes i login-id-tokenet, fra userinfo-endpointet. Indstillingen overskrives, hvis den globale indstilling enrich_login_id_token_with_userinfo er slået til.", From bd46bf75f0ca3f7b04e9f0b495d95e01d106ac06 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Thu, 17 Sep 2026 09:32:57 +0200 Subject: [PATCH 20/20] fix(backend): match the bearer auth-scheme case-insensitively getCurrentUserId() guarded the Authorization header with two case-sensitive str_starts_with() checks for 'bearer ' and 'Bearer ', while the very next statement stripped the scheme with the case-insensitive '/^bearer\s+/i'. The guard was therefore strictly narrower than the code it protects: any other spelling of the scheme was turned away before a token validator ever ran, and so was a horizontal tab between the scheme and the credentials, even though the strip would have handled both. Since getCurrentUserId() is the IApacheBackend entry point, this applies to every API and WebDAV request from an affected client, and it fails closed with only a debug level 'No Bearer token' line to go on. RFC 9110 section 11.1 defines auth-scheme as a case-insensitive token and separates it from the credentials by one or more spaces or horizontal tabs, so the guard now reuses the very pattern of the strip that follows it. Nothing new is accepted: a missing header, a different scheme, a missing separator and empty credentials all still resolve to no user, which the added regression tests pin down. isSessionActive() is deliberately left alone: it only checks that the Authorization header is non-empty and does no scheme matching, so it is unaffected. Co-authored-by: Git'Fellow <12234510+solracsf@users.noreply.github.com> Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Misha M.-Kupriyanov --- lib/User/Backend.php | 5 +- tests/unit/User/BackendTest.php | 120 +++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/lib/User/Backend.php b/lib/User/Backend.php index 967ff0cf..ebdc3e9f 100644 --- a/lib/User/Backend.php +++ b/lib/User/Backend.php @@ -254,8 +254,11 @@ public function getCurrentUserId(): string { } // get the bearer token from headers + // the auth-scheme is case-insensitive and is separated from the credentials + // by one or more spaces or horizontal tabs (RFC 9110, section 11.1), so this + // guard has to accept exactly what the strip below removes $headerToken = $this->request->getHeader(Application::OIDC_API_REQ_HEADER); - if (!str_starts_with($headerToken, 'bearer ') && !str_starts_with($headerToken, 'Bearer ')) { + if (preg_match('/^bearer\s+/i', $headerToken) !== 1) { $this->logger->debug('No Bearer token'); return ''; } diff --git a/tests/unit/User/BackendTest.php b/tests/unit/User/BackendTest.php index 8045da60..806af8b4 100644 --- a/tests/unit/User/BackendTest.php +++ b/tests/unit/User/BackendTest.php @@ -27,6 +27,7 @@ use OCP\IUserManager; use OCP\IUserSession; use OCP\Server; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; @@ -60,6 +61,7 @@ class BackendTest extends \Test\TestCase { private const TOKEN_USER_ID = 'oidc-token-user'; private const PROVIDER_ID = 1; + private const BEARER_CREDENTIALS = 'a-valid-token'; private IConfig&MockObject $config; private UserMapper&MockObject $userMapper; @@ -120,11 +122,7 @@ protected function setUp(): void { */ public function testBearerAuthWithAutoProvisioningDoesNotLogTheUserIn(): void { $this->givenAValidBearerToken(); - - $user = $this->givenAUserThatHasLoggedInBefore(self::TOKEN_USER_ID); - $this->userManager->method('userExists')->with(self::TOKEN_USER_ID)->willReturn(true); - $this->userManager->method('get')->with(self::TOKEN_USER_ID)->willReturn($user); - $this->ldapService->method('isLdapDeletedUser')->with($user)->willReturn(false); + $this->givenTheTokenUserExists(); $this->assertResolvesUserWithoutLoggingIn(self::TOKEN_USER_ID); } @@ -159,16 +157,87 @@ public function testBearerAuthForUserOfAnotherBackendDoesNotLogTheUserIn(): void } /** - * Wires up a request carrying a bearer token that the self encoded validator - * accepts for a provider with bearer checking turned on. + * RFC 9110, section 11.1 (and RFC 7235, section 2.1 before it): the auth-scheme + * of an Authorization header is case-insensitive, and it is separated from the + * credentials by one or more spaces or horizontal tabs. The guard in + * getCurrentUserId() used to accept only the exact spellings 'bearer ' and + * 'Bearer ', so a client sending 'BEARER ' was turned away before any + * token validator ran, even though the strip right after it was already + * case-insensitive. + * + * @see https://github.com/nextcloud/user_oidc/pull/1386 + */ + #[DataProvider('acceptedAuthorizationHeaderProvider')] + public function testBearerSchemeIsRecognisedRegardlessOfSpellingAndSeparator(string $authorizationHeader): void { + $this->givenAValidBearerToken(authorizationHeader: $authorizationHeader); + $this->givenTheTokenUserExists(); + + $this->assertResolvesUserWithoutLoggingIn(self::TOKEN_USER_ID); + } + + /** + * Accepting every spelling of the scheme must not make the guard accept anything + * that is not a bearer token: none of these may reach a token validator. + */ + #[DataProvider('rejectedAuthorizationHeaderProvider')] + public function testNonBearerAuthorizationHeaderIsNotValidated(string $authorizationHeader): void { + $this->givenARequestWithAuthorizationHeader($authorizationHeader); + + $validator = $this->createMock(SelfEncodedValidator::class); + $validator->expects($this->never())->method('isValidBearerToken'); + $this->overwriteService(SelfEncodedValidator::class, $validator); + + $this->assertSame('', $this->backend->getCurrentUserId()); + } + + /** + * @return array + */ + public static function acceptedAuthorizationHeaderProvider(): array { + return [ + 'canonical spelling' => ['Bearer ' . self::BEARER_CREDENTIALS], + 'all lower case' => ['bearer ' . self::BEARER_CREDENTIALS], + 'all upper case' => ['BEARER ' . self::BEARER_CREDENTIALS], + 'mixed case' => ['BeArEr ' . self::BEARER_CREDENTIALS], + 'several spaces' => ['Bearer ' . self::BEARER_CREDENTIALS], + 'horizontal tab' => ["Bearer\t" . self::BEARER_CREDENTIALS], + 'tab and space' => ["Bearer \t " . self::BEARER_CREDENTIALS], + ]; + } + + /** + * @return array + */ + public static function rejectedAuthorizationHeaderProvider(): array { + return [ + 'no header at all' => [''], + 'another scheme' => ['Basic dXNlcjpwYXNzd29yZA=='], + // the scheme and the credentials need a separator between them + 'no separator' => ['Bearertoken'], + 'scheme only' => ['Bearer'], + // these do pass the scheme guard and are caught by the empty credentials + // check right after the strip + 'empty credentials' => ['Bearer '], + 'empty credentials, upper case' => ['BEARER '], + 'whitespace only credentials' => ["Bearer \t "], + // the scheme has to come first + 'leading whitespace' => [' Bearer ' . self::BEARER_CREDENTIALS], + 'scheme in the middle' => ['X Bearer ' . self::BEARER_CREDENTIALS], + ]; + } + + /** + * Wires up a request carrying $authorizationHeader for a provider with bearer + * checking turned on. No token validator is registered: callers decide whether + * the credentials are expected to reach one. * * @param array $systemConfig the 'user_oidc' system config */ - private function givenAValidBearerToken(array $systemConfig = []): void { + private function givenARequestWithAuthorizationHeader(string $authorizationHeader, array $systemConfig = []): void { $this->config->method('getSystemValue')->with('user_oidc', [])->willReturn($systemConfig); $this->request->method('getHeader') ->with(Application::OIDC_API_REQ_HEADER) - ->willReturn('Bearer a-valid-token'); + ->willReturn($authorizationHeader); $provider = new Provider(); $provider->setId(self::PROVIDER_ID); @@ -183,12 +252,43 @@ private function givenAValidBearerToken(array $systemConfig = []): void { $this->discoveryService->method('obtainDiscovery')->willReturn([]); $this->timeFactory->method('getTime')->willReturn(1700000000); + } + + /** + * Wires up a request carrying a bearer token that the self encoded validator + * accepts for a provider with bearer checking turned on. + * + * @param array $systemConfig the 'user_oidc' system config + */ + private function givenAValidBearerToken( + array $systemConfig = [], + string $authorizationHeader = 'Bearer ' . self::BEARER_CREDENTIALS, + ): void { + $this->givenARequestWithAuthorizationHeader($authorizationHeader, $systemConfig); $validator = $this->createMock(SelfEncodedValidator::class); - $validator->method('isValidBearerToken')->willReturn(self::TOKEN_USER_ID); + // the validator only accepts the credentials, so a guard or a strip that + // mangles the auth-scheme cannot pass this by returning the uid regardless + $validator->method('isValidBearerToken')->willReturnCallback( + static fn (Provider $provider, string $bearerToken): ?string + => $bearerToken === self::BEARER_CREDENTIALS ? self::TOKEN_USER_ID : null + ); $this->overwriteService(SelfEncodedValidator::class, $validator); } + /** + * The token user already exists, so auto-provisioning reuses it instead of + * creating it. + */ + private function givenTheTokenUserExists(): IUser&MockObject { + $user = $this->givenAUserThatHasLoggedInBefore(self::TOKEN_USER_ID); + $this->userManager->method('userExists')->with(self::TOKEN_USER_ID)->willReturn(true); + $this->userManager->method('get')->with(self::TOKEN_USER_ID)->willReturn($user); + $this->ldapService->method('isLdapDeletedUser')->with($user)->willReturn(false); + + return $user; + } + private function givenAUserThatHasLoggedInBefore(string $uid): IUser&MockObject { $user = $this->createMock(IUser::class); $user->method('getUID')->willReturn($uid);