From 3c10a578328c1d840aa34c32884662c697854179 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 4 Sep 2024 21:24:22 +0000 Subject: [PATCH 01/29] Version bump --- box.json | 2 +- changelog.md | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 49b62dc..5d2b1d3 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.0.0", + "version":"1.1.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 1d14dc8..70c294d 100644 --- a/changelog.md +++ b/changelog.md @@ -9,10 +9,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.2] - 2024-09-04 + +## [1.0.1] - 2024-09-04 + ## [1.0.0] - 2024-09-04 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.0...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.2...HEAD + +[1.0.2]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.1...v1.0.2 + +[1.0.1]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/coldbox-modules/cbSSO/compare/ea53937f976749c7a0057038dc6174671e838579...v1.0.0 From 4b3c2e4ce2f2d1a17cda39fc8cfed25ffd88691e Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 4 Sep 2024 22:01:20 +0000 Subject: [PATCH 02/29] Version bump --- box.json | 2 +- changelog.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 5d2b1d3..85e3fd1 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.1.0", + "version":"1.2.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 70c294d..321546b 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.3] - 2024-09-04 + ## [1.0.2] - 2024-09-04 ## [1.0.1] - 2024-09-04 @@ -17,7 +19,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.2...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.3...HEAD + +[1.0.3]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.2...v1.0.3 [1.0.2]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.1...v1.0.2 From cfdcc0aa701f526ad7f86f64317762af79b9b840 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 4 Sep 2024 22:08:31 +0000 Subject: [PATCH 03/29] Version bump --- box.json | 2 +- changelog.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 85e3fd1..701ae17 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.2.0", + "version":"1.3.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 321546b..73aac91 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.4] - 2024-09-04 + ## [1.0.3] - 2024-09-04 ## [1.0.2] - 2024-09-04 @@ -19,7 +21,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.3...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.4...HEAD + +[1.0.4]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.3...v1.0.4 [1.0.3]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.2...v1.0.3 From a94d31b1a965298050ebfefee4be75f1d0784f74 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 4 Sep 2024 22:14:28 +0000 Subject: [PATCH 04/29] Version bump --- box.json | 2 +- changelog.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 701ae17..4d3c460 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.3.0", + "version":"1.4.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 73aac91..83584c3 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.5] - 2024-09-04 + ## [1.0.4] - 2024-09-04 ## [1.0.3] - 2024-09-04 @@ -21,7 +23,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.4...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.5...HEAD + +[1.0.5]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.4...v1.0.5 [1.0.4]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.3...v1.0.4 From fbc40ebd323fe1ff6a2d07784ee644a25385f114 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Wed, 4 Sep 2024 22:19:39 +0000 Subject: [PATCH 05/29] Version bump --- box.json | 2 +- changelog.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 4d3c460..faeb4f3 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.4.0", + "version":"1.5.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 83584c3..bda20bf 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.6] - 2024-09-04 + ## [1.0.5] - 2024-09-04 ## [1.0.4] - 2024-09-04 @@ -23,7 +25,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.5...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.6...HEAD + +[1.0.6]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.5...v1.0.6 [1.0.5]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.4...v1.0.5 From d9cd4c0749803286dec5104c463d8a3e4029816f Mon Sep 17 00:00:00 2001 From: Github Actions Date: Thu, 5 Sep 2024 03:03:28 +0000 Subject: [PATCH 06/29] Version bump --- box.json | 2 +- changelog.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index faeb4f3..93d2561 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.5.0", + "version":"1.6.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index bda20bf..f72f854 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.7] - 2024-09-05 + ## [1.0.6] - 2024-09-04 ## [1.0.5] - 2024-09-04 @@ -25,7 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for several SSO IP integrations -[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.6...HEAD +[Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.7...HEAD + +[1.0.7]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.6...v1.0.7 [1.0.6]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.5...v1.0.6 From 8065d5f630e32ef46562b43ab5ffe26047b8d3ef Mon Sep 17 00:00:00 2001 From: Github Actions Date: Thu, 12 Sep 2024 16:45:44 +0000 Subject: [PATCH 07/29] Version bump --- box.json | 2 +- changelog.md | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/box.json b/box.json index 93d2561..208031c 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.6.0", + "version":"1.7.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index f72f854..3b060c9 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.7] - 2024-09-12 + ## [1.0.7] - 2024-09-05 ## [1.0.6] - 2024-09-04 @@ -29,7 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.7...HEAD -[1.0.7]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.6...v1.0.7 +[1.0.7]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.7...v1.0.7 + [1.0.6]: https://github.com/coldbox-modules/cbSSO/compare/v1.0.5...v1.0.6 From 6e65a2634214e70b128ffe590f1a64aec7183a29 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Fri, 6 Dec 2024 18:56:21 +0000 Subject: [PATCH 08/29] Version bump --- box.json | 2 +- changelog.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/box.json b/box.json index 208031c..2edba7d 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.7.0", + "version":"1.8.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", diff --git a/changelog.md b/changelog.md index 3b060c9..5fcc358 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.7] - 2024-12-06 + ## [1.0.7] - 2024-09-12 ## [1.0.7] - 2024-09-05 From 12cdca36d39ef8a17fca24052051217d8e31bd81 Mon Sep 17 00:00:00 2001 From: John Whish Date: Fri, 18 Jul 2025 08:17:38 +0100 Subject: [PATCH 09/29] Remove erroneous character Unexpected character at the end of the file which appears to be a typo. This commit does not change functionality, it is a clean up. --- tasks/Build.cfc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/Build.cfc b/tasks/Build.cfc index 55bb5e1..971ceab 100644 --- a/tasks/Build.cfc +++ b/tasks/Build.cfc @@ -247,4 +247,4 @@ component { variables.exportsDir = variables.artifactsDir & "/#projectName#/#arguments.version#"; directoryCreate( variables.exportsDir, true, true ); } -}e \ No newline at end of file +} From c350c7b60b6ee1ad3eda99d730ce6508792d7052 Mon Sep 17 00:00:00 2001 From: Oscar Tisnado Date: Thu, 6 Nov 2025 16:02:32 -0600 Subject: [PATCH 10/29] Add support for boxlang@1 in test matrix and create server configuration --- .github/workflows/tests.yml | 5 ++++- server-boxlang@1.json | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 server-boxlang@1.json diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 78bb88c..3211a4f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - cfengine: [ "lucee@5" ] + cfengine: [ "lucee@5", "boxlang@1" ] coldboxVersion: [ "^6.0.0", "^7.0.0" ] experimental: [ false ] # Here we tests all engines against ColdBox@BE @@ -26,6 +26,9 @@ jobs: - coldboxVersion: "be" cfengine: "lucee@5" experimental: true + - coldboxVersion: "be" + cfengine: "boxlang@1" + experimental: true steps: - name: Checkout Repository uses: actions/checkout@v3 diff --git a/server-boxlang@1.json b/server-boxlang@1.json new file mode 100644 index 0000000..6ea7677 --- /dev/null +++ b/server-boxlang@1.json @@ -0,0 +1,34 @@ +{ + "name":"cbstorages-boxlang@1", + "app":{ + "serverHomeDirectory":".engine/boxlang", + "cfengine":"boxlang@1" + }, + "web":{ + "http":{ + "port":"60299" + }, + "rewrites":{ + "enable": true + }, + "webroot": "test-harness", + "aliases":{ + "/moduleroot/cbSSO":"../" + } + }, + "JVM":{ + "heapSize":"768", + "javaVersion":"openjdk21_jre", + "args":"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888" + }, + "openBrowser":"false", + "cfconfig":{ + "file":".cfconfig.json" + }, + "env":{ + "BOXLANG_DEBUG":true + }, + "scripts":{ + "onServerInitialInstall":"install bx-esapi,bx-compat-cfml --noSave" + } +} \ No newline at end of file From 6842bfb68b24d1a7e427149659457fb8acf1caf9 Mon Sep 17 00:00:00 2001 From: Oscar Tisnado Date: Thu, 6 Nov 2025 16:13:40 -0600 Subject: [PATCH 11/29] Upgrade workflow environments to Ubuntu 22.04 across all YAML files --- .github/workflows/pr.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/snapshot.yml | 2 +- .github/workflows/tests.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index d78c2d7..3157c1a 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -19,7 +19,7 @@ jobs: formatCheck: name: Checks Source Code Formatting - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout Repository uses: actions/checkout@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bab4a3d..33cbed5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: ########################################################################################## build: name: Build & Publish - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -128,7 +128,7 @@ jobs: prep_next_release: name: Prep Next Release if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: [ build ] steps: # Checkout development diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index d2c7113..590979f 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -18,7 +18,7 @@ jobs: ########################################################################################## format: name: Code Auto-Formatting - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3211a4f..de11e9f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,7 @@ on: jobs: tests: name: Tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 env: DB_USER: root DB_PASSWORD: root From 32ea70d22e8805bfdbe454990bea67ce633647d3 Mon Sep 17 00:00:00 2001 From: Oscar Tisnado Date: Thu, 6 Nov 2025 16:25:00 -0600 Subject: [PATCH 12/29] Upgrade actions/upload-artifact to version 4 in test workflow --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index de11e9f..52fc7f7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -108,7 +108,7 @@ jobs: - name: Upload Test Results to Artifacts if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-results-${{ matrix.cfengine }}-${{ matrix.coldboxVersion }} path: | @@ -121,7 +121,7 @@ jobs: - name: Upload Debug Logs To Artifacts if: ${{ failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Failure Debugging Info - ${{ matrix.cfengine }} - ${{ matrix.coldboxVersion }} path: | From fc7381714f63948ba370e99d247a78e58f360cf2 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:20:23 -0600 Subject: [PATCH 13/29] Improve BoxLang compatibility --- .bxlint.json | 3 + .vscode/settings.json | 3 +- interceptors/cbAuth.cfc | 4 + java/cbsso-opensaml/app/build.gradle | 3 + models/BaseProvider.cfc | 177 ------- models/BaseUser.cfc | 24 - models/providers/BaseProvider.cfc | 15 + models/providers/FacebookProvider.cfc | 18 +- models/providers/GitHubProvider.cfc | 18 +- models/providers/GoogleProvider.cfc | 18 +- models/providers/MicrosoftSAMLProvider.cfc | 43 +- models/testing/BaseProviderSpec.cfc | 44 -- models/utility/SAMLParsingService.cfc | 100 ++++ server-boxlang.json | 30 ++ server-lucee@5.json | 6 +- test-harness/config/Coldbox.cfc | 23 +- test-harness/models/UserService.cfc | 3 - test-harness/test.bxm | 18 + test-harness/test.xml | 86 ++++ test-harness/tests/resources/coolblog.sql | 473 ------------------ .../tests/resources/errorSAMLResponse.xml | 87 ++++ .../tests/resources/validSAMLResponse.xml | 86 ++++ .../tests/specs/ProviderServiceSpec.cfc | 43 -- .../tests/specs/SAMLParsingServiceTest.cfc | 68 +++ .../specs/providers/GoogleProviderSpec.cfc | 57 --- 25 files changed, 554 insertions(+), 896 deletions(-) create mode 100644 .bxlint.json delete mode 100644 models/BaseProvider.cfc delete mode 100644 models/BaseUser.cfc create mode 100644 models/providers/BaseProvider.cfc delete mode 100644 models/testing/BaseProviderSpec.cfc create mode 100644 models/utility/SAMLParsingService.cfc create mode 100644 server-boxlang.json create mode 100644 test-harness/test.bxm create mode 100644 test-harness/test.xml delete mode 100644 test-harness/tests/resources/coolblog.sql create mode 100644 test-harness/tests/resources/errorSAMLResponse.xml create mode 100644 test-harness/tests/resources/validSAMLResponse.xml create mode 100644 test-harness/tests/specs/SAMLParsingServiceTest.cfc delete mode 100644 test-harness/tests/specs/providers/GoogleProviderSpec.cfc diff --git a/.bxlint.json b/.bxlint.json new file mode 100644 index 0000000..4fdf576 --- /dev/null +++ b/.bxlint.json @@ -0,0 +1,3 @@ +{ + "exclude": [ "ModuleConfig.cfc" ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 2506a17..8b196e3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,6 @@ "directoryPath": "./test-harness/testbox", "isPhysicalDirectoryPath": false } - ] + ], + "java.configuration.updateBuildConfiguration": "interactive" } diff --git a/interceptors/cbAuth.cfc b/interceptors/cbAuth.cfc index 819f52e..f2562e5 100644 --- a/interceptors/cbAuth.cfc +++ b/interceptors/cbAuth.cfc @@ -6,6 +6,10 @@ component { var authService = getInstance( "authenticationService@cbauth" ); var userService = authService.getUserService(); + if( !data.ssoAuthorizationEvent.wasSuccessful() ){ + relocate( moduleSettings.errorRedirect ); + } + var user = userService.findBySSO( data.ssoAuthorizationEvent, data.provider ); if( isNull( user ) ){ diff --git a/java/cbsso-opensaml/app/build.gradle b/java/cbsso-opensaml/app/build.gradle index 4e86f97..f95afdb 100644 --- a/java/cbsso-opensaml/app/build.gradle +++ b/java/cbsso-opensaml/app/build.gradle @@ -60,6 +60,9 @@ jar { shadowJar { archiveBaseName = "cbsso-opensaml" mergeServiceFiles() + dependencies { + exclude(dependency('org.apache.commons:commons-lang3')) + } minimize{ exclude( dependency( "org.opensaml:opensaml-core:.*" ) ) exclude( dependency( "org.slf4j:.*:.*" ) ) diff --git a/models/BaseProvider.cfc b/models/BaseProvider.cfc deleted file mode 100644 index 86e2ab8..0000000 --- a/models/BaseProvider.cfc +++ /dev/null @@ -1,177 +0,0 @@ -/** - * - * The base model to set up an oauth provider - * - * */ -component accessors="true" { - - property name="hyper" inject="HyperBuilder@hyper"; - - property name="identifier" type="string"; - - property name="name" type="string"; - - /** - * Constructor - */ - function init(){ - variables.identifier = createUUID(); - variables.name = ""; - return this; - } - - public string function getProviderName(){ - return variables.name; - } - - - /** - * getAuthUrl - */ - string function buildAuthUrl( struct params = {}, boolean state = false ){ - var queryString = structToQueryString( - params.isEmpty() ? getCodeRequestParams( arguments.state ) : arguments.params - ); - return variables.authEndpoint & "?" & queryString; - } - - - /** - * I make the HTTP request to obtain the access token. - * - * @code The code returned from the authentication request. - * @formfields An optional array of structs for the provider requirements to add new form fields. - * @headers An optional array of structs to add custom headers to the request if required. - **/ - public struct function makeAccessTokenRequest( - required string code, - array bodyFields = [], - array headers = [] - ){ - var hyper = hyper.new(); - var stuResponse = {}; - var requestHeaders = { "Content-Type" : "application/x-www-form-urlencoded" }; - - if ( arrayLen( arguments.headers ) ) { - for ( var item in arguments.headers ) { - requestHeaders.append( { "#item[ "name" ]#" : item[ "value" ] } ); - } - } - - var response = hyper - .setMethod( "POST" ) - .setUrl( variables.accessTokenEndpoint ) - .setHeaders( requestHeaders ) - .setBody( structToQueryString( getTokenRequestParams( arguments.code ) ) ) - .send(); - - if ( response.isSuccess() ) { - stuResponse.success = true; - stuResponse.content = response.getData(); - } else { - stuResponse.success = false; - stuResponse.content = response; - } - - return stuResponse; - } - - /** - * I make the HTTP request to refresh the access token. - * - * @refresh_token The refresh_token returned from the accessTokenRequest request. - **/ - public struct function refreshAccessTokenRequest( - required string refresh_token, - array formfields = [], - array headers = [] - ){ - var hyper = hyper.new(); - var stuResponse = {}; - var requestHeaders = { "Content-Type" : "application/x-www-form-urlencoded" }; - - if ( arrayLen( arguments.headers ) ) { - for ( var item in arguments.headers ) { - requestHeaders.append( { "#item[ "name" ]#" : item[ "value" ] } ); - } - } - - var requestParams = { - client_id : variables.clientId, - client_secret : variables.clientSecret, - refresh_token : arguments.refresh_token, - grant_type : "refresh_token" - }; - - var response = hyper - .setMethod( "POST" ) - .setUrl( variables.accessTokenEndpoint ) - .withHeaders( requestHeaders ) - .setBody( requestParams ) - .asFormFields() - .send(); - - if ( response.isSuccess() ) { - stuResponse.success = true; - stuResponse.content = response.getData(); - } else { - stuResponse.success = false; - stuResponse.content = response.getStatusText(); - } - - return stuResponse; - } - - - /** - * getCodeParams - * - * Will return an struct of the needed params to create the auth url - */ - function getCodeRequestParams( string state = "" ){ - var params = { - "client_id" : variables.clientId, - "redirect_uri" : variables.redirectURI, - "response_type" : variables.responseType - }; - if ( !variables.stateless ) { - params[ "state" ] = arguments.state; - } - return params; - } - - function getTokenRequestParams( required String code ){ - return { - "code" : arguments.code, - "client_id" : variables.clientId, - "client_secret" : variables.clientSecret, - "redirect_uri" : variables.redirectURI, - "grant_type" : "authorization_code" - }; - } - - /** - * Create a query string from an struct - * - * @paramsStruct the struct I want to conver - */ - function structToQueryString( required struct args ){ - var queryStr = ""; - - if ( structCount( arguments.args ) ) { - var intCount = 1; - - for ( var key in arguments.args ) { - if ( listLen( queryStr ) && intCount > 1 ) { - queryStr &= "&"; - } - - queryStr &= lCase( key ) & "=" & encodeForURL( trim( arguments.args[ key ] ) ); - intCount++; - } - } - - return queryStr; - } - -} diff --git a/models/BaseUser.cfc b/models/BaseUser.cfc deleted file mode 100644 index 7e59d43..0000000 --- a/models/BaseUser.cfc +++ /dev/null @@ -1,24 +0,0 @@ -/** - * - * The base model to retrieve user information when user logs in - * - * */ -component accessors="true" { - - property name="subjet"; // The unique identifier for the user. - property name="username"; // The username. - property name="givenName"; // User's first name - property name="lastName"; // User's last name - property name="fullname"; // The user's fullname. - property name="email"; // The user's email address. - property name="emailVerified"; // If user is already verified on google, if so, there is no need to verify on app. - property name="avatar"; // The user's avatar image URL. - - /** - * Constructor - */ - function init(){ - return this; - } - -} diff --git a/models/providers/BaseProvider.cfc b/models/providers/BaseProvider.cfc new file mode 100644 index 0000000..30feb4e --- /dev/null +++ b/models/providers/BaseProvider.cfc @@ -0,0 +1,15 @@ +component { + public string function getRedirectUri( required any event ){ + if ( + structKeyExists( variables, "redirectURI" ) + && !isNull( variables.redirectURI ) + && len( variables.redirectURI ) + ) { + return variables.redirectURI; + } + + var event = requestService.getContext(); + + return "#event.getHTMLBaseURL()#cbsso/auth/#variables.name.lcase()#"; + } +} \ No newline at end of file diff --git a/models/providers/FacebookProvider.cfc b/models/providers/FacebookProvider.cfc index 94f94e5..ddc4cd1 100644 --- a/models/providers/FacebookProvider.cfc +++ b/models/providers/FacebookProvider.cfc @@ -1,4 +1,8 @@ -component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { +component + accessors="true" + extends="BaseProvider" + implements="cbsso.models.ISSOIntegrationProvider" +{ property name="Name"; property name="clientId"; @@ -23,21 +27,11 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { return variables.name; } - public string function getRedirectUri(){ - if ( !isNull( variables.redirectUri ) ) { - return variables.redirectUri; - } - - var protocol = cgi.HTTPS == "" ? "http://" : "https://"; - - return "#protocol##cgi.HTTP_HOST#/cbsso/auth/#variables.name.lcase()#"; - } - public string function startAuthenticationWorflow( required any event ){ return oAuthService.buildAuthUrl( authEndpoint = getAuthEndpoint(), client_id = getClientId(), - redirect_uri = getRedirectUri(), + redirect_uri = getRedirectUri( event ), response_type = "code", extraParams = { "scope" : getScope() } ); diff --git a/models/providers/GitHubProvider.cfc b/models/providers/GitHubProvider.cfc index 0c33eb8..3c38ea2 100644 --- a/models/providers/GitHubProvider.cfc +++ b/models/providers/GitHubProvider.cfc @@ -1,4 +1,8 @@ -component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { +component + accessors="true" + extends="BaseProvider" + implements="cbsso.models.ISSOIntegrationProvider" +{ property name="Name"; property name="clientId"; @@ -23,16 +27,6 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { return variables.name; } - public string function getRedirectUri(){ - if ( !isNull( variables.redirectUri ) ) { - return variables.redirectUri; - } - - var protocol = cgi.HTTPS == "" ? "http://" : "https://"; - - return "#protocol##cgi.HTTP_HOST#/cbsso/auth/#variables.name.lcase()#"; - } - public string function startAuthenticationWorflow( required any event ){ return oAuthService.buildAuthUrl( authEndpoint = getAuthEndpoint(), @@ -62,7 +56,7 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { var res = oAuthService.makeAccessTokenRequest( getClientId(), getClientSecret(), - getRedirectUri(), + getRedirectUri( event ), getAccessTokenEndpoint(), event.getValue( "code" ) ); diff --git a/models/providers/GoogleProvider.cfc b/models/providers/GoogleProvider.cfc index 39d1db0..bac49be 100644 --- a/models/providers/GoogleProvider.cfc +++ b/models/providers/GoogleProvider.cfc @@ -1,4 +1,8 @@ -component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { +component + accessors="true" + extends="BaseProvider" + implements="cbsso.models.ISSOIntegrationProvider" +{ property name="Name"; property name="clientId"; @@ -21,21 +25,11 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { return variables.name; } - public string function getRedirectUri(){ - if ( !isNull( variables.redirectUri ) ) { - return variables.redirectUri; - } - - var protocol = cgi.HTTPS == "" ? "http://" : "https://"; - - return "#protocol##cgi.HTTP_HOST#/cbsso/auth/#variables.name.lcase()#"; - } - public string function startAuthenticationWorflow( required any event ){ return oAuthService.buildAuthUrl( authEndpoint = getAuthEndpoint(), client_id = getClientId(), - redirect_uri = getRedirectUri(), + redirect_uri = getRedirectUri( event ), response_type = "code", extraParams = { "scope" : getScope() } ); diff --git a/models/providers/MicrosoftSAMLProvider.cfc b/models/providers/MicrosoftSAMLProvider.cfc index bdc66d0..b6a6d55 100644 --- a/models/providers/MicrosoftSAMLProvider.cfc +++ b/models/providers/MicrosoftSAMLProvider.cfc @@ -1,4 +1,8 @@ -component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { +component + accessors="true" + extends="BaseProvider" + implements="cbsso.models.ISSOIntegrationProvider" +{ property name="Name"; property name="clientId"; @@ -11,6 +15,7 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { property name="wirebox" inject="wirebox"; property name="AuthNRequestGenerator" inject="javaloader:cbsso.opensaml.AuthNRequestGenerator"; property name="responseValidator" inject="javaloader:cbsso.opensaml.AuthResponseValidator"; + property name="SAMLParsingService" inject="SAMLParsingService@cbsso"; variables.name = "Microsoft Entra"; @@ -22,16 +27,6 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { return variables.name; } - public string function getRedirectUri(){ - if ( !isNull( variables.redirectUri ) ) { - return variables.redirectUri; - } - - var protocol = cgi.HTTPS == "" ? "http://" : "https://"; - - return "#protocol##cgi.HTTP_HOST#/cbsso/auth/#variables.name.lcase()#"; - } - public any function setFederationMetadataURL( required string federationMetadataURL ){ variables.federationMetadataURL = federationMetadataURL; @@ -52,7 +47,7 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { try { var decoded = binaryDecode( event.getValue( "SAMLResponse" ), "base64" ); var data = charsetEncode( decoded, "utf-8" ); - var xmlData = xmlParse( data.reREplace( "xmlns="".+?""", "", "all" ) ); + var samlData = SAMLParsingService.extractUserInfo( data ); authResponse.setRawResponseData( data ); @@ -70,19 +65,19 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { } - if ( !detectSuccess( xmlData ) ) { + if ( !samlData.success ) { return authResponse .setWasSuccessful( false ) .setRawResponseData( data ) - .setErrorMessage( extractErrorMessage( xmlData ) ); + .setErrorMessage( samlData.errorMessage ); } return authResponse .setWasSuccessful( true ) - .setFirstName( extractFirstName( xmlData ) ) - .setLastName( extractLastName( xmlData ) ) - .setEmail( extractEmail( xmlData ) ) - .setUserId( extractUserId( xmlData ) ) + .setFirstName( samlData.firstName ) + .setLastName( samlData.lastName ) + .setEmail( samlData.email ) + .setUserId( samlData.userId ) .setRawResponseData( data ); } catch ( any e ) { return authResponse.setWasSuccessful( false ).setErrorMessage( e.message ); @@ -112,39 +107,39 @@ component accessors="true" implements="cbsso.models.ISSOIntegrationProvider" { private boolean function detectSuccess( required xmlDoc ){ return xmlSearch( xmlDoc, - "samlp:Response//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" + "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" ).len() == 1; } private boolean function extractErrorMessage( required xmlDoc ){ - return xmlSearch( xmlDoc, "samlp:Response//samlp:StatusMessage" )[ 1 ].xmlchildren[ 1 ].xmltext; + return xmlSearch( xmlDoc, "//samlp:StatusMessage" )[ 1 ].xmlchildren[ 1 ].xmltext; } private string function extractFirstName( required xmlDoc ){ return xmlSearch( xmlDoc, - "samlp:Response//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']" + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']" )[ 1 ].xmlchildren[ 1 ].xmltext; } private string function extractLastName( required xmlDoc ){ return xmlSearch( xmlDoc, - "samlp:Response//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']" + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']" )[ 1 ].xmlchildren[ 1 ].xmltext; } private string function extractEmail( required xmlDoc ){ return xmlSearch( xmlDoc, - "samlp:Response//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name']" + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']" )[ 1 ].xmlchildren[ 1 ].xmltext; } private string function extractUserId( required xmlDoc ){ return xmlSearch( xmlDoc, - "samlp:Response//Attribute[@Name='http://schemas.microsoft.com/identity/claims/objectidentifier']" + "//Attribute[@Name='http://schemas.microsoft.com/identity/claims/objectidentifier']" )[ 1 ].xmlchildren[ 1 ].xmltext; } diff --git a/models/testing/BaseProviderSpec.cfc b/models/testing/BaseProviderSpec.cfc deleted file mode 100644 index b3f22e2..0000000 --- a/models/testing/BaseProviderSpec.cfc +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Disk Service Spec - */ -component extends="cbPlaywright.models.ColdBoxPlaywrightTestCase" { - - this.loadColdbox = true; - // Unload Coldbox after this spec, since we are doing a shutdown of all disks - this.unLoadColdBox = true; - this.autowire = true; - - variables.provider = ""; - - /*********************************** LIFE CYCLE Methods ***********************************/ - - /** - * executes before all suites+specs in the run() method - */ - function beforeAll(){ - super.beforeAll(); - setup(); - } - - /** - * executes after all suites+specs in the run() method - */ - function afterAll(){ - super.afterAll(); - } - - /** - * ------------------------------------------------------------ - * Test Helpers - * ------------------------------------------------------------ - */ - - function getProvider(){ - return getInstance( "ProviderService@cbsso" ).get( variables.providerName ); - } - - function getProvidersList(){ - return getInstance( "ProviderService@cbsso" ).names(); - } - -} diff --git a/models/utility/SAMLParsingService.cfc b/models/utility/SAMLParsingService.cfc new file mode 100644 index 0000000..37fefd1 --- /dev/null +++ b/models/utility/SAMLParsingService.cfc @@ -0,0 +1,100 @@ +component singleton { + + public struct function extractUserInfo( required string rawSAMLResponse ){ + var data = { + "success": false, + "errorMessage": "", + "error": "", + "firstName": "", + "lastName": "", + "email": "", + "userId": "" + }; + var xmlData = xmlParse( rawSAMLResponse.reReplace( "xmlns="".+?""", "", "all" ) ); + + try{ + data.success = detectSuccess( xmlData ); + + if( !data.success ){ + data.errorMessage = extractErrorMessage( xmlData ); + return data; + } + + try{ + data.firstName = extractFirstName( xmlData ); + data.lastName = extractLastName( xmlData ); + data.email = extractEmail( xmlData ); + data.userId = extractUserId( xmlData ); + + return data; + } catch( any e ){ + data.success = false; + data.errorMessage = "Failed to extract user information: " & e.message; + data.error = e; + return data; + } + } + catch( any e ){ + data.success = false; + data.errorMessage = "Failed to extract user information: " & e.message; + data.error = e; + } + + return data; + } + + private boolean function detectSuccess( required xmlDoc ){ + return xmlSearch( + xmlDoc, + "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" + ).len() == 1; + } + + private string function extractErrorMessage( required xmlDoc ){ + try{ + return xmlSearch( xmlDoc, "//samlp:StatusMessage" )[ 1 ].xmlchildren[ 1 ].xmltext; + } + catch( any e ){ + try{ + var nodes = xmlSearch( xmlDoc, "//*" ); + for( var node in nodes ){ + if( node.xmlname.toLowerCase().contains( "statusmessage" ) ){ + return node.xmltext; + } + } + } + catch( any ex ){ + // do nothing + } + return "Invalid SAML Response - could not extract error message."; + } + } + + private string function extractFirstName( required xmlDoc ){ + return xmlSearch( + xmlDoc, + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']" + )[ 1 ].xmlchildren[ 1 ].xmltext; + } + + private string function extractLastName( required xmlDoc ){ + return xmlSearch( + xmlDoc, + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']" + )[ 1 ].xmlchildren[ 1 ].xmltext; + } + + private string function extractEmail( required xmlDoc ){ + return xmlSearch( + xmlDoc, + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress']" + )[ 1 ].xmlchildren[ 1 ].xmltext; + } + + private string function extractUserId( required xmlDoc ){ + return xmlSearch( + xmlDoc, + "//Attribute[@Name='http://schemas.microsoft.com/identity/claims/objectidentifier']" + )[ 1 ].xmlchildren[ 1 ].xmltext; + } +} \ No newline at end of file diff --git a/server-boxlang.json b/server-boxlang.json new file mode 100644 index 0000000..59f52c8 --- /dev/null +++ b/server-boxlang.json @@ -0,0 +1,30 @@ +{ + "name":"cbsso-boxlang", + "app":{ + "serverHomeDirectory":".engine/boxlang", + "cfengine":"boxlang@be", + "libDirs":"./java/cbsso-opensaml/app/build/libs" + }, + "jvm":{ + "javaVersion":"openjdk21_jdk" + }, + "web":{ + "http":{ + "port":"9181" + }, + "rewrites":{ + "enable":"true" + }, + "webroot":"test-harness", + "aliases":{ + "/moduleroot/cbSSO":"../" + } + }, + "openBrowser":"false", + "cfconfig":{ + "file":".cfconfig.json" + }, + "scripts":{ + "onServerInitialInstall":"install bx-compat-cfml,bx-esapi" + } +} diff --git a/server-lucee@5.json b/server-lucee@5.json index 0e48031..e0e7371 100644 --- a/server-lucee@5.json +++ b/server-lucee@5.json @@ -1,13 +1,13 @@ { - "name":"oAuth2-lucee@5", + "name":"cbsso-lucee", "app":{ "serverHomeDirectory":".engine/lucee5", "cfengine":"lucee@5", - "libDirs":"./lib" + "libDirs":"./java/cbsso-opensaml/app/build/libs" }, "web":{ "http":{ - "port":"2140" + "port":"9181" }, "rewrites":{ "enable":"true" diff --git a/test-harness/config/Coldbox.cfc b/test-harness/config/Coldbox.cfc index 6022b7c..df41181 100644 --- a/test-harness/config/Coldbox.cfc +++ b/test-harness/config/Coldbox.cfc @@ -66,32 +66,33 @@ { // name: "google", type: "GoogleProvider@cbsso", - clientId : getJavaSystem().getProperty( "GOOGLE_CLIENT_ID" ), - clientSecret : getJavaSystem().getProperty( "GOOGLE_CLIENT_SECRET" ) + clientId : getSystemSetting( "GOOGLE_CLIENT_ID" ), + clientSecret : getSystemSetting( "GOOGLE_CLIENT_SECRET" ) }, { type: "GitHubProvider@cbsso", - clientId : getJavaSystem().getProperty( "GITHUB_CLIENT_ID" ), - clientSecret : getJavaSystem().getProperty( "GITHUB_CLIENT_SECRET" ) + clientId : getSystemSetting( "GITHUB_CLIENT_ID" ), + clientSecret : getSystemSetting( "GITHUB_CLIENT_SECRET" ) }, { type: "FacebookProvider@cbsso", - clientId : getJavaSystem().getProperty( "FACEBOOK_CLIENT_ID" ), - clientSecret : getJavaSystem().getProperty( "FACEBOOK_CLIENT_SECRET" ) + clientId : getSystemSetting( "FACEBOOK_CLIENT_ID" ), + clientSecret : getSystemSetting( "FACEBOOK_CLIENT_SECRET" ) }, { name: "entra", type: "MicrosoftSAMLProvider@cbsso", - clientId : getJavaSystem().getProperty( "MS_ENTRA_CLIENT_ID" ), - clientSecret : getJavaSystem().getProperty( "MS_ENTRA_CLIENT_SECRET" ), - authEndpoint : getJavaSystem().getProperty( "MS_ENTRA_SIGN_ON_ENDPOINT" ), - expectedIssuer : getJavaSystem().getProperty( "MS_ENTRA_ISSUER" ), - federationMetadataURL : getJavaSystem().getProperty( "MS_ENTRA_FEDERATION_METADATA_URL" ) + clientId : getSystemSetting( "MS_ENTRA_CLIENT_ID" ), + clientSecret : getSystemSetting( "MS_ENTRA_CLIENT_SECRET" ), + authEndpoint : getSystemSetting( "MS_ENTRA_SIGN_ON_ENDPOINT" ), + expectedIssuer : getSystemSetting( "MS_ENTRA_ISSUER" ), + federationMetadataURL : getSystemSetting( "MS_ENTRA_FEDERATION_METADATA_URL" ) } ] } }; + // environment settings, create a detectEnvironment() method to detect it yourself. // create a function with the name of the environment so it can be executed if that environment is detected // the value of the environment is a list of regex patterns to match the cgi.http_host. diff --git a/test-harness/models/UserService.cfc b/test-harness/models/UserService.cfc index a678f28..4d03ca2 100644 --- a/test-harness/models/UserService.cfc +++ b/test-harness/models/UserService.cfc @@ -37,9 +37,6 @@ component { public any function createFromSSO( required any ssoEvent, required any provider ){ var a = new User(); - writeDump( ssoEvent ); - abort; - a.setEmail( ssoEvent.getEmail() ) .setId( ssoEvent.getUserId() ); diff --git a/test-harness/test.bxm b/test-harness/test.bxm new file mode 100644 index 0000000..367775c --- /dev/null +++ b/test-harness/test.bxm @@ -0,0 +1,18 @@ + + a = fileread( "../test-entra.xml") + theXML = xmlParse( a.reReplace( "xmlns="".+?""", "", "all" ) ); + // found = xmlSearch( theXML, '//samlp:StatusCode[@Value="urn:oasis:names:tc:SAML:2.0:status:Success"]' ) + + // found = xmlSearch( + // theXML, + // "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname']" + // )[ 1 ].xmlchildren[ 1 ].xmltext; + found = xmlSearch( + theXML, + "//Attribute[@Name='http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name']" + )[ 1 ].xmlchildren[ 1 ].xmltext; + + dump( found.len() ) + dump( found ) + dump( theXML ) + \ No newline at end of file diff --git a/test-harness/test.xml b/test-harness/test.xml new file mode 100644 index 0000000..e409fbe --- /dev/null +++ b/test-harness/test.xml @@ -0,0 +1,86 @@ + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + + + + + + + + + g+8/KlVZ5JXko4kGfayO1JGscvpsb1Mp1rXZsWLE+SU= + + + + o2aU1QdJGqi6NZoK2cURVMpq6nj3zG4lWAcTpJ7UagEsqi3IRh/kPELk/F8iMkFQ1zcn/AQSLKlM2U5+UFarg7IVwurdU2NnYyynPfVsck/OrRIbIgE7D+qMayImm7kR09PCi9rxcdmx0lyBQauA3QE150z3Iy2UNgmlFRrcC/+bkK+BQoSS/NrIDPOC0GSwOFRtYDYy45HEmaxaiOKr82cT7xqeVBFOsOT1bglzSd/OUGsoBaOnXIcDuk5vkDLHe0VpeuVzBXLGiYmfYXl6cwwP606ytEr9EsBAPoyhVf/RvWxw/ym01TfgARmmBvQMsXd8fbO6Nk4MgR/f0OYX0w== + + + + MIIC/jCCAeagAwIBAgIJAPJGEpowIhBNMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjUxMDI2MTk0NjQ1WhcNMzAxMDI2MTk0NjQ1WjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsE+vzm1BhzJJ5KKgJKPGX4M3GbeM0c25HOVQL1aLbOEHm92HBFk1djM9a8WLDfg/d8SLh3Ehta0i0ctATwU0CSeeodvsqL4mKEOXYEqIi1f8ixCX0c7vJ0ESNcyWeAm18F9WNtFKKDOM7gzCn0zuuAZR3m/rBaPDOkoX1AULrkMZjnantrw4z8hL344dLAneta5JiulJor2NiJGNU5EHcVjw7eMDunPTpC/IAxDKF5/hTQ0Hj4+R2AzuSBO0DZ3T2G7/6lmIguOIanfGoYGKev4JvumXahkVGf/tgZ3WuoUqB8KEIM8VGjS0MjBFgCtxX6GmvRD+H3F58x4bsBAZxwIDAQABoyEwHzAdBgNVHQ4EFgQU+A6C3/xdVe7vu2wezFXPLQE0nyMwDQYJKoZIhvcNAQELBQADggEBADAAoTCjqbO+Ku6E1nbOUkq513ETV+7iL6g7FnxY4ysl2qPAsgPcLOO/HoWGLNfu4fbqyBqtSpoHYQUEe2e4FNF9T0EB5B5NShFiSlLVcQyp23PcrcInQRnb7x9iX/ztxm1bpNnLXrQrh/RTsdev6LqiIfhC2XH70Avb6LTYcBMkUuo9Y2kxT3WtyklSl0Ogr3td/lPZne1vcPP4h64uzE9+GKcm+2iZRyWGMjtG6DnC1whmoetqDDmQ9pmHi2xlxSjcTS8oq/FwEA20sjNO4DdBN9tS2VMwVZldZ/Z594sRKOPo3kPVdKhJZud5Yt2nt+xiHcjKY48HmOXRnF8AOto= + + + + + + mMceg+Qeu9APYxQDW9LuA4GaTXm8u1BOinCPhAKrNrw= + + + + + + + spn:caaa139f-4810-4355-a5b5-d8417b406909 + + + + + d8f22d4c-22ab-4713-90d8-652b57f7d30f + + + ab143efb-18d5-4888-8005-97ae69a9f6f5 + + + Beers + + + Jacob + + + Jacob Beers + + + jbeers@ortussolutions.com + + + live.com + + + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password + http://schemas.microsoft.com/claims/multipleauthn + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/unspecified + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + + + + \ No newline at end of file diff --git a/test-harness/tests/resources/coolblog.sql b/test-harness/tests/resources/coolblog.sql deleted file mode 100644 index d1af264..0000000 --- a/test-harness/tests/resources/coolblog.sql +++ /dev/null @@ -1,473 +0,0 @@ -# ************************************************************ -# Sequel Pro SQL dump -# Version 4529 -# -# http://www.sequelpro.com/ -# https://github.com/sequelpro/sequelpro -# -# Host: Localhost (MySQL 5.6.21) -# Database: coolblog -# Generation Time: 2016-02-27 23:03:57 +0000 -# ************************************************************ - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - - -# Dump of table blogEntries -# ------------------------------------------------------------ -USE `coolblog`; - -DROP TABLE IF EXISTS `blogEntries`; - -CREATE TABLE `blogEntries` ( - `blogEntriesID` int(11) NOT NULL AUTO_INCREMENT, - `blogEntriesLink` longtext NOT NULL, - `blogEntriesTitle` longtext NOT NULL, - `blogEntriesDescription` longtext NOT NULL, - `blogEntriesDatePosted` datetime NOT NULL, - `blogEntriesdateUpdated` datetime NOT NULL, - `blogEntriesIsActive` bit(1) NOT NULL, - `blogsID` int(11) DEFAULT NULL, - PRIMARY KEY (`blogEntriesID`), - KEY `FK2828728E45296FD` (`blogsID`), - CONSTRAINT `FK2828728E45296FD` FOREIGN KEY (`blogsID`) REFERENCES `blogs` (`blogsID`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `blogEntries` WRITE; -/*!40000 ALTER TABLE `blogEntries` DISABLE KEYS */; - -INSERT INTO `blogEntries` (`blogEntriesID`, `blogEntriesLink`, `blogEntriesTitle`, `blogEntriesDescription`, `blogEntriesDatePosted`, `blogEntriesdateUpdated`, `blogEntriesIsActive`, `blogsID`) -VALUES - (1,'http://blog.coldbox.org/post.cfm/coldbox-wiki-docs-skins-shared','ColdBox Wiki Docs Skins Shared','Since we love collaboration and giving back to the community, we have just opened our Wiki Docs Skins github repository so you can check out how we build out our wiki docs skins for CodexWiki and hopefully you guys can send us your skins and we can use them on the wiki docs site :)','2011-04-06 11:13:52','2011-04-06 11:13:52',b'1',1), - (2,'http://blog.coldbox.org/post.cfm/new-coldbox-wiki-docs','New ColdBox Wiki Docs','We have been wanting to update all our sites for a long time and the docs where first. Yesterday we updated our codex skins for the coldbox wiki docs and also started our documentation revisions and updates. You will see that it is now much much better organized and our new quick index feature enables you to get to content even faster. Hopefully in the coming weeks we will have all our documentation updated and running. Thank you for your support and feedback.','2011-04-06 10:57:17','2011-04-06 10:57:17',b'1',1), - (3,'http://blog.coldbox.org/post.cfm/modules-contest-ends-this-friday','Modules Contest Ends This Friday','Just a quick reminder that our Modules Contest ends this Friday! So get to it, build some apps! Modules Contest URL: http://blog.coldbox.org/post.cfm/coldbox-modules-contest-extended','2011-04-04 11:22:19','2011-04-04 11:22:19',b'1',1), - (4,'http://blog.coldbox.org/post.cfm/coldbox-connection-recording-coldbox-3-0-0','ColdBox Connection Recording: ColdBox 3.0.0','Thanks for attending our 3rd ColdBox Connection webinar today!  This webinar focused on ColdBox 3.0.0 release and goodies.  Here is the recording for the show!','2011-03-30 15:42:16','2011-03-30 15:42:16',b'1',1), - (5,'http://blog.coldbox.org/post.cfm/coldbox-platform-3-0-0-released','ColdBox Platform 3.0.0 Released','\n \n \nI am so happy to finally announce ColdBox Platform 3.0.0 today on March 3.0, 2011. It has been over a year of research, testing, development, coding, long long nights, 1 beautiful baby girl, lots of headaches, lots of smiles, inspiration, blessings, new contributors, new team members, new company, new hopes, and ambitions. Overall, what an incredible year for ColdFusion and ColdBox development. I can finally say that this release has been the most ambitious release and project I have tackled in my entire professional life. I am so happy of the results and its incredible community response and involvement. So thank you so much Team ColdBox and all the community for the support and long hours of testing, ideas and development.\nColdBox 3 has been on a journey of 6 defined milestones and 2 release candidates in a spawn of over a year of development. Our vision was revamping the engine into discrete and isolated parts:\n\nCore\nLogBox : Enterprise Logging Library\nWireBox : Enterprise Dependency Injection and AOP framework\nCacheBox : Enterprise Caching Engine & Cache Aggregator\nMockBox : Mocking/Stubbing Framework\n\nAll of these parts are now standalone and can be used with any ColdFusion application or ColdFusion framework. We believe we build great tools and would like everybody to have access to them even though they might not even use ColdBox MVC. Apart from the incredible amount of enhancements, we also ventured into several incredible new features:\n\nWhat\'s New\nColdBox Modules : Bringing Modular Architecture to ANY ColdBox application\nProgrammatic configuration, no more XML\nIncredible caching enhancements and integrations\nExtensible and enterprise dependency injection\nAspect oriented programming\nIntegration testing, mocking, stubbing and incredible amount of tools for testing and verification\nCustomizable Flash RAM and future web flows\nColdFusion ORM and Hibernate Services\nRESTful web services enhancement and easy creations\nTons more\n\n \nThe What\'s New page can say it all! An incredible more than 700 issue tickets closed and ColdBox 3.1 is already in full planning phases. So apart from all this work culminating, we can also say we have transitioned into a complete professional open source software offering an incredible amount of professional services and backup to any enterprise or company running ColdBox or any of our supporting products (Relax, CodexWiki, ForumMan, DataBoss, Messaging, ...):\n\nSupport & Mentoring Plans\nArchitecture & Design\nOver 4 professional training courses\nServer Setup, Tuning and Optimizations\nCustom Consulting and','2011-03-29 23:30:18','2011-03-29 23:30:18',b'1',1), - (6,'http://blog.coldbox.org/post.cfm/cachebox-1-2-released','CacheBox 1.2 Released','\n \n In the spirit of more releases, here is: CacheBox 1.2.0.  CacheBox is an enterprise caching engine, aggregator and API for ColdFusion applications. It is part of the ColdBox 3.0.0 Platform but it can also function on its own as a standalone framework and use it in any ColdFusion application and in any ColdFusion framework. \nThe milestone page for this release can be found in our Assembla Code Tracker. Here is a synopsis of the tickets closed:\n \n\n \n\n1179 new cachebox store: BlackholeStore used for optimization and testing\n1180 cf store does not use createTimeSpan to create minute timespans for puts\n1181 railo store does not use createTimeSpan to create minute timespans for puts\n1182 updates to make it coldbox 3.0 compatible\n1192 store locking mechanisms updated to improve locking and concurrency\n\nSo have fun playing with our new CacheBox release:\n\nDownload\nCheatsheet\nSource Code\nDocumentation\n\n ','2011-03-29 23:26:09','2011-03-29 23:26:09',b'1',1), - (7,'http://blog.coldbox.org/post.cfm/wirebox-1-1-1-released','WireBox 1.1.1 Released!','I am happy to announce WireBox 1.1.1 to the ColdFusion community. This release sports 3 critical fixes that will make your WireBox injectors run smoother and happier, especially for those doing java integration, this will help you some more.\n\n\nDownload\nCheatsheet\nSource Code\nDocumentation\nOur primer: Getting Jiggy Wit It!\n\n Issues Fixed\n\n1184 changed way providers accessed scoped injectors via scope registration structure instead of injector references to avoid memory leaks\n 1188 updated the java builder to ignore empty init arguments.\n 1189 updated the java builder to do noInit() as it was ignoring it\n','2011-03-29 23:20:32','2011-03-29 23:20:32',b'1',1), - (8,'http://blog.coldbox.org/post.cfm/module-lifecycles-explained','Module Lifecycles Explained','In this short entry I just wanted to lay out a few new diagrams that explain the lifecycle of ColdBox modules.  As always, all our documentation reflects these changes as well.  This might help some of you developers getting ready to win that ColdBox Modules contest and get some cash and beer!\n\nModule Service\nThe beauty of ColdBox Modules is that you have an internal module service that you can tap to in order to dynamically interact with the ColdBox Modules. This service is available by talking to the main ColdBox controller and calling its getModuleService() method: \n// get module service from handlers, plugins, layouts, interceptors or views.\nms = controller.getModuleService();\n\n// You can also inject it via our autowire DSL\nproperty name=\"moduleService\" inject=\"coldbox:moduleService\";\n\n \nModule Lifecycle\n\n \n\nHowever, before we start reviewing the module service methods let\'s review how modules get loaded in a ColdBox application. Below is a simple bullet point of what happens in your application when it starts up and you can also look at the diagram above: \n\nColdBox main application and configuration loads \nColdBox Cache, Logging and WireBox are created \nModule Service calls on registerAllModules() to read all the modules in the modules locations (with include/excludes) and start registering their configurations one by one. If the module had parent settings, interception points, datasoures or webservices, these are registered here. \nAll main application interceptors are loaded and configured \nColdBox is marked as initialized \nModule service calls on activateAllModules() so it begins activating only the registered modules one by one. This registers the module\'s SES URL Mappings, model objects, etc \nafterConfigurationLoad interceptors are fired \nColdBox aspects such as i18n, javaloader, ColdSpring/LightWire factories are loaded \nafterAspectsLoad interceptors are fired \n\nThe most common methods that you can use to control the modules in your application are the following: \n\nreloadAll() : Reload all modules in the application. This clears out all module settings, re-registers from disk, re-configures them and activates them \nreload(module) : Target a module reload by name \nunloadAll() : Unload all modules \nunload(module) : Target a module unload by name \nregisterAllModules() : Registers all module configurations \nregisterModule(module) : Target a module configuration registration \nactivateAllModules() : Activate all registered modules \nactivateModule(module) : Target activate a module that has been registered already \ngetLoadedModules() : Get an array of loaded module names \nrebuildModuleRegistry() : Rescan all the module lcoations for newly installed modules and rebuild the registry so these modules can be registered and activated. \nregisterAndActivateModule(module) : Registe','2011-03-29 11:42:49','2011-03-29 11:42:49',b'1',1), - (9,'http://blog.coldbox.org/post.cfm/coldbox-connection-show-wednesday','ColdBox Connection Show Wednesday','Just a reminder that this March 3.0.0, 2011 we will be holding a special ColdBox Open Forum Connection at 9 AM PST.  You can find more information below:Location:  http://experts.adobeconnect.com/coldbox-connection/ColdBox Connection Shows: http://www.coldbox.org/media/connectionWatch out!! Something is coming!!','2011-03-28 20:59:29','2011-03-28 20:59:29',b'1',1), - (10,'http://blog.coldbox.org/post.cfm/coldbox-modules-contest-extended','ColdBox Modules Contest Extended','We are extending our Modules Contest to allow for more time for entries to trickle in and of course to leverage ColdBox 3 coming this week.\nDeadline: Module entries must be submitted by March 29th EXTENDED: April 8th, 2011 no later than 12PM PST to contests@ortussolutions.com\nWinners Announced on March 30th EXTENDED: April 14th, 2011 The ColdBox Connection show at 9AM PST\nColdBox 3.0 Modules ContestCreate a ColdBox 3.0.0 module that is a fully functional application that can be portable for any ColdBox 3.0 application. Here are some guidelines the ColdBox team will be evaluating the module on\n\nDownload ColdBox\n\nThe code must reside on either github or a public repository so it is publicly accessible\n\nThe user must create a forgebox entry and submit the module code to it: http://coldbox.org/forgebox\n\nThe more internal libraries it uses the more points it gets: LogBox, MockBox, WireBox, CacheBox\n\nThe module should do something productive, no say hello modules accepted\n\nBest practices on MVC separation of concerns\n\nPortability\n\nDocumentation (You had that one coming!!) as it might need DB setup or DSN setup\n\nBe creative!\n\nMake sure it works!\n\n\n1st Prize\n\nAn Adobe ColdFusion 9 Standard License\n\n$100 Amazon Gift Card\n\nSix pack of \"BrewFather\" beer\n\n\n2nd Prize\n\nA ColdBox Book\n\nA ColdBox T-Shirt\n\n$25 Amazon Gift Card\n\nSix pack of \"BrewFather\" beer\n','2011-03-27 20:29:07','2011-03-27 20:29:07',b'1',1), - (11,'http://blog.coldbox.org/post.cfm/coldbox-3-release-training-special-discounts','ColdBox 3 Release Training Special Discounts','\n We are currently holding a special promotion that starts today March 27, 2011 until April 3rd, 2011\n at 3:00 PM PST. Take advantage of this insane $300 off any training of your choice in honor \n of our ColdBox 3.0.0 release this week.  Just use our discount code \n viva3 in our training registration pages or follow our links below and get this discount. \n Hurry as the code expires on April 3rd, 2011 at 3PM PST.\n \n \nCalifornia Ontario/Los Angeles Training - April 27 to May 1, 2011\n\nDiscount Link: http://coldbox.eventbrite.com/?discount=viva3 \nCBOX-101 ColdBox Core on April 27 - April 29, 2011\nCBOX-203 ColdBox Modules on April 30 - May 1, 2011\n\nPre-CFObjective Minneapolis Training - May 10-11, 2011\n\nDiscount Link: http://coldbox-cfobjective.eventbrite.com/?discount=viva3 \nCBOX-100 ColdBox Core on May 10-11, 2011\nCBOX-202 WireBox Dependency Injection on May 10-11, 2011\n\nHouston, Texas Training - April 27 to May 1, 2011\n\nDiscount Link: http://coldbox-texas.eventbrite.com/?discount=viva3 \nCBOX-101 ColdBox Core on July 6-8, 2011\nCBOX-203 ColdBox Modules on July 7-8, 2011\n','2011-03-27 20:18:44','2011-03-27 20:18:44',b'1',1), - (12,'http://blog.coldbox.org/post.cfm/coldbox-connection-recordings-page','ColdBox Connection Recordings Page','We just created our new recordings page for the ColdBox Connection today, so you can get in one location all of the recordings.  Hopefully in the near future we will expand it with tags and search.','2011-03-25 11:36:08','2011-03-25 11:36:08',b'1',1), - (13,'http://blog.coldbox.org/post.cfm/coldbox-connection-recording-coldbox-modules','ColdBox Connection Recording: ColdBox Modules','Thanks for attending our 2nd ColdBox Connection webinar today!  This webinar focused on ColdBox modules, modularity and architecture.  Thanks go to Curt Gratz for presenting such excellent topic.  Here is the recording for the show and also please note that we will have another show March 3.0!','2011-03-24 11:41:53','2011-03-24 11:41:53',b'1',1), - (14,'http://blog.coldbox.org/post.cfm/coldbox-connection-thursday-modules','ColdBox Connection Thursday: Modules','Just a reminder that our ColdBox Connection Show continues this Thursday at 9 AM PST! Curt Gratz will be presenting on ColdBox Modules and of course we will all be there for questions and help. See you there!Location: http://experts.adobeconnect.com/coldbox-connection/Our full calendar of events can be found here: http://coldbox.org/about/eventscalendar','2011-03-22 08:48:10','2011-03-22 08:48:10',b'1',1), - (15,'http://blog.coldbox.org/post.cfm/coldbox-relax-v1-4-released','ColdBox Relax v1.4 released!','Here is a cool new update for ColdBox Relax - RESTful Tools For Lazy Experts!  This update fixes a few issues reported and also enhances the Relaxer console and updates its ability to support definitions for multiple tiers and much more. So download it now!\nHere are the closed issues for this release:\n\n #14 api_logs direct usage reference removed fixes\n #15 basic http authentication added to relaxer console so you can easily hit resources that require basic auth\n #10 entry points can now be a structure of name value pairs for multiple tiers\n #16 new browser results tab window to show how the results are rendered by a browser\n #17 addition http proxy as advanced settings to relaxer console so you can proxy your relaxed requests\n #11 Route Auto Generation - Method security fixes so implicit structures are generated alongside json structures\n\nHere is also a nice screencast showcasing version 1.4 capabilities:\n \n\n\n\n \nWhat is Relax? ColdBox Relax is a set of RESTful tools for lazy experts. We pride ourselves in helping developers work smarter and of course document more in less time by providing them the necessary tools to automagically document and test. ColdBox Relax is a way to describe RESTful web services, test RESTful web services, monitor RESTful web services and document RESTful web services. The following introductory video will explain it better than words!\n \n\n\n\nSo what are you waiting for? Get Relax Now!\n\n Source Code\n Download\n Documentation\n\n \n','2011-03-21 16:51:09','2011-03-21 16:51:09',b'1',1); - -/*!40000 ALTER TABLE `blogEntries` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table blogs -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `blogs`; - -CREATE TABLE `blogs` ( - `blogsID` int(11) NOT NULL AUTO_INCREMENT, - `blogsURL` longtext NOT NULL, - `blogsWebsiteurl` longtext NOT NULL, - `blogslanguage` varchar(10) NOT NULL, - `blogsTitle` longtext NOT NULL, - `blogsDescription` longtext NOT NULL, - `blogsdateBuilt` datetime NOT NULL, - `blogsdateSumitted` datetime NOT NULL, - `blogsIsActive` bit(1) NOT NULL, - `blogsAuthorname` varchar(200) DEFAULT NULL, - `blogsauthorEmail` varchar(200) DEFAULT NULL, - `blogsauthorURL` longtext, - PRIMARY KEY (`blogsID`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `blogs` WRITE; -/*!40000 ALTER TABLE `blogs` DISABLE KEYS */; - -INSERT INTO `blogs` (`blogsID`, `blogsURL`, `blogsWebsiteurl`, `blogslanguage`, `blogsTitle`, `blogsDescription`, `blogsdateBuilt`, `blogsdateSumitted`, `blogsIsActive`, `blogsAuthorname`, `blogsauthorEmail`, `blogsauthorURL`) -VALUES - (1,'http://blog.coldbox.org/feeds/rss.cfm','http://blog.coldbox.org/','','ColdBox Platform','The official ColdBox Blog','2011-04-08 15:19:13','2011-04-08 15:19:13',b'1',NULL,NULL,NULL); - -/*!40000 ALTER TABLE `blogs` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table cacheBox -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `cacheBox`; - -CREATE TABLE `cacheBox` ( - `id` varchar(100) NOT NULL, - `objectKey` varchar(255) NOT NULL, - `objectValue` longtext NOT NULL, - `hits` int(11) NOT NULL DEFAULT '1', - `timeout` int(11) NOT NULL, - `lastAccessTimeout` int(11) NOT NULL, - `created` datetime NOT NULL, - `lastAccessed` datetime NOT NULL, - `isExpired` tinyint(4) NOT NULL DEFAULT '1', - `isSimple` tinyint(4) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -LOCK TABLES `cacheBox` WRITE; -/*!40000 ALTER TABLE `cacheBox` DISABLE KEYS */; - -INSERT INTO `cacheBox` (`id`, `objectKey`, `objectValue`, `hits`, `timeout`, `lastAccessTimeout`, `created`, `lastAccessed`, `isExpired`, `isSimple`) -VALUES - ('DF658A103F07DC012AB905014C32D4C7','myKey','hello',1,0,0,'2016-02-25 16:34:00','2016-02-25 16:34:00',1,1); - -/*!40000 ALTER TABLE `cacheBox` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table categories -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `categories`; - -CREATE TABLE `categories` ( - `category_id` varchar(50) NOT NULL, - `category` varchar(100) NOT NULL, - `description` varchar(100) NOT NULL, - `modifydate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `testValue` varchar(100) DEFAULT NULL, - PRIMARY KEY (`category_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `categories` WRITE; -/*!40000 ALTER TABLE `categories` DISABLE KEYS */; - -INSERT INTO `categories` (`category_id`, `category`, `description`, `modifydate`, `testValue`) -VALUES - ('3A2C516C-41CE-41D3-A9224EA690ED1128','Presentations','

Presso

','2011-02-18 00:00:00',NULL), - ('40288110380cda3301382644c7f90008','LM','LM
','2012-06-10 23:00:00',NULL), - ('402881882814615e012826481061000c','Marc','This is marcs category
','2010-04-21 22:00:00',NULL), - ('402881882814615e01282bb047fd001e','Cool Wow','A cool wow category
','2010-04-22 22:00:00',NULL), - ('402881882b89b49b012b9201bda80002','PascalNews','PascalNews','2010-10-09 00:00:00',NULL), - ('402881a144f57bfd0144fa47bf040007','ads','asdf','2014-01-25 00:00:00',NULL), - ('5898F818-A9B6-4F5D-96FE70A31EBB78AC','Release','

Releases

','2009-04-18 11:48:53',NULL), - ('88B689EA-B1C0-8EEF-143A84813ACADA35','general','A general category','2010-03-31 12:53:21',NULL), - ('88B689EA-B1C0-8EEF-143A84813BCADA35','general','A second test general category','2010-03-31 12:53:21',NULL), - ('88B6C087-F37E-7432-A13A84D45A0F703B','News','A news cateogyr','2009-04-18 11:48:53',NULL), - ('99fc94fd3b98c834013b98c9b2140002','Fancy','Fancy Editor
','2012-12-14 00:00:00',NULL), - ('99fc94fd3b9a459d013b9db89c060002','Markus','Hello Markus
','2012-12-14 15:00:00',NULL), - ('A13C0DB0-0CBC-4D85-A5261F2E3FCBEF91','Training','unittest','2014-05-07 19:05:21',NULL), - ('ff80808128c9fa8b0128cc3af5d90007','Geeky Stuff','Geeky Stuff','2010-05-25 16:00:00',NULL), - ('ff80808128c9fa8b0128cc3b20bf0008','ColdBox','ColdBox','2010-05-23 16:00:00',NULL), - ('ff80808128c9fa8b0128cc3b7cdd000a','ColdFusion','ColdFusion','2010-05-23 16:00:00',NULL); - -/*!40000 ALTER TABLE `categories` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table comments -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `comments`; - -CREATE TABLE `comments` ( - `comment_id` varchar(50) NOT NULL, - `FKentry_id` varchar(50) NOT NULL, - `comment` text NOT NULL, - `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`comment_id`), - KEY `FK_comments_1` (`FKentry_id`), - KEY `FKentry_id` (`FKentry_id`), - CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`FKentry_id`) REFERENCES `entries` (`entry_id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `comments` WRITE; -/*!40000 ALTER TABLE `comments` DISABLE KEYS */; - -INSERT INTO `comments` (`comment_id`, `FKentry_id`, `comment`, `time`) -VALUES - ('40288110380cda330138265bf9c4000a','8a64b3712e3a0a5e012e3a11a2cf0004','tt','2012-06-12 23:00:00'), - ('40288110380cda3301382c7fe50d0012','88B82629-B264-B33E-D1A144F97641614E','Test','2012-06-06 23:00:00'), - ('402881882814615e01282b13bbc20013','88B82629-B264-B33E-D1A144F97641614E','This entire blog post really offended me, I hate you','2010-04-22 22:00:00'), - ('402881882814615e01282b13fb290014','88B82629-B264-B33E-D1A144F97641614E','Why are you so hurtful man!','2010-04-22 22:00:00'), - ('402881882814615e01282b142cc60015','88B82629-B264-B33E-D1A144F97641614E','La realidad, que barbaro!','2010-04-22 22:00:00'), - ('88B8C6C7-DFB7-0F34-C2B0EFA4E5D7DA4C','88B82629-B264-B33E-D1A144F97641614E','this blog sucks.','2010-09-02 11:39:04'), - ('8a64b3712e3a0a5e012e3a10321d0002','402881882814615e01282b14964d0016','Vlad is awesome!','2011-02-18 00:00:00'), - ('8a64b3712e3a0a5e012e3a12b1d10005','8a64b3712e3a0a5e012e3a11a2cf0004','Vlad is awesome!','2011-02-18 00:00:00'); - -/*!40000 ALTER TABLE `comments` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table contact -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `contact`; - -CREATE TABLE `contact` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `firstName` varchar(255) DEFAULT NULL, - `lastName` varchar(255) DEFAULT NULL, - `email` varchar(255) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `contact` WRITE; -/*!40000 ALTER TABLE `contact` DISABLE KEYS */; - -INSERT INTO `contact` (`id`, `firstName`, `lastName`, `email`) -VALUES - (1,'Luis','Majano','lmajano@ortussolutions.com'), - (2,'Jorge','Reyes','lmajano@gmail.com'), - (3,'','',''); - -/*!40000 ALTER TABLE `contact` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table entries -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `entries`; - -CREATE TABLE `entries` ( - `entry_id` varchar(50) NOT NULL, - `entryBody` text NOT NULL, - `title` varchar(50) NOT NULL, - `postedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `FKuser_id` varchar(36) NOT NULL, - PRIMARY KEY (`entry_id`), - KEY `FKuser_id` (`FKuser_id`), - CONSTRAINT `entries_ibfk_1` FOREIGN KEY (`FKuser_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 9216 kB; (`FKuser_id`) REFER `coolblog/users`(`'; - -LOCK TABLES `entries` WRITE; -/*!40000 ALTER TABLE `entries` DISABLE KEYS */; - -INSERT INTO `entries` (`entry_id`, `entryBody`, `title`, `postedDate`, `FKuser_id`) -VALUES - ('402881882814615e01282b14964d0016','Wow, welcome to my new blog, enjoy your stay
','My awesome post','2010-04-22 22:00:00','88B73A03-FEFA-935D-AD8036E1B7954B76'), - ('88B82629-B264-B33E-D1A144F97641614E','A first cool blog,hope it does not crash','A cool blog first posting','2009-04-08 00:00:00','88B73A03-FEFA-935D-AD8036E1B7954B76'), - ('8a64b3712e3a0a5e012e3a11a2cf0004','ContentBox is a professional open source modular content management engine that allows you to easily build websites adfsadf adfsadf asfddasfddasfddasfdd','My First Awesome Post My First Awesome Post','2013-04-16 22:00:00','88B73A03-FEFA-935D-AD8036E1B7954B76'), - ('8aee965b3cfff278013d0007d9540002','Mobile browsing popularity is skyrocketing.  According to a new Pew Internet Project report, 25% of Americans use smartphones instead of computers for the majority of their web browsing.\r\nMissing out on the mobile marketing trend is\r\n likely to translate into loss of market share and decreased sales. \r\nThat’s not to say that it’s right for every business, but you at least \r\nneed to consider your target market persona before simply dismissing \r\nmobile as a fad.\r\nOne simple step you can take in the mobile direction is to learn how to add Apple icons to your website.\r\n

What Are Apple Icons & Why Use Them?

\r\n\"GuavaBoxApple\r\n Icons are simply the graphics you’ve chosen to represent your site when\r\n a user saves your page to their home screen in iOS.\r\nIf you don’t have Apple Icons created for your site, iOS grabs a \r\ncompressed thumbnail of your website and displays it as the icon.  The \r\nresult is typically indistinguishable and unappealing.\r\nApple Icons are an awesome branding opportunity and give you the chance to g
','Test','2013-04-23 00:00:00','402884cc310b1ae901311be89381000a'), - ('99fc94fd3ba7f266013bad4a8a3b0004','This is my first blog post from Bern!
','This is my first blog post from Bern!','2012-12-17 15:00:00','99fc94fd3ba7f266013bad49e3c50003'); - -/*!40000 ALTER TABLE `entries` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table entry_categories -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `entry_categories`; - -CREATE TABLE `entry_categories` ( - `FKcategory_id` varchar(50) NOT NULL, - `FKentry_id` varchar(50) NOT NULL, - KEY `FKcategory_id` (`FKcategory_id`), - KEY `FKentry_id` (`FKentry_id`), - CONSTRAINT `entry_categories_ibfk_1` FOREIGN KEY (`FKcategory_id`) REFERENCES `categories` (`category_id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `entry_categories_ibfk_2` FOREIGN KEY (`FKentry_id`) REFERENCES `entries` (`entry_id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `entry_categories` WRITE; -/*!40000 ALTER TABLE `entry_categories` DISABLE KEYS */; - -INSERT INTO `entry_categories` (`FKcategory_id`, `FKentry_id`) -VALUES - ('88B689EA-B1C0-8EEF-143A84813ACADA35','88B82629-B264-B33E-D1A144F97641614E'), - ('88B6C087-F37E-7432-A13A84D45A0F703B','88B82629-B264-B33E-D1A144F97641614E'), - ('3A2C516C-41CE-41D3-A9224EA690ED1128','99fc94fd3ba7f266013bad4a8a3b0004'), - ('5898F818-A9B6-4F5D-96FE70A31EBB78AC','99fc94fd3ba7f266013bad4a8a3b0004'), - ('99fc94fd3b98c834013b98c9b2140002','99fc94fd3ba7f266013bad4a8a3b0004'), - ('5898F818-A9B6-4F5D-96FE70A31EBB78AC','402881882814615e01282b14964d0016'), - ('40288110380cda3301382644c7f90008','402881882814615e01282b14964d0016'), - ('3A2C516C-41CE-41D3-A9224EA690ED1128','402881882814615e01282b14964d0016'), - ('402881882b89b49b012b9201bda80002','402881882814615e01282b14964d0016'), - ('99fc94fd3b98c834013b98c9b2140002','402881882814615e01282b14964d0016'), - ('5898F818-A9B6-4F5D-96FE70A31EBB78AC','8a64b3712e3a0a5e012e3a11a2cf0004'), - ('A13C0DB0-0CBC-4D85-A5261F2E3FCBEF91','8a64b3712e3a0a5e012e3a11a2cf0004'), - ('3A2C516C-41CE-41D3-A9224EA690ED1128','8a64b3712e3a0a5e012e3a11a2cf0004'); - -/*!40000 ALTER TABLE `entry_categories` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table logs -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `logs`; - -CREATE TABLE `logs` ( - `id` varchar(36) NOT NULL, - `severity` varchar(10) NOT NULL, - `category` varchar(100) NOT NULL, - `logdate` datetime NOT NULL, - `appendername` varchar(100) NOT NULL, - `message` text, - `extrainfo` text, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - - - -# Dump of table relax_logs -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `relax_logs`; - -CREATE TABLE `relax_logs` ( - `id` varchar(36) NOT NULL, - `severity` varchar(10) NOT NULL, - `category` varchar(100) NOT NULL, - `logdate` datetime NOT NULL, - `appendername` varchar(100) NOT NULL, - `message` longtext, - `extrainfo` longtext, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - - - -# Dump of table roles -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `roles`; - -CREATE TABLE `roles` ( - `roleID` int(11) NOT NULL AUTO_INCREMENT, - `role` varchar(100) DEFAULT NULL, - PRIMARY KEY (`roleID`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `roles` WRITE; -/*!40000 ALTER TABLE `roles` DISABLE KEYS */; - -INSERT INTO `roles` (`roleID`, `role`) -VALUES - (1,'Administrator'), - (2,'Moderator'), - (3,'Anonymous'), - (4,'Super User'), - (5,'Editor'); - -/*!40000 ALTER TABLE `roles` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table todo -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `todo`; - -CREATE TABLE `todo` ( - `blogsID` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(100) DEFAULT NULL, - PRIMARY KEY (`blogsID`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8; - -LOCK TABLES `todo` WRITE; -/*!40000 ALTER TABLE `todo` DISABLE KEYS */; - -INSERT INTO `todo` (`blogsID`, `name`) -VALUES - (1,'AL-{ts \'2011-04-07 11:15:55\'}'), - (2,'AL-{ts \'2011-04-07 11:16:22\'}'), - (3,'AL-{ts \'2011-04-07 11:17:06\'}'), - (4,'AL-{ts \'2011-04-07 11:21:52\'}'), - (5,'AL-{ts \'2011-04-07 11:23:06\'}'), - (6,'AL-{ts \'2011-04-07 11:23:08\'}'), - (7,'AL-{ts \'2011-04-18 17:23:59\'}'), - (8,'AL-{ts \'2011-04-18 17:37:15\'}'), - (9,'AL-{ts \'2011-04-18 17:37:20\'}'), - (10,'AL-{ts \'2011-04-18 17:38:06\'}'), - (11,'AL-{ts \'2011-04-18 17:38:08\'}'), - (12,'AL-{ts \'2011-04-18 17:38:09\'}'), - (13,'AL-{ts \'2011-04-18 17:38:10\'}'), - (14,'AL-{ts \'2011-04-18 17:38:11\'}'), - (15,'AL-{ts \'2011-04-18 17:38:12\'}'), - (16,'AL-{ts \'2011-04-18 17:38:14\'}'), - (17,'AL-{ts \'2011-04-18 17:38:15\'}'), - (18,'AL-{ts \'2011-04-18 17:38:16\'}'), - (19,'AL-{ts \'2011-04-18 17:38:17\'}'), - (20,'AL-{ts \'2011-04-18 17:38:18\'}'), - (21,'AL-{ts \'2011-04-18 17:38:19\'}'), - (22,'AL-{ts \'2011-04-18 17:38:20\'}'), - (23,'AL-{ts \'2011-04-18 17:38:21\'}'), - (24,'AL-{ts \'2011-04-18 17:40:41\'}'), - (25,'AL-{ts \'2011-04-18 17:40:44\'}'), - (26,'AL-{ts \'2011-04-18 17:40:47\'}'), - (27,'AL-{ts \'2011-04-18 17:41:38\'}'), - (28,'AL-{ts \'2011-04-18 17:44:15\'}'), - (29,'AL-{ts \'2011-04-18 17:44:25\'}'), - (30,'AL-{ts \'2011-04-18 17:44:39\'}'), - (31,'AL-{ts \'2011-04-18 17:49:44\'}'), - (32,'AL-{ts \'2011-04-18 17:50:10\'}'), - (33,'AL-{ts \'2011-04-18 17:51:07\'}'), - (34,'AL-{ts \'2011-04-18 17:57:44\'}'), - (35,'AL-{ts \'2011-04-18 18:03:33\'}'), - (36,'AL-{ts \'2011-04-18 19:32:04\'}'), - (37,'AL-{ts \'2011-04-18 19:32:08\'}'), - (38,'AL-{ts \'2011-04-18 19:32:31\'}'), - (39,'AL-{ts \'2011-04-18 19:32:51\'}'), - (40,'AL-{ts \'2011-04-18 20:02:55\'}'), - (41,'AL-{ts \'2011-04-18 20:03:52\'}'), - (42,'AL-{ts \'2011-04-18 20:04:10\'}'), - (43,'AL-{ts \'2011-04-18 20:12:52\'}'), - (44,'AL-{ts \'2011-04-19 15:43:36\'}'), - (45,'AL-{ts \'2011-04-19 15:44:20\'}'), - (46,'AL-{ts \'2011-04-19 15:48:26\'}'), - (47,'AL-{ts \'2011-04-19 15:50:59\'}'), - (48,'AL-{ts \'2011-04-19 15:51:08\'}'), - (49,'AL-{ts \'2011-04-19 15:51:15\'}'), - (50,'AL-{ts \'2011-04-23 12:58:04\'}'); - -/*!40000 ALTER TABLE `todo` ENABLE KEYS */; -UNLOCK TABLES; - - -# Dump of table users -# ------------------------------------------------------------ - -DROP TABLE IF EXISTS `users`; - -CREATE TABLE `users` ( - `user_id` varchar(50) NOT NULL, - `firstName` varchar(50) NOT NULL, - `lastName` varchar(50) NOT NULL, - `userName` varchar(50) NOT NULL, - `password` varchar(50) NOT NULL, - `lastLogin` datetime DEFAULT NULL, - `FKRoleID` int(11) DEFAULT NULL, - `isActive` bit(1) DEFAULT b'1', - PRIMARY KEY (`user_id`), - KEY `FKRoleID` (`FKRoleID`), - CONSTRAINT `users_ibfk_1` FOREIGN KEY (`FKRoleID`) REFERENCES `roles` (`roleID`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=latin1; - -LOCK TABLES `users` WRITE; -/*!40000 ALTER TABLE `users` DISABLE KEYS */; - -INSERT INTO `users` (`user_id`, `firstName`, `lastName`, `userName`, `password`, `lastLogin`, `FKRoleID`, `isActive`) -VALUES - ('4028818e2fb6c893012fe637c5db00a7','George','Form Injector','george','george',NULL,2,b'1'), - ('402884cc310b1ae901311be89381000a','ken','Advanced Guru','kenneth','smith','2014-03-25 00:00:00',2,b'1'), - ('4A386F4D-DCF4-6587-7B89B3BD57C97155','Joe','Fernando','joe','joe','2009-05-15 00:00:00',1,b'1'), - ('88B73A03-FEFA-935D-AD8036E1B7954B76','Luis','Majano','lui','lmajano','2009-04-08 00:00:00',1,b'1'), - ('8a64b3712e3a0a5e012e3a110fab0003','Vladymir','Ugryumov','vlad','vlad','2011-02-18 00:00:00',1,b'1'), - ('99fc94fd3b98c834013b98c928120001','Juerg','Anderegg','juerg','juerg','2012-12-14 00:00:00',NULL,b'1'), - ('99fc94fd3ba7f266013bad49e3c50003','Tanja','Zogg','tanja','tanja','2012-12-18 00:00:00',NULL,b'1'); - -/*!40000 ALTER TABLE `users` ENABLE KEYS */; -UNLOCK TABLES; - - - -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/test-harness/tests/resources/errorSAMLResponse.xml b/test-harness/tests/resources/errorSAMLResponse.xml new file mode 100644 index 0000000..5b494cc --- /dev/null +++ b/test-harness/tests/resources/errorSAMLResponse.xml @@ -0,0 +1,87 @@ + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + Invalid Content + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + + + + + + + + + Txfsqs7WpACUggDqTW+N9SCLE4dPuyb+czbNkyJd6P0= + + + + XmBC/mDZwrMJsjliH9oRuvogvDwmwslqrlvSIUbVmYjJXcrUG7jPwjCAGffuK3nIoiLPfCiTKDX25EtIf558dUNwL7AQnHNj10l1M4D3qJThHApXvUoFXIBMMK23ninfyfluYNfozeOtoahz3lsJFCjdSTKGe7aFyH3pOlVHyn+kzX2vRPjQ8AobW52DiSq5YvgZGbuylCyZoDWF9Lwy99vGWRanVjumMTtDeCgjErzX0nyW7RqiYmx3R4LQtGHD3j/0jdc2jV+YqCaSIOkvO6DNULRJpafONkpOIdLzRf2YhNnaeVdXszRc+Yt9A6FTnoL2RTuAv/2bG9zoEShEMg== + + + + MIIC/jCCAeagAwIBAgIJAPJGEpowIhBNMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjUxMDI2MTk0NjQ1WhcNMzAxMDI2MTk0NjQ1WjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsE+vzm1BhzJJ5KKgJKPGX4M3GbeM0c25HOVQL1aLbOEHm92HBFk1djM9a8WLDfg/d8SLh3Ehta0i0ctATwU0CSeeodvsqL4mKEOXYEqIi1f8ixCX0c7vJ0ESNcyWeAm18F9WNtFKKDOM7gzCn0zuuAZR3m/rBaPDOkoX1AULrkMZjnantrw4z8hL344dLAneta5JiulJor2NiJGNU5EHcVjw7eMDunPTpC/IAxDKF5/hTQ0Hj4+R2AzuSBO0DZ3T2G7/6lmIguOIanfGoYGKev4JvumXahkVGf/tgZ3WuoUqB8KEIM8VGjS0MjBFgCtxX6GmvRD+H3F58x4bsBAZxwIDAQABoyEwHzAdBgNVHQ4EFgQU+A6C3/xdVe7vu2wezFXPLQE0nyMwDQYJKoZIhvcNAQELBQADggEBADAAoTCjqbO+Ku6E1nbOUkq513ETV+7iL6g7FnxY4ysl2qPAsgPcLOO/HoWGLNfu4fbqyBqtSpoHYQUEe2e4FNF9T0EB5B5NShFiSlLVcQyp23PcrcInQRnb7x9iX/ztxm1bpNnLXrQrh/RTsdev6LqiIfhC2XH70Avb6LTYcBMkUuo9Y2kxT3WtyklSl0Ogr3td/lPZne1vcPP4h64uzE9+GKcm+2iZRyWGMjtG6DnC1whmoetqDDmQ9pmHi2xlxSjcTS8oq/FwEA20sjNO4DdBN9tS2VMwVZldZ/Z594sRKOPo3kPVdKhJZud5Yt2nt+xiHcjKY48HmOXRnF8AOto= + + + + + + pO+tkeMWqlmQJ6WmA1k2HOVlYfBGf0CnHApnDU9cGTk= + + + + + + + spn:caaa139f-4810-4355-a5b5-d8417b406909 + + + + + x + + + x + + + Beers + + + Jacob + + + Jacob Beers + + + jbeers@ortussolutions.com + + + live.com + + + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password + http://schemas.microsoft.com/claims/multipleauthn + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/unspecified + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + + + + \ No newline at end of file diff --git a/test-harness/tests/resources/validSAMLResponse.xml b/test-harness/tests/resources/validSAMLResponse.xml new file mode 100644 index 0000000..a77fd6b --- /dev/null +++ b/test-harness/tests/resources/validSAMLResponse.xml @@ -0,0 +1,86 @@ + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + + + https://sts.windows.net/d8f22d4c-22ab-4713-90d8-652b57f7d30f/ + + + + + + + + + + + Txfsqs7WpACUggDqTW+N9SCLE4dPuyb+czbNkyJd6P0= + + + + XmBC/mDZwrMJsjliH9oRuvogvDwmwslqrlvSIUbVmYjJXcrUG7jPwjCAGffuK3nIoiLPfCiTKDX25EtIf558dUNwL7AQnHNj10l1M4D3qJThHApXvUoFXIBMMK23ninfyfluYNfozeOtoahz3lsJFCjdSTKGe7aFyH3pOlVHyn+kzX2vRPjQ8AobW52DiSq5YvgZGbuylCyZoDWF9Lwy99vGWRanVjumMTtDeCgjErzX0nyW7RqiYmx3R4LQtGHD3j/0jdc2jV+YqCaSIOkvO6DNULRJpafONkpOIdLzRf2YhNnaeVdXszRc+Yt9A6FTnoL2RTuAv/2bG9zoEShEMg== + + + + MIIC/jCCAeagAwIBAgIJAPJGEpowIhBNMA0GCSqGSIb3DQEBCwUAMC0xKzApBgNVBAMTImFjY291bnRzLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMjUxMDI2MTk0NjQ1WhcNMzAxMDI2MTk0NjQ1WjAtMSswKQYDVQQDEyJhY2NvdW50cy5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsE+vzm1BhzJJ5KKgJKPGX4M3GbeM0c25HOVQL1aLbOEHm92HBFk1djM9a8WLDfg/d8SLh3Ehta0i0ctATwU0CSeeodvsqL4mKEOXYEqIi1f8ixCX0c7vJ0ESNcyWeAm18F9WNtFKKDOM7gzCn0zuuAZR3m/rBaPDOkoX1AULrkMZjnantrw4z8hL344dLAneta5JiulJor2NiJGNU5EHcVjw7eMDunPTpC/IAxDKF5/hTQ0Hj4+R2AzuSBO0DZ3T2G7/6lmIguOIanfGoYGKev4JvumXahkVGf/tgZ3WuoUqB8KEIM8VGjS0MjBFgCtxX6GmvRD+H3F58x4bsBAZxwIDAQABoyEwHzAdBgNVHQ4EFgQU+A6C3/xdVe7vu2wezFXPLQE0nyMwDQYJKoZIhvcNAQELBQADggEBADAAoTCjqbO+Ku6E1nbOUkq513ETV+7iL6g7FnxY4ysl2qPAsgPcLOO/HoWGLNfu4fbqyBqtSpoHYQUEe2e4FNF9T0EB5B5NShFiSlLVcQyp23PcrcInQRnb7x9iX/ztxm1bpNnLXrQrh/RTsdev6LqiIfhC2XH70Avb6LTYcBMkUuo9Y2kxT3WtyklSl0Ogr3td/lPZne1vcPP4h64uzE9+GKcm+2iZRyWGMjtG6DnC1whmoetqDDmQ9pmHi2xlxSjcTS8oq/FwEA20sjNO4DdBN9tS2VMwVZldZ/Z594sRKOPo3kPVdKhJZud5Yt2nt+xiHcjKY48HmOXRnF8AOto= + + + + + + pO+tkeMWqlmQJ6WmA1k2HOVlYfBGf0CnHApnDU9cGTk= + + + + + + + spn:caaa139f-4810-4355-a5b5-d8417b406909 + + + + + x + + + x + + + Beers + + + Jacob + + + Jacob Beers + + + jbeers@ortussolutions.com + + + live.com + + + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password + http://schemas.microsoft.com/claims/multipleauthn + + http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/unspecified + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:Password + + + + \ No newline at end of file diff --git a/test-harness/tests/specs/ProviderServiceSpec.cfc b/test-harness/tests/specs/ProviderServiceSpec.cfc index cc42f26..96bb2c9 100644 --- a/test-harness/tests/specs/ProviderServiceSpec.cfc +++ b/test-harness/tests/specs/ProviderServiceSpec.cfc @@ -37,49 +37,6 @@ component extends="coldbox.system.testing.BaseTestCase" { it( "can be created", function(){ expect( service ).toBeComponent(); } ); - - // xstory( "I want to get disk records for registered disks", function(){ - // given( "a valid disk name", function(){ - // then( "I will get the disk record", function(){ - // service.register( provider: "Google" ); - // expect( service.getProviderRecord( "Google" ) ).toBeStruct(); - // } ); - // } ); - // given( "an invalid disk name", function(){ - // then( "It will throw an InvalidDiskException ", function(){ - // expect( function(){ - // service.getProviderRecord( "LinkedIn" ); - // } ).toThrow( "InvalidProviderException" ); - // } ); - // } ); - // } ); - - // xstory( "I want to retrieve providers via the get() operation", function(){ - // given( "a provider that has not been created yet", function(){ - // then( "it should build it, register it and return it", function(){ - // service.register( provider: "Google" ); - // var oProvider = service.get( "Google" ); - // expect( oProvider ).toBeComponent(); - // expect( oProvider.getProviderName() ).toBe( "Google" ); - // } ); - // } ); - - // given( "a previously built provider", function(){ - // then( "it should return the same provider", function(){ - // service.register( provider: "Google" ); - // var oProvider = service.get( "Google" ); - // expect( service.get( "Google" ).getIdentifier() ).toBe( oProvider.getIdentifier() ); - // } ); - // } ); - - // given( "an invalid and unregistered provider", function(){ - // then( "it should throw a InvalidProviderException", function(){ - // expect( function(){ - // service.get( "LinkedIn" ); - // } ).toThrow( "InvalidProviderException" ); - // } ); - // } ); - // } ); } ); } diff --git a/test-harness/tests/specs/SAMLParsingServiceTest.cfc b/test-harness/tests/specs/SAMLParsingServiceTest.cfc new file mode 100644 index 0000000..8c3af66 --- /dev/null +++ b/test-harness/tests/specs/SAMLParsingServiceTest.cfc @@ -0,0 +1,68 @@ +/** + * Disk Service Spec + */ +component extends="coldbox.system.testing.BaseTestCase" { + + this.loadColdbox = true; + // Unload Coldbox after this spec, since we are doing a shutdown of all disks + this.unLoadColdBox = false; + + /*********************************** LIFE CYCLE Methods ***********************************/ + + /** + * executes before all suites+specs in the run() method + */ + function beforeAll(){ + super.beforeAll(); + setup(); + } + + /** + * executes after all suites+specs in the run() method + */ + function afterAll(){ + super.afterAll(); + } + + /*********************************** BDD SUITES ***********************************/ + + function run( testResults, testBox ){ + // all your suites go here. + describe( "SAMLParsingService", function(){ + beforeEach( function( currentSpec ){ + setup(); + service = getInstance( "SAMLParsingService@cbsso" ); + } ); + + it( "can be created", function(){ + expect( service ).toBeComponent(); + } ); + + it( "should extract user info from a valid SAML response", function(){ + var rawSAMLResponse = fileRead( expandPath( "../resources/validSAMLResponse.xml" ) ); + var result = service.extractUserInfo( rawSAMLResponse ); + + expect( result.success ).toBeTrue(); + expect( result.firstName ).toBe( "Jacob" ); + expect( result.lastName ).toBe( "Beers" ); + expect( result.email ).toBe( "jbeers@ortussolutions.com" ); + } ); + + it( "should return an error message from the xml", function(){ + var rawSAMLResponse = fileRead( expandPath( "../resources/errorSAMLResponse.xml" ) ); + var result = service.extractUserInfo( rawSAMLResponse ); + + expect( result.success ).toBeFalse(); + expect( result.errorMessage ).toBe( "Invalid Content" ); + } ); + + it( "should return an error response if it can't parse the xml", function(){ + var result = service.extractUserInfo( "" ); + + expect( result.success ).toBeFalse(); + expect( result.errorMessage ).toStartWith( "Invalid SAML Response - could not extract error message." ); + } ); + }); + } + +} diff --git a/test-harness/tests/specs/providers/GoogleProviderSpec.cfc b/test-harness/tests/specs/providers/GoogleProviderSpec.cfc deleted file mode 100644 index 43a4be1..0000000 --- a/test-harness/tests/specs/providers/GoogleProviderSpec.cfc +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Disk Service Spec - */ -component extends="cbsso.models.testing.BaseProviderSpec" { - - this.loadColdbox = true; - // Unload Coldbox after this spec, since we are doing a shutdown of all disks - this.unLoadColdBox = false; - - variables.providerName = "GOogle"; - - function beforeAll(){ - super.beforeAll(); - setup(); - } - - /*********************************** BDD SUITES ***********************************/ - - function run( testResults, testBox ){ - // all your suites go here. - describe( "Google Specs", function(){ - beforeEach( function( currentSpec ){ - setup(); - provider = getProvider(); - var hyper = getInstance( "HyperRequest@hyper" ); - } ); - - story( "The service", function(){ - it( "should exist", function(){ - expect( provider ).toBeComponent(); - } ); - } ); - - // story( "I can authenticate with the provider", function(){ - // it( "can build the auth url", function(){ - // var authUrl = provider.buildAuthUrl(); - // var browser = launchInteractiveBrowser( variables.playwright.firefox() ); - // var page = browser.newPage(); - // navigate( page, authUrl ); - // waitForLoadState( page ); - // page.pause(); - // var oauthMessage = page.getByText( "The OAuth client was not found." ); - - // expect( oauthMessage.isVisible() ).toBeTrue(); - // } ); - - // it( "can build the request token url", function(){ - // var code = "any-token"; - // var tokenResponse = provider.makeAccessTokenRequest( code ); - - // expect( tokenResponse.content.getRequest().getBody() ).toInclude( code ); - // } ); - // } ); - } ); - } - -} From 25f9bb0ca1b3380387f38db77d6de960de32de5d Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:20:35 -0600 Subject: [PATCH 14/29] Change dependencies --- box.json | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/box.json b/box.json index 2edba7d..2ead2a4 100644 --- a/box.json +++ b/box.json @@ -24,13 +24,14 @@ "dependencies":{ "hyper":"^7.2.1", "jwt-cfml":"^1.2.0", - "cbjavaloader":"^2.1.1+8" + "cbjavaloader":"^2.1.1+8" }, "devDependencies":{ "commandbox-cfformat":"*", "commandbox-docbox":"*", "commandbox-dotenv":"*", - "commandbox-cfconfig":"*" + "commandbox-cfconfig":"*", + "bx-esapi":"^1.6.0+9" }, "ignore":[ "**/.*", @@ -62,6 +63,7 @@ "installPaths":{ "hyper":"modules/hyper/", "jwt-cfml":"modules/jwtcfml/", - "cbjavaloader":"modules/cbjavaloader/" + "cbjavaloader":"modules/cbjavaloader/", + "bx-esapi":".engine/boxlang/WEB-INF/boxlang/modules/bx-esapi/" } } From f23ea162253f10d149e6c49afd8a26ca0dcec1c9 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:20:40 -0600 Subject: [PATCH 15/29] Test --- .github/workflows/snapshot.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 590979f..02b2874 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -9,9 +9,9 @@ jobs: ########################################################################################## # Module Tests ########################################################################################## - # tests: - # secrets: inherit - # uses: ./.github/workflows/tests.yml + tests: + secrets: inherit + uses: ./.github/workflows/tests.yml ########################################################################################## # Format Source Code @@ -35,9 +35,9 @@ jobs: ########################################################################################## # Release it ########################################################################################## - release: - uses: ./.github/workflows/release.yml - needs: [ format ] - secrets: inherit - with: - snapshot: true + # release: + # uses: ./.github/workflows/release.yml + # needs: [ format ] + # secrets: inherit + # with: + # snapshot: true From c0fa35a9be365a1a0cbad0334b0e9126b0e3d3a8 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:22:33 -0600 Subject: [PATCH 16/29] Test --- .github/workflows/tests.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 52fc7f7..a18cd85 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,6 +2,7 @@ name: Test Suites # We are a reusable Workflow only on: + workflow_dispatch: workflow_call: secrets: SLACK_WEBHOOK_URL: @@ -128,15 +129,15 @@ jobs: .engine/**/logs/* .engine/**/WEB-INF/cfusion/logs/* - - name: Slack Notifications - # Only on failures and NOT in pull requests - if: ${{ failure() && !startsWith( 'pull_request', github.event_name ) }} - uses: rtCamp/action-slack-notify@v2 - env: - SLACK_CHANNEL: coding - SLACK_COLOR: ${{ job.status }} # or a specific color like 'green' or '#ff00ff' - SLACK_ICON_EMOJI: ":bell:" - SLACK_MESSAGE: '${{ github.repository }} tests failed :cry:' - SLACK_TITLE: ${{ github.repository }} Tests For ${{ matrix.cfengine }} with ColdBox ${{ matrix.coldboxVersion }} failed - SLACK_USERNAME: CI - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} + # - name: Slack Notifications + # # Only on failures and NOT in pull requests + # if: ${{ failure() && !startsWith( 'pull_request', github.event_name ) }} + # uses: rtCamp/action-slack-notify@v2 + # env: + # SLACK_CHANNEL: coding + # SLACK_COLOR: ${{ job.status }} # or a specific color like 'green' or '#ff00ff' + # SLACK_ICON_EMOJI: ":bell:" + # SLACK_MESSAGE: '${{ github.repository }} tests failed :cry:' + # SLACK_TITLE: ${{ github.repository }} Tests For ${{ matrix.cfengine }} with ColdBox ${{ matrix.coldboxVersion }} failed + # SLACK_USERNAME: CI + # SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} From e8eebff98efdf3e2da049cf96d8819d3a417cfeb Mon Sep 17 00:00:00 2001 From: jbeers Date: Tue, 25 Nov 2025 18:23:08 +0000 Subject: [PATCH 17/29] Apply cfformat changes --- models/providers/BaseProvider.cfc | 18 +-- models/providers/FacebookProvider.cfc | 4 +- models/providers/GitHubProvider.cfc | 4 +- models/providers/GoogleProvider.cfc | 4 +- models/providers/MicrosoftSAMLProvider.cfc | 15 +-- models/utility/SAMLParsingService.cfc | 117 +++++++++--------- .../tests/specs/SAMLParsingServiceTest.cfc | 14 ++- 7 files changed, 86 insertions(+), 90 deletions(-) diff --git a/models/providers/BaseProvider.cfc b/models/providers/BaseProvider.cfc index 30feb4e..60e7f8b 100644 --- a/models/providers/BaseProvider.cfc +++ b/models/providers/BaseProvider.cfc @@ -1,15 +1,17 @@ component { - public string function getRedirectUri( required any event ){ - if ( - structKeyExists( variables, "redirectURI" ) - && !isNull( variables.redirectURI ) - && len( variables.redirectURI ) - ) { + + public string function getRedirectUri( required any event ){ + if ( + structKeyExists( variables, "redirectURI" ) + && !isNull( variables.redirectURI ) + && len( variables.redirectURI ) + ) { return variables.redirectURI; } var event = requestService.getContext(); - return "#event.getHTMLBaseURL()#cbsso/auth/#variables.name.lcase()#"; + return "#event.getHTMLBaseURL()#cbsso/auth/#variables.name.lcase()#"; } -} \ No newline at end of file + +} diff --git a/models/providers/FacebookProvider.cfc b/models/providers/FacebookProvider.cfc index ddc4cd1..265b7bb 100644 --- a/models/providers/FacebookProvider.cfc +++ b/models/providers/FacebookProvider.cfc @@ -1,6 +1,6 @@ component - accessors="true" - extends="BaseProvider" + accessors ="true" + extends ="BaseProvider" implements="cbsso.models.ISSOIntegrationProvider" { diff --git a/models/providers/GitHubProvider.cfc b/models/providers/GitHubProvider.cfc index 3c38ea2..d66e022 100644 --- a/models/providers/GitHubProvider.cfc +++ b/models/providers/GitHubProvider.cfc @@ -1,6 +1,6 @@ component - accessors="true" - extends="BaseProvider" + accessors ="true" + extends ="BaseProvider" implements="cbsso.models.ISSOIntegrationProvider" { diff --git a/models/providers/GoogleProvider.cfc b/models/providers/GoogleProvider.cfc index bac49be..7c2386b 100644 --- a/models/providers/GoogleProvider.cfc +++ b/models/providers/GoogleProvider.cfc @@ -1,6 +1,6 @@ component - accessors="true" - extends="BaseProvider" + accessors ="true" + extends ="BaseProvider" implements="cbsso.models.ISSOIntegrationProvider" { diff --git a/models/providers/MicrosoftSAMLProvider.cfc b/models/providers/MicrosoftSAMLProvider.cfc index b6a6d55..3f77f24 100644 --- a/models/providers/MicrosoftSAMLProvider.cfc +++ b/models/providers/MicrosoftSAMLProvider.cfc @@ -1,6 +1,6 @@ component - accessors="true" - extends="BaseProvider" + accessors ="true" + extends ="BaseProvider" implements="cbsso.models.ISSOIntegrationProvider" { @@ -15,7 +15,7 @@ component property name="wirebox" inject="wirebox"; property name="AuthNRequestGenerator" inject="javaloader:cbsso.opensaml.AuthNRequestGenerator"; property name="responseValidator" inject="javaloader:cbsso.opensaml.AuthResponseValidator"; - property name="SAMLParsingService" inject="SAMLParsingService@cbsso"; + property name="SAMLParsingService" inject="SAMLParsingService@cbsso"; variables.name = "Microsoft Entra"; @@ -45,8 +45,8 @@ component var authResponse = wirebox.getInstance( "SSOAuthorizationResponse@cbsso" ); try { - var decoded = binaryDecode( event.getValue( "SAMLResponse" ), "base64" ); - var data = charsetEncode( decoded, "utf-8" ); + var decoded = binaryDecode( event.getValue( "SAMLResponse" ), "base64" ); + var data = charsetEncode( decoded, "utf-8" ); var samlData = SAMLParsingService.extractUserInfo( data ); authResponse.setRawResponseData( data ); @@ -105,10 +105,7 @@ component } private boolean function detectSuccess( required xmlDoc ){ - return xmlSearch( - xmlDoc, - "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" - ).len() == 1; + return xmlSearch( xmlDoc, "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" ).len() == 1; } private boolean function extractErrorMessage( required xmlDoc ){ diff --git a/models/utility/SAMLParsingService.cfc b/models/utility/SAMLParsingService.cfc index 37fefd1..45b7f17 100644 --- a/models/utility/SAMLParsingService.cfc +++ b/models/utility/SAMLParsingService.cfc @@ -1,73 +1,67 @@ component singleton { - public struct function extractUserInfo( required string rawSAMLResponse ){ - var data = { - "success": false, - "errorMessage": "", - "error": "", - "firstName": "", - "lastName": "", - "email": "", - "userId": "" - }; - var xmlData = xmlParse( rawSAMLResponse.reReplace( "xmlns="".+?""", "", "all" ) ); + public struct function extractUserInfo( required string rawSAMLResponse ){ + var data = { + "success" : false, + "errorMessage" : "", + "error" : "", + "firstName" : "", + "lastName" : "", + "email" : "", + "userId" : "" + }; + var xmlData = xmlParse( rawSAMLResponse.reReplace( "xmlns="".+?""", "", "all" ) ); - try{ - data.success = detectSuccess( xmlData ); + try { + data.success = detectSuccess( xmlData ); - if( !data.success ){ - data.errorMessage = extractErrorMessage( xmlData ); - return data; - } + if ( !data.success ) { + data.errorMessage = extractErrorMessage( xmlData ); + return data; + } - try{ - data.firstName = extractFirstName( xmlData ); - data.lastName = extractLastName( xmlData ); - data.email = extractEmail( xmlData ); - data.userId = extractUserId( xmlData ); + try { + data.firstName = extractFirstName( xmlData ); + data.lastName = extractLastName( xmlData ); + data.email = extractEmail( xmlData ); + data.userId = extractUserId( xmlData ); - return data; - } catch( any e ){ - data.success = false; - data.errorMessage = "Failed to extract user information: " & e.message; - data.error = e; - return data; - } - } - catch( any e ){ - data.success = false; - data.errorMessage = "Failed to extract user information: " & e.message; - data.error = e; - } + return data; + } catch ( any e ) { + data.success = false; + data.errorMessage = "Failed to extract user information: " & e.message; + data.error = e; + return data; + } + } catch ( any e ) { + data.success = false; + data.errorMessage = "Failed to extract user information: " & e.message; + data.error = e; + } - return data; - } - - private boolean function detectSuccess( required xmlDoc ){ - return xmlSearch( - xmlDoc, - "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" - ).len() == 1; + return data; + } + + private boolean function detectSuccess( required xmlDoc ){ + return xmlSearch( xmlDoc, "//samlp:StatusCode[@Value='urn:oasis:names:tc:SAML:2.0:status:Success']" ).len() == 1; } private string function extractErrorMessage( required xmlDoc ){ - try{ - return xmlSearch( xmlDoc, "//samlp:StatusMessage" )[ 1 ].xmlchildren[ 1 ].xmltext; - } - catch( any e ){ - try{ - var nodes = xmlSearch( xmlDoc, "//*" ); - for( var node in nodes ){ - if( node.xmlname.toLowerCase().contains( "statusmessage" ) ){ - return node.xmltext; - } - } - } - catch( any ex ){ - // do nothing - } - return "Invalid SAML Response - could not extract error message."; - } + try { + return xmlSearch( xmlDoc, "//samlp:StatusMessage" )[ 1 ].xmlchildren[ 1 ].xmltext; + } catch ( any e ) { + try { + var nodes = xmlSearch( xmlDoc, "//*" ); + for ( var node in nodes ) { + if ( node.xmlname.toLowerCase().contains( "statusmessage" ) ) { + return node.xmltext; + } + } + } catch ( any ex ) { + // do nothing + } + return "Invalid SAML Response - could not extract error message."; + } } private string function extractFirstName( required xmlDoc ){ @@ -97,4 +91,5 @@ component singleton { "//Attribute[@Name='http://schemas.microsoft.com/identity/claims/objectidentifier']" )[ 1 ].xmlchildren[ 1 ].xmltext; } -} \ No newline at end of file + +} diff --git a/test-harness/tests/specs/SAMLParsingServiceTest.cfc b/test-harness/tests/specs/SAMLParsingServiceTest.cfc index 8c3af66..7f5b105 100644 --- a/test-harness/tests/specs/SAMLParsingServiceTest.cfc +++ b/test-harness/tests/specs/SAMLParsingServiceTest.cfc @@ -40,29 +40,31 @@ component extends="coldbox.system.testing.BaseTestCase" { it( "should extract user info from a valid SAML response", function(){ var rawSAMLResponse = fileRead( expandPath( "../resources/validSAMLResponse.xml" ) ); - var result = service.extractUserInfo( rawSAMLResponse ); + var result = service.extractUserInfo( rawSAMLResponse ); expect( result.success ).toBeTrue(); expect( result.firstName ).toBe( "Jacob" ); expect( result.lastName ).toBe( "Beers" ); - expect( result.email ).toBe( "jbeers@ortussolutions.com" ); + expect( result.email ).toBe( "jbeers@ortussolutions.com" ); } ); it( "should return an error message from the xml", function(){ var rawSAMLResponse = fileRead( expandPath( "../resources/errorSAMLResponse.xml" ) ); - var result = service.extractUserInfo( rawSAMLResponse ); + var result = service.extractUserInfo( rawSAMLResponse ); expect( result.success ).toBeFalse(); expect( result.errorMessage ).toBe( "Invalid Content" ); } ); it( "should return an error response if it can't parse the xml", function(){ - var result = service.extractUserInfo( "" ); + var result = service.extractUserInfo( "" ); expect( result.success ).toBeFalse(); - expect( result.errorMessage ).toStartWith( "Invalid SAML Response - could not extract error message." ); + expect( result.errorMessage ).toStartWith( + "Invalid SAML Response - could not extract error message." + ); } ); - }); + } ); } } From 8821a33503de7237bb2c0c37b3dcc7fd8028e765 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:25:38 -0600 Subject: [PATCH 18/29] Add java build --- .github/workflows/tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a18cd85..2a96736 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,6 +46,10 @@ jobs: distribution: "temurin" java-version: "11" + - name: Build Java Deps + run: | + ./gradlew clean build + - name: Setup CommandBox CLI uses: Ortus-Solutions/setup-commandbox@v2.0.1 From 37090517de5b8e062d03e4059d915b28c1c49edc Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:27:29 -0600 Subject: [PATCH 19/29] Setup env --- .github/workflows/tests.yml | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a96736..302a686 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -54,19 +54,30 @@ jobs: uses: Ortus-Solutions/setup-commandbox@v2.0.1 # Not Needed in this module - #- name: Setup Environment For Testing Process - # run: | - # # Setup .env - # touch .env - # # ENV - # printf "DB_HOST=localhost\n" >> .env - # printf "DB_DATABASE=mydatabase\n" >> .env - # printf "DB_DRIVER=MySQL\n" >> .env - # printf "DB_USER=${{ env.DB_USER }}\n" >> .env - # printf "DB_PASSWORD=${{ env.DB_PASSWORD }}\n" >> .env - # printf "DB_CLASS=com.mysql.cj.jdbc.Driver\n" >> .env - # printf "DB_BUNDLEVERSION=8.0.19\n" >> .env - # printf "DB_BUNDLENAME=com.mysql.cj\n" >> .env + - name: Setup Environment For Testing Process + run: | + # Setup .env + touch .env + # ENV + printf "DB_HOST=localhost\n" >> .env + printf "GOOGLE_CLIENT_ID=test\n" >> .env + printf "GOOGLE_CLIENT_SECRET=test\n" >> .env + printf "GOOGLE_REDIRECT_URI=test\n" >> .env + printf "GOOGLE_AUTH_ENDPOINT=test\n" >> .env + printf "GOOGLE_ACCESS_TOKEN=test\n" >> .env + printf "GITHUB_CLIENT_ID=test\n" >> .env + printf "GITHUB_CLIENT_SECRET=test\n" >> .env + printf "GITHUB_REDIRECT_URI=test\n" >> .env + printf "GITHUB_AUTH_ENDPOINT=test\n" >> .env + printf "GITHUB_ACCESS_TOKEN=test\n" >> .env + printf "FACEBOOK_CLIENT_ID=test\n" >> .env + printf "FACEBOOK_CLIENT_SECRET=test\n" >> .env + printf "MS_ENTRA_REDIRECT_URI=test\n" >> .env + printf "MS_ENTRA_CLIENT_ID=test\n" >> .env + printf "MS_ENTRA_CLIENT_SECRET=test\n" >> .env + printf "MS_ENTRA_SIGN_ON_ENDPOINT=test\n" >> .env + printf "MS_ENTRA_FEDERATION_METADATA_URL=test\n" >> .env + printf "MS_ENTRA_ISSUER=test\n" >> .env - name: "Setup Environment Variables For Tests" id: current_version From 854107aeabc5c27969963696b8417da7ec775bd5 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:30:45 -0600 Subject: [PATCH 20/29] Add java build --- .github/workflows/tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 302a686..8b6c9c9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -48,7 +48,8 @@ jobs: - name: Build Java Deps run: | - ./gradlew clean build + cd java/cbsso-opensaml + ./gradlew :app:build - name: Setup CommandBox CLI uses: Ortus-Solutions/setup-commandbox@v2.0.1 From 338c5fc83daed84eb01acb417ae63971098b299f Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:32:02 -0600 Subject: [PATCH 21/29] Make executable --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8b6c9c9..87a7fbe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -49,6 +49,7 @@ jobs: - name: Build Java Deps run: | cd java/cbsso-opensaml + chmod +x ./gradlew ./gradlew :app:build - name: Setup CommandBox CLI From e0bfedb029135dd150197bc45616b2a7a8aac4ab Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:37:33 -0600 Subject: [PATCH 22/29] Fix tests --- .github/workflows/tests.yml | 20 +------------------- server-boxlang@1.json | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 87a7fbe..5fd2f3d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -81,24 +81,6 @@ jobs: printf "MS_ENTRA_FEDERATION_METADATA_URL=test\n" >> .env printf "MS_ENTRA_ISSUER=test\n" >> .env - - name: "Setup Environment Variables For Tests" - id: current_version - run: | - # master or snapshot - echo "Github Ref is $GITHUB_REF" - - # Setup .env - touch ./test-harness/.env - printf "GOOGLE_CLIENT_ID=new_google_id\n" >> ./test-harness/.env - printf "GOOGLE_CLIENT_SECRET=google_secret\n" >> ./test-harness/.env - printf "GITHUB_CLIENT_ID=test-value\n" >> ./test-harness/.env - printf "GITHUB_CLIENT_SECRET=test-value\n" >> ./test-harness/.env - printf "FACEBOOK_CLIENT_ID=test-value\n" >> ./test-harness/.env - printf "FACEBOOK_CLIENT_SECRET=test-value\n" >> ./test-harness/.env - printf "MS_ENTRA_CLIENT_ID=test-value\n" >> ./test-harness/.env - printf "MS_ENTRA_CLIENT_SECRET=test-value\n" >> ./test-harness/.env - printf "MS_ENTRA_SIGN_ON_ENDPOINT=test-value\n" >> ./test-harness/.env - - name: Install Test Harness with ColdBox ${{ matrix.coldboxVersion }} run: | box install @@ -109,7 +91,7 @@ jobs: - name: Start ${{ matrix.cfengine }} Server run: | box server start serverConfigFile="server-${{ matrix.cfengine }}.json" --noSaveSettings --debug - curl http://127.0.0.1:60299 + curl http://127.0.0.1:9181 - name: Run Tests run: | diff --git a/server-boxlang@1.json b/server-boxlang@1.json index 6ea7677..59f52c8 100644 --- a/server-boxlang@1.json +++ b/server-boxlang@1.json @@ -1,34 +1,30 @@ { - "name":"cbstorages-boxlang@1", + "name":"cbsso-boxlang", "app":{ "serverHomeDirectory":".engine/boxlang", - "cfengine":"boxlang@1" + "cfengine":"boxlang@be", + "libDirs":"./java/cbsso-opensaml/app/build/libs" + }, + "jvm":{ + "javaVersion":"openjdk21_jdk" }, "web":{ "http":{ - "port":"60299" + "port":"9181" }, "rewrites":{ - "enable": true + "enable":"true" }, - "webroot": "test-harness", - "aliases":{ + "webroot":"test-harness", + "aliases":{ "/moduleroot/cbSSO":"../" } }, - "JVM":{ - "heapSize":"768", - "javaVersion":"openjdk21_jre", - "args":"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888" - }, - "openBrowser":"false", + "openBrowser":"false", "cfconfig":{ "file":".cfconfig.json" }, - "env":{ - "BOXLANG_DEBUG":true - }, "scripts":{ - "onServerInitialInstall":"install bx-esapi,bx-compat-cfml --noSave" + "onServerInitialInstall":"install bx-compat-cfml,bx-esapi" } -} \ No newline at end of file +} From 5a8212cc4c3d5be6ca26f7ca1bcdde1404ffc043 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:42:37 -0600 Subject: [PATCH 23/29] Fix tests --- build/Build.cfc | 4 ++-- test-harness/views/main/index.cfm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build/Build.cfc b/build/Build.cfc index ae3231d..806181a 100644 --- a/build/Build.cfc +++ b/build/Build.cfc @@ -12,8 +12,8 @@ component { variables.cwd = getCWD().reReplace( "\.$", "" ); variables.artifactsDir = cwd & "/.artifacts"; variables.buildDir = cwd & "/.tmp"; - variables.apiDocsURL = "http://localhost:60299/apidocs/"; - variables.testRunner = "http://localhost:60299/tests/runner.cfm"; + variables.apiDocsURL = "http://localhost:9181/apidocs/"; + variables.testRunner = "http://localhost:9181/tests/runner.cfm"; // Source Excludes Not Added to final binary variables.excludes = [ diff --git a/test-harness/views/main/index.cfm b/test-harness/views/main/index.cfm index 0a4178f..2142944 100644 --- a/test-harness/views/main/index.cfm +++ b/test-harness/views/main/index.cfm @@ -5,7 +5,7 @@ Module Tester try{ user = getInstance( "AuthenticationService@cbauth" ).getUser(); - writeDUmp( user ); + writeDUmp( user.getEmail() ); } catch( NoUserLoggedIn e ){ writeDump( [ "no user" ] ); From 09dfb0896375bf6467ae24bcbd12971049a195a0 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:52:31 -0600 Subject: [PATCH 24/29] Fix tests --- box.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/box.json b/box.json index 2ead2a4..8b9b17b 100644 --- a/box.json +++ b/box.json @@ -58,7 +58,7 @@ "logs:2021":"server log serverConfigFile=server-adobe@2021.json --follow" }, "testbox":{ - "runner":"http://localhost:60299/tests/runner.cfm" + "runner":"http://localhost:9181/tests/runner.cfm" }, "installPaths":{ "hyper":"modules/hyper/", From a32dd858b948ee2981e7a13c299e450dbf8e1e21 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 12:57:42 -0600 Subject: [PATCH 25/29] Fix tests --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5fd2f3d..abc30b5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -78,7 +78,7 @@ jobs: printf "MS_ENTRA_CLIENT_ID=test\n" >> .env printf "MS_ENTRA_CLIENT_SECRET=test\n" >> .env printf "MS_ENTRA_SIGN_ON_ENDPOINT=test\n" >> .env - printf "MS_ENTRA_FEDERATION_METADATA_URL=test\n" >> .env + printf "MS_ENTRA_FEDERATION_METADATA_URL=https://login.microsoftonline.com/2b263285-61e2-49c4-a257-8234f38486a2/federationmetadata/2007-06/federationmetadata.xml\n" >> .env printf "MS_ENTRA_ISSUER=test\n" >> .env - name: Install Test Harness with ColdBox ${{ matrix.coldboxVersion }} From e808a51f4faf2b74eac824fa331fd911dbe585a8 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 13:09:55 -0600 Subject: [PATCH 26/29] Change mappings --- test-harness/tests/specs/SAMLParsingServiceTest.cfc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-harness/tests/specs/SAMLParsingServiceTest.cfc b/test-harness/tests/specs/SAMLParsingServiceTest.cfc index 7f5b105..6c2c566 100644 --- a/test-harness/tests/specs/SAMLParsingServiceTest.cfc +++ b/test-harness/tests/specs/SAMLParsingServiceTest.cfc @@ -39,7 +39,7 @@ component extends="coldbox.system.testing.BaseTestCase" { } ); it( "should extract user info from a valid SAML response", function(){ - var rawSAMLResponse = fileRead( expandPath( "../resources/validSAMLResponse.xml" ) ); + var rawSAMLResponse = fileRead( expandPath( "/tests/resources/validSAMLResponse.xml" ) ); var result = service.extractUserInfo( rawSAMLResponse ); expect( result.success ).toBeTrue(); @@ -49,7 +49,7 @@ component extends="coldbox.system.testing.BaseTestCase" { } ); it( "should return an error message from the xml", function(){ - var rawSAMLResponse = fileRead( expandPath( "../resources/errorSAMLResponse.xml" ) ); + var rawSAMLResponse = fileRead( expandPath( "/tests/resources/errorSAMLResponse.xml" ) ); var result = service.extractUserInfo( rawSAMLResponse ); expect( result.success ).toBeFalse(); From bf1977683c9456797027fa7c6aeef884e71147a4 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Tue, 25 Nov 2025 13:15:47 -0600 Subject: [PATCH 27/29] Bump version --- .github/workflows/snapshot.yml | 12 ++++++------ .github/workflows/tests.yml | 2 +- box.json | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 02b2874..aba4a20 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -35,9 +35,9 @@ jobs: ########################################################################################## # Release it ########################################################################################## - # release: - # uses: ./.github/workflows/release.yml - # needs: [ format ] - # secrets: inherit - # with: - # snapshot: true + release: + uses: ./.github/workflows/release.yml + needs: [ format ] + secrets: inherit + with: + snapshot: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index abc30b5..1c7bf7f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: cfengine: [ "lucee@5", "boxlang@1" ] - coldboxVersion: [ "^6.0.0", "^7.0.0" ] + coldboxVersion: [ "^7.0.0", "^8.0.0" ] experimental: [ false ] # Here we tests all engines against ColdBox@BE include: diff --git a/box.json b/box.json index 8b9b17b..e8d02e3 100644 --- a/box.json +++ b/box.json @@ -1,6 +1,6 @@ { "name":"cbsso", - "version":"1.8.0", + "version":"2.0.0", "location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsso/@build.version@/cbsso-@build.version@.zip", "author":"Ortus Solutions ", "homepage":"https://github.com/coldbox-modules/cbsso", From fe2085a21a8bd4c2487f2a277e73c4a4b03d8358 Mon Sep 17 00:00:00 2001 From: jbeers Date: Wed, 26 Nov 2025 19:08:55 +0000 Subject: [PATCH 28/29] Apply cfformat changes --- models/providers/MicrosoftSAMLProvider.cfc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/models/providers/MicrosoftSAMLProvider.cfc b/models/providers/MicrosoftSAMLProvider.cfc index 0c76f78..4c2ec29 100644 --- a/models/providers/MicrosoftSAMLProvider.cfc +++ b/models/providers/MicrosoftSAMLProvider.cfc @@ -12,12 +12,12 @@ component property name="federationMetadataURL"; property name="expectedIssuer"; - property name="wirebox" inject="wirebox"; - property name="AuthNRequestGenerator" ; - property name="responseValidator" ; - property name="SAMLParsingService" inject="SAMLParsingService@cbsso"; + property name="wirebox" inject="wirebox"; + property name="AuthNRequestGenerator"; + property name="responseValidator"; + property name="SAMLParsingService" inject="SAMLParsingService@cbsso"; - variables.name = "Entra"; + variables.name = "Entra"; variables.federationMetadataURL = ""; public string function getName(){ @@ -142,12 +142,12 @@ component } private void function initializeOpenSAMLLib(){ - if( !isNull( variables.AuthNRequestGenerator ) ){ + if ( !isNull( variables.AuthNRequestGenerator ) ) { return; } variables.AuthNRequestGenerator = createObject( "java", "cbsso.opensaml.AuthNRequestGenerator" ); - variables.responseValidator = createObject( "java", "cbsso.opensaml.AuthResponseValidator" ); + variables.responseValidator = createObject( "java", "cbsso.opensaml.AuthResponseValidator" ); variables.AuthNRequestGenerator.initOpenSAML(); responseValidator.cacheCerts( variables.federationMetadataURL ); From 7e1871fb262e869a9a2a27bdfe91b35a711444b9 Mon Sep 17 00:00:00 2001 From: Jacob Beers Date: Wed, 26 Nov 2025 13:17:48 -0600 Subject: [PATCH 29/29] Add saml init call --- models/providers/MicrosoftSAMLProvider.cfc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/models/providers/MicrosoftSAMLProvider.cfc b/models/providers/MicrosoftSAMLProvider.cfc index 4c2ec29..bc8d71e 100644 --- a/models/providers/MicrosoftSAMLProvider.cfc +++ b/models/providers/MicrosoftSAMLProvider.cfc @@ -27,6 +27,8 @@ component public any function setFederationMetadataURL( required string federationMetadataURL ){ variables.federationMetadataURL = federationMetadataURL; + initializeOpenSAMLLib(); + responseValidator.cacheCerts( variables.federationMetadataURL ); return this;