Compare commits

...
255 Commits
Author SHA1 Message Date
keycloak-bot 9481a351ed Set version to 3.0.0.Final 2017-03-22 14:14:35 +00:00
Stian Thorgersen f98dcf2d7e Merge pull request #3967 from vramik/3.0.x
KEYCLOAK-4638 Migrator to 3.0.0 contains code coppied from 2.5.0
2017-03-22 14:09:57 +01:00
vramik 27807c9bff KEYCLOAK-4638 Migrator to 3.0.0 contains code coppied from 2.5.0 2017-03-22 13:08:50 +01:00
keycloak-bot 22b56679e3 Set version to 3.0.1.Final-SNAPSHOT 2017-03-22 08:35:36 +00:00
keycloak-bot 3ba8989681 Set version to 3.0.0.Final 2017-03-22 07:52:15 +00:00
keycloak-bot bdd20b9699 Set version to 3.0.0.Final-SNAPSHOT 2017-03-16 13:24:15 +00:00
keycloak-bot 1cdecab650 Set version to 3.0.0.CR1 2017-03-16 12:04:07 +00:00
Stian Thorgersen de1650ccc4 Added jboss parent to boms parent 2017-03-16 11:23:40 +01:00
Pavel Drozd c30cdb5411 Merge pull request #3932 from vmuzikar/KEYCLOAK-4169
KEYCLOAK-4169 Instructions on how to run UI and Welcome Page tests
2017-03-15 23:53:49 +01:00
Pavel Drozd b2d677256d Merge pull request #3877 from mhajas/KEYCLOAK-3955
KEYCLOAK-3955 Add CORS tests to integration arquillian testsuite
2017-03-15 23:52:03 +01:00
Stian Thorgersen f44405207b Merge pull request #3828 from wildloop/master
verifySSL() - debug info
2017-03-15 09:55:42 +01:00
Stian Thorgersen feeac69197 Merge pull request #3888 from daklassen/KEYCLOAK-4421
KEYCLOAK-4421 Change any http maven urls to https to reduce build-time MITM vulnerability
2017-03-15 09:54:21 +01:00
Stian Thorgersen 2aa93d7d55 Merge pull request #3924 from daklassen/KEYCLOAK-2486
KEYCLOAK-2486: Update SimpleHTTP to use Apache HTTP Client
2017-03-15 09:50:06 +01:00
wildloop 80c9e23282 Update RequestAuthenticator.java 2017-03-15 09:14:48 +01:00
wildloop 366dee6575 Update RequestAuthenticator.java 2017-03-15 09:13:41 +01:00
Stian Thorgersen 44907503a4 Merge pull request #3935 from knutz3n/KEYCLOAK-4559
KEYCLOAK-4559 Filter users by realm id when search for user by attribute
2017-03-15 08:44:43 +01:00
Bill Burke 1974b34c29 Merge pull request #3928 from sebastienblanc/test-utilities
KEYCLOAK-4322 : adding a helper class
2017-03-14 11:32:49 -04:00
Bill Burke 6d51862057 Merge pull request #3897 from anderius/feature/KEYCLOAK-4504-redirect-logout
[WIP] Saml broker: Option to specify logout request binding
2017-03-14 11:32:26 -04:00
wildloop d723c608d6 Update RequestAuthenticator.java 2017-03-14 11:36:57 +01:00
Johannes Knutsen 9a0de676c4 KEYCLOAK-4559 Filter users by realm id when searching for user by user attribute 2017-03-14 11:05:12 +01:00
Stian Thorgersen a555f99b1a Merge pull request #3937 from sebastienblanc/document_sb_properties
KEYCLOAK-4565 : javadoc for adapter properties and add metada generator
2017-03-14 10:19:34 +01:00
David Klassen 32d3f760ec KEYCLOAK-4421: Change http url to https
Change any http maven urls to https to reduce build-time MITM vulnerability
2017-03-14 10:18:40 +01:00
Stian Thorgersen 99581748e0 Merge pull request #3921 from gmarziou/fix-french-plural
KEYCLOAK-4561 Fix plural error in French translation
2017-03-14 09:32:37 +01:00
Stian Thorgersen f0ae34d1ad Merge pull request #3885 from sk8ter/master
add Swedish translation for account, email, login
2017-03-14 09:31:36 +01:00
Stian Thorgersen 4f39cf8abd Merge pull request #3947 from ssilvert/master
KEYCLOAK-4535: Needless heading while adding or editing a Role
2017-03-14 08:56:21 +01:00
Stan Silvert e6df617cfc KEYCLOAK-4535: Needless heading while adding or editing a Role 2017-03-13 21:03:05 -04:00
Pedro Igor 9d1d22565c Merge pull request #3938 from pedroigor/authz-fixes
AuthZ Services Fixes
2017-03-13 15:20:41 -03:00
Pedro Igor e7e6314146 [KEYCLOAK-4555] - Fixes and improvements to evaluation code 2017-03-13 14:08:54 -03:00
Marek Posolda 649ca36ece Merge pull request #3945 from mposolda/master
KEYCLOAK-4572 AccountTest.changeProfileNoAccess unstable
2017-03-13 15:57:43 +01:00
Pavel Drozd 253c8a342b Merge pull request #3941 from pdrozd/KEYCLOAK-4569
KEYCLOAK-4569 SSSDTest rewrited to be usable in different enviroments
2017-03-13 15:50:06 +01:00
Pavel Drozd 71a9d51c56 Merge pull request #3940 from pdrozd/KEYCLOAK-4304
KEYCLOAK-4304 Updated Kerberos tests to be able to run them on differ…
2017-03-13 15:49:01 +01:00
Stian Thorgersen ef164f5e69 Merge pull request #3943 from stianst/TRAVIS
Add --no-snapshot-updates to Travis builds
2017-03-13 15:41:05 +01:00
Stian Thorgersen b0484409d4 Remove adapter tests from Travis as no tests where being ran 2017-03-13 14:42:39 +01:00
mposolda aa84709087 KEYCLOAK-4572 AccountTest.changeProfileNoAccess unstable 2017-03-13 13:58:46 +01:00
Stian Thorgersen adf3eaf8fe Merge pull request #3942 from stianst/KEYCLOAK-4570
KEYCLOAK-4570
2017-03-13 12:32:08 +01:00
Stian Thorgersen 4dcb8d2c2a Merge pull request #3931 from hmlnarik/KEYCLOAK-4552
KEYCLOAK-4552
2017-03-13 12:31:33 +01:00
Stian Thorgersen 2cf4518ffd Disable snapshot for repositories 2017-03-13 09:03:46 +01:00
Stian Thorgersen 3f29c68e92 Add --no-snapshot-updates to Travis builds 2017-03-13 08:53:03 +01:00
Stian Thorgersen a56dd1651b KEYCLOAK-4570
Boms should not use keycloak-parent
2017-03-13 08:34:52 +01:00
Pavel Drozd f32fc99e80 KEYCLOAK-4569 SSSDTest rewrited to be usable in different enviroments 2017-03-13 08:05:30 +01:00
Pavel Drozd b5433720c1 KEYCLOAK-4304 Updated Kerberos tests to be able to run them on different environment 2017-03-13 08:00:41 +01:00
Bill Burke 613f4bb4c6 Merge pull request #3939 from alexeykazakov/patch-1
KEYCLOAK-4568 Identity broker service may fail to validate client ses…
2017-03-11 19:39:39 -05:00
Alexey Kazakov 063f5303dd KEYCLOAK-4568 Identity broker service may fail to validate client session if there is more then one active session 2017-03-11 12:59:25 -08:00
Pedro Igor 45caea4dbd [KEYCLOAK-4549] - Scope Permission Form is not showing saved resource 2017-03-10 17:32:55 -03:00
sebastienblanc 68da8c23ad KEYCLOAK-4565 : javadoc for adapter properties and add metada generator 2017-03-10 18:13:19 +01:00
Pavel Drozd 282896b653 Merge pull request #3930 from vmuzikar/KEYCLOAK-4554-2
KEYCLOAK-4554 Fix WelcomePage test
2017-03-10 15:57:47 +01:00
Pavel Drozd 3884dd974a Merge pull request #3925 from vmuzikar/KEYCLOAK-4553
KEYCLOAK-4553 Truststore not found in Arquillian tests in "other" module
2017-03-10 15:56:40 +01:00
sebastienblanc 64f20b580a adding a helper class 2017-03-10 14:43:16 +01:00
Stian Thorgersen e7cd8d41c6 Merge pull request #3558 from glavoie/KEYCLOAK-3989
KEYCLOAK-3989: Replacing COMPOSITE_ROLE Collection with Set.
2017-03-10 12:00:59 +01:00
Vaclav Muzikar f3e842fdd9 KEYCLOAK-4169 Instructions on how to run UI and Welcome Page tests 2017-03-10 11:26:21 +01:00
Hynek Mlnarik 42954e84d9 KEYCLOAK-4552 2017-03-10 10:59:50 +01:00
Bill Burke 0ff4223184 Merge pull request #3922 from hmlnarik/KEYCLOAK-4288-SAML-logouts-are-not-invalidating-the-sessions-for-all-the-logged-in-applications
KEYCLOAK-4288 Invalidate sessions in cluster for SAML logouts
2017-03-09 19:13:37 -05:00
Bill Burke b618dbd97f Merge pull request #3926 from mrpardijs/KEYCLOAK-4360-Add-SAML-OneTimeUse-Condition
KEYCLOAK-4360: Add OneTimeUse condition to SAMLResponse
2017-03-09 19:09:02 -05:00
Bill Burke 213cffa9c5 Merge pull request #3929 from gmarziou/update-freeotp-url
Update URL for FreeOTP
2017-03-09 19:00:13 -05:00
Vaclav Muzikar dc2d2cdbde Merge branch 'master' of https://github.com/keycloak/keycloak into KEYCLOAK-4553 2017-03-09 16:54:08 +01:00
Vaclav Muzikar 8b888fdf0c KEYCLOAK-4554 Fix WelcomePage test 2017-03-09 16:41:54 +01:00
Gaël MARZIOU 46c6db1739 Update URL for FreeOTP
It was poniting to obsolete location: https://fedorahosted.org/freeotp/

Now pointing to: https://freeotp.github.io/
2017-03-09 16:20:28 +01:00
Pavel Drozd 11d93994c2 Merge pull request #3919 from vramik/KEYCLOAK-4210
KEYCLOAK-4210 remove redundant dependency
2017-03-09 15:49:55 +01:00
Mark Pardijs c78c0b73d3 KEYCLOAK-4360: Add OneTimeUse condition to SAMLResponse
Add OneTimeUse Condition to SAMLResponse when configured in client settings
2017-03-09 13:01:05 +01:00
Vaclav Muzikar 2175f66a30 KEYCLOAK-4553 Truststore not found in Arquillian tests in "other" module 2017-03-09 11:17:42 +01:00
David Klassen 7029ef80f8 KEYCLOAK-2486: Update SimpleHTTP to use Apache HTTP Client
Update SimpleHTTP to use Apache HTTP client under the covers.
2017-03-09 09:23:09 +01:00
Marek Posolda 16d5ca3378 Merge pull request #3859 from thomasdarimont/issue/KEYCLOAK-4205-role-mapper-value-as-array
KEYCLOAK-4205 Allow to return json arrays in Client and Realm Role Mappers
2017-03-09 08:47:29 +01:00
Stian Thorgersen 5b4e3434bb Merge pull request #3886 from anderius/feature/newlines-in-saml
KEYCLOAK-4489 SAML encrypted assertion with newlines fails during parsing
2017-03-09 08:29:55 +01:00
Thomas Darimont 1dea38bdbb KEYCLOAK-4205 Allow to return json arrays in Client and Realm Role Mappers
Previously the ClientRoleMapper and RealmRoleMapper returned
roles as a comma delimited String in OIDC tokens which
needed to be parsed by client applications.
We now support to generate the role information as JSON
arrays by setting "multi valued" to "true" in the
client role mapper or realm role mappers respectively
which makes it easier for clients to consume.

The default setting for "multi valued" is "false" to
remain backwards compatible.

An example AccessToken that shows the two modes can be found here:
https://gist.github.com/thomasdarimont/dff0cd691cd6e0b5e33c2eb4c76ae5e8
2017-03-08 20:56:56 +01:00
Gael MARZIOU 0fc4cd134f Fix plural error in French translation 2017-03-08 18:47:06 +01:00
Bill Burke efffcc5f41 Merge pull request #3915 from TeliaSoneraNorge/KEYCLOAK-4524
KEYCLOAK-4524
2017-03-08 10:08:04 -05:00
Bill Burke 6f2ace538f Merge pull request #3917 from reneploetz/master
KEYCLOAK-4537 Jetty 9.4 implementation (OIDC/SAML)
2017-03-08 09:44:33 -05:00
Stian Thorgersen 50af3212f1 Merge pull request #3920 from stianst/master
KEYCLOAK-4536 Added troubleshooting section to Cordova example
2017-03-08 12:25:01 +01:00
Stian Thorgersen e2e91ef098 KEYCLOAK-4536 Added troubleshooting section to Cordova example 2017-03-08 12:23:57 +01:00
vramik 0c4a1b1489 KEYCLOAK-4210 remove redundant dependency 2017-03-08 10:51:18 +01:00
Stian Thorgersen 61c3d6eb74 Merge pull request #3913 from sebastienblanc/adapter_dist
add adapters dist artifact
2017-03-08 09:10:56 +01:00
Pavel Drozd 62876b9694 Merge pull request #3912 from vmuzikar/KEYCLOAK-4526
KEYCLOAK-4526 Fix Node.js Arquillian tests
2017-03-07 21:53:30 +01:00
Pavel Drozd 739dae0846 Merge pull request #3908 from vramik/KEYCLOAK-4348
KEYCLOAK-4348 upgrade maven-surefire-plugin version
2017-03-07 21:52:24 +01:00
Pavel Drozd 7ab67d205b Merge pull request #3903 from tkyjovsk/KEYCLOAK-4515
KEYCLOAK-4515 Make it possible to clean-up other DB types than mysql or postgres
2017-03-07 21:50:48 +01:00
Anders Båtstrand 224c9c5395 KEYCLOAK-4489 Use event reader from AbstractParser, which handles newlines and whitespace. 2017-03-07 19:05:07 +01:00
wildloop 7904ce5a37 one-line debug log 2017-03-07 16:01:13 +01:00
Rene Ploetz e770a05db0 KEYCLOAK-4537 Jetty 9.4 implementation (OIDC/SAML) 2017-03-06 23:01:24 +01:00
Pavel Drozd 89c89b4867 Merge pull request #3873 from mhajas/KEYCLOAK-3961
KEYCLOAK-3961
2017-03-06 13:01:16 +01:00
mhajas 213ed6fa4b KEYCLOAK-3955 2017-03-06 10:22:06 +01:00
mhajas 280689055f KEYCLOAK-3961 2017-03-06 10:17:59 +01:00
Bill Burke 1d11cb468c Merge pull request #3914 from patriot1burke/master
KEYCLOAK-4501 KEYCLOAK-4511 KEYCLOAK-4513
2017-03-03 14:13:59 -05:00
Bill Burke 05e080624b import after each test 2017-03-03 11:32:48 -05:00
Bill Burke c6dc59f63e Merge remote-tracking branch 'upstream/master' 2017-03-03 11:00:32 -05:00
Martin Hardselius a0a85f62c6 KEYCLOAK-4524 possible to add identity prover mappers with same name into single identity provider
- unique name enforcement working
- test added
2017-03-03 16:40:49 +01:00
Bill Burke 3bb29e033b KEYCLOAK-4501, KEYCLOAK-4511, KEYCLOAK-4513 2017-03-03 09:48:52 -05:00
sebastienblanc 87c9c99259 add adapters dist artifact 2017-03-03 11:45:13 +01:00
Vaclav Muzikar b0b0bfdf76 KEYCLOAK-4526 Fix Node.js Arquillian tests 2017-03-03 11:08:13 +01:00
Marek Posolda b8767d13d5 Merge pull request #3907 from mposolda/cross-dc
KEYCLOAK-4520 Enable testsuite logging when running test from IDE
2017-03-02 12:23:36 +01:00
Marek Posolda 686f82342b Merge pull request #3905 from Dichotomia/patch-3
administrator Spelling mistake
2017-03-02 12:23:20 +01:00
Marek Posolda cfb8d25ff2 Merge pull request #3900 from KillerDiller/wellknownprovider-four-oh-four
KEYCLOAK-4519: Avoid NPE for unknown paths under .../.well-known/.
2017-03-02 12:22:35 +01:00
vramik a24070c2b0 KEYCLOAK-4348 upgrade maven-surefire-plugin version 2017-03-02 12:09:15 +01:00
mposolda 69e61398a6 KEYCLOAK-4520 Enable testsuite logging when running test from IDE 2017-03-02 10:50:50 +01:00
Stan Silvert 89768ef003 Merge pull request #3906 from ssilvert/update-migration-scripts
KEYCLOAK-4514: Update migration scripts according to changes to the
2017-03-01 15:54:57 -05:00
Stan Silvert 794defe6fc KEYCLOAK-4514: Update migration scripts according to changes to the
subsystem
2017-03-01 13:53:40 -05:00
Hynek Mlnarik 27ba4eb978 KEYCLOAK-4288 Tests for EAP6 and Wildfly 2017-03-01 15:17:39 +01:00
Hynek Mlnarik 3a0c2be885 KEYCLOAK-4288 AS 7 / EAP 6 2017-03-01 15:17:39 +01:00
Hynek Mlnarik 04da679628 KEYCLOAK-4288 Wildfly 2017-03-01 15:17:39 +01:00
Hynek Mlnarik 43be3fc409 KEYCLOAK-4288 Use SessionListener to keep track of local HTTP-SSO session mappings 2017-03-01 15:17:39 +01:00
Hynek Mlnarik 567393a102 KEYCLOAK-4288 Fix SAML logout session for Tomcat/EAP6
When logging out via application (via ?GLO=true query parameter),
CatalineSamlSessionStore does not expire session, while it does that
in logging by SAML session index.

This causes distributed sessions being invalidated only on node hanling
the request, but remains active in other nodes of the cluster. Then the
session can be resurrected on next cache replication back even to the
node where the logout was performed. This behaviour is fixed here.
2017-03-01 15:17:39 +01:00
Quentin Caillard 75851ee0b3 administrator Spelling mistake 2017-03-01 12:32:55 +01:00
Marek Posolda b54d7c37b6 Merge pull request #3890 from daklassen/KEYCLOAK-2994
KEYCLOAK-2994: Revise german translations
2017-03-01 12:22:44 +01:00
Marek Posolda 69cf7b4d0d Merge pull request #3891 from mikaoelitiana/KEYCLOAK-4497
Update french translation in admin console
2017-03-01 12:21:42 +01:00
Marek Posolda 4f4ae44a16 Merge pull request #3896 from thomasdarimont/issue/KEYCLOAK-4505-expose-clientSession-binding-to-ScriptBasedAuthenticator
KEYCLOAK-4505 Expose current clientSession binding to ScriptBasedAuthenticator
2017-03-01 12:17:29 +01:00
Marek Posolda 31191bdfc8 Merge pull request #3904 from mposolda/testsuite-import
KEYCLOAK-1590 Realm import per test class
2017-03-01 11:49:15 +01:00
mposolda 091b376624 KEYCLOAK-1590 Realm import per test class 2017-03-01 09:38:44 +01:00
Pavel Drozd 52fbe00c04 Merge pull request #3874 from vramik/KEYCLOAK-4258
KEYCLOAK-4258 add server-config-migration module to parent pom
2017-03-01 08:27:59 +01:00
Tomas Kyjovsky c94b7922aa Added profile jdbc-driver-depencency to arq. testsuite; changed jdbc module path from layers/base/com/${db} to layers/base/test/jdbc/${db} 2017-03-01 01:37:53 +01:00
Anders Båtstrand 8d82390843 KEYCLOAK-4504 New configuration option for SAML Broker:
* postBindingLogout: Indicates if POST or redirect should be used for the logout requests.

This applies to both IdP-initiated logout, and Keycloak-initiated logout. If unset (for example when upgrading Keycloak), the setting is initially set to the same as postBindingResponse.

The flag is also set when importing IdP metadata.
2017-02-28 12:08:22 +01:00
Bill Burke 0765b01189 Merge remote-tracking branch 'upstream/master' 2017-02-27 18:46:09 -05:00
Bill Burke b4f625e1ce KEYCLOAK-4501 2017-02-27 18:46:00 -05:00
Marek Posolda b5b0f433ac Merge pull request #3899 from hmlnarik/KEYCLOAK-4368-htmlUnit-for-adapter-tests-without-examples
KEYCLOAK-4368 Enable htmlUnit for adapter tests (not examples though)
2017-02-27 08:32:18 +01:00
Stefan Paletta bcbde3fdf0 Avoid NPE for unknown paths under .../.well-known/. 2017-02-27 02:42:02 +01:00
Hynek Mlnarik 1970e03361 KEYCLOAK-4368 Enable htmlUnit for adapter tests (not examples though) 2017-02-26 16:56:26 +01:00
Stian Thorgersen 07f99a946d Merge pull request #3895 from stianst/KEYCLOAK-943
KEYCLOAK-943 Added initial implementation for update profile
2017-02-24 15:17:46 +01:00
Stan Silvert 6ea9581c6c Merge pull request #3855 from tsabirgaliev/master
angular2-product-app: simplify KeycloakHttp
2017-02-24 08:09:31 -05:00
Thomas Darimont 18a8ed3e95 KEYCLOAK-4505 Expose current clientSession binding to ScriptBasedAuthenticator.
Previously the ScriptBasedAuthenticator did not expose the current
clientSession from the AuthenticationFlowContext.
In order to implement client specific authentications with javascript
one needs information about the current client.
2017-02-24 14:01:10 +01:00
Stian Thorgersen e2b1c97e26 KEYCLOAK-943 Added initial implementation for update profile 2017-02-24 13:19:29 +01:00
Tair Sabirgaliev 6a809a2009 update readme 2017-02-24 15:16:06 +06:00
Tair Sabirgaliev 6b808d78e6 refactor and implement unit and e2e tests 2017-02-24 14:13:09 +06:00
Tair Sabirgaliev 26edcdf6bc proper license and ng test 2017-02-24 06:38:09 +06:00
vramik f77670c4dd KEYCLOAK-4262 disable server-config-migration for distribution and add possibility to run it with profile 2017-02-23 14:46:05 +01:00
Tair Sabirgaliev 5a64d67404 Angular 2 PoC based on angular-cli generated project
- use `frontend-maven-plugin` to pull node/npm automatically
- tie `npm install` to relevant lifecycle (`mvn wildfly:deploy` automatically builds and includes build products into WAR)
- extern keycloak and product database base url, use `--env=war` to build a war colocated with keycloak and database app

Issues/Todos:
- when testing with `ng serve` will have to disable browser web security (product-database doesn’t allow cross-origin requests)
- no unit / e2e / arquillian tests for now
- `src/main/frontend/node_modules` is included in distribution build, this is a portability debt
2017-02-23 14:45:00 +06:00
Mika Andrianarijaona ceb5a3a04b Update french translation in admin console 2017-02-23 11:04:55 +03:00
David Klassen 999a3f62ac KEYCLOAK-2994: Revise german translations
Corrected a huge amount of typos. Improved some translations.
2017-02-23 08:45:51 +01:00
Stian Thorgersen ca64b90cbf Merge pull request #3889 from stianst/master
KEYCLOAK-4483
2017-02-23 04:26:36 +01:00
Stian Thorgersen 2a7f595d1c KEYCLOAK-4483
Overlay standalone differs from dist standalone
2017-02-22 19:44:01 +01:00
Pavel Drozd 089bde3571 Merge pull request #3852 from tkyjovsk/user-storage-tests
UserStorageTest migrated to Arquillian testsuite
2017-02-22 16:09:57 +01:00
Pavel Drozd 2f45183ee5 Merge pull request #3884 from vramik/KEYCLOAK-4262
KEYCLOAK-4262 make AbstractSamlTest class abstract
2017-02-22 16:08:51 +01:00
Tomas Kyjovsky a5677e87db UserStorageTest migrated to Arquillian testsuite 2017-02-22 13:54:11 +01:00
Stan Silvert 0d7b4bab11 Merge pull request #3883 from ssilvert/ace-warning
KEYCLOAK-4463: JS warnings caused by ui-ace while manipulating with
2017-02-22 07:33:57 -05:00
Viktor Kostov 2cf25b6c57 add Swedish translation for account, email, login 2017-02-22 11:51:30 +01:00
vramik 4fbb8ed994 KEYCLOAK-4262 make AbstractSamlTest class abstract 2017-02-22 10:20:34 +01:00
Stan Silvert 4f78312a98 KEYCLOAK-4463: JS warnings caused by ui-ace while manipulating with
mappers
2017-02-21 19:31:25 -05:00
Marek Posolda 48832f8ff4 Merge pull request #3880 from mposolda/hardcoded-ldap-mapper
KEYCLOAK-4433 Added HardcodedLDAPAttributeMapper
2017-02-21 11:20:02 +01:00
mposolda 098d8e915d KEYCLOAK-4433 Added HardcodedLDAPAttributeMapper 2017-02-21 08:29:57 +01:00
Marek Posolda 49e8918462 Merge pull request #3876 from mposolda/perf-htmlunit
KEYCLOAK-4368 Switch default WebDriver impl to htmlUnit
2017-02-20 22:49:36 +01:00
Stan Silvert 0f1e73facc Merge pull request #3878 from ssilvert/funny-realm-names
KEYCLOAK-4467: Realm name collides with sidebar navigation
2017-02-20 16:35:14 -05:00
mposolda f6bc0806d5 KEYCLOAK-4368 Switch default WebDriver impl to htmlUnit 2017-02-20 21:52:15 +01:00
Stan Silvert 3bf9428cc0 KEYCLOAK-4467: Realm name collides with sidebar navigation 2017-02-20 15:43:46 -05:00
Pavel Drozd ec32acec27 Merge pull request #3872 from mhajas/KEYCLOAK-4179
KEYCLOAK-4179
2017-02-20 15:44:29 +01:00
Pavel Drozd 152b4f13e7 Merge pull request #3871 from mhajas/KEYCLOAK-4626
KEYCLOAK-4626 KEYCLOAK-4261 KEYCLOAK-4181 KEYCLOAK-4160 Add tests for SAML issues
2017-02-20 15:43:38 +01:00
Pavel Drozd 284ef5992d Merge pull request #3868 from zschwarz/12-16-failing-ssl-tests-z
KEYCLOAK-4084 Fix ssl adapter tests
2017-02-20 15:42:19 +01:00
Stian Thorgersen faf0e98665 Merge pull request #3736 from guusdk/api-documentation
Improving the generated REST API documentation
2017-02-20 15:30:32 +01:00
Pedro Igor 4d614ed635 Merge pull request #3834 from ramunask/HttpMethod-null-pointer-fix
NPE fix for HttpMethod
2017-02-20 11:28:18 -03:00
Stian Thorgersen 3653d7ed9a Merge pull request #3762 from sldab/hide-providers
KEYCLOAK-4224 Allow hiding identity providers on login page
2017-02-17 12:04:35 +01:00
Stian Thorgersen eb5e30579d Merge pull request #3875 from stianst/master
Fix server dist broken due to userSessionPersister removed
2017-02-16 16:18:01 +01:00
Stian Thorgersen 1625e6c977 Fix server dist broken due to userSessionPersister removed 2017-02-16 16:15:40 +01:00
Pavel Drozd 6af06348bd Merge pull request #3806 from hmlnarik/KEYCLOAK-4191-OIDCProtocolMappersTest-sometimes-fails-on-mariadb
KEYCLOAK-4191 Fix for OIDCProtocolMappersTest on mariadb
2017-02-16 13:36:25 +01:00
vramik e960e45671 Enable server-config-migration for distribution 2017-02-16 13:00:27 +01:00
mhajas 5bce87d6e7 KEYCLOAK-4179 2017-02-16 10:50:10 +01:00
Stian Thorgersen 7db6d51a39 Merge pull request #3870 from stianst/MONGO-REMOVAL
KEYCLOAK-4384 Remove Mongo support
2017-02-16 10:50:04 +01:00
mhajas b1510c43ff KEYCLOAK-4160 2017-02-16 08:09:11 +01:00
mhajas 44c81910bf KEYCLOAK-4181 2017-02-16 08:04:42 +01:00
mhajas 27e390965e KEYCLOAK-4261 2017-02-16 08:04:23 +01:00
mhajas 119435ac76 KEYCLOAK-4262 Test for rejected consent 2017-02-16 08:04:06 +01:00
Pavel Drozd b31c38a158 Merge pull request #3862 from mhajas/KEYCLOAK-4329
KEYCLOAK-4329 Add test for empty KeyInfo
2017-02-16 07:52:13 +01:00
Stian Thorgersen 49ac3587b6 KEYCLOAK-4384 Remove Mongo support 2017-02-15 15:20:58 +01:00
Stian Thorgersen 06da1d164d Merge pull request #3866 from stianst/master
KEYCLOAK-4394 Use JBoss logging
2017-02-15 12:37:02 +01:00
mhajas f2a4fd029d KEYCLOAK-4084 Fix ssl adapter tests 2017-02-15 09:35:15 +01:00
Stian Thorgersen aa59c2f95f KEYCLOAK-4394 Use JBoss logging 2017-02-15 09:05:42 +01:00
Stian Thorgersen 8d5a8085a4 Merge pull request #3864 from sebastienblanc/springboot-starter
KEYCLOAK-4423 : Adding Spring Boot Starter
2017-02-15 08:54:10 +01:00
sebastienblanc 083f27f19d KEYCLOAK-4423 : Adding Spring Boot Adapter 2017-02-14 14:33:15 +01:00
Stian Thorgersen fe0b9e9893 Merge pull request #3850 from sebastienblanc/bom_update
added all the adapters in BOM
2017-02-14 13:09:41 +01:00
mhajas 91bcc24977 KEYCLOAK-4329 Add test for empty KeyInfo 2017-02-14 12:36:17 +01:00
Stian Thorgersen d72b67c460 Merge pull request #3857 from anderius/feature/KEYCLOAK-4392-component-id
KEYCLOAK-4392 Copy component id from representation to model
2017-02-14 09:43:38 +01:00
Bill Burke 68b5afed06 Merge pull request #3858 from patriot1burke/master
KEYCLOAK-4382
2017-02-13 13:34:41 -05:00
Bill Burke c3e72b11db KEYCLOAK-4382 2017-02-13 10:51:10 -05:00
Stan Silvert 224f93f25d Merge pull request #3782 from cargosoft/master
KEYCLOAK-4270 Custom login protocol doesn't show when creating a client
2017-02-13 07:58:21 -05:00
Anders Båtstrand 3af9f2f989 KEYCLOAK-4392 Copy component id from representation to model 2017-02-13 13:03:57 +01:00
Pavel Drozd 8668eff1b6 Merge pull request #3856 from mhajas/KEYCLOAK-3987
KEYCLOAK-3987 Add test for grant role from token
2017-02-13 10:43:32 +01:00
Pavel Drozd 3cec57da6a Merge pull request #3827 from mhajas/KEYCLOAK-4346
KEYCLOAK-4346 Validation tests are failing because of ban on server w…
2017-02-13 10:42:08 +01:00
Pavel Drozd 6602123b55 Merge pull request #3824 from mhajas/KEYCLOAK-4020
KEYCLOAK-4020 add test for boolean attribute
2017-02-13 10:41:04 +01:00
Pavel Drozd 767b4a2e2a Merge pull request #3811 from mhajas/KEYCLOAK-4286
KEYCLOAK-4286 Use desired version of JS-adapter
2017-02-13 10:39:56 +01:00
Pavel Drozd beb96b7f01 Merge pull request #3810 from vramik/KEYCLOAK-4337
KEYCLOAK-4337 Few fixes for testsuite
2017-02-13 10:38:31 +01:00
Pavel Drozd 4ede1174b7 Merge pull request #3805 from mhajas/KEYCLOAK-3841
KEYCLOAK-3841 Fix tests on windows
2017-02-13 10:37:32 +01:00
Stian Thorgersen e3a8bed5b2 Merge pull request #3853 from pedroigor/RHSSO-767
[RHSSO-767] - Wrong implementation of Request.getRelativePath causing failures on Tomcat-like adapters
2017-02-13 10:26:34 +01:00
Stian Thorgersen 4f214921e3 Merge pull request #3841 from mposolda/KEYCLOAK-4385
KEYCLOAK-4385 Added BundleBasedKeycloakConfigResolver
2017-02-13 10:25:44 +01:00
mhajas 00932f4eb3 KEYCLOAK-3987 Add test for grant role from token 2017-02-10 10:27:38 +01:00
Tair Sabirgaliev dbe87d6592 angular2-product-app: simplify KeycloakHttp 2017-02-10 05:41:49 +06:00
Pedro Igor 9416ee7224 [RHSSO-767] - Wrong implementation of Request.getRelativePath causing failures on Tomcat-like adapters 2017-02-09 21:27:28 -02:00
Bill Burke 75909a0add Merge pull request #3851 from patriot1burke/master
LDAP No-Import
2017-02-09 10:29:55 -05:00
Bill Burke d9633dc20c Merge remote-tracking branch 'upstream/master' 2017-02-09 09:13:00 -05:00
Bill Burke 75bee51ac1 console remote imported/unlink users 2017-02-09 09:11:48 -05:00
mhajas 7d203ed448 KEYCLOAK-4346 Validation tests are failing because of ban on server which provides some imports to SAML xsd 2017-02-09 14:15:45 +01:00
sebastienblanc bb9da83e52 added all the adapters in BOM 2017-02-09 11:15:07 +01:00
Stian Thorgersen 8e16e5d953 Merge pull request #3839 from stianst/SOCIAL_LOGIN_TEST
KEYCLOAK-4265 Social login tests
2017-02-09 10:15:17 +01:00
Stian Thorgersen 44180a68e6 Merge pull request #3845 from frelibert/KEYCLOAK-4378
KEYCLOAK-4378 New user attribute is not added after first login from …
2017-02-09 10:02:09 +01:00
Bill Burke cf5e2a1d20 unlink/remoteimported 2017-02-08 19:48:22 -05:00
Stian Thorgersen ceece3dce4 Merge pull request #3847 from stianst/KEYCLOAK-4008-CHECKSUMS
KEYCLOAK-4008 Include checksums in download files
2017-02-08 20:05:39 +01:00
Stian Thorgersen 520839a29b Merge pull request #3835 from mposolda/KEYCLOAK-4371
KEYCLOAK-4371 Offline Tokens still useless When SSO Session Max is Re…
2017-02-08 15:42:31 +01:00
Stian Thorgersen a6b1e4f5f7 Merge pull request #3829 from mposolda/master
KEYCLOAK-4364 Fix OpenLDAP issue with renaming DN
2017-02-08 15:40:42 +01:00
Stian Thorgersen c4df0d2690 Merge pull request #3843 from pedroigor/KEYCLOAK-4373
[KEYCLOAK-4373] - Adapter Feature Pack is missing keycloak-authz-client
2017-02-08 14:58:33 +01:00
Stian Thorgersen 3de77b7be9 KEYCLOAK-4008 Include checksums in download files 2017-02-08 14:51:36 +01:00
Frederik Libert f3a552ac9d KEYCLOAK-4378 New user attribute is not added after first login from broker 2017-02-07 15:37:16 +01:00
Pedro Igor 27c0f783bc [KEYCLOAK-4373] - Adapter Feature Pack is missing keycloak-authz-client 2017-02-07 08:43:53 -02:00
mposolda 72a5d03f34 KEYCLOAK-4385 Added BundleBasedKeycloakConfigResolver 2017-02-06 21:24:20 +01:00
Stian Thorgersen 5b5dc3e442 KEYCLOAK-4265 Social login tests 2017-02-06 13:50:10 +01:00
Stian Thorgersen 1c7de24084 Merge pull request #3832 from stianst/KEYCLOAK-4370
KEYCLOAK-4370 Prevent LDAP provider from being migrated twice
2017-02-06 08:21:30 +01:00
Bill Burke f157e2e637 LDAP No-Import: more tests 2017-02-05 09:41:52 -05:00
Bill Burke f128be9b31 LDAP No-Import 2017-02-04 10:29:34 -05:00
mposolda 8a16ab52a9 KEYCLOAK-4371 Offline Tokens still useless When SSO Session Max is Reached and normal userSession expired 2017-02-03 11:55:58 +01:00
Ramūnas Kraujutis b693a3ee47 In case of PKI validation exception HttpMethod throws NPE, because bytes value is null. 2017-02-03 11:24:30 +02:00
Stian Thorgersen f73aaef67a KEYCLOAK-4370 Prevent LDAP provider from being migrated twice 2017-02-03 10:05:57 +01:00
Stian Thorgersen 652152f167 Merge pull request #3825 from stianst/KEYCLOAK-4338
Various fixes to JS adapter
2017-02-03 08:58:44 +01:00
Agile Developer d60c3b7c0c missing import 2017-02-03 00:47:41 +01:00
mposolda 73cad40fb7 KEYCLOAK-4364 Fix OpenLDAP issue with renaming DN 2017-02-02 22:21:29 +01:00
Agile Developer cde3e87ad9 verifySSL() - debug info
DEBUG report like this:

SSL Verification: 
		passed: true, request is secure: true, 
		SSL is required for: EXTERNAL, 
		SSL is required for remote addr 192.168.100.123: false
2017-02-02 21:18:14 +01:00
Stian Thorgersen 68a171f36c Merge pull request #3823 from ssilvert/split-domain-script
KEYCLOAK-4362: Split domain script into two separate scripts
2017-02-02 21:08:18 +01:00
Stian Thorgersen be2378a424 Merge pull request #3820 from patriot1burke/master
KEYCLOAK-4363
2017-02-02 11:32:30 +01:00
Stian Thorgersen 9aa2dacec9 KEYCLOAK-4366 Issues when keycloak.js is initialized with token 2017-02-02 10:57:03 +01:00
mhajas ddf9301ceb KEYCLOAK-4020 add test for boolean attribute 2017-02-02 09:47:52 +01:00
vramik 7abe140621 resolve 'There is no context available for qualifier' message 2017-02-02 09:20:03 +01:00
Stian Thorgersen ee62c52543 KEYCLOAK-4338 KEYCLOAK-4331 Fixes to session iframe 2017-02-02 08:12:29 +01:00
Stan Silvert b4e4cbcbaa KEYCLOAK-4262: Update pom version 2017-02-01 14:38:52 -05:00
Stan Silvert a7c3d1b8df KEYCLOAK-4262 Split migration-domain script into two separate scripts 2017-02-01 14:23:20 -05:00
Bill Burke 79dede8e78 KEYCLOAK-4363 2017-02-01 10:19:15 -05:00
Bill Burke 1d04d56bdb Merge pull request #3816 from patriot1burke/master
KEYCLOAK-4218
2017-02-01 08:55:10 -05:00
Bill Burke 0d308e2b69 KEYCLOAK-4218 2017-01-31 15:15:49 -05:00
Pedro Igor 0c16a15b7d Merge pull request #3814 from pedroigor/authz-export-fixes
Authz export fixes
2017-01-31 15:57:40 -02:00
Marek Posolda beebeaa265 Merge pull request #3813 from mposolda/master
KEYCLOAK-4339 MigrationTest fails to run
2017-01-31 16:51:11 +01:00
Pedro Igor c705a8ffc8 [KEYCLOAK-4340] - Exporting authorization settings is updating policies with wrong data 2017-01-31 13:11:14 -02:00
Pedro Igor 57c74e3f39 [KEYCLOAK-4341] - Resources are not properly exported when exporting authorization settings 2017-01-31 13:10:25 -02:00
mposolda f92dd6bd16 KEYCLOAK-4339 MigrationTest fails to run 2017-01-31 16:00:16 +01:00
mhajas 99e1482e06 KEYCLOAK-4286 Use desired version of JS-adapter 2017-01-31 14:04:14 +01:00
vramik aec59a7e91 refactor asserts in ExportImportTest to be more verbose 2017-01-31 13:24:06 +01:00
vramik 9a16805f17 assumeCommunity for AccountPageTest.testLocalizedReferrerLinkContent 2017-01-31 13:22:16 +01:00
vramik 2fd0c38ad1 Removed unused import from LDAPBinaryAttributesTest 2017-01-31 13:18:22 +01:00
Marek Posolda 2990703aeb Merge pull request #3809 from mposolda/master
KEYCLOAK-4169 Add how-to-run.md to testsuite
2017-01-31 09:11:06 +01:00
mposolda acf2e30c2f Fix MigrationTest 2017-01-30 22:23:19 +01:00
mposolda 5c5b7a33d3 KEYCLOAK-4169 Add initial testsuite how-to 2017-01-30 22:23:08 +01:00
Stian Thorgersen e28ca0ae61 Merge pull request #3807 from hmlnarik/KEYCLOAK-4329-NPE-when-not-providing-KeyInfo-element-in-IdP-initiated-SSO-SAML-
KEYCLOAK-4329 Fix NPE when not providing KeyInfo element in IdP initiated SSO SAML
2017-01-30 15:28:38 +01:00
Hynek Mlnarik ad0630d04f KEYCLOAK-4329 Fix NPE when not providing KeyInfo element in IdP initiated SSO SAML 2017-01-30 11:40:48 +01:00
Hynek Mlnarik 4d362fe9ca KEYCLOAK-4191 Fix for OIDCProtocolMappersTest on mariadb 2017-01-30 10:52:17 +01:00
Bill Burke bb77ab4a81 account link tests 2017-01-27 17:37:08 -05:00
Marek Posolda b42af99866 Merge pull request #3804 from mposolda/master
KEYCLOAK-4285 Adapter tests for examples fail in Wildfly/EAP6
2017-01-27 21:26:53 +01:00
mhajas 1a073629ec KEYCLOAK-3841 2017-01-27 14:43:46 +01:00
mposolda 265522a2e3 KEYCLOAK-4285 Adapter tests for examples fail in Wildfly/EAP6 2017-01-27 14:26:21 +01:00
Stian Thorgersen c10be4b1cf Merge pull request #3802 from stianst/RUN-TEST-ON-KC
KEYCLOAK-3729 Ability to run tests within Keycloak server
2017-01-27 13:45:51 +01:00
Stian Thorgersen 065c931a83 Merge pull request #3803 from stianst/BOMS
KEYCLOAK-4195 Keycloak adapter and SPI bom
2017-01-27 13:44:53 +01:00
Stian Thorgersen 7210ea36d2 KEYCLOAK-4195 Keycloak adapter and SPI bom 2017-01-27 12:19:40 +01:00
Stian Thorgersen 5fd3eb2990 KEYCLOAK-3729 Ability to run tests within Keycloak server 2017-01-27 12:14:19 +01:00
Stian Thorgersen 3a366dd0a6 Merge pull request #3800 from mstruk/KEYCLOAK-4324
KEYCLOAK-4324 Upgrade and unify Aesh version to 0.66.12
2017-01-27 09:23:29 +01:00
Marek Posolda 1674bf1643 Merge pull request #3799 from mposolda/master
KEYCLOAK-4271 Migration test for offline tokens
2017-01-26 18:50:30 +01:00
Marko Strukelj 3e13ffda65 KEYCLOAK-4324 Upgrade and unify Aesh version to 0.66.12 2017-01-26 18:08:48 +01:00
mposolda 42ad8aec64 KEYCLOAK-4271 Migration test for offline tokens 2017-01-26 17:19:03 +01:00
Marek Posolda 835d4c0aad Merge pull request #3798 from mposolda/master
KEYCLOAK-2813 Remove LegacyImportTest as the legacy JSON export/impor…
2017-01-26 12:13:51 +01:00
Stian Thorgersen ef9006e1a3 Merge pull request #3797 from stianst/master
Bump version to 3.0.0.CR1
2017-01-26 10:17:15 +01:00
mposolda a8e2c8ef31 KEYCLOAK-2813 Remove LegacyImportTest as the legacy JSON export/import tested with MigrationTest 2017-01-26 09:48:29 +01:00
Stian Thorgersen 6f22f88d85 Bump version to 3.0.0.CR1 2017-01-26 06:18:11 +01:00
Dmitry Telegin 5bacd2919d KEYCLOAK-4270 Custom login protocol doesn't show when creating a client 2017-01-21 01:46:34 +03:00
Slawomir Dabek 9bb65ba9b7 KEYCLOAK-4224 Allow hiding identity providers on login page 2017-01-17 14:32:59 +01:00
Guus der Kinderen ba73ab1c2a API documentation: Overview to left-hand side 2017-01-10 17:08:32 +01:00
Guus der Kinderen 45f5fa6a74 API documentation: Introduce and group by tags.
This commit introduces grouping of the documented REST resources. The grouping is based
on a free-form name of a resource (a 'tag' in Swagger terminology), which is introduced
by adding a @resource javadoc tag to every Resource class.
2017-01-10 17:08:27 +01:00
Guus der Kinderen 50b7dbe7b2 API documentation: Update dependencies. 2017-01-10 17:08:14 +01:00
Gabriel Lavoie 4910b35d69 KEYCLOAK-3989: Replacing COMPOSITE_ROLE Collection with Set.
- Hibernate optimization that avoids deleting/re-inserting all composite roles when adding/removing a composite.
2016-11-28 09:43:05 -05:00
1086 changed files with 90225 additions and 21687 deletions

No files matched your search

+1 -2
View File
@@ -16,7 +16,6 @@ env:
- TESTS=group2
- TESTS=group3
- TESTS=group4
- TESTS=adapter
- TESTS=old
jdk:
@@ -26,7 +25,7 @@ before_script:
- export MAVEN_SKIP_RC=true
install:
- travis_wait 60 mvn install -Pdistribution -DskipTests=true -B -V -q
- travis_wait 60 mvn install --no-snapshot-updates -Pdistribution -DskipTests=true -B -V -q
script:
- ./travis-run-tests.sh $TESTS
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -24,6 +24,7 @@ import org.keycloak.KeycloakPrincipal;
import org.keycloak.adapters.spi.AuthChallenge;
import org.keycloak.adapters.spi.AuthOutcome;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.common.enums.SslRequired;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -160,7 +161,8 @@ public abstract class RequestAuthenticator {
protected boolean verifySSL() {
if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
log.warn("SSL is required to authenticate");
log.warnf("SSL is required to authenticate. Remote address %s is secure: %s, SSL required for: %s .",
facade.getRequest().getRemoteAddr(), facade.getRequest().isSecure(), deployment.getSslRequired().name());
return true;
}
return false;
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-as7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-as7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-integration-pom</artifactId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -106,6 +106,8 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
public abstract JettyUserSessionManagement createSessionManagement(Request request);
public void logoutCurrent(Request request) {
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
@@ -287,7 +289,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
log.debug("*** deployment isn't configured return false");
return Authentication.UNAUTHENTICATED;
}
PreAuthActionsHandler handler = new PreAuthActionsHandler(new JettyUserSessionManagement(request.getSessionManager()), deploymentContext, facade);
PreAuthActionsHandler handler = new PreAuthActionsHandler(createSessionManagement(request), deploymentContext, facade);
if (handler.handleRequest()) {
return Authentication.SEND_SUCCESS;
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -15,19 +15,26 @@
* limitations under the License.
*/
package org.keycloak.models.mongo.keycloak.entities;
package org.keycloak.adapters.jetty;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@MongoCollection(collectionName = "userConsents")
public class MongoUserConsentEntity extends UserConsentEntity implements MongoIdentifiableEntity {
public class Jetty81SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty81SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public void afterRemove(MongoStoreInvocationContext invocationContext) {
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -25,6 +25,7 @@ import org.keycloak.adapters.AdapterTokenStore;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import javax.servlet.ServletRequest;
@@ -44,6 +45,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty81SessionManager(request.getSessionManager()));
}
@Override
protected Request resolveRequest(ServletRequest req) {
return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty91SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty91SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -27,6 +27,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import javax.servlet.ServletRequest;
@@ -46,6 +47,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty91SessionManager(request.getSessionManager()));
}
@Override
protected Request resolveRequest(ServletRequest req) {
return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty92SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty92SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -27,6 +27,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import javax.servlet.ServletRequest;
@@ -61,6 +62,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty92SessionManager(request.getSessionManager()));
}
@Override
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty93SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty93SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -26,6 +26,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import javax.servlet.ServletRequest;
@@ -60,6 +61,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty93SessionManager(request.getSessionManager()));
}
@Override
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
+156
View File
@@ -0,0 +1,156 @@
<?xml version="1.0"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-jetty94-adapter</artifactId>
<name>Keycloak Jetty 9.4.x Integration</name>
<properties>
<jetty9.version>9.4.2.v20170220</jetty9.version>
<keycloak.osgi.export>
org.keycloak.adapters.jetty.*
</keycloak.osgi.export>
<keycloak.osgi.import>
org.eclipse.jetty.*;resolution:=optional,
javax.servlet.*;version="[3.0,4)";resolution:=optional,
org.keycloak.*;version="${project.version}",
*;resolution:=optional
</keycloak.osgi.import>
</properties>
<description />
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss.logging.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jetty-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-ClassPath>.</Bundle-ClassPath>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Import-Package>${keycloak.osgi.import}</Import-Package>
<Export-Package>${keycloak.osgi.export}</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,47 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.Request;
import org.keycloak.adapters.AdapterTokenStore;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
import org.keycloak.adapters.spi.HttpFacade;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty94RequestAuthenticator extends JettyRequestAuthenticator {
public Jetty94RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
super(facade, deployment, tokenStore, sslRedirectPort, request);
}
@Override
protected String changeHttpSessionId(boolean create) {
Request request = this.request;
HttpSession session = request.getSession(false);
if (session == null) {
return request.getSession(true).getId();
}
if (!deployment.isTurnOffChangeSessionIdOnLogin()) return request.changeSessionId();
else return session.getId();
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.session.SessionHandler;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty94SessionManager implements JettySessionManager {
protected SessionHandler sessionHandler;
public Jetty94SessionManager(SessionHandler sessionHandler) {
this.sessionHandler = sessionHandler;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionHandler.getHttpSession(id);
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.MultiMap;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.spi.AdapterSessionStore;
import org.keycloak.common.util.MultivaluedHashMap;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JettyAdapterSessionStore implements AdapterSessionStore {
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
protected Request myRequest;
public JettyAdapterSessionStore(Request request) {
this.myRequest = request; // for IDE/compilation purposes
}
protected MultiMap<String> extractFormParameters(Request base_request) {
MultiMap<String> formParameters = new MultiMap<String>();
base_request.extractFormParameters(formParameters);
return formParameters;
}
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
base_request.setContentParameters(j_post);
}
public boolean restoreRequest() {
HttpSession session = myRequest.getSession(false);
if (session == null) return false;
synchronized (session) {
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
if (j_uri != null) {
// check if the request is for the same url as the original and restore
// params if it was a post
StringBuffer buf = myRequest.getRequestURL();
if (myRequest.getQueryString() != null)
buf.append("?").append(myRequest.getQueryString());
if (j_uri.equals(buf.toString())) {
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
myRequest.setMethod(method);
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
if (j_post != null) {
myRequest.setContentType("application/x-www-form-urlencoded");
MultiMap<String> map = new MultiMap<String>();
for (String key : j_post.keySet()) {
for (String val : j_post.getList(key)) {
map.add(key, val);
}
}
restoreFormParameters(map, myRequest);
}
session.removeAttribute(FormAuthenticator.__J_URI);
session.removeAttribute(JettyHttpFacade.__J_METHOD);
session.removeAttribute(FormAuthenticator.__J_POST);
}
return true;
}
}
return false;
}
public void saveRequest() {
// remember the current URI
HttpSession session = myRequest.getSession();
synchronized (session) {
// But only if it is not set already, or we save every uri that leads to a login form redirect
if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
StringBuffer buf = myRequest.getRequestURL();
if (myRequest.getQueryString() != null)
buf.append("?").append(myRequest.getQueryString());
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
MultiMap<String> formParameters = extractFormParameters(myRequest);
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
for (String key : formParameters.keySet()) {
for (Object value : formParameters.getValues(key)) {
map.add(key, (String) value);
}
}
session.setAttribute(CACHED_FORM_PARAMETERS, map);
}
}
}
}
}
@@ -0,0 +1,75 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.jetty;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.keycloak.adapters.AdapterTokenStore;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import javax.servlet.ServletRequest;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
public KeycloakJettyAuthenticator() {
super();
}
@Override
protected Request resolveRequest(ServletRequest req) {
return Request.getBaseRequest(req);
}
@Override
protected Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
@Override
public void logout() {
logoutCurrent(request);
}
};
}
@Override
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty94SessionManager(request.getSessionHandler()));
}
@Override
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
return new Jetty94RequestAuthenticator(facade, deployment, tokenStore, -1, request);
}
}
+2 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak Jetty Integration</name>
@@ -36,5 +36,6 @@
<module>jetty9.1</module>
<module>jetty9.2</module>
<module>jetty9.3</module>
<module>jetty9.4</module>
</modules>
</project>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+15 -16
View File
@@ -87,6 +87,10 @@
}
kc.flow = initOptions.flow;
}
if (initOptions.timeSkew != null) {
kc.timeSkew = initOptions.timeSkew;
}
}
if (!kc.responseMode) {
@@ -162,12 +166,8 @@
kc.onAuthSuccess && kc.onAuthSuccess();
initPromise.setSuccess();
}).error(function () {
kc.onAuthError && kc.onAuthError();
if (initOptions.onLoad) {
onLoad();
} else {
initPromise.setError();
}
setToken(null, null, null);
initPromise.setSuccess();
});
});
} else {
@@ -369,6 +369,11 @@
throw 'Not authenticated';
}
if (kc.timeSkew == null) {
console.info('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set');
return true;
}
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
if (minValidity) {
expiresIn -= minValidity;
@@ -653,12 +658,7 @@
if (token) {
kc.token = token;
kc.tokenParsed = decodeToken(token);
var sessionId = kc.realm + '/' + kc.tokenParsed.sub;
if (kc.tokenParsed.session_state) {
sessionId = sessionId + '/' + kc.tokenParsed.session_state;
}
kc.sessionId = sessionId;
kc.sessionId = kc.tokenParsed.session_state;
kc.authenticated = true;
kc.subject = kc.tokenParsed.sub;
kc.realmAccess = kc.tokenParsed.realm_access;
@@ -666,6 +666,9 @@
if (timeLocal) {
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
}
if (kc.timeSkew != null) {
console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
if (kc.onTokenExpired) {
@@ -677,11 +680,7 @@
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
}
}
} else {
kc.updateToken(-1);
}
} else if (refreshToken) {
kc.updateToken(-1);
} else {
delete kc.token;
delete kc.tokenParsed;
@@ -53,7 +53,8 @@
req.send();
} else {
if (clientId === init.clientId && origin === init.origin) {
if (sessionState === cookie) {
var c = cookie.split('/');
if (sessionState === c[2]) {
callback('unchanged');
} else {
callback('changed');
@@ -81,7 +82,7 @@
var origin = event.origin;
var data = event.data.split(' ');
if (data.length != 2) {
event.source.postMessage('error', origin);
return;
}
var clientId = data[0];
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,83 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.osgi;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.spi.HttpFacade;
import org.osgi.framework.BundleContext;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class BundleBasedKeycloakConfigResolver implements KeycloakConfigResolver {
private volatile KeycloakDeployment cachedDeployment;
private BundleContext bundleContext;
private String configLocation = "WEB-INF/keycloak.json";
public BundleContext getBundleContext() {
return bundleContext;
}
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
public String getConfigLocation() {
return configLocation;
}
public void setConfigLocation(String configLocation) {
this.configLocation = configLocation;
}
@Override
public KeycloakDeployment resolve(HttpFacade.Request request) {
if (cachedDeployment != null) {
return cachedDeployment;
} else {
cachedDeployment = findDeployment(request);
return cachedDeployment;
}
}
protected KeycloakDeployment findDeployment(HttpFacade.Request request) {
if (bundleContext == null) {
throw new IllegalStateException("bundleContext must be set for BundleBasedKeycloakConfigResolver!");
}
URL url = bundleContext.getBundle().getResource(configLocation);
if (url == null) {
throw new IllegalStateException("Failed to find the file " + configLocation + " on classpath.");
}
try {
InputStream is = url.openStream();
return KeycloakDeploymentBuilder.build(is);
} catch (IOException ioe) {
throw new IllegalStateException("Error reading file' " + configLocation + "' from bundle classpath.", ioe);
}
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<name>Keycloak OIDC Client Adapter Modules</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -53,6 +53,9 @@ import java.util.regex.Pattern;
* @version $Revision: 1 $
*/
public class KeycloakOIDCFilter implements Filter {
public static final String SKIP_PATTERN_PARAM = "keycloak.config.skipPattern";
protected AdapterDeploymentContext deploymentContext;
protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
protected NodesRegistrationManagement nodesRegistrationManagement;
@@ -63,7 +66,7 @@ public class KeycloakOIDCFilter implements Filter {
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
String skipPatternDefinition = filterConfig.getInitParameter("keycloak.config.skipPattern");
String skipPatternDefinition = filterConfig.getInitParameter(SKIP_PATTERN_PARAM);
if (skipPatternDefinition != null) {
skipPattern = Pattern.compile(skipPatternDefinition, Pattern.DOTALL);
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+9 -2
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -31,7 +31,7 @@
<description/>
<properties>
<spring-boot.version>1.2.1.RELEASE</spring-boot.version>
<spring-boot.version>1.3.0.RELEASE</spring-boot.version>
</properties>
<dependencies>
@@ -111,6 +111,13 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
@@ -38,9 +38,16 @@ public class KeycloakSpringBootProperties extends AdapterConfig {
return config;
}
/**
* To provide Java EE security constraints
*/
private List<SecurityConstraint> securityConstraints = new ArrayList<SecurityConstraint>();
@ConfigurationProperties()
public static class SecurityConstraint {
/**
* A list of security collections
*/
private List<SecurityCollection> securityCollections = new ArrayList<SecurityCollection>();
public List<SecurityCollection> getSecurityCollections() {
@@ -51,13 +58,31 @@ public class KeycloakSpringBootProperties extends AdapterConfig {
this.securityCollections = securityCollections;
}
}
@ConfigurationProperties()
public static class SecurityCollection {
/**
* The name of your security constraint
*/
private String name;
/**
* The description of your security collection
*/
private String description;
/**
* A list of roles that applies for this security collection
*/
private List<String> authRoles = new ArrayList<String>();
/**
* A list of URL patterns that should match to apply the security collection
*/
private List<String> patterns = new ArrayList<String>();
/**
* A list of HTTP methods that applies for this security collection
*/
private List<String> methods = new ArrayList<String>();
/**
* A list of HTTP methods that will be omitted for this security collection
*/
private List<String> omittedMethods = new ArrayList<String>();
public List<String> getAuthRoles() {
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak Tomcat Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -25,6 +25,7 @@ import org.apache.catalina.Manager;
import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AdapterTokenStore;
@@ -48,8 +49,6 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Keycloak authentication valve
@@ -62,7 +61,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
private final static Logger log = Logger.getLogger(""+AbstractKeycloakAuthenticatorValve.class);
private final static Logger log = Logger.getLogger(AbstractKeycloakAuthenticatorValve.class);
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
protected AdapterDeploymentContext deploymentContext;
protected NodesRegistrationManagement nodesRegistrationManagement;
@@ -118,22 +117,22 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
try {
KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
deploymentContext = new AdapterDeploymentContext(configResolver);
log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
log.debugv("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
} catch (Exception ex) {
log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", configResolverClass, ex.getMessage());
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
}
} else {
InputStream configInputStream = getConfigInputStream(context);
KeycloakDeployment kd;
if (configInputStream == null) {
log.warning("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
log.warn("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
kd = new KeycloakDeployment();
} else {
kd = KeycloakDeploymentBuilder.build(configInputStream);
}
deploymentContext = new AdapterDeploymentContext(kd);
log.fine("Keycloak is using a per-deployment configuration.");
log.debug("Keycloak is using a per-deployment configuration.");
}
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
@@ -149,8 +148,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
if (json == null) {
return null;
}
log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
log.finest(json);
log.trace("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
return new ByteArrayInputStream(json.getBytes());
}
@@ -159,13 +157,13 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
if (is == null) {
String path = context.getServletContext().getInitParameter("keycloak.config.file");
if (path == null) {
log.finest("**** using /WEB-INF/keycloak.json");
log.trace("**** using /WEB-INF/keycloak.json");
is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json");
} else {
try {
is = new FileInputStream(path);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, "NOT FOUND {0}", path);
log.errorv("NOT FOUND {0}", path);
throw new RuntimeException(e);
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak WildFly Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Keycloak Adapters</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -22,9 +22,10 @@ import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.keycloak.adapters.jbossweb.JBossWebPrincipalFactory;
import org.keycloak.adapters.saml.AbstractSamlAuthenticatorValve;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.saml.*;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
import javax.servlet.http.HttpServletResponse;
@@ -71,4 +72,11 @@ public class SamlAuthenticatorValve extends AbstractSamlAuthenticatorValve {
protected GenericPrincipalFactory createPrincipalFactory() {
return new JBossWebPrincipalFactory();
}
@Override
protected void addTokenStoreUpdaters() {
context.addApplicationListenerInstance(new IdMapperUpdaterSessionListener(mapper));
setIdMapperUpdater(SessionIdMapperUpdater.EXTERNAL);
super.addTokenStoreUpdaters();
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jbossweb.infinispan;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import org.apache.catalina.Context;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.manager.EmbeddedCacheManager;
import org.jboss.logging.Logger;
/**
*
* @author hmlnarik
*/
public class InfinispanSessionCacheIdMapperUpdater {
private static final Logger LOG = Logger.getLogger(InfinispanSessionCacheIdMapperUpdater.class);
public static final String DEFAULT_CACHE_CONTAINER_JNDI_NAME = "java:jboss/infinispan/container/web";
private static final String DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.cacheContainerJndi";
private static final String DEPLOYMENT_CACHE_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.deploymentCacheName";
private static final String SSO_CACHE_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.cacheName";
public static SessionIdMapperUpdater addTokenStoreUpdaters(Context context, SessionIdMapper mapper, SessionIdMapperUpdater previousIdMapperUpdater) {
boolean distributable = context.getDistributable();
if (! distributable) {
LOG.warnv("Deployment {0} does not use supported distributed session cache mechanism", context.getName());
return previousIdMapperUpdater;
}
ServletContext servletContext = context.getServletContext();
String cacheContainerLookup = (servletContext != null && servletContext.getInitParameter(DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME) != null)
? servletContext.getInitParameter(DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME)
: DEFAULT_CACHE_CONTAINER_JNDI_NAME;
// the following is based on https://github.com/jbossas/jboss-as/blob/7.2.0.Final/clustering/web-infinispan/src/main/java/org/jboss/as/clustering/web/infinispan/DistributedCacheManagerFactory.java#L116-L122
String host = context.getParent() == null ? "" : context.getParent().getName();
String contextPath = context.getPath();
if ("/".equals(contextPath)) {
contextPath = "/ROOT";
}
boolean deploymentSessionCacheNamePreset = servletContext != null && servletContext.getInitParameter(DEPLOYMENT_CACHE_NAME_PARAM_NAME) != null;
String deploymentSessionCacheName = deploymentSessionCacheNamePreset
? servletContext.getInitParameter(DEPLOYMENT_CACHE_NAME_PARAM_NAME)
: host + contextPath;
boolean ssoCacheNamePreset = servletContext != null && servletContext.getInitParameter(SSO_CACHE_NAME_PARAM_NAME) != null;
String ssoCacheName = ssoCacheNamePreset
? servletContext.getInitParameter(SSO_CACHE_NAME_PARAM_NAME)
: deploymentSessionCacheName + ".ssoCache";
try {
EmbeddedCacheManager cacheManager = (EmbeddedCacheManager) new InitialContext().lookup(cacheContainerLookup);
Configuration ssoCacheConfiguration = cacheManager.getCacheConfiguration(ssoCacheName);
if (ssoCacheConfiguration == null) {
Configuration cacheConfiguration = cacheManager.getCacheConfiguration(deploymentSessionCacheName);
if (cacheConfiguration == null) {
LOG.debugv("Using default cache container configuration for SSO cache. lookup={0}, looked up configuration of cache={1}", cacheContainerLookup, deploymentSessionCacheName);
ssoCacheConfiguration = cacheManager.getDefaultCacheConfiguration();
} else {
LOG.debugv("Using distributed HTTP session cache configuration for SSO cache. lookup={0}, configuration taken from cache={1}", cacheContainerLookup, deploymentSessionCacheName);
ssoCacheConfiguration = cacheConfiguration;
cacheManager.defineConfiguration(ssoCacheName, ssoCacheConfiguration);
}
} else {
LOG.debugv("Using custom configuration for SSO cache. lookup={0}, cache name={1}", cacheContainerLookup, ssoCacheName);
}
CacheMode ssoCacheMode = ssoCacheConfiguration.clustering().cacheMode();
if (ssoCacheMode != CacheMode.REPL_ASYNC && ssoCacheMode != CacheMode.REPL_SYNC) {
LOG.warnv("SSO cache mode is {0}, it is recommended to use replicated mode instead", ssoCacheConfiguration.clustering().cacheModeString());
}
Cache<String, String[]> ssoCache = cacheManager.getCache(ssoCacheName, true);
ssoCache.addListener(new SsoSessionCacheListener(mapper));
LOG.debugv("Added distributed SSO session cache, lookup={0}, cache name={1}", cacheContainerLookup, deploymentSessionCacheName);
SsoCacheSessionIdMapperUpdater updater = new SsoCacheSessionIdMapperUpdater(ssoCache, previousIdMapperUpdater);
return updater;
} catch (NamingException ex) {
LOG.warnv("Failed to obtain distributed session cache container, lookup={0}", cacheContainerLookup);
return previousIdMapperUpdater;
}
}
}
@@ -0,0 +1,60 @@
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jbossweb.infinispan;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import org.infinispan.Cache;
/**
*
* @author hmlnarik
*/
public class SsoCacheSessionIdMapperUpdater implements SessionIdMapperUpdater {
private final SessionIdMapperUpdater delegate;
/**
* Cache where key is a HTTP session ID, and value is a pair (user session ID, principal name) of Strings.
*/
private final Cache<String, String[]> httpSessionToSsoCache;
public SsoCacheSessionIdMapperUpdater(Cache<String, String[]> httpSessionToSsoCache, SessionIdMapperUpdater previousIdMapperUpdater) {
this.delegate = previousIdMapperUpdater;
this.httpSessionToSsoCache = httpSessionToSsoCache;
}
// SessionIdMapperUpdater methods
@Override
public void clear(SessionIdMapper idMapper) {
httpSessionToSsoCache.clear();
this.delegate.clear(idMapper);
}
@Override
public void map(SessionIdMapper idMapper, String sso, String principal, String httpSessionId) {
httpSessionToSsoCache.put(httpSessionId, new String[] {sso, principal});
this.delegate.map(idMapper, sso, principal, httpSessionId);
}
@Override
public void removeSession(SessionIdMapper idMapper, String httpSessionId) {
httpSessionToSsoCache.remove(httpSessionId);
this.delegate.removeSession(idMapper, httpSessionId);
}
}
@@ -0,0 +1,156 @@
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jbossweb.infinispan;
import org.keycloak.adapters.spi.SessionIdMapper;
import java.util.*;
import java.util.concurrent.*;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.*;
import org.infinispan.notifications.cachelistener.event.*;
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStarted;
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStopped;
import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent;
import org.infinispan.notifications.cachemanagerlistener.event.CacheStoppedEvent;
import org.infinispan.transaction.xa.GlobalTransaction;
import org.jboss.logging.Logger;
/**
*
* @author hmlnarik
*/
@Listener
public class SsoSessionCacheListener {
private static final Logger LOG = Logger.getLogger(SsoSessionCacheListener.class);
private final ConcurrentMap<GlobalTransaction, Queue<Event>> map = new ConcurrentHashMap<>();
private final SessionIdMapper idMapper;
private ExecutorService executor = Executors.newSingleThreadExecutor();
public SsoSessionCacheListener(SessionIdMapper idMapper) {
this.idMapper = idMapper;
}
@TransactionRegistered
public void startTransaction(TransactionRegisteredEvent event) {
map.put(event.getGlobalTransaction(), new ConcurrentLinkedQueue<Event>());
}
@CacheStarted
public void cacheStarted(CacheStartedEvent event) {
this.executor = Executors.newSingleThreadExecutor();
}
@CacheStopped
public void cacheStopped(CacheStoppedEvent event) {
this.executor.shutdownNow();
}
@CacheEntryCreated
@CacheEntryRemoved
@CacheEntryModified
public void addEvent(TransactionalEvent event) {
if (event.isPre() == false) {
map.get(event.getGlobalTransaction()).add(event);
}
}
@TransactionCompleted
public void endTransaction(TransactionCompletedEvent event) {
Queue<Event> events = map.remove(event.getGlobalTransaction());
if (events == null || ! event.isTransactionSuccessful()) {
return;
}
if (event.isOriginLocal()) {
// Local events are processed by local HTTP session listener
return;
}
for (final Event e : events) {
switch (e.getType()) {
case CACHE_ENTRY_CREATED:
this.executor.submit(new Runnable() {
@Override public void run() {
cacheEntryCreated((CacheEntryCreatedEvent) e);
}
});
break;
case CACHE_ENTRY_MODIFIED:
this.executor.submit(new Runnable() {
@Override public void run() {
cacheEntryModified((CacheEntryModifiedEvent) e);
}
});
break;
case CACHE_ENTRY_REMOVED:
this.executor.submit(new Runnable() {
@Override public void run() {
cacheEntryRemoved((CacheEntryRemovedEvent) e);
}
});
break;
}
}
}
private void cacheEntryCreated(CacheEntryCreatedEvent event) {
if (! (event.getKey() instanceof String) || ! (event.getValue() instanceof String[])) {
return;
}
String httpSessionId = (String) event.getKey();
String[] value = (String[]) event.getValue();
String ssoId = value[0];
String principal = value[1];
LOG.tracev("cacheEntryCreated {0}:{1}", httpSessionId, ssoId);
this.idMapper.map(ssoId, principal, httpSessionId);
}
private void cacheEntryModified(CacheEntryModifiedEvent event) {
if (! (event.getKey() instanceof String) || ! (event.getValue() instanceof String[])) {
return;
}
String httpSessionId = (String) event.getKey();
String[] value = (String[]) event.getValue();
String ssoId = value[0];
String principal = value[1];
LOG.tracev("cacheEntryModified {0}:{1}", httpSessionId, ssoId);
this.idMapper.removeSession(httpSessionId);
this.idMapper.map(ssoId, principal, httpSessionId);
}
private void cacheEntryRemoved(CacheEntryRemovedEvent event) {
if (! (event.getKey() instanceof String)) {
return;
}
LOG.tracev("cacheEntryRemoved {0}", event.getKey());
this.idMapper.removeSession((String) event.getKey());
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML EAP Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -308,7 +308,7 @@
</xs:attribute>
<xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is http://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is https://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="encryption" type="xs:boolean" use="optional">
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -104,12 +104,14 @@ public abstract class AbstractSamlAuthenticator extends LoginAuthenticator {
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
JettySamlSessionStore store;
store = new JettySamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
store = new JettySamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
return store;
}
public abstract AdapterSessionStore createSessionTokenStore(Request request, SamlDeployment resolvedDeployment);
public abstract JettyUserSessionManagement createSessionManagement(Request request);
public void logoutCurrent(Request request) {
JettyHttpFacade facade = new JettyHttpFacade(request, null);
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -15,20 +15,26 @@
* limitations under the License.
*/
package org.keycloak.models.mongo.keycloak.entities;
package org.keycloak.adapters.saml.jetty;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@MongoCollection(collectionName = "clientTemplates")
public class MongoClientTemplateEntity extends ClientTemplateEntity implements MongoIdentifiableEntity {
public class Jetty8SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty8SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public void afterRemove(MongoStoreInvocationContext context) {
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -21,6 +21,7 @@ import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.spi.AdapterSessionStore;
@@ -42,6 +43,11 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
return new JettyAdapterSessionStore(request);
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty8SessionManager(request.getSessionManager()));
}
@Override
protected Request resolveRequest(ServletRequest req) {
return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty9SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty9SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -44,6 +44,11 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
return new JettyAdapterSessionStore(request);
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
}
@Override
protected Request resolveRequest(ServletRequest req) {
return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
@@ -62,7 +67,7 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
@Override
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
JettySamlSessionStore store;
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
return store;
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty9SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty9SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -59,10 +59,15 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
return new JettyAdapterSessionStore(request);
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
}
@Override
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
JettySamlSessionStore store;
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
return store;
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.SessionManager;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty9SessionManager implements JettySessionManager {
protected SessionManager sessionManager;
public Jetty9SessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionManager.getHttpSession(id);
}
}
@@ -58,10 +58,15 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
return new JettyAdapterSessionStore(request);
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
}
@Override
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
JettySamlSessionStore store;
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
return store;
}
}
+162
View File
@@ -0,0 +1,162 @@
<?xml version="1.0"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>3.0.0.Final</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-saml-jetty94-adapter</artifactId>
<name>Keycloak Jetty 9.4.x SAML Integration</name>
<properties>
<jetty9.version>9.4.2.v20170220</jetty9.version>
<keycloak.osgi.export>
org.keycloak.adapters.jetty.*
</keycloak.osgi.export>
<keycloak.osgi.import>
org.eclipse.jetty.*;resolution:=optional,
javax.servlet.*;version="[3.0,4)";resolution:=optional,
org.keycloak.*;version="${project.version}",
*;resolution:=optional
</keycloak.osgi.import>
</properties>
<description />
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss.logging.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-common</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-adapter-api-public</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-adapter-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-adapter-spi</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-jetty-adapter-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${jetty9.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-ClassPath>.</Bundle-ClassPath>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Import-Package>${keycloak.osgi.import}</Import-Package>
<Export-Package>${keycloak.osgi.export}</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,44 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.Request;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.spi.AdapterSessionStore;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.SessionIdMapper;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty9SamlSessionStore extends JettySamlSessionStore {
public Jetty9SamlSessionStore(Request request, AdapterSessionStore sessionStore, HttpFacade facade, SessionIdMapper idMapper, JettyUserSessionManagement sessionManagement, SamlDeployment deployment) {
super(request, sessionStore, facade, idMapper, sessionManagement, deployment);
}
@Override
protected String changeSessionId(HttpSession session) {
Request request = this.request;
if (!deployment.turnOffChangeSessionIdOnLogin()) return request.changeSessionId();
else return session.getId();
}
}
@@ -0,0 +1,40 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.session.SessionHandler;
import org.keycloak.adapters.jetty.spi.JettySessionManager;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Jetty9SessionManager implements JettySessionManager {
protected SessionHandler sessionHandler;
public Jetty9SessionManager(SessionHandler sessionHandler) {
this.sessionHandler = sessionHandler;
}
@Override
public HttpSession getHttpSession(String id) {
return sessionHandler.getHttpSession(id);
}
}
@@ -0,0 +1,111 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.MultiMap;
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
import org.keycloak.adapters.spi.AdapterSessionStore;
import org.keycloak.common.util.MultivaluedHashMap;
import javax.servlet.http.HttpSession;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JettyAdapterSessionStore implements AdapterSessionStore {
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
protected Request myRequest;
public JettyAdapterSessionStore(Request request) {
this.myRequest = request; // for IDE/compilation purposes
}
protected MultiMap<String> extractFormParameters(Request base_request) {
MultiMap<String> formParameters = new MultiMap<String>();
base_request.extractFormParameters(formParameters);
return formParameters;
}
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
base_request.setContentParameters(j_post);
}
public boolean restoreRequest() {
HttpSession session = myRequest.getSession(false);
if (session == null) return false;
synchronized (session) {
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
if (j_uri != null) {
// check if the request is for the same url as the original and restore
// params if it was a post
StringBuffer buf = myRequest.getRequestURL();
if (myRequest.getQueryString() != null)
buf.append("?").append(myRequest.getQueryString());
if (j_uri.equals(buf.toString())) {
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
myRequest.setMethod(method);
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
if (j_post != null) {
myRequest.setContentType("application/x-www-form-urlencoded");
MultiMap<String> map = new MultiMap<String>();
for (String key : j_post.keySet()) {
for (String val : j_post.getList(key)) {
map.add(key, val);
}
}
restoreFormParameters(map, myRequest);
}
session.removeAttribute(FormAuthenticator.__J_URI);
session.removeAttribute(JettyHttpFacade.__J_METHOD);
session.removeAttribute(FormAuthenticator.__J_POST);
}
return true;
}
}
return false;
}
public void saveRequest() {
// remember the current URI
HttpSession session = myRequest.getSession();
synchronized (session) {
// But only if it is not set already, or we save every uri that leads to a login form redirect
if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
StringBuffer buf = myRequest.getRequestURL();
if (myRequest.getQueryString() != null)
buf.append("?").append(myRequest.getQueryString());
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
MultiMap<String> formParameters = extractFormParameters(myRequest);
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
for (String key : formParameters.keySet()) {
for (Object value : formParameters.getValues(key)) {
map.add(key, (String) value);
}
}
session.setAttribute(CACHED_FORM_PARAMETERS, map);
}
}
}
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.jetty;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.spi.AdapterSessionStore;
import org.keycloak.adapters.spi.HttpFacade;
import javax.servlet.ServletRequest;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
public KeycloakSamlAuthenticator() {
super();
}
@Override
protected Request resolveRequest(ServletRequest req) {
return Request.getBaseRequest(req);
}
@Override
public Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
@Override
public void logout() {
logoutCurrent(request);
}
};
}
@Override
public AdapterSessionStore createSessionTokenStore(Request request, SamlDeployment resolvedDeployment) {
return new JettyAdapterSessionStore(request);
}
@Override
public JettyUserSessionManagement createSessionManagement(Request request) {
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionHandler()));
}
@Override
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
JettySamlSessionStore store;
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
return store;
}
}
+2 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Jetty Integration</name>
@@ -36,5 +36,6 @@
<module>jetty9.1</module>
<module>jetty9.2</module>
<module>jetty9.3</module>
<module>jetty9.4</module>
</modules>
</project>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Client Adapter Modules</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Tomcat Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -24,13 +24,11 @@ import org.apache.catalina.LifecycleListener;
import org.apache.catalina.authenticator.FormAuthenticator;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jboss.logging.Logger;
import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
import org.keycloak.adapters.spi.AuthChallenge;
import org.keycloak.adapters.spi.AuthOutcome;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.InMemorySessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.*;
import org.keycloak.adapters.tomcat.CatalinaHttpFacade;
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
@@ -45,8 +43,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.lang.reflect.*;
import java.util.Map;
/**
* Keycloak authentication valve
@@ -59,10 +57,11 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
private final static Logger log = Logger.getLogger(""+AbstractSamlAuthenticatorValve.class);
private final static Logger log = Logger.getLogger(AbstractSamlAuthenticatorValve.class);
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
protected SamlDeploymentContext deploymentContext;
protected SessionIdMapper mapper = new InMemorySessionIdMapper();
protected SessionIdMapperUpdater idMapperUpdater = SessionIdMapperUpdater.DIRECT;
@Override
public void lifecycleEvent(LifecycleEvent event) {
@@ -70,7 +69,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
cache = false;
} else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
keycloakInit();
} else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
} else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
beforeStop();
}
}
@@ -103,14 +102,14 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
//deploymentContext = new SamlDeploymentContext(configResolver);
//log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
} catch (Exception ex) {
log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", configResolverClass, ex.getMessage());
//deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
}
} else {
InputStream is = getConfigInputStream(context);
final SamlDeployment deployment;
if (is == null) {
log.info("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
log.error("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
deployment = new DefaultSamlDeployment();
} else {
try {
@@ -126,10 +125,12 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
}
}
deploymentContext = new SamlDeploymentContext(deployment);
log.fine("Keycloak is using a per-deployment configuration.");
log.debug("Keycloak is using a per-deployment configuration.");
}
context.getServletContext().setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
addTokenStoreUpdaters();
}
protected void beforeStop() {
@@ -140,8 +141,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
if (xml == null) {
return null;
}
log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
log.finest(xml);
log.trace("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
return new ByteArrayInputStream(xml.getBytes());
}
@@ -150,13 +150,13 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
if (is == null) {
String path = context.getServletContext().getInitParameter("keycloak.config.file");
if (path == null) {
log.fine("**** using /WEB-INF/keycloak-saml.xml");
log.trace("**** using /WEB-INF/keycloak-saml.xml");
is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak-saml.xml");
} else {
try {
is = new FileInputStream(path);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE, "NOT FOUND {0}", path);
log.errorv("NOT FOUND {0}", path);
throw new RuntimeException(e);
}
}
@@ -166,7 +166,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
log.fine("*********************** SAML ************");
log.trace("*********************** SAML ************");
CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
if (request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml")) {
@@ -208,11 +208,11 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
}
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
log.fine("authenticateInternal");
log.trace("authenticateInternal");
CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
if (deployment == null || !deployment.isConfigured()) {
log.fine("deployment not configured");
log.trace("deployment not configured");
return false;
}
SamlSessionStore tokenStore = getSessionStore(request, facade, deployment);
@@ -225,7 +225,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
protected boolean executeAuthenticator(Request request, HttpServletResponse response, CatalinaHttpFacade facade, SamlDeployment deployment, SamlAuthenticator authenticator) {
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
log.fine("AUTHENTICATED");
log.trace("AUTHENTICATED");
if (facade.isEnded()) {
return false;
}
@@ -237,13 +237,13 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
forwardToLogoutPage(request, response, deployment);
}
log.fine("Logging OUT");
log.trace("Logging OUT");
return false;
}
AuthChallenge challenge = authenticator.getChallenge();
if (challenge != null) {
log.fine("challenge");
log.trace("challenge");
challenge.challenge(facade);
}
return false;
@@ -275,8 +275,68 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
protected SamlSessionStore createSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
SamlSessionStore store;
store = new CatalinaSamlSessionStore(userSessionManagement, createPrincipalFactory(), mapper, request, this, facade, resolvedDeployment);
store = new CatalinaSamlSessionStore(userSessionManagement, createPrincipalFactory(), mapper, idMapperUpdater, request, this, facade, resolvedDeployment);
return store;
}
protected void addTokenStoreUpdaters() {
SessionIdMapperUpdater updater = getIdMapperUpdater();
try {
String idMapperSessionUpdaterClasses = context.getServletContext().getInitParameter("keycloak.sessionIdMapperUpdater.classes");
if (idMapperSessionUpdaterClasses == null) {
return;
}
for (String clazz : idMapperSessionUpdaterClasses.split("\\s*,\\s*")) {
if (! clazz.isEmpty()) {
updater = invokeAddTokenStoreUpdaterMethod(clazz, updater);
}
}
} finally {
setIdMapperUpdater(updater);
}
}
private SessionIdMapperUpdater invokeAddTokenStoreUpdaterMethod(String idMapperSessionUpdaterClass, SessionIdMapperUpdater previousIdMapperUpdater) {
try {
Class<?> clazz = context.getLoader().getClassLoader().loadClass(idMapperSessionUpdaterClass);
Method addTokenStoreUpdatersMethod = clazz.getMethod("addTokenStoreUpdaters", Context.class, SessionIdMapper.class, SessionIdMapperUpdater.class);
if (! Modifier.isStatic(addTokenStoreUpdatersMethod.getModifiers())
|| ! Modifier.isPublic(addTokenStoreUpdatersMethod.getModifiers())
|| ! SessionIdMapperUpdater.class.isAssignableFrom(addTokenStoreUpdatersMethod.getReturnType())) {
log.errorv("addTokenStoreUpdaters method in class {0} has to be public static. Ignoring class.", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
}
log.debugv("Initializing sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return (SessionIdMapperUpdater) addTokenStoreUpdatersMethod.invoke(null, context, mapper, previousIdMapperUpdater);
} catch (ClassNotFoundException ex) {
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (NoSuchMethodException ex) {
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (SecurityException ex) {
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (IllegalAccessException ex) {
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (IllegalArgumentException ex) {
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (InvocationTargetException ex) {
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
}
}
public SessionIdMapperUpdater getIdMapperUpdater() {
return idMapperUpdater;
}
public void setIdMapperUpdater(SessionIdMapperUpdater idMapperUpdater) {
this.idMapperUpdater = idMapperUpdater;
}
}
@@ -24,6 +24,7 @@ import org.apache.catalina.realm.GenericPrincipal;
import org.jboss.logging.Logger;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
import org.keycloak.common.util.KeycloakUriBuilder;
@@ -45,17 +46,20 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
private final CatalinaUserSessionManagement sessionManagement;
protected final GenericPrincipalFactory principalFactory;
private final SessionIdMapper idMapper;
private final SessionIdMapperUpdater idMapperUpdater;
protected final Request request;
protected final AbstractSamlAuthenticatorValve valve;
protected final HttpFacade facade;
protected final SamlDeployment deployment;
public CatalinaSamlSessionStore(CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory,
SessionIdMapper idMapper, Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade,
SessionIdMapper idMapper, SessionIdMapperUpdater idMapperUpdater,
Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade,
SamlDeployment deployment) {
this.sessionManagement = sessionManagement;
this.principalFactory = principalFactory;
this.idMapper = idMapper;
this.idMapperUpdater = idMapperUpdater;
this.request = request;
this.valve = valve;
this.facade = facade;
@@ -89,11 +93,13 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
Session sessionInternal = request.getSessionInternal(false);
if (sessionInternal == null) return;
HttpSession session = sessionInternal.getSession();
List<String> ids = new LinkedList<String>();
if (session != null) {
SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
if (samlSession != null) {
if (samlSession.getSessionIndex() != null) {
idMapper.removeSession(session.getId());
ids.add(session.getId());
idMapperUpdater.removeSession(idMapper, session.getId());
}
session.removeAttribute(SamlSession.class.getName());
}
@@ -101,6 +107,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
}
sessionInternal.setPrincipal(null);
sessionInternal.setAuthType(null);
logoutSessionIds(ids);
}
@Override
@@ -111,7 +118,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
ids.addAll(sessions);
logoutSessionIds(ids);
for (String id : ids) {
idMapper.removeSession(id);
idMapperUpdater.removeSession(idMapper, id);
}
}
@@ -125,7 +132,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
String sessionId = idMapper.getSessionFromSSO(id);
if (sessionId != null) {
sessionIds.add(sessionId);
idMapper.removeSession(sessionId);
idMapperUpdater.removeSession(idMapper, sessionId);
}
}
@@ -141,7 +148,6 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
@Override
public boolean isLoggedIn() {
Session session = request.getSessionInternal(false);
if (session == null) return false;
if (session == null) {
log.debug("session was null, returning null");
return false;
@@ -193,7 +199,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
request.setUserPrincipal(principal);
request.setAuthType("KEYCLOAK-SAML");
String newId = changeSessionId(session);
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), newId);
idMapperUpdater.map(idMapper, account.getSessionIndex(), account.getPrincipal().getSamlSubject(), newId);
}
@@ -0,0 +1,93 @@
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml;
import org.keycloak.adapters.spi.SessionIdMapper;
import java.util.Objects;
import javax.servlet.http.*;
/**
*
* @author hmlnarik
*/
public class IdMapperUpdaterSessionListener implements HttpSessionListener, HttpSessionAttributeListener {
private final SessionIdMapper idMapper;
public IdMapperUpdaterSessionListener(SessionIdMapper idMapper) {
this.idMapper = idMapper;
}
@Override
public void sessionCreated(HttpSessionEvent hse) {
HttpSession session = hse.getSession();
Object value = session.getAttribute(SamlSession.class.getName());
map(session.getId(), value);
}
@Override
public void sessionDestroyed(HttpSessionEvent hse) {
HttpSession session = hse.getSession();
unmap(session.getId(), session.getAttribute(SamlSession.class.getName()));
}
@Override
public void attributeAdded(HttpSessionBindingEvent hsbe) {
HttpSession session = hsbe.getSession();
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
map(session.getId(), hsbe.getValue());
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
HttpSession session = hsbe.getSession();
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
unmap(session.getId(), hsbe.getValue());
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
HttpSession session = hsbe.getSession();
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
unmap(session.getId(), hsbe.getValue());
map(session.getId(), session.getAttribute(SamlSession.class.getName()));
}
}
private void map(String sessionId, Object value) {
if (! (value instanceof SamlSession) || sessionId == null) {
return;
}
SamlSession account = (SamlSession) value;
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
}
private void unmap(String sessionId, Object value) {
if (! (value instanceof SamlSession) || sessionId == null) {
return;
}
SamlSession samlSession = (SamlSession) value;
if (samlSession.getSessionIndex() != null) {
idMapper.removeSession(sessionId);
}
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -24,6 +24,7 @@ import org.keycloak.adapters.saml.CatalinaSamlSessionStore;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
@@ -33,7 +34,7 @@ import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
*/
public class Tomcat8SamlSessionStore extends CatalinaSamlSessionStore {
public Tomcat8SamlSessionStore(CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory, SessionIdMapper idMapper, Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade, SamlDeployment deployment) {
super(sessionManagement, principalFactory, idMapper, request, valve, facade, deployment);
super(sessionManagement, principalFactory, idMapper, SessionIdMapperUpdater.DIRECT, request, valve, facade, deployment);
}
@Override
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,103 @@
/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.adapters.saml.undertow;
import org.keycloak.adapters.saml.SamlSession;
import org.keycloak.adapters.spi.SessionIdMapper;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.session.Session;
import io.undertow.server.session.SessionListener;
import java.util.Objects;
/**
*
* @author hmlnarik
*/
public class IdMapperUpdaterSessionListener implements SessionListener {
private final SessionIdMapper idMapper;
public IdMapperUpdaterSessionListener(SessionIdMapper idMapper) {
this.idMapper = idMapper;
}
@Override
public void sessionCreated(Session session, HttpServerExchange exchange) {
Object value = session.getAttribute(SamlSession.class.getName());
map(session.getId(), value);
}
@Override
public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
if (reason != SessionDestroyedReason.UNDEPLOY) {
unmap(session.getId(), session.getAttribute(SamlSession.class.getName()));
}
}
@Override
public void attributeAdded(Session session, String name, Object value) {
if (Objects.equals(name, SamlSession.class.getName())) {
map(session.getId(), value);
}
}
@Override
public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) {
if (Objects.equals(name, SamlSession.class.getName())) {
unmap(session.getId(), oldValue);
map(session.getId(), newValue);
}
}
@Override
public void attributeRemoved(Session session, String name, Object oldValue) {
if (Objects.equals(name, SamlSession.class.getName())) {
unmap(session.getId(), oldValue);
}
}
@Override
public void sessionIdChanged(Session session, String oldSessionId) {
Object value = session.getAttribute(SamlSession.class.getName());
if (value != null) {
unmap(oldSessionId, value);
map(session.getId(), value);
}
}
private void map(String sessionId, Object value) {
if (! (value instanceof SamlSession) || sessionId == null) {
return;
}
SamlSession account = (SamlSession) value;
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
}
private void unmap(String sessionId, Object value) {
if (! (value instanceof SamlSession) || sessionId == null) {
return;
}
SamlSession samlSession = (SamlSession) value;
if (samlSession.getSessionIndex() != null) {
idMapper.removeSession(sessionId);
}
}
}
@@ -154,7 +154,7 @@ public class SamlServletExtension implements ServletExtension {
servletContext.setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
final ServletSamlAuthMech mech = createAuthMech(deploymentInfo, deploymentContext, userSessionManagement);
mech.addTokenStoreUpdaters(deploymentInfo);
// setup handlers
@@ -21,35 +21,89 @@ import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.handlers.ServletRequestContext;
import io.undertow.util.Headers;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.saml.SamlDeploymentContext;
import org.keycloak.adapters.saml.SamlSessionStore;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.InMemorySessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.*;
import org.keycloak.adapters.undertow.ServletHttpFacade;
import org.keycloak.adapters.undertow.UndertowHttpFacade;
import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
import io.undertow.servlet.api.DeploymentInfo;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.Map;
import org.jboss.logging.Logger;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ServletSamlAuthMech extends AbstractSamlAuthMech {
private static final Logger LOG = Logger.getLogger(ServletSamlAuthMech.class);
protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
protected SessionIdMapperUpdater idMapperUpdater = SessionIdMapperUpdater.DIRECT;
public ServletSamlAuthMech(SamlDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement, String errorPage) {
super(deploymentContext, sessionManagement, errorPage);
}
public void addTokenStoreUpdaters(DeploymentInfo deploymentInfo) {
deploymentInfo.addSessionListener(new IdMapperUpdaterSessionListener(idMapper)); // This takes care of HTTP sessions manipulated locally
SessionIdMapperUpdater updater = SessionIdMapperUpdater.EXTERNAL;
try {
Map<String, String> initParameters = deploymentInfo.getInitParameters();
String idMapperSessionUpdaterClasses = initParameters == null
? null
: initParameters.get("keycloak.sessionIdMapperUpdater.classes");
if (idMapperSessionUpdaterClasses == null) {
return;
}
for (String clazz : idMapperSessionUpdaterClasses.split("\\s*,\\s*")) {
if (! clazz.isEmpty()) {
updater = invokeAddTokenStoreUpdaterMethod(clazz, deploymentInfo, updater);
}
}
} finally {
setIdMapperUpdater(updater);
}
}
private SessionIdMapperUpdater invokeAddTokenStoreUpdaterMethod(String idMapperSessionUpdaterClass, DeploymentInfo deploymentInfo,
SessionIdMapperUpdater previousIdMapperUpdater) {
try {
Class<?> clazz = deploymentInfo.getClassLoader().loadClass(idMapperSessionUpdaterClass);
Method addTokenStoreUpdatersMethod = clazz.getMethod("addTokenStoreUpdaters", DeploymentInfo.class, SessionIdMapper.class, SessionIdMapperUpdater.class);
if (! Modifier.isStatic(addTokenStoreUpdatersMethod.getModifiers())
|| ! Modifier.isPublic(addTokenStoreUpdatersMethod.getModifiers())
|| ! SessionIdMapperUpdater.class.isAssignableFrom(addTokenStoreUpdatersMethod.getReturnType())) {
LOG.errorv("addTokenStoreUpdaters method in class {0} has to be public static. Ignoring class.", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
}
LOG.debugv("Initializing sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return (SessionIdMapperUpdater) addTokenStoreUpdatersMethod.invoke(null, deploymentInfo, idMapper, previousIdMapperUpdater);
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) {
LOG.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
LOG.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
return previousIdMapperUpdater;
}
}
@Override
protected SamlSessionStore getTokenStore(HttpServerExchange exchange, HttpFacade facade, SamlDeployment deployment, SecurityContext securityContext) {
return new ServletSamlSessionStore(exchange, sessionManagement, securityContext, idMapper, deployment);
return new ServletSamlSessionStore(exchange, sessionManagement, securityContext, idMapper, idMapperUpdater, deployment);
}
@Override
@@ -84,5 +138,11 @@ public class ServletSamlAuthMech extends AbstractSamlAuthMech {
return null;
}
public SessionIdMapperUpdater getIdMapperUpdater() {
return idMapperUpdater;
}
protected void setIdMapperUpdater(SessionIdMapperUpdater idMapperUpdater) {
this.idMapperUpdater = idMapperUpdater;
}
}
@@ -24,11 +24,13 @@ import io.undertow.server.session.SessionManager;
import io.undertow.servlet.handlers.ServletRequestContext;
import io.undertow.servlet.spec.HttpSessionImpl;
import org.jboss.logging.Logger;
import org.keycloak.adapters.saml.SamlDeployment;
import org.keycloak.adapters.saml.SamlSession;
import org.keycloak.adapters.saml.SamlSessionStore;
import org.keycloak.adapters.saml.SamlUtil;
import org.keycloak.adapters.spi.SessionIdMapper;
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
import org.keycloak.adapters.undertow.ChangeSessionId;
import org.keycloak.adapters.undertow.SavedRequest;
import org.keycloak.adapters.undertow.ServletHttpFacade;
@@ -44,6 +46,8 @@ import java.util.List;
import java.util.Set;
/**
* Session store manipulation methods per single HTTP exchange.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@@ -55,17 +59,20 @@ public class ServletSamlSessionStore implements SamlSessionStore {
private final UndertowUserSessionManagement sessionManagement;
private final SecurityContext securityContext;
private final SessionIdMapper idMapper;
private final SessionIdMapperUpdater idMapperUpdater;
protected final SamlDeployment deployment;
public ServletSamlSessionStore(HttpServerExchange exchange, UndertowUserSessionManagement sessionManagement,
SecurityContext securityContext,
SessionIdMapper idMapper, SamlDeployment deployment) {
SessionIdMapper idMapper, SessionIdMapperUpdater idMapperUpdater,
SamlDeployment deployment) {
this.exchange = exchange;
this.sessionManagement = sessionManagement;
this.securityContext = securityContext;
this.idMapper = idMapper;
this.deployment = deployment;
this.idMapperUpdater = idMapperUpdater;
}
@Override
@@ -97,7 +104,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
if (samlSession != null) {
if (samlSession.getSessionIndex() != null) {
idMapper.removeSession(session.getId());
idMapperUpdater.removeSession(idMapper, session.getId());
}
session.removeAttribute(SamlSession.class.getName());
}
@@ -113,7 +120,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
ids.addAll(sessions);
logoutSessionIds(ids);
for (String id : ids) {
idMapper.removeSession(id);
idMapperUpdater.removeSession(idMapper, id);
}
}
@@ -127,7 +134,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
String sessionId = idMapper.getSessionFromSSO(id);
if (sessionId != null) {
sessionIds.add(sessionId);
idMapper.removeSession(sessionId);
idMapperUpdater.removeSession(idMapper, sessionId);
}
}
@@ -177,7 +184,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
session.setAttribute(SamlSession.class.getName(), account);
sessionManagement.login(servletRequestContext.getDeployment().getSessionManager());
String sessionId = changeSessionId(session);
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
idMapperUpdater.map(idMapper, account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
}
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>2.5.1.Final-SNAPSHOT</version>
<version>3.0.0.Final</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Wildfly Integration</name>
Loaded 100 of 1086 files, more files were not shown because too many files have changed in this diff. Show more