Compare commits

..
601 Commits
Author SHA1 Message Date
Stian Thorgersen f402fb1a55 Version bump 2015-05-20 07:13:14 +02:00
Stian Thorgersen dc64260c31 NotSerializableException: org.keycloak.models.sessions.infinispan.entities.LoginFailureKey 2015-05-20 07:12:07 +02:00
Stian Thorgersen d26712a1d4 Version bump 2015-01-28 14:23:05 +01:00
Stian Thorgersen db8935444f Fix federation provider example to load users file from it's own ClassLoader instead of Thread CL 2015-01-28 13:23:00 +01:00
Stian Thorgersen 5b769ed829 Updates to migration guide 2015-01-28 12:03:59 +01:00
Stian Thorgersen 7585b5ab49 Added provider section to docs 2015-01-28 11:25:11 +01:00
Stian Thorgersen 95287b2faa Removed details on using deployment overrides, this will need reviewing and adding to 1.2 instead 2015-01-28 10:48:07 +01:00
Stian Thorgersen d707133742 Update Travis CI config 2015-01-28 09:25:03 +01:00
Stian Thorgersen c0e0391a87 Add travis.yml 2015-01-28 09:25:03 +01:00
Stian Thorgersen 7139c683cc KEYCLOAK-999 Load providers from file-system 2015-01-28 09:25:01 +01:00
mposolda 19939068d5 Fixed test failures caused by uncleared Time offset 2015-01-26 17:20:05 +01:00
mposolda 9ffe8287a7 Improve OOTB experience for ssh and jmx authentication in fuse 2015-01-23 20:40:38 +01:00
girirajsharma be74476de1 Updated KeyCloak relative URI as per scheme, host and port of request. 2015-01-21 17:15:34 +01:00
girirajsharma 45c5fa28fc Fixed KeyCloak relative URI optimization with auth-server-url in docbook 2015-01-21 17:15:25 +01:00
mposolda a4bed6e433 Added docs and example for SSH and JMX authentication on fuse 2015-01-21 13:36:00 +01:00
Stian Thorgersen 575943fbb4 KEYCLOAK-980 Password reset is possible with expired link 2015-01-21 13:10:43 +01:00
Stian Thorgersen 46fa593d4a KEYCLOAK-983 Fix login after reset-password 2015-01-21 12:26:58 +01:00
mposolda 9819d9997e Have fuse example working on newest fuse 6.2. Refactoring of ServletReregistrationService to work on fuse 6.1, 6.2 and karaf 3.0.2 2015-01-20 21:42:36 +01:00
Stian Thorgersen cdb0d6b5bf KEYCLOAK-977 Use reflection to find constructor for JBossGenericPrincipal to support EAP 6.4 2015-01-20 13:25:33 +01:00
mposolda ae86028e6e KEYCLOAK-981 Module org.picketlink.federation.bindings doesn't work with EAP6 2015-01-20 11:13:39 +01:00
mposolda 0cfe4c694a Fix SAML examples. Fix links in README files for SAML examples 2015-01-20 11:13:10 +01:00
Stian Thorgersen 034735cd64 KEYCLOAK-975 Client/app secret should be read-only, not disabled 2015-01-19 14:07:55 +01:00
mposolda 7567fea6c1 Update instructions for fuse demo 2015-01-19 13:21:06 +01:00
Stian Thorgersen 3af087e36f Fix OAuthRedirectUriTest 2015-01-19 12:21:26 +01:00
mposolda 45e04944a4 Remove references about installing auth-server on JBoss AS 7.1.1 2015-01-16 17:59:33 +01:00
mposolda 0706e6f778 Make it easier to run demo on different host then auth-server 2015-01-16 17:39:37 +01:00
Stian Thorgersen 655aa6194e Fix OAuthRedirectUriTest 2015-01-16 13:06:27 +01:00
mposolda 862baf2d5b KEYCLOAK-974 ServerVersionResource doesn't handle cors requests 2015-01-16 12:25:13 +01:00
Stian Thorgersen fc148207ce KEYCLOAK-967 Username is displayed as undefined in Cordova example 2015-01-16 11:48:23 +01:00
Stian Thorgersen 095561cb29 KEYCLOAK-964 JS Console has two tabs for Show ID Token 2015-01-16 11:27:52 +01:00
Stian Thorgersen 9bd3f43ce5 KEYCLOAK-965 NPE in TokenManager.verifyAccess if application is deleted 2015-01-16 11:25:24 +01:00
Stian Thorgersen 4ea49a14ea KEYCLOAK-962 Changed access token request to use redirect_uri from initial request instead of the resolved redirect_uri 2015-01-16 11:01:53 +01:00
Stian Thorgersen 12c155cd9c KEYCLOAK-963 Change code output to single-line for 'urn:ietf:wg:oauth:2.0:oob' 2015-01-16 11:01:48 +01:00
mposolda 0249adbacc Typo in packaging 2015-01-15 19:52:29 +01:00
mposolda d69b01ad3c KEYCLOAK-853 Documentation for login modules 2015-01-15 18:58:40 +01:00
mposolda e7dbfecdb0 Documentation for fuse adapter and example 2015-01-15 18:58:40 +01:00
Stian Thorgersen 37b396c106 KEYCLOAK-960 Fix pagination of app sessions 2015-01-15 14:03:29 +01:00
Marek Posolda b03dddccf4 Merge pull request #917 from mposolda/fuse2
KEYCLOAK-539 Fuse adapter. OSGI bundling. OSGI headers in keycloak adapt...
2015-01-15 13:24:27 +01:00
mposolda 1b7e019042 KEYCLOAK-539 Fuse adapter. OSGI bundling. OSGI headers in keycloak adapter maven artifacts. Rename package in jetty-core 2015-01-15 13:11:30 +01:00
Stian Thorgersen 33c47c8441 KEYCLOAK-958 Support role names with '/' and '\' 2015-01-15 12:21:58 +01:00
Stian Thorgersen 8e5325b5d5 KEYCLOAK-959 Warning message in server log after logging out all sessions 2015-01-15 09:54:52 +01:00
Stian Thorgersen e37c6f262b Add redirect_uri to access token request in keycloak.js 2015-01-14 15:17:22 +01:00
Stian Thorgersen 5bebd31b0c KEYCLOAK-955 Fix AeroGear project integration example 2015-01-14 14:31:39 +01:00
Stian Thorgersen cc76dcf58b KEYCLOAK-949 Disabled user with wrong credentials receive wrong error message 2015-01-14 10:10:36 +01:00
Stian Thorgersen d0b614fdcf KEYCLOAK-957 Access Token Request does not verify redirect_uri 2015-01-14 09:59:04 +01:00
Stian Thorgersen c325b9f04d Merge pull request #914 from gerbermichi/email
Passwort reset dialog shows an error message if the user has an invalid email
2015-01-14 09:15:26 +01:00
girirajsharma c311f47d5d Minor changes : Fixed spell/grammatical errors in docbook. 2015-01-14 09:13:28 +01:00
Michael Gerber aa95ff6d84 check if email is null 2015-01-12 20:33:08 +01:00
Stian Thorgersen de566ec741 Merge pull request #912 from gerbermichi/login-hint
Pass login_hint param to Keycloak login page
2015-01-12 10:35:12 +01:00
Michael Gerber 9c484b9938 add test 2015-01-09 14:03:36 +01:00
Michael Gerber 7ce1502bc5 pass login_hint parameter to the keycloak login page 2015-01-09 11:58:44 +01:00
Marek Posolda 78d5b09b4b Merge pull request #911 from mposolda/master
Fix resolving of current hostname and logout bug
2015-01-08 11:44:08 +01:00
mposolda fff8ae9f8a KEYCLOAK-942 Incorrect condition in ResourceAdminManager could cause global logout 2015-01-08 11:09:11 +01:00
mposolda e62858cefd KEYCLOAK-900 Fix resolving of current hostname 2015-01-08 11:09:11 +01:00
Stian Thorgersen 526e25abc7 Fixes for commons-io dep issues in KeycloakServer 2015-01-08 09:53:43 +01:00
Bill Burke dc94fac9f5 Merge pull request #910 from patriot1burke/master
saml persistent and transient id support
2015-01-07 19:31:43 -05:00
Bill Burke 110783ff2f Merge remote-tracking branch 'upstream/master' 2015-01-07 19:23:47 -05:00
Bill Burke 795b1d2893 saml persistent and transient id support 2015-01-07 19:23:33 -05:00
Stian Thorgersen b7dae5c88f Fixes for regression introduced by KEYCLOAK-923 2015-01-07 14:54:18 +01:00
Stian Thorgersen 37d6a79205 Merge pull request #909 from pedroigor/master
[KEYCLOAK-928] - Validate duplicated emails when updating profile.
2015-01-07 14:20:02 +01:00
pedroigor c4892428ae [KEYCLOAK-928] - Validate duplicated emails when updating profile. 2015-01-07 11:09:40 -02:00
Stian Thorgersen 2b1ae89608 KEYCLOAK-933 expose-token setting not working - empty string returned instead of token 2015-01-07 12:58:42 +01:00
Bill Burke 2a7fc53300 Merge pull request #908 from patriot1burke/master
fix cached principal adapter
2015-01-06 15:57:56 -05:00
Marek Posolda f4c06b7cd0 Merge pull request #907 from mposolda/master
KEYCLOAK-929 Don't remove principal on session passivation
2015-01-06 19:57:32 +01:00
Bill Burke 0f4953dcd2 fix cached principal adapter 2015-01-06 13:47:02 -05:00
mposolda c7b0c4fb05 KEYCLOAK-929 Don't remove principal on session passivation 2015-01-06 19:44:07 +01:00
Stian Thorgersen 6aa0cb5e3d Merge pull request #906 from gerbermichi/email-event
add error event if mail can not be send
2015-01-06 13:45:30 +01:00
Michael Gerber 181c1c8b5b add error event if mail can not be send 2015-01-06 13:02:27 +01:00
Stian Thorgersen 74ba508e4a KEYCLOAK-918 Reverse proxy triggers NPE in undertow adapter 2015-01-06 10:14:57 +01:00
Stian Thorgersen 992455e273 KEYCLOAK-923 Login redirect should support query param in keycloak.js 2015-01-06 09:56:03 +01:00
Stian Thorgersen 6c8013182b Merge branch 'gerbermichi-reset-password' 2015-01-05 14:34:57 +01:00
Stian Thorgersen 45a1f4361e Add test 2015-01-05 14:34:08 +01:00
Stian Thorgersen 39daeca09c Merge branch 'reset-password' of https://github.com/gerbermichi/keycloak into gerbermichi-reset-password 2015-01-05 14:26:51 +01:00
gerbermichi 0c73e67372 a disabled user should not receive an email to reset the password 2015-01-05 14:07:03 +01:00
Stian Thorgersen 628437c146 KEYCLOAK-760 OAuth2 refresh token expiration date 2015-01-05 10:50:50 +01:00
Stian Thorgersen 528196f786 Merge pull request #903 from gerbermichi/reset-password-email-feature
Add redirect URI to the reset password email web service
2015-01-05 08:59:19 +01:00
Michael Gerber ec1499cdf6 Merge remote-tracking branch 'upstream/master' into reset-password-email-feature 2015-01-02 14:11:51 +01:00
Michael Gerber 019bb558d1 reset-password-email with redirect_uri and client_id 2015-01-02 14:10:44 +01:00
Stian Thorgersen 6462da2c72 Merge pull request #902 from gerbermichi/reset-password-email-fix
fix reset-password-email
2015-01-02 13:51:08 +01:00
Stian Thorgersen d1119a1c26 KEYCLOAK-830
RestEasy client proxy NullPointerException with Keycloak
2015-01-02 12:52:39 +01:00
Michael Gerber 53e18b3ebe fix reset-password-email 2015-01-02 12:52:21 +01:00
Stian Thorgersen f97b71c207 KEYCLOAK-903
No client session for direct grant
2014-12-30 13:28:08 +01:00
Stian Thorgersen a367473386 KEYCLOAK-902 State should not be required 2014-12-30 10:38:08 +01:00
Stian Thorgersen f157dd7915 Updated instructions to test on PostgreSQL 2014-12-30 10:05:27 +01:00
Stian Thorgersen 2eb2ec50e3 KEYCLOAK-885 Support Liquibase updateSQL 2014-12-29 14:40:00 +01:00
Stian Thorgersen 9d63482759 KEYCLOAK-869 Rename EventEntity time column to entity_time 2014-12-29 14:39:42 +01:00
Stian Thorgersen ebf85cf04b Add test to add/remove RequiredAction to UserTest 2014-12-29 08:56:23 +01:00
Bill Burke 3a9a7976fa Merge pull request #901 from patriot1burke/master
error page adapter support
2014-12-23 16:33:29 -05:00
Bill Burke ec9ce6ef2f error page adapter support 2014-12-23 16:33:08 -05:00
Bill Burke 30cfabb08d Merge pull request #900 from patriot1burke/master
update wildfly distro
2014-12-22 16:40:54 -05:00
Bill Burke a280c11897 update wildfly distro 2014-12-22 16:40:29 -05:00
Bill Burke 358f968429 Merge pull request #899 from patriot1burke/master
RESTEASY-901
2014-12-22 16:06:52 -05:00
Bill Burke e39ea2adaf remove redundant tests 2014-12-22 16:06:19 -05:00
Bill Burke 8a1b7e39af RESTEASY-901 2014-12-22 15:59:25 -05:00
Bill Burke af3efa547c Merge pull request #898 from gerbermichi/master
Fix the java.lang.NoClassDefFoundError: org/xnio/OptionMap error
2014-12-22 14:01:26 -05:00
Bill Burke fdbe5c879e Merge pull request #896 from ssilvert/fix-demo-readme
Fix demo readme.
2014-12-22 10:38:14 -05:00
Michael Gerber 3be930f6cf Not required authentication test cases 2014-12-21 15:32:36 +01:00
Michael Gerber bcbb658ae4 Not required authentication bugfix 2014-12-20 14:16:29 +01:00
Michael Gerber 512a68c5fa Not required authentication bugfix 2014-12-20 14:12:35 +01:00
gerbermichi 1eaafcd3d9 bugfix for excluded post rest services 2014-12-19 16:55:46 +01:00
gerbermichi 2a33b177d5 fix nio bug 2014-12-18 16:58:36 +01:00
gerbermichi 1cbf5a5d99 Merge remote-tracking branch 'upstream/master' 2014-12-18 07:54:23 +01:00
Bill Burke 28a56289d9 Merge pull request #897 from patriot1burke/master
saved requests
2014-12-17 22:29:46 -05:00
Bill Burke 08be04b337 saved requests 2014-12-17 22:29:18 -05:00
Bill Burke 519d051eb0 Merge pull request #895 from ssilvert/KEYCLOAK-880-props-in-subsys
KEYCLOAK-880 Fix use of ${..} props in subsystem XML
2014-12-17 16:08:12 -05:00
Stan Silvert fe10913780 Fix demo readme. 2014-12-17 15:55:32 -05:00
Stan Silvert 0082892f7c KEYCLOAK-880 Fix use of ${..} props in subsystem XML 2014-12-17 15:40:02 -05:00
Stian Thorgersen 3a9de56f9c KEYCLOAK-869 Time field in EventEntity should be escaped 2014-12-17 15:04:53 +01:00
Stian Thorgersen e174802b0d KEYCLOAK-825
Log out user sessions on password reset
2014-12-17 14:54:33 +01:00
Stian Thorgersen e42fe6fb23 KEYCLOAK-891 Create server info page on admin console 2014-12-17 13:24:47 +01:00
Stian Thorgersen 6cf42db584 KEYCLOAK-891 Create server info page on admin console 2014-12-17 13:21:31 +01:00
gerbermichi 2186fe32a9 Bugfix: Can not read keycloak-server.json if the path contains a space
https://issues.jboss.org/browse/KEYCLOAK-892
2014-12-17 12:32:06 +01:00
Stian Thorgersen 7886d2aecc Merge pull request #894 from stianst/master
KEYCLOAK-895 Document polyfillers for IE9 compatibility in keycloak.js
2014-12-17 12:16:21 +01:00
Stian Thorgersen 2030ab159d KEYCLOAK-895 Document polyfillers for IE9 compatibility in keycloak.js 2014-12-17 12:15:46 +01:00
Stian Thorgersen ee62f5b1a1 Merge pull request #891 from nilspreusker/ie9-compatibility
IE9 Compatibility
2014-12-17 10:56:14 +01:00
gerbermichi 0755cb6996 Bugfix: Can not read keycloak-server.json if the path contains a space
https://issues.jboss.org/browse/KEYCLOAK-892
2014-12-16 18:54:48 +01:00
gerbermichi 1650cb33c6 Merge remote-tracking branch 'upstream/master' 2014-12-16 18:50:52 +01:00
gerbermichi c34b3a8017 Bugfix: Can not read keycloak-server.json if the path contains a space
https://issues.jboss.org/browse/KEYCLOAK-892
2014-12-16 18:44:09 +01:00
Bill Burke 000a85fe99 Merge pull request #892 from patriot1burke/master
common eap code
2014-12-16 12:27:32 -05:00
Bill Burke 17a8a92bb3 common eap code 2014-12-16 12:26:56 -05:00
Nils Preusker ce1fd8eedc using JSON.stringify(...) and JSON.parse(...)
see
http://lists.jboss.org/pipermail/keycloak-user/2014-December/thread.html
#1355
2014-12-16 16:14:13 +01:00
Stian Thorgersen 919a4c661b Merge pull request #890 from stianst/master
KEYCLOAK-874
2014-12-16 15:31:33 +01:00
Stian Thorgersen cf11911f6b KEYCLOAK-874
keycloak-example-themes-dist:zip:1.1.0.Beta2 does not exist
2014-12-16 15:31:02 +01:00
Stian Thorgersen f620b04656 Merge pull request #888 from gerbermichi/master
Bugfix: Changed timezone to GMT so IE can store cookie
2014-12-16 14:38:08 +01:00
Marek Posolda a3f5ace895 Merge pull request #889 from mposolda/master
Minor improvements/fixes in documentation
2014-12-16 14:22:25 +01:00
mposolda fbe26e28f1 Minor improvements/fixes in documentation 2014-12-16 14:04:04 +01:00
Michael Gerber 9169a3df76 IE 11 does not store cookie because of wrong time zone
https://issues.jboss.org/browse/KEYCLOAK-875
2014-12-13 21:24:49 +01:00
Marek Posolda 5ee0827a84 Merge pull request #887 from mposolda/master
KEYCLOAK-879 Added missing transport element in clustering documentation
2014-12-12 12:20:06 +01:00
mposolda c4462c6de7 KEYCLOAK-879 Added missing transport element in clustering documentation 2014-12-12 12:19:24 +01:00
Bill Burke 4c6f1b6a60 Merge pull request #886 from patriot1burke/master
bump
2014-12-05 21:10:45 -05:00
Bill Burke 6c04e26376 bump 2014-12-05 21:09:38 -05:00
Bill Burke 2ba266c98a Merge pull request #885 from patriot1burke/master
bump version
2014-12-05 19:04:00 -05:00
Bill Burke c0059a875b bump version 2014-12-05 19:03:13 -05:00
Bill Burke 541f23e1bb Merge pull request #884 from patriot1burke/master
rm adapters from appliance/war-dist
2014-12-05 18:33:12 -05:00
Bill Burke b768d593a2 rm adapters from appliance/war-dist 2014-12-05 18:30:41 -05:00
Bill Burke f5fe5c8d73 Merge pull request #883 from patriot1burke/master
proxy fixes
2014-12-05 17:47:14 -05:00
Bill Burke 2350baee14 Merge remote-tracking branch 'upstream/master' 2014-12-05 17:39:12 -05:00
Bill Burke 38073d2aaa fix proxy 2014-12-05 17:38:56 -05:00
Bill Burke 78be1280d3 Merge pull request #880 from ssilvert/master
Restore old AS7 subsystem
2014-12-04 19:25:22 -05:00
Stan Silvert 952436f129 Restore old AS7 subystem. 2014-12-04 14:53:50 -05:00
Stan Silvert a3002cfee6 Remove keycloak subsystem from AS7 dist. 2014-12-04 14:53:49 -05:00
Bill Burke 85ee8f2d43 Merge pull request #882 from patriot1burke/master
bump undertow version
2014-12-04 10:18:46 -05:00
Bill Burke e94f7ca741 bump undertow version 2014-12-04 10:18:16 -05:00
Stian Thorgersen 7de0c8f78b Merge pull request #881 from rexorient/master
Added CORS preflight support for realms/<realm>/tokens/refresh
2014-12-03 08:39:29 +01:00
apenders f3adf02eea Added CORS preflight support for realms/<realm>/tokens/refresh 2014-12-02 15:33:15 -07:00
Marek Posolda f240b60d4b Merge pull request #879 from mposolda/master
Fix osgi packaging
2014-12-02 21:34:25 +01:00
mposolda cd8bee8e29 Fix osgi packaging 2014-12-02 21:33:22 +01:00
Bill Burke 2195c35c70 Merge pull request #878 from patriot1burke/master
adapter testsuite port
2014-12-02 14:39:58 -05:00
Bill Burke 090162ce8a Merge remote-tracking branch 'upstream/master' 2014-12-02 14:38:57 -05:00
Bill Burke 82c3e4c1bc adapter testsuite port and adapter fixes 2014-12-02 14:38:33 -05:00
Marek Posolda e963f7c905 Merge pull request #877 from mposolda/master
Fix eap63 distribution and docker-cluster tool
2014-12-02 20:31:03 +01:00
mposolda 2802ad4ad5 Fix eap63 distribution and docker-cluster tool 2014-12-02 20:28:27 +01:00
Marek Posolda 8eed641f79 Merge pull request #876 from mposolda/master
KEYCLOAK-863 Osgi packaging for karaf/fuse
2014-12-01 15:12:59 +01:00
mposolda bfab7361f4 KEYCLOAK-863 Osgi packaging for karaf/fuse 2014-12-01 15:10:19 +01:00
Stian Thorgersen 4afcbc0610 Merge branch 'objectiser-RTGOV-620' 2014-12-01 13:47:33 +01:00
Stian Thorgersen e069f303a4 Added full scope to app in JaxrsBasicAuthTest 2014-12-01 13:39:19 +01:00
objectiser 8e01f8ecf1 KEYCLOAK-861 Support basic authentication against user credentials managed by KeyCloak. 2014-12-01 11:43:19 +00:00
Marek Posolda 3e8495f435 Merge pull request #875 from mposolda/master
Allow login modules to be more flexible
2014-11-28 20:08:41 +01:00
mposolda c5d000cefc Allow login modules to be more flexible 2014-11-28 20:06:18 +01:00
Stian Thorgersen 5c2e7df7de Merge pull request #873 from stianst/master
Use HmacSHA256 for code signatures
2014-11-27 10:34:51 +01:00
Stian Thorgersen c1360270d0 Ignore ProxyTest 2014-11-27 10:33:54 +01:00
Stian Thorgersen a843e31c12 KEYCLOAK-862 Use HmacSHA256 for code signatures 2014-11-27 10:02:08 +01:00
Stian Thorgersen 6b3e7c76bd Merge pull request #870 from ssilvert/eap-subsys
KEYCLOAK-856 Merge WildFly and EAP subsystems
2014-11-27 10:02:01 +01:00
Bill Burke fde8316693 Merge pull request #872 from patriot1burke/master
proxy headers
2014-11-25 15:14:01 -05:00
Bill Burke 7d4f28f52d proxy headers 2014-11-25 15:13:11 -05:00
Bill Burke 8c451af3f5 Merge pull request #871 from patriot1burke/master
proxy distro and docs
2014-11-24 19:22:44 -05:00
Bill Burke e14c5adf55 Merge remote-tracking branch 'upstream/master' 2014-11-24 19:16:34 -05:00
Bill Burke cdd751a38b proxy docs 2014-11-24 19:16:20 -05:00
Bill Burke d7dfacabfa proxy testing 2014-11-24 18:31:05 -05:00
Bill Burke d0856e024f proxy distro 2014-11-24 18:12:17 -05:00
Stan Silvert 0e58378489 KEYCLOAK-856 Update docs 2014-11-24 17:22:22 -05:00
Stan Silvert d53b01eb2b KEYCLOAK-856 Rename wildfly-subsystem to keycloak-subsystem 2014-11-24 16:52:16 -05:00
Marek Posolda ba9c3c9142 Merge pull request #869 from mposolda/master
KEYCLOAK-859 Added DirectAccessGrantsLoginModule
2014-11-24 19:08:53 +01:00
mposolda 2a78d0d4d0 KEYCLOAK-859 Added DirectAccessGrantsLoginModule 2014-11-24 18:56:51 +01:00
Stan Silvert 34e18c176d KEYCLOAK-856 Remove EAP subsystem 2014-11-23 09:35:19 -05:00
Bill Burke a6f231abbf Merge pull request #868 from patriot1burke/master
proxy config
2014-11-21 18:53:23 -05:00
Bill Burke 4bad1fea86 Merge remote-tracking branch 'upstream/master' 2014-11-21 18:45:02 -05:00
Bill Burke bc6e7c249b proxy config 2 2014-11-21 18:44:39 -05:00
Marek Posolda 21eb40e2c2 Merge pull request #867 from mposolda/master
KEYCLOAK-858 avoid creating inner DeploymentDelegate for each request
2014-11-21 23:50:20 +01:00
mposolda f1378a6092 KEYCLOAK-858 avoid creating inner DeploymentDelegate for each request 2014-11-21 23:49:29 +01:00
Marek Posolda e0d884ac1a Merge pull request #866 from mposolda/master
KEYCLOAK-857 add getter/setter for principalAttribute to AdapterDeployme...
2014-11-21 22:52:39 +01:00
mposolda 829f9f4386 KEYCLOAK-857 add getter/setter for principalAttribute to AdapterDeploymentContext 2014-11-21 22:51:22 +01:00
Stan Silvert f537661341 KEYCLOAK-856 Merge WildFly and EAP subsystems 2014-11-21 13:33:14 -05:00
Marek Posolda 8abbcca76b Merge pull request #865 from mposolda/master
Minor fixes in testsuite
2014-11-21 17:46:58 +01:00
mposolda e3e47a9246 Fix location of Tomcat6 home to be inside target 2014-11-21 17:34:30 +01:00
mposolda 96d430cd7e Fix CookieTokenStoreAdapterTest sometimes failing 2014-11-21 17:34:30 +01:00
Bill Burke b53707a129 Merge pull request #864 from patriot1burke/master
proxy constraints
2014-11-21 11:21:23 -05:00
Bill Burke 3a95401086 proxy constraints 2014-11-21 11:20:47 -05:00
Bill Burke 0143d71728 Merge pull request #863 from patriot1burke/master
proxy
2014-11-20 21:55:49 -05:00
Bill Burke 21279fc9ed proxy 2014-11-20 21:48:59 -05:00
Stian Thorgersen 0327bc0d5a Merge pull request #862 from stianst/master
KEYCLOAK-791 Denial of Service by invalid character injection
2014-11-18 14:59:01 +01:00
Stian Thorgersen ed1073ca92 KEYCLOAK-791 Denial of Service by invalid character injection 2014-11-18 14:58:20 +01:00
Bill Burke ca946d4b19 Merge pull request #860 from carljmosca/master
added support for Tivoli LDAP unique identifier
2014-11-17 10:52:50 -05:00
Bill Burke 7244e2f173 Merge pull request #859 from patriot1burke/master
tomcat6
2014-11-15 12:00:18 -05:00
Bill Burke 5be045c42b tomcat6 2014-11-15 11:59:33 -05:00
Marek Posolda a991ccf909 Merge pull request #858 from mposolda/master
Fixes to login module
2014-11-15 00:14:57 +01:00
mposolda b08930961f Fixes to login module 2014-11-14 21:06:07 +01:00
Bill Burke e01c634ed7 Merge remote-tracking branch 'upstream/master' 2014-11-14 09:20:17 -05:00
Bill Burke 46983d68f3 move ServerCookie to core 2014-11-14 09:20:03 -05:00
Marek Posolda 4ebca3ca43 Merge pull request #857 from mposolda/master
KEYCLOAK-853 Added jaas login module BearerTokenLoginModule
2014-11-14 13:40:58 +01:00
mposolda 68bff44b2e KEYCLOAK-853 Added jaas login module BearerTokenLoginModule 2014-11-14 13:40:12 +01:00
Carl J. Mosca aedbb8eb87 added support for Tivoli LDAP unique identifier 2014-11-13 16:17:40 -05:00
Bill Burke 41c6aacce8 Merge pull request #856 from patriot1burke/master
tomcat 8
2014-11-12 19:04:04 -05:00
Bill Burke a65560c5e6 tomcat8 2014-11-12 19:03:22 -05:00
Bill Burke e2045907d4 tomcat8 2014-11-12 18:56:18 -05:00
Bill Burke f552057b06 Merge remote-tracking branch 'upstream/master' 2014-11-12 15:38:05 -05:00
Bill Burke 81dc076bae Merge pull request #855 from ssilvert/subsys-enhancements
KEYCLOAK-839 Auth Server overlay enhancements
2014-11-12 15:37:39 -05:00
Stan Silvert 67c0182a49 KEYCLOAK-839 Auth Server overlay enhancements 2014-11-12 13:39:39 -05:00
Stan Silvert c85a31be7f KEYCLOAK-839 Auth Server overlay enhancements 2014-11-12 13:39:38 -05:00
Bill Burke ac2b8af172 overview update 2014-11-12 11:00:48 -05:00
Bill Burke 8b515ae625 Merge pull request #854 from patriot1burke/master
jetty 8 support
2014-11-12 10:44:53 -05:00
Bill Burke 9a622a05b1 jetty 8 docs 2014-11-12 10:44:20 -05:00
Bill Burke eccb295076 fix jsps with bad import 2014-11-12 10:34:21 -05:00
Bill Burke dd8c40b0d8 last jetty8 stuff 2014-11-12 10:32:37 -05:00
Bill Burke 25740508b5 fix artifact 2014-11-12 10:08:42 -05:00
Bill Burke 7f23c0dff8 Merge pull request #853 from patriot1burke/master
fix JWS impl, fix contributor SAML PR
2014-11-11 22:10:10 -05:00
Bill Burke 5c6dd8e0c3 temp fix for contributor SAML PR 2014-11-11 22:09:38 -05:00
Bill Burke 3b347d5f52 Merge remote-tracking branch 'upstream/master' 2014-11-11 21:28:49 -05:00
Bill Burke 0636cd898f fix incorrect JWS implementation 2014-11-11 21:28:35 -05:00
Bill Burke 43cb52b319 Merge pull request #852 from eivim/master
Add SAML NameID Formats and include certificate in signature
2014-11-11 20:42:29 -05:00
Eivind Mikkelsen 24a2773524 Add SAML NameID Formats and include certificate in signature
The NameID Format in the AuthnRequest NameIDPolicy is now respected,
and support has been added for the following NameID Formats:

  - urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
  - urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
  - urn:oasis:names:tc:SAML:2.0:nameid-format:transient

The persistent NameID format was previously used in all responses
and mapped to the principal's username. Now, unspecified is mapped
to the principal's username and used by default if no NameIDPolicy
is specified by the SP.

The persistent format requires generating a pseudo-random identifier
that must be generated by the IdP on first login and stored in the
user's profile. Persistent NameID Format is not yet implemented.

The certificate is now added to the signature to enable support for
integration with Service Providers where only the IdP's certificate
fingerprint is configured (e.g. Zendesk).
2014-11-12 01:24:51 +01:00
Marek Posolda 7f29d4c247 Merge pull request #851 from mposolda/pl-upgrade
PL upgrade to 2.7.0.CR2 and ldap improvements
2014-11-11 15:20:46 +01:00
mposolda 279a70bcb8 Fix failing tests 2014-11-11 15:17:32 +01:00
mposolda 2f0498bb7f KEYCLOAK-827 add entryDN as one of attributes, which can be mapped to username 2014-11-11 13:20:12 +01:00
mposolda 64e777a4f4 Upgrade to picketlink 2.7.0.CR2 and minor LDAP improvements 2014-11-11 12:58:49 +01:00
Bill Burke 3fd8cd66d6 Merge pull request #850 from patriot1burke/master
update readme
2014-11-10 17:11:29 -05:00
Bill Burke d72bcebdf0 update readme 2014-11-10 17:11:07 -05:00
Bill Burke 7e9dbce259 Merge pull request #849 from patriot1burke/master
jetty 8
2014-11-10 17:09:39 -05:00
Bill Burke 3b6f10913c merge 2014-11-10 17:09:00 -05:00
Bill Burke 3fbffc9d7d jetty 8 2014-11-10 16:59:31 -05:00
Marek Posolda b4e0a1e6f5 Merge pull request #848 from mposolda/fuse
KEYCLOAK-835 KEYCLOAK-836
2014-11-10 22:26:11 +01:00
mposolda 63198288df Add jetty modules to distribution 2014-11-10 22:16:20 +01:00
mposolda 07fd8ae9d7 KEYCLOAK-836 Added OsgiJaxrsBearerTokenFilterImpl to be used in fuse 2014-11-10 22:16:20 +01:00
mposolda a94ab5883d KEYCLOAK-835 Move AdapterConstants to different package 2014-11-10 22:16:20 +01:00
mposolda d1e819cef1 KEYCLOAK-836 Refactoring of JaxrsBearerTokenFilter to work with both resteasy and Apache CXF. Added test 2014-11-10 22:16:14 +01:00
Bill Burke ebb795af5a Merge pull request #847 from patriot1burke/master
Jetty 9.x adapters
2014-11-07 21:11:24 -05:00
Bill Burke b0a5161e6b final jetty stuff 2014-11-07 21:10:15 -05:00
Bill Burke 3805510e20 more jetty adapter 2014-11-07 18:34:53 -05:00
Bill Burke 31050e0580 Merge pull request #811 from ssilvert/deploy-auth-in-subsys
KEYCLOAK-795 Move Auth Server into Keycloak Subsystem
2014-11-06 17:57:19 -05:00
Bill Burke 2e9f1908f0 Merge pull request #846 from patriot1burke/master
document truststore classpath:
2014-11-06 17:46:21 -05:00
Bill Burke f12cd5fa09 document truststore classpath: 2014-11-06 17:46:01 -05:00
Bill Burke b487d6c836 Merge pull request #844 from Monezz/master
KEYCLOAK-829 Support loading keystore from classpath
2014-11-06 17:39:37 -05:00
Bill Burke 47ea0f5e23 Merge pull request #845 from patriot1burke/master
jetty adapter
2014-11-06 17:36:48 -05:00
Bill Burke d77f1f090f merge for jetty 2014-11-06 17:36:22 -05:00
Bill Burke 666851a44a Merge remote-tracking branch 'upstream/master' 2014-11-06 17:27:44 -05:00
Bill Burke cd25d7019b jetty adapter 2014-11-06 17:27:31 -05:00
Timon Veenstra 7c9e3f4555 KEYCLOAK-829 Adjustment to KetstoreUtil to support loading keystore from classpath 2014-11-06 21:43:49 +01:00
Marek Posolda c0f377c8c7 Merge pull request #841 from jpkrohling/JPK-KEYCLOAK-821
KEYCLOAK-821 - Support for comma-separated list of file names to import.
2014-11-06 20:32:31 +01:00
Stian Thorgersen 4a38b04e3e Merge pull request #843 from stianst/master
KEYCLOAK-824 Wrong digit shown in Invalid Password message
2014-11-06 13:08:42 +01:00
Stian Thorgersen 9343cf2aca KEYCLOAK-824 Wrong digit shown in Invalid Password message 2014-11-06 12:30:24 +01:00
Marek Posolda 3d70bae994 Merge pull request #842 from mposolda/master
KEYCLOAK-822 More mandatory fields in LDAP configuration in admin consol...
2014-11-05 17:20:31 +01:00
mposolda 8895d0b91e KEYCLOAK-822 More mandatory fields in LDAP configuration in admin console 2014-11-05 17:14:03 +01:00
Juraci Paixão Kröhling cd0ad70952 KEYCLOAK-821 - Support for comma-separated list of file names to import. 2014-11-05 17:04:17 +01:00
Stian Thorgersen 5041d6ed80 Merge pull request #840 from stianst/master
KEYCLOAK-820  Don't expose realm private key through admin endpoints
2014-11-05 15:35:32 +01:00
Stian Thorgersen e7625c2bb1 KEYCLOAK-820 Don't expose realm private key through admin endpoints 2014-11-05 15:34:56 +01:00
Stan Silvert 63712039e7 KEYCLOAK-795: Update CLI 2014-11-05 08:31:09 -05:00
Stan Silvert aa55a86ff6 KEYCLOAK-795 Update documentation. Add latest version of CLI to appliance
dist.
2014-11-05 08:31:08 -05:00
Stan Silvert e8e50d2d1c KEYCLOAK-795 Cleanup appliance dist. 2014-11-05 08:31:07 -05:00
Stan Silvert 3f75ebf029 KEYCLOAK-795 Move Auth Server into Keycloak Subsystem 2014-11-05 08:31:07 -05:00
Stan Silvert f9215e961d Incremental commit because I haven't done one in awhile. 2014-11-05 08:31:06 -05:00
Stan Silvert 4776582a6a Old experiment with keycloak-server.json embedded into standalone.xml 2014-11-05 08:31:05 -05:00
Stian Thorgersen 5091e07555 Fix label for certificate on realm-keys page 2014-11-05 13:57:27 +01:00
Stian Thorgersen 5943af79af Update pom for 'examples/demo-template/example-ear' to not deploy to repo 2014-11-05 13:54:14 +01:00
Stian Thorgersen 875e9ba513 Merge pull request #839 from jpkrohling/JPK-Wildfly-Adapter-Dist-Zip-Bug
KEYCLOAK-816 Removed undertow-adapter as dependency from wildfly-adapter-zip
2014-11-05 13:14:04 +01:00
Juraci Paixão Kröhling 8c8f82d0fd KEYCLOAK-816 - Removed undertow-adapter as dependency from wildfly-adapter-zip 2014-11-05 12:15:37 +01:00
Bill Burke 00167ee76a Merge pull request #838 from patriot1burke/master
doclet fix
2014-11-04 16:05:44 -05:00
Bill Burke 9c175bfb5d Merge remote-tracking branch 'upstream/master' 2014-11-04 15:55:47 -05:00
Bill Burke ede59a4441 fix jax-doclets 2014-11-04 15:55:33 -05:00
Stian Thorgersen e91129db92 Merge pull request #837 from stianst/master
Fixes
2014-11-04 16:00:54 +01:00
Stian Thorgersen ebf04c01c6 Fix version in pom for admin-client 2014-11-04 15:57:14 +01:00
Stian Thorgersen 797c2762c8 Fix for sybase 2014-11-04 14:47:51 +01:00
Stian Thorgersen cfb6fb3d06 Update to server-installation.xml 2014-11-04 14:31:07 +01:00
Stian Thorgersen a147136db0 Minor updates to admin-client and multi-tenant examples 2014-11-04 14:22:07 +01:00
Stian Thorgersen 7327423a03 Fix ResetPasswordTest 2014-11-04 13:05:50 +01:00
Stian Thorgersen 91529ef6fd Fix MultiTenancyTest 2014-11-04 13:05:44 +01:00
Stian Thorgersen 431fa29ef1 Use relative urls for multi-tenant example 2014-11-04 10:33:49 +01:00
Stian Thorgersen 1797f7e704 KEYCLOAK-814 Admin Client Example 2014-11-04 10:33:42 +01:00
Stian Thorgersen 0f8c073354 Version bump 2014-11-04 09:01:06 +01:00
Marek Posolda 61a538ba29 Merge pull request #836 from mposolda/master
Fix LDAP test for case-insensitive databases like MySQL
2014-11-03 21:40:45 +01:00
mposolda 9ae8d6aee1 Fix LDAP test for case-insensitive databases like MySQL 2014-11-03 21:35:12 +01:00
Marek Posolda 98852e2f3f Merge pull request #835 from mposolda/master
Docs for AS 7.1.1 and EAP 6.2 workaround
2014-11-03 17:11:47 +01:00
mposolda d997e73f2d Docs for AS 7.1.1 and EAP 6.2 workaround 2014-11-03 17:05:28 +01:00
Stian Thorgersen fd08a884ad Merge pull request #834 from ssilvert/KEYCLOAK-812-remove-confidential-transport
KEYCLOAK-812: Remove confidential transport from auth server web.xml and
2014-11-03 15:55:20 +01:00
Stan Silvert 6c02510b92 KEYCLOAK-812: Remove confidential transport from auth server we.xml and
documentation.
2014-11-03 09:36:55 -05:00
Marek Posolda 7408600f94 Merge pull request #833 from mposolda/master
Fix servlet logout on wildfly/undertow
2014-11-03 13:00:30 +01:00
mposolda 229391d48b Fix servlet logout on wildfly/undertow 2014-11-03 12:59:40 +01:00
Marek Posolda 187fbfaf03 Merge pull request #832 from mposolda/master
Multitenancy example working on AS 7.1.1
2014-11-03 10:44:25 +01:00
mposolda 28547b0620 Multitenancy example working on AS 7.1.1 2014-11-03 10:41:49 +01:00
Bill Burke 380f5dfb4e Merge pull request #831 from patriot1burke/master
principal token attribute mapping
2014-10-31 16:40:30 -04:00
Bill Burke 9c7e297118 principal token attribute mapping 2014-10-31 16:40:07 -04:00
Bill Burke ce94b7e9de Merge pull request #830 from patriot1burke/master
servlet logout fixes
2014-10-31 10:46:27 -04:00
Bill Burke f209476a1b merged 2014-10-31 10:45:35 -04:00
Bill Burke bd08643f6c Merge remote-tracking branch 'upstream/master' 2014-10-31 10:29:13 -04:00
Bill Burke a9770073b2 logout ffixes 2014-10-31 10:29:06 -04:00
Stian Thorgersen da5332608c Merge pull request #829 from stianst/master
KEYCLOAK-805 Add overview section to migration docs
2014-10-31 14:42:26 +01:00
Stian Thorgersen c43040a08e KEYCLOAK-805 Add overview section to migration docs 2014-10-31 14:41:54 +01:00
Stian Thorgersen 488351e46f Merge pull request #828 from stianst/master
KEYCLOAK-787 Clicking back to login after sending password reset email f...
2014-10-31 14:05:31 +01:00
Stian Thorgersen bb2de4dc59 KEYCLOAK-787 Clicking back to login after sending password reset email fails 2014-10-31 13:59:56 +01:00
Marek Posolda fe27f5364a Merge pull request #827 from mposolda/master
Remove realm property from KeycloakSecurityContext. Fix multitenancy on EAP 6.3
2014-10-31 13:32:11 +01:00
mposolda 82af7cbfa2 Fix multi-tenancy on EAP63/AS7 2014-10-31 13:17:35 +01:00
mposolda 44d4f6eb95 Remove redundant realm property from KeycloakSecurityContext 2014-10-31 13:17:35 +01:00
Stian Thorgersen 8d1548bd4d Merge pull request #826 from stianst/master
Fixes
2014-10-31 12:45:31 +01:00
Stian Thorgersen 9b0d5acb50 KEYCLOAK-704 KEYCLOAK-768 Improvements to access code generation 2014-10-31 12:45:03 +01:00
Marek Posolda 39686d5d4e Merge pull request #824 from mposolda/master
KEYCLOAK-808 Issue when DB search is case-sensitive byt LDAP search is n...
2014-10-31 10:42:35 +01:00
mposolda 78a1df693c KEYCLOAK-808 Issue when DB search is case-sensitive byt LDAP search is not 2014-10-31 10:27:55 +01:00
Stian Thorgersen 8adad9dddf KEYCLOAK-806
Increase defaults for 'SSO Session Idle Timeout'
2014-10-31 09:41:21 +01:00
Marek Posolda 65362be4dd Merge pull request #823 from mposolda/master
KEYCLOAK-788 Ensure expired ClientSessions removed during UserSessionPro...
2014-10-30 23:34:27 +01:00
mposolda a6ca925340 KEYCLOAK-788 Ensure expired ClientSessions removed during UserSessionProvider.removeExpiredUserSessions 2014-10-30 23:02:48 +01:00
Marek Posolda 97907cd7ff Merge pull request #822 from mposolda/master
KEYCLOAK-800 and tomcat7 test fixes
2014-10-30 21:42:17 +01:00
mposolda 3d11a4746c Set basedir for Tomcat7 test to avoid creating dirs in workspace 2014-10-30 21:40:35 +01:00
mposolda 0f25280611 KEYCLOAK-800 Ensure that loginFailures infinispan cache is defined 2014-10-30 21:15:52 +01:00
Stian Thorgersen 99016cdc83 Merge pull request #821 from keycloak/multi-tenant-adapter
KEYCLOAK-779
2014-10-30 16:55:00 +01:00
Juraci Paixão Kröhling 8e764e642f KEYCLOAK-779
Adapter multi-tenancy support
2014-10-30 16:54:26 +01:00
Bill Burke a56cef47f2 Merge pull request #820 from patriot1burke/master
remove info logging
2014-10-30 09:53:27 -04:00
Bill Burke cf747dac22 remove info logging 2014-10-30 09:53:06 -04:00
Marek Posolda 0234bdb619 Merge pull request #819 from mposolda/master
KEYCLOAK-799 - Configurable connections pooling for mongo client
2014-10-30 11:20:03 +01:00
mposolda b88b520bad KEYCLOAK-799 - Configurable connections pooling for mongo client 2014-10-30 11:19:16 +01:00
Bill Burke 5446bf77e8 Merge pull request #818 from patriot1burke/master
migrate docs
2014-10-29 16:05:04 -04:00
Bill Burke c5b72464cb migrate docs 2014-10-29 16:04:46 -04:00
Bill Burke 917eb112ff Merge pull request #817 from patriot1burke/master
tomcat7 and bug fix
2014-10-29 16:03:43 -04:00
Bill Burke 0183ac43bc aud should be client-id, issuer should be realm 2014-10-29 15:56:25 -04:00
Bill Burke c660be7bbb tomcat7 docbook 2014-10-29 14:48:10 -04:00
Bill Burke 935045926e tomcat7 distro 2014-10-29 12:30:12 -04:00
Bill Burke d289fa7402 Merge remote-tracking branch 'upstream/master' 2014-10-29 11:42:36 -04:00
Bill Burke 5831cffc19 add logging to pom 2014-10-29 11:42:24 -04:00
Stian Thorgersen 03b8aa1fc2 Merge pull request #812 from stianst/master
Fixes
2014-10-29 14:21:18 +01:00
Stian Thorgersen 05b6dc7af4 KEYCLOAK-797
login-status-iframe.html fails if domain contains hyphen
2014-10-29 14:02:38 +01:00
Stian Thorgersen 8c2d4812b0 KEYCLOAK-763
Document reverse proxy setup on AS7/EAP
2014-10-29 14:02:16 +01:00
Stian Thorgersen fb5482a725 Merge pull request #810 from jpkrohling/JPK-rename-adapter-core
Changed name for adapter-core maven module
2014-10-29 10:35:49 +01:00
Juraci Paixão Kröhling e43dd0ad19 Changed name for adapter-core maven module 2014-10-29 10:18:49 +01:00
Stian Thorgersen 0e6b25fa8d Merge pull request #809 from stianst/master
KEYCLOAK-756 Adding missing metadata to MANIFEST
2014-10-29 10:11:28 +01:00
Stian Thorgersen 6f147f890d KEYCLOAK-756 Adding missing metadata to MANIFEST 2014-10-29 10:08:48 +01:00
Stian Thorgersen 22ddf8b9d1 Merge pull request #808 from stianst/master
KEYCLOAK-726 Downloading a OAuth client installation file results on wro...
2014-10-29 09:13:12 +01:00
Stian Thorgersen 3b23101365 KEYCLOAK-726 Downloading a OAuth client installation file results on wrong JSON 2014-10-29 09:12:14 +01:00
Bill Burke 5e8ca5a140 Merge pull request #807 from patriot1burke/master
add tomcat7 adapter test
2014-10-28 18:41:57 -04:00
Bill Burke da27f43573 add tomcat7 adapter test 2014-10-28 18:41:35 -04:00
Stian Thorgersen c697945d39 Merge pull request #806 from stianst/master
KEYCLOAK-772 Event settings are not imported
2014-10-28 20:35:42 +01:00
Stian Thorgersen fcda005d88 KEYCLOAK-772 Event settings are not imported 2014-10-28 20:21:03 +01:00
Stian Thorgersen ca96c071e8 Merge pull request #805 from stianst/master
Fixes
2014-10-28 20:14:55 +01:00
Stian Thorgersen b23bf58170 KEYCLOAK-352 Third level of navigation is not necessary in some pages 2014-10-28 20:05:18 +01:00
Stian Thorgersen 27d217c220 KEYCLOAK-351 Third level of navigation disappears in 'Add Role' pages 2014-10-28 20:02:27 +01:00
Stian Thorgersen 6e4785e74c KEYCLOAK-777 No login event for social login 2014-10-28 19:56:41 +01:00
Stian Thorgersen 4eb60a169b KEYCLOAK-728 2014-10-28 19:48:11 +01:00
Bill Burke eaaaf91963 Merge pull request #804 from patriot1burke/master
idp descriptor
2014-10-28 12:49:54 -04:00
Bill Burke 12e2a4698d idp descriptor 2014-10-28 12:49:31 -04:00
Bill Burke e5934e9d54 saml docs 2014-10-28 12:16:54 -04:00
Bill Burke 802e184ca9 Merge pull request #803 from patriot1burke/master
saml entity descriptor importer
2014-10-28 12:04:11 -04:00
Bill Burke cb110d095f conflict 2014-10-28 11:55:52 -04:00
Bill Burke e3609cc85b app importer 2014-10-28 11:54:58 -04:00
Marek Posolda e2fd4d3b90 Merge pull request #802 from mposolda/master
KEYCLOAK-740 Documentation of adapters clustering
2014-10-27 23:42:50 +01:00
mposolda b1cfedb488 KEYCLOAK-740 Documentation of adapters clustering 2014-10-27 23:41:36 +01:00
mposolda c6fc44bcc2 Minor fixes and javadoc 2014-10-27 22:02:09 +01:00
Marek Posolda 4b87b8f7e3 Merge pull request #801 from mposolda/master
KEYCLOAK-702 - Added AdapterTokenStore spi. Possibility to save account ...
2014-10-27 17:06:49 +01:00
mposolda a538e25b9d KEYCLOAK-702 - Added AdapterTokenStore spi. Possibility to save account info to cookie as alternative to http session 2014-10-27 16:20:01 +01:00
Bill Burke 971f0f5c16 publish protocol support 2014-10-24 11:25:04 -04:00
Bill Burke 1be070e34d cleanup 2014-10-24 11:00:34 -04:00
Bill Burke dba7864180 Merge remote-tracking branch 'upstream/master' 2014-10-24 10:58:46 -04:00
Bill Burke ce76270ad8 saml key refactor 2014-10-24 10:58:32 -04:00
Stian Thorgersen a2e38d8bd4 Merge pull request #800 from stianst/master
KEYCLOAK-786
2014-10-23 21:00:16 +02:00
Stian Thorgersen 319578f390 KEYCLOAK-786
Value in input fields should be escaped
2014-10-23 20:43:49 +02:00
Marek Posolda 1e68f63715 Merge pull request #797 from mposolda/dynamic-adapter-registration
KEYCLOAK-778 InfinispanUserCacheProvider not working on EAP6 / AS7
2014-10-23 11:38:43 +02:00
mposolda d9331998c3 KEYCLOAK-778 InfinispanUserCacheProvider not working on EAP6 / AS7 2014-10-23 11:36:06 +02:00
Bill Burke ad7e2cd12e Merge pull request #796 from patriot1burke/master
readme
2014-10-22 16:22:09 -04:00
Bill Burke 3b30b63bcc readme 2014-10-22 16:21:46 -04:00
Bill Burke 4417f28c5a Merge pull request #795 from patriot1burke/master
force post binding switch and saml docs
2014-10-22 15:19:02 -04:00
Bill Burke 5fa5379f81 document saml 2014-10-22 15:18:24 -04:00
Bill Burke f715a026ba force post binding switch 2014-10-22 14:32:46 -04:00
Bill Burke de29b566fe Merge pull request #794 from patriot1burke/master
more saml config options
2014-10-22 14:06:51 -04:00
Bill Burke b3fe650e27 Merge remote-tracking branch 'upstream/master' 2014-10-22 14:01:09 -04:00
Bill Burke f38c6d3412 config optiosn 2014-10-22 14:00:56 -04:00
Marek Posolda ed3d13d398 Merge pull request #793 from mposolda/dynamic-adapter-registration
Rewrite NodeRegistrationManagement to better suit multi-tenant usecase
2014-10-22 17:52:19 +02:00
mposolda 5bfb0e73ac Rewrite NodeRegistrationManagement to better suit multi-tenant usecase 2014-10-22 17:11:05 +02:00
Bill Burke 3bfa79e210 Merge pull request #792 from patriot1burke/master
saml distro and examples
2014-10-21 21:39:43 -04:00
Bill Burke 4d3299ae08 saml distro and examples 2014-10-21 21:39:10 -04:00
Marek Posolda 8ec2b2398c Merge pull request #791 from mposolda/dynamic-adapter-registration
Send node registration at 1st request instead of deployment startup. Bug...
2014-10-21 23:22:51 +02:00
mposolda f3da9760a3 Send node registration at 1st request instead of deployment startup. Bugfixing 2014-10-21 23:15:21 +02:00
Bill Burke 87d4cc59a4 Merge pull request #790 from patriot1burke/master
sig alg and upload cert support
2014-10-21 16:39:26 -04:00
Bill Burke a36e43bacc Merge remote-tracking branch 'upstream/master' 2014-10-21 16:33:44 -04:00
Bill Burke 668497df4d upload keys 2014-10-21 16:33:17 -04:00
Bill Burke d3375962ad signature algorithm support 2014-10-21 10:35:39 -04:00
Bill Burke b155382523 Merge pull request #789 from patriot1burke/master
more saml unit tests
2014-10-21 09:10:18 -04:00
Bill Burke e0730e5517 Merge remote-tracking branch 'upstream/master' 2014-10-21 09:05:37 -04:00
Bill Burke c1694a2791 more saml unit tests 2014-10-21 09:05:24 -04:00
Stian Thorgersen dec82ddf68 Merge pull request #787 from stianst/master
KEYCLOAK-711 HttpServletReqest.logout() does not work with relative URI
2014-10-21 12:42:34 +02:00
Marek Posolda 00834ce3c1 Merge pull request #786 from mposolda/dynamic-adapter-registration
KEYCLOAK-759 Added adapter clustering to admin console
2014-10-21 12:37:14 +02:00
Stian Thorgersen 2c218c9aa0 KEYCLOAK-711 HttpServletReqest.logout() does not work with relative URI 2014-10-21 12:36:20 +02:00
mposolda 01c705b4d3 KEYCLOAK-759 Added adapter clustering to admin console 2014-10-21 12:32:53 +02:00
Stian Thorgersen 9565a785b2 Merge pull request #784 from stianst/master
KEYCLOAK-710 Ignore missing roles in access-code
2014-10-21 11:24:28 +02:00
Stian Thorgersen dd4b2f811b KEYCLOAK-710 Ignore missing roles in access-code 2014-10-21 11:15:35 +02:00
Stian Thorgersen ea6d7e1fac Merge pull request #780 from stianst/master
Fixes
2014-10-21 10:01:22 +02:00
Stian Thorgersen 6b2a4229e3 KEYCLOAK-700 Check path is valid in account/login-redirect 2014-10-21 09:57:56 +02:00
Stian Thorgersen 63b41e2548 KEYCLOAK-703 Check valid origin is passed to login-status-iframe 2014-10-21 09:57:56 +02:00
Stian Thorgersen ed895ce02d KEYCLOAK-699 Set maximum size of qr-code 2014-10-21 09:57:56 +02:00
Stian Thorgersen 61b71082f7 Merge pull request #779 from stianst/master
KEYCLOAK-706 SMTP port field should not be mandatory
2014-10-21 09:16:06 +02:00
Stian Thorgersen 5478f282dc KEYCLOAK-706 SMTP port field should not be mandatory 2014-10-21 09:11:49 +02:00
Bill Burke ebaa5bebe5 Merge pull request #778 from patriot1burke/master
saml unit tests
2014-10-20 16:31:39 -04:00
Bill Burke e2de6edff8 saml unit tests 2014-10-20 16:31:00 -04:00
Stian Thorgersen 1d324d6b9a Merge pull request #777 from stianst/master
KEYCLOAK-766 Keycloak fails with OpenShift PostgreSQL 9.2 cartridge, wor...
2014-10-20 19:30:52 +02:00
Stian Thorgersen b0ce226005 KEYCLOAK-766 Keycloak fails with OpenShift PostgreSQL 9.2 cartridge, works fine with MySQL one 2014-10-20 16:50:07 +02:00
Stian Thorgersen a2be747f45 Merge pull request #776 from stianst/master
KEYCLOAK-761
2014-10-20 12:35:48 +02:00
Stian Thorgersen f8e68dadb5 KEYCLOAK-761
Broken databases
2014-10-20 12:35:11 +02:00
Bill Burke 8b05e2ebf8 Merge pull request #775 from patriot1burke/master
saml redirect binding
2014-10-17 16:54:56 -04:00
Bill Burke d0ce72167d merge 2014-10-17 16:54:25 -04:00
Bill Burke c91ecc3033 saml redirect binding 2014-10-17 16:48:45 -04:00
Marek Posolda 4ae6190b79 Merge pull request #774 from mposolda/dynamic-adapter-registration
Fix type in jpa-changelog
2014-10-17 22:13:53 +02:00
mposolda d87a26818e Fix type in jpa-changelog 2014-10-17 22:13:31 +02:00
Marek Posolda 0dae2240e5 Merge pull request #773 from mposolda/dynamic-adapter-registration
KEYCLOAK-759 dynamic registration of managementUrls in cluster
2014-10-17 22:02:47 +02:00
mposolda 7d8f265789 KEYCLOAK-759 dynamic registration of managementUrls in cluster 2014-10-17 21:51:46 +02:00
Stian Thorgersen 8545457f5a Merge pull request #772 from stianst/master
KEYCLOAK-761 Fix database schema
2014-10-17 14:42:57 +02:00
Stian Thorgersen ca2223abb8 KEYCLOAK-761 Fix database schema 2014-10-17 14:21:31 +02:00
Stian Thorgersen 01507fc1dc KEYCLOAK-747 Fix onUserRemoved in user session providers 2014-10-17 13:35:07 +02:00
Bill Burke b9389100cd Merge pull request #771 from patriot1burke/master
saml encryption
2014-10-16 11:52:22 -04:00
Bill Burke 91c545534e Merge remote-tracking branch 'upstream/master' 2014-10-16 11:45:03 -04:00
Bill Burke 3e5afcde9e saml encryption 2014-10-16 11:44:51 -04:00
Bill Burke c90bf2d9e1 Merge pull request #770 from patriot1burke/master
saml signatures
2014-10-16 09:20:08 -04:00
Bill Burke 638ce06f77 Merge remote-tracking branch 'upstream/master' 2014-10-16 09:14:30 -04:00
Bill Burke 4750b22b6d saml signatures 2014-10-16 09:14:04 -04:00
Stian Thorgersen 7d59117fc1 Merge pull request #769 from stianst/master
Added promptOnNonLocalDatabase=false to clean-jpa
2014-10-16 13:03:39 +02:00
Stian Thorgersen 425b2199f2 Added promptOnNonLocalDatabase=false to clean-jpa 2014-10-16 13:03:00 +02:00
Stian Thorgersen a882f95749 Merge pull request #768 from stianst/master
Simplified embedded infinispan connection config
2014-10-16 12:40:08 +02:00
Stian Thorgersen cdcbafa311 Simplified embedded infinispan connection config 2014-10-16 12:39:14 +02:00
Stian Thorgersen a36fd419b5 Merge pull request #767 from stianst/master
Add clean-jpa profile to testsuite
2014-10-16 10:02:53 +02:00
Stian Thorgersen 9029ec4f28 Add clean-jpa profile to testsuite 2014-10-16 10:02:24 +02:00
Stian Thorgersen d013e9869a Merge pull request #766 from stianst/master
KEYCLOAK-761 Fix type of credential#salt
2014-10-16 09:35:55 +02:00
Stian Thorgersen fe5eb1a06d KEYCLOAK-761 Fix type of credential#salt 2014-10-16 09:34:53 +02:00
Bill Burke 582ee8897e Merge pull request #765 from patriot1burke/master
app cert generation support
2014-10-14 19:17:26 -04:00
Bill Burke 4e41041469 db 2014-10-14 19:13:23 -04:00
Bill Burke 8fbc8fc736 Merge remote-tracking branch 'upstream/master' 2014-10-14 18:39:08 -04:00
Bill Burke 7760887ac1 app cert support, bug fixes 2014-10-14 18:38:48 -04:00
Stian Thorgersen 7e7ab86821 Merge pull request #763 from stianst/master
KEYCLOAK-755 Support env variables in keycloak-server.json
2014-10-14 15:06:57 +02:00
Stian Thorgersen 106a0cb48d KEYCLOAK-755 Support env variables in keycloak-server.json 2014-10-14 15:06:18 +02:00
Stian Thorgersen 75be776aa1 Removed properties from server keycloak-server.json 2014-10-14 15:06:18 +02:00
Stian Thorgersen 2dbebd164f Merge pull request #762 from stianst/master
KEYCLOAK-753 Add 'username:' prefix to remember me cookie to prevent iss...
2014-10-14 13:49:59 +02:00
Stian Thorgersen 1021e8af5c KEYCLOAK-753 Add 'username:' prefix to remember me cookie to prevent issue with old cookie 2014-10-14 13:44:03 +02:00
Stian Thorgersen 2ad688a663 Merge pull request #761 from stianst/liquibase
KEYCLOAK-736 Fix class-path issues
2014-10-14 13:05:25 +02:00
Stian Thorgersen bf7effc6f2 KEYCLOAK-736 Fix class-path issues 2014-10-14 13:04:38 +02:00
Stian Thorgersen d86547620a Merge pull request #760 from stianst/liquibase
KEYCLOAK-736 Database migration support"
2014-10-14 10:41:48 +02:00
Stian Thorgersen 94de88ef3b KEYCLOAK-736 Database migration support" 2014-10-14 10:07:41 +02:00
Stian Thorgersen 101c7697fd Merge pull request #759 from stianst/master
KEYCLOAK-744 Document view-event and manage-event roles
2014-10-13 14:02:47 +02:00
Stian Thorgersen cf94f4f84a KEYCLOAK-744 Document view-event and manage-event roles 2014-10-13 14:02:20 +02:00
Stian Thorgersen 6855b2f0e4 Merge pull request #758 from stianst/master
KEYCLOAK-746 Allow linking to account from external provider
2014-10-13 13:19:36 +02:00
Stian Thorgersen 4d401224de KEYCLOAK-746 Allow linking to account from external provider 2014-10-13 10:48:45 +02:00
Bill Burke 4d007c776a generate/store realm certificate 2014-10-11 10:49:04 -04:00
Bill Burke eac1fb23cf Merge pull request #757 from patriot1burke/master
use id for oauth in admin console
2014-10-10 16:56:47 -04:00
Bill Burke d9ff44b870 Merge remote-tracking branch 'upstream/master' 2014-10-10 16:56:16 -04:00
Bill Burke deffa9b4e1 oauth id in admin console 2014-10-10 16:55:57 -04:00
Bill Burke 3d7fca885e Merge pull request #756 from patriot1burke/master
freeotp
2014-10-10 16:08:03 -04:00
Bill Burke 08c5fed1b3 freeotp 2014-10-10 16:07:35 -04:00
Bill Burke 23d0361168 Merge pull request #755 from patriot1burke/master
admin console and model attributes
2014-10-09 18:31:16 -04:00
Bill Burke 0ace5cd746 merge conflicts 2014-10-09 18:26:14 -04:00
Bill Burke 94da99bf10 use app id in admin console urls 2014-10-09 18:22:02 -04:00
Marek Posolda 3d5d7777f6 Merge pull request #754 from mposolda/master
KEYCLOAK748 cluster-aware logout for non-distributable applications
2014-10-09 21:36:13 +02:00
mposolda 9954d68a1f KEYCLOAK-748 cluster-aware logout for non-distributable apps 2014-10-09 21:33:07 +02:00
mposolda 00716b7bfc Docker config update 2014-10-09 21:33:06 +02:00
Stian Thorgersen 6d1555262e Merge branch 'abstractj-totp-name' 2014-10-09 13:08:54 +02:00
Bruno Oliveira c00c712c39 KEYCLOAK-745 Display the realm name for OTP QR code scan 2014-10-09 13:03:48 +02:00
Marek Posolda 63f4a32f2e Merge pull request #752 from mposolda/stateless-session-mgmt
Test for KEYCLOAK-741
2014-10-09 12:36:40 +02:00
mposolda 2445575a04 Test for KEYCLOAK-741 2014-10-09 12:30:30 +02:00
Marek Posolda 56fe821bef Merge pull request #751 from mposolda/stateless-session-mgmt
Fix mongo to pass with testsuite
2014-10-09 11:38:59 +02:00
mposolda 36cc298b32 Fix mongo to pass with testsuite 2014-10-09 11:37:42 +02:00
Marek Posolda a00d36eea2 Merge pull request #750 from mposolda/stateless-session-mgmt
Stateless session mgmt
2014-10-08 23:32:51 +02:00
mposolda ac8b43358d Reduce logging 2014-10-08 23:28:02 +02:00
mposolda 1e33931f23 KEYCLOAK-741 Failure to refresh token should invalidate http session 2014-10-08 22:18:11 +02:00
mposolda 7e7406ddb7 KEYCLOAK-743 Stateless session mgmt. Drop statistics for adapters. 2014-10-08 22:18:10 +02:00
mposolda 84e1ace539 KEYCLOAK-742 Added always-refresh-token option to adapters 2014-10-08 22:18:10 +02:00
Bill Burke a1d1877751 ClientModel attributes and protocol 2014-10-08 10:54:13 -04:00
Bill Burke 390ca0930b Merge pull request #749 from patriot1burke/master
undertow slash redirect problem
2014-10-08 09:46:20 -04:00
Bill Burke 13a2108846 undertow slash redirect problem 2014-10-08 09:45:49 -04:00
Bill Burke 9ffd517b53 Merge pull request #747 from patriot1burke/master
saml backchannel logout
2014-10-07 18:18:54 -04:00
Bill Burke 5f1e6f3a23 merge 2014-10-07 18:17:44 -04:00
Bill Burke 6d5ab0f66b saml backchannel logout 2014-10-07 18:06:02 -04:00
Marek Posolda bc85be23b7 Merge pull request #746 from mposolda/master
KEYCLOAK-738 Possible NPE in MemUserSessionProvider.getUserSessions
2014-10-07 19:21:14 +02:00
mposolda 6522455b44 KEYCLOAK-738 Possible NPE in MemUserSessionProvider.getUserSessions 2014-10-07 19:19:46 +02:00
Stian Thorgersen 2e76be45fa Merge pull request #744 from pilhuhn/patch-1
Update adapter-config.xml
2014-10-07 13:15:05 +02:00
Marek Posolda 0c3a9be1a1 Merge pull request #745 from mposolda/docker
Possibility to test EAP6 cluster with docker+fig
2014-10-07 12:42:08 +02:00
mposolda a6bbc492b8 Possibility to test EAP6 cluster with docker+fig 2014-10-07 12:33:44 +02:00
Heiko W. Rupp 3d4ef91bf1 Update adapter-config.xml
Fix some minor typos in the json, Otherwise it is invalid.

Also deploying in the keycloak 1.0.1 appliance, the line

"cors-allowed-methods" : [ "POST", "PUT", "DELETE", "GET" ],

makes parsing fail with 

11:19:10,121 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) JBAS014613: Operation ("full-replace-deployment") failed - address: ([]) - failure description: {"JBAS014671: Failed services" => {"jboss.undertow.deployment.default-server.default-host./rhq-metrics" => "org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./rhq-metrics: Failed to start service
    Caused by: java.lang.RuntimeException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
 at [Source: java.io.BufferedInputStream@1605c2fe; line: 9, column: 24] (through reference chain: org.keycloak.representations.adapters.config.AdapterConfig[\"cors-allowed-methods\"])
    Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
 at [Source: java.io.BufferedInputStream@1605c2fe; line: 9, column: 24] (through reference chain: org.keycloak.representations.adapters.config.AdapterConfig[\"cors-allowed-methods\"])"}}
2014-10-07 11:21:15 +02:00
Stian Thorgersen 1604315e40 Merge pull request #743 from stianst/master
KEYCLOAK-730 Document clustering
2014-10-06 13:58:57 +02:00
Stian Thorgersen f702d8f1ff KEYCLOAK-730 Document clustering 2014-10-06 13:58:32 +02:00
Marek Posolda 87f826c850 Merge pull request #742 from mposolda/master
Simplify method signature in JsonSerialization
2014-10-05 22:12:19 +02:00
mposolda 59bf7e524f Change method signature 2014-10-05 20:07:54 +02:00
Bill Burke e01424b815 Merge pull request #741 from patriot1burke/master
saml basic
2014-10-04 22:15:56 -04:00
Bill Burke c609ae3496 saml 2014-10-04 22:15:25 -04:00
Bill Burke e3a3933390 saml basic 2014-10-04 21:27:48 -04:00
Stian Thorgersen 1f40ab407c Merge pull request #739 from stianst/master
KEYCLOAK-729
2014-10-03 14:11:49 +02:00
Stian Thorgersen 1d66bd9c15 KEYCLOAK-729
Update themes documentation
2014-10-03 14:11:03 +02:00
Stian Thorgersen 777999e0ea Merge pull request #737 from stianst/master
KEYCLOAK-722 Refreshing token throws RuntimeException if realm keys have...
2014-10-03 13:23:53 +02:00
Stian Thorgersen 0d5be568f8 KEYCLOAK-722 Refreshing token throws RuntimeException if realm keys have changed 2014-10-03 13:23:21 +02:00
Stian Thorgersen 17bb42d60e Merge pull request #736 from stianst/master
KEYCLOAK-662 NPE when using direct grant API with email as username
2014-10-03 12:12:16 +02:00
Stian Thorgersen d6f030a05a KEYCLOAK-662 NPE when using direct grant API with email as username 2014-10-03 12:10:52 +02:00
Marek Posolda 18401815af Merge pull request #734 from mposolda/master
Workaround for WFLY-3345 so logout can work for 'distributable' applicat...
2014-10-03 11:27:28 +02:00
mposolda 10e618dee9 Workaround for WFLY-3345 so logout can work for 'distributable' applications 2014-10-03 11:26:34 +02:00
Stian Thorgersen 98f9c798f0 Merge pull request #733 from stianst/master
KEYCLOAK-701 Use built-in themes if specified theme is not found
2014-10-03 11:24:40 +02:00
Stian Thorgersen 49f3172163 KEYCLOAK-701 Use built-in themes if specified theme is not found 2014-10-03 11:17:12 +02:00
Stian Thorgersen 53489cd556 Merge pull request #731 from stianst/master
Add login test with multiple sessions for same user
2014-10-03 10:42:39 +02:00
Stian Thorgersen a5aa1da841 Add login test with multiple sessions for same user 2014-10-03 10:41:04 +02:00
Marek Posolda e11180a4f0 Merge pull request #729 from mposolda/master
KEYCLOAK-732 AuthenticationManager.logout should logout just current use...
2014-10-02 22:54:31 +02:00
mposolda e6121f301f KEYCLOAK-732 AuthenticationManager.logout should logout just current userSession 2014-10-02 22:52:44 +02:00
Marek Posolda 4050cf9ac3 Merge pull request #728 from mposolda/master
KEYCLOAK-731
2014-10-02 19:19:09 +02:00
mposolda 50f148cd7c Use one option "auth-server-url-for-backend-requests" instead of 3 options 2014-10-02 19:16:04 +02:00
mposolda 72b5632cfe KEYCLOAK-731 Support for replacing configuration of Java adapters with system properties 2014-10-02 19:15:37 +02:00
Stian Thorgersen 8855bcf3c1 Merge pull request #727 from stianst/master
KEYCLOAK-727: 'logout'->'log out' + moved message to bundle
2014-10-02 10:55:01 +02:00
Lukas Fryc a85b58dccd KEYCLOAK-727: 'logout'->'log out' + moved message to bundle 2014-10-02 10:54:26 +02:00
Stian Thorgersen 01e6d09d79 Merge pull request #725 from stianst/master
Fixes to infinispan user session provider
2014-10-02 09:43:21 +02:00
Stian Thorgersen 597ee2b8c9 Fixes to infinispan user session provider 2014-10-02 09:00:48 +02:00
Marek Posolda 6ff37cfc24 Merge pull request #724 from mposolda/master
KEYCLOAK-709 ResourceAdminManager.logoutApplication shouldn't immediatel...
2014-10-01 23:21:46 +02:00
mposolda 95521e8a95 KEYCLOAK-709 ResourceAdminManager.logoutApplication shouldn't immediatelly fail with RuntimeException 2014-10-01 23:20:49 +02:00
Bill Burke 4b254475da Merge pull request #723 from patriot1burke/master
finish login protocol refactoring
2014-10-01 14:58:42 -04:00
Bill Burke 6cf62a2768 move pre-auth 2014-10-01 14:57:52 -04:00
Bill Burke 71216bf2c9 merge 2014-10-01 14:21:23 -04:00
Bill Burke cbc383d494 finish protocol refactoring 2014-10-01 14:19:59 -04:00
Marek Posolda a75c9ee04e Merge pull request #722 from mposolda/master
Http session replication working for example apps on Wildfly
2014-10-01 19:14:14 +02:00
mposolda d7bcd41909 Ensure that KeycloakUndertowAccount and referenced classes can be serialized in session 2014-10-01 19:08:41 +02:00
Bill Burke 546d45b009 protocol abstraction 2014-10-01 10:38:42 -04:00
Bill Burke 99738ea4ad Merge remote-tracking branch 'upstream/master' 2014-10-01 10:01:59 -04:00
Bill Burke 4b399fe05a login protocol abstraction 2014-10-01 10:01:42 -04:00
mposolda eb920b4993 Examples: Don't require to create HttpSession when visiting JSP pages 2014-10-01 13:44:38 +02:00
mposolda 1b6b95bb9a Added distributable to customer-portal in cluster test 2014-10-01 11:52:16 +02:00
Marek Posolda bd077a3adb Merge pull request #721 from mposolda/master
Use infinispan UserSession provider for docker cluster env. Don't prepar...
2014-10-01 10:52:48 +02:00
mposolda fd0a000823 Use infinispan UserSession provider for docker cluster env. Don't prepare nodes during each fig start 2014-10-01 10:51:24 +02:00
Bill Burke a6ae8d08ac Merge pull request #720 from patriot1burke/master
token service refactoring
2014-09-30 16:03:13 -04:00
Bill Burke e32f73880f Merge remote-tracking branch 'upstream/master' 2014-09-30 15:58:39 -04:00
Bill Burke 63b65c933b token service refactoring 2014-09-30 15:58:20 -04:00
Marek Posolda 72ec9ccb00 Merge pull request #719 from mposolda/master
KEYCLOAK-721 Possibility to resolve relative URI by hostname. Examples working in docker clustering env
2014-09-30 20:17:25 +02:00
mposolda 89dc55a106 Make examples working in docker cluster env 2014-09-30 19:50:17 +02:00
mposolda 80a9a8984a Cleanup. Support to use-hostname-for-local-requests added to Demo examples 2014-09-30 17:37:36 +02:00
mposolda 18fe808ce0 KEYCLOAK-720 Support for relative URI resolved by hostname in wildfly adapter 2014-09-30 17:37:36 +02:00
mposolda 337b03fc62 KEYCLOAK-720 added support for oauth clients 2014-09-30 17:37:36 +02:00
Stian Thorgersen 617c61034f Merge pull request #718 from stianst/master
KEYCLOAK-725 Add realm update to the Admin Client
2014-09-30 15:44:16 +02:00
Stian Thorgersen f026772c87 KEYCLOAK-725 Add realm update to the Admin Client 2014-09-30 15:43:18 +02:00
Stian Thorgersen 0f307afd16 Merge pull request #717 from stianst/master
Fixes to JPA user session provider
2014-09-30 14:47:45 +02:00
Stian Thorgersen a1f223735c Fixes to JPA user session provider 2014-09-30 14:47:22 +02:00
Stian Thorgersen d1bb872aec Merge pull request #716 from stianst/master
Fixes to Mongo user session provider
2014-09-30 14:25:49 +02:00
Stian Thorgersen 1d4e842cc0 Fixes to Mongo user session provider 2014-09-30 14:24:49 +02:00
Stian Thorgersen 209fdc1255 Fix UserSessionProviderTest.testGetByClientPaginated 2014-09-30 10:59:37 +02:00
Stian Thorgersen 3ded1943e2 Merge pull request #715 from keycloak/clustering
Fixes to UserSessionProviderTest
2014-09-30 10:23:10 +02:00
Stian Thorgersen bdeb59f87e Fixes to UserSessionProviderTest 2014-09-30 10:22:33 +02:00
Stian Thorgersen 994adaf493 Merge pull request #714 from keycloak/clustering
Clustering support
2014-09-30 10:21:21 +02:00
Stian Thorgersen 99c73a9cc7 Clustering support 2014-09-30 09:40:20 +02:00
Bill Burke 6075ef221f Merge pull request #713 from patriot1burke/master
action url refactor
2014-09-29 16:58:27 -04:00
Bill Burke fc867e59ea action url refactor 2014-09-29 16:57:58 -04:00
Bill Burke 6212403569 Merge pull request #712 from patriot1burke/master
login refactor phase 2, still more to do
2014-09-29 16:16:10 -04:00
Bill Burke 75a3093dda login refactor phase 2, still more to do 2014-09-29 16:15:33 -04:00
Bill Burke 6c46af5b3c Merge pull request #711 from patriot1burke/master
cliensession refactor
2014-09-29 10:01:35 -04:00
Bill Burke 67f10bee24 Merge remote-tracking branch 'upstream/master' 2014-09-29 09:56:37 -04:00
Bill Burke 524b423733 ClientSession everywhere refactor phase1 2014-09-26 17:44:33 -04:00
Stian Thorgersen c05f83c9b3 Merge pull request #709 from stianst/master
Add test to add/remove attributes to user through admin endpoints
2014-09-25 19:36:43 +02:00
Stian Thorgersen f2e97ff9d6 Add test to add/remove attributes to user through admin endpoints 2014-09-25 19:35:57 +02:00
Stian Thorgersen ca4ed6d528 Merge pull request #708 from stianst/master
Fix cordova example
2014-09-25 19:00:45 +02:00
Stian Thorgersen 8006ea073b Fix cordova example 2014-09-25 19:00:13 +02:00
Stian Thorgersen f8b4a91fa8 Merge pull request #707 from sebastienblanc/all_origins
change origin to * so it will work even if KC is behind https (like on OpenShift)
2014-09-25 18:49:36 +02:00
Sebastien Blanc e17d6c81f9 change origin to * 2014-09-25 17:43:10 +02:00
Stian Thorgersen f77de41b2e Merge pull request #706 from stianst/master
Fix welcome-theme for testsuite
2014-09-25 11:54:21 +02:00
Stian Thorgersen c12577e886 Fix welcome-theme for testsuite 2014-09-25 11:53:28 +02:00
Stian Thorgersen 5daec20a6e Merge pull request #705 from cvasilak/doc-link
fix docbook link
2014-09-24 12:05:11 +01:00
Christos Vasilakis 6d3aaa0560 fix docbook link 2014-09-24 12:58:18 +03:00
Stian Thorgersen 2e11e71453 Merge pull request #704 from cvasilak/link.fix
fix create-realm link
2014-09-24 10:03:21 +01:00
Christos Vasilakis fb561b8fd6 fix create-realm link 2014-09-24 11:40:22 +03:00
Bill Burke 0bf6c36ca7 add auth method to ClientSession 2014-09-23 11:18:39 -04:00
Bill Burke 66d58476d0 refactor security page flow 2014-09-23 11:05:10 -04:00
Bill Burke bf42227224 remove junk 2014-09-22 16:35:22 -04:00
Bill Burke 99a6713e6f clientsession notes 2014-09-22 16:34:42 -04:00
Bill Burke a26ac1758c Merge pull request #703 from patriot1burke/master
KEYCLOAK-705 and 687
2014-09-19 11:37:25 -04:00
Bill Burke ef60e17641 security vulnerability doc 2014-09-19 11:35:15 -04:00
Bill Burke 53943f8246 KEYCLOAK-705 2014-09-19 11:03:08 -04:00
Bill Burke 0b8b31a3ea KEYCLOAK-705 2014-09-19 10:00:47 -04:00
Stian Thorgersen 6f3132eafd Merge pull request #701 from stianst/master
KEYCLOAK-696 Display Keycloak version in admin console
2014-09-18 13:24:38 +02:00
Stian Thorgersen dcb5717154 KEYCLOAK-696 Display Keycloak version in admin console 2014-09-18 13:24:03 +02:00
Stian Thorgersen bfdb8d4e2d Merge pull request #700 from stianst/master
Removed info log statement
2014-09-18 12:38:48 +02:00
Stian Thorgersen 91fced3b87 Removed info log statement 2014-09-18 12:37:51 +02:00
Marek Posolda 825c475c7f Merge pull request #699 from mposolda/master
Admin console fixes, KEYCLOAK_REMEMBER_ME life changed to 1 year
2014-09-18 11:15:09 +02:00
mposolda 89471b7db1 KEYCLOAK-695 Let KEYCLOAK_REMEMBER_ME cookie to be valid for 1 year 2014-09-18 11:03:44 +02:00
mposolda 95233af485 KEYCLOAK-694 Fix JS error which could happen when creating application 2014-09-18 10:51:10 +02:00
mposolda fc37398235 KEYCLOAK-693 Hide top navigation when creating OAuth client 2014-09-18 10:50:18 +02:00
Marek Posolda 16ea18370d Merge pull request #698 from mposolda/master
Prefill login form just if rememberMe enabled for the realm
2014-09-17 08:59:00 +02:00
mposolda 1049bca433 Prefill login form just if rememberMe enabled for the realm 2014-09-17 08:54:29 +02:00
Marek Posolda 364174fb7e Merge pull request #697 from mposolda/master
Cookie & rememberMe fix. Fixing testsuite with mongo
2014-09-16 22:15:27 +02:00
mposolda 5352872b4b Use KEYCLOAK_REMEMBER_ME as hint to prefill login form. Change lifespan of KEYCLOAK_IDENTITY to maxSsoSessionLifespan 2014-09-16 22:09:27 +02:00
mposolda bd0887d18e Fixing testsuite for mongo 2014-09-16 20:02:30 +02:00
Marek Posolda 9a5f42039d Merge pull request #696 from mposolda/master
Added directive kcNavigationApplication and kcNavigationOauthClient. Hide Scope and Claims for bearer-only apps
2014-09-12 20:16:52 +02:00
mposolda ce8dd136bd Added directive kcNavigationApplication and kcNavigationOauthClient. Hide Scope and Claims for bearer-only apps 2014-09-12 20:15:11 +02:00
mposolda 1be2bff95f Typo 2014-09-12 16:57:02 +02:00
Stian Thorgersen 485ca9c90f Merge pull request #695 from stianst/master
KEYCLOAK-657 Set cache-control for keycloak.js and login-iframe
2014-09-12 13:47:20 +02:00
Stian Thorgersen 811cfd52c9 KEYCLOAK-657 Set cache-control for keycloak.js and login-iframe 2014-09-12 13:46:56 +02:00
Stian Thorgersen 5c1807eb2d Merge pull request #694 from stianst/master
Fixes to KEYCLOAK-682
2014-09-12 12:27:31 +02:00
Stian Thorgersen 7c15a70f53 Fixes to KEYCLOAK-682 2014-09-12 12:26:52 +02:00
Stian Thorgersen c9c525e942 Merge pull request #693 from stianst/master
KEYCLOAK-682 Only send logout admin action to clients associated with us...
2014-09-12 11:47:30 +02:00
Stian Thorgersen 5d141d4d8a KEYCLOAK-682 Only send logout admin action to clients associated with user session 2014-09-12 11:47:11 +02:00
Stian Thorgersen e96d6f0dfd Merge pull request #692 from stianst/master
Change version schema to match JBoss
2014-09-12 09:36:27 +02:00
Stian Thorgersen 423dc1b8a7 Change version schema to match JBoss 2014-09-12 09:35:08 +02:00
Marek Posolda ab080dcdd8 Merge pull request #691 from mposolda/master
Preserve form values in account mgmt after error. Allow valid email during registration or account mgmt
2014-09-11 20:57:27 +02:00
mposolda 6f173d4554 KEYCLOAK-678 Preserve form values in account mgmt after error 2014-09-11 20:54:48 +02:00
mposolda 649a40f58c KEYCLOAK-676 Validate email address format during registration or account mgmt 2014-09-11 20:05:00 +02:00
Stian Thorgersen d06668d39b Merge pull request #690 from stianst/master
KEYCLOAK-653 Add theme support to welcome-pages
2014-09-11 15:58:51 +02:00
Stian Thorgersen b23463a1d2 KEYCLOAK-653 Add theme support to welcome-pages 2014-09-11 15:58:29 +02:00
Stian Thorgersen 7f81032577 Merge pull request #689 from stianst/master
KEYCLOAK-680 Add/remove social-links through admin api
2014-09-11 12:10:23 +02:00
Stian Thorgersen 280cbf2174 KEYCLOAK-680 Add/remove social-links through admin api 2014-09-11 12:09:55 +02:00
Stian Thorgersen 228bb297c2 Merge pull request #688 from stianst/master
Added KEYCLOAK_DEV_PORT env variable for KeycloakServer
2014-09-11 11:05:53 +02:00
Stian Thorgersen f96e59d085 Added KEYCLOAK_DEV_PORT env variable for KeycloakServer 2014-09-11 11:05:29 +02:00
Stian Thorgersen 86300e7e86 Merge pull request #687 from stianst/master
Version bump
2014-09-11 09:29:37 +02:00
Stian Thorgersen 5dea07793b Version bump 2014-09-11 09:27:58 +02:00
1220 changed files with 51600 additions and 7257 deletions

No files matched your search

+6
View File
@@ -9,6 +9,12 @@
.settings
.classpath
# NetBeans #
############
nbactions.xml
nb-configuration.xml
catalog.xml
# Compiled source #
###################
*.com
+8
View File
@@ -0,0 +1,8 @@
language: java
cache:
directories:
- $HOME/.m2
sudo: false
after_script: 'misc/.travis/after.sh'
+4 -3
View File
@@ -5,14 +5,14 @@ Please visit [http://keycloak.org](http://keycloak.org) for more information on
and video tutorials.
Keycloak is an SSO Service for web apps and REST services.
It can be used for social applications as well as enterprise applications. It is based on OpenID Connect with SAML support in the works.
It can be used for social applications as well as enterprise applications. It is based on OpenID Connect with support for SAML 2.0 as well.
Here's some of the features:
* SSO and Single Log Out for browser applications
* Social Broker. Enable Google, Facebook, Yahoo, Twitter social login with no code required.
* Optional LDAP/Active Directory integration
* Optional User Registration
* Password and TOTP support (via Google Authenticator). Client cert auth coming soon.
* Password and TOTP support (via Google Authenticator or FreeOTP). Client cert auth coming soon.
* User session management from both admin and user perspective
* Customizable themes for user facing pages: login, grant pages, account management, emails, and admin console all customizable!
* OAuth Bearer token auth for REST Services
@@ -24,12 +24,13 @@ Here's some of the features:
* Completely centrally managed user and role mapping metadata. Minimal configuration at the application side
* Admin Console for managing users, roles, role mappings, applications, user sessions, allowed CORS web origins, and OAuth clients.
* Deployable as a WAR, appliance, or an Openshift cloud service (SaaS).
* Supports JBoss AS7, EAP 6.x, and Wildfly applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java applications.
* Supports JBoss AS7, EAP 6.x, Wildfly, Tomcat, and Jetty applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java applications.
* Javascript/HTML 5 adapter for pure Javascript apps
* Session management from admin console
* Revocation policies
* Password policies
* OpenID Connect Support
* SAML Support
Please visit [http://keycloak.org](http://keycloak.org) for more information on Keycloak including how to download, documentation,
and video tutorials.
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0"?>
<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>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-infinispan</artifactId>
<name>Keycloak Connections Infinispan</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,26 @@
package org.keycloak.connections.infinispan;
import org.infinispan.Cache;
import org.infinispan.manager.EmbeddedCacheManager;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultInfinispanConnectionProvider implements InfinispanConnectionProvider {
private EmbeddedCacheManager cacheManager;
public DefaultInfinispanConnectionProvider(EmbeddedCacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@Override
public <K, V> Cache<K, V> getCache(String name) {
return cacheManager.getCache(name);
}
@Override
public void close() {
}
}
@@ -0,0 +1,123 @@
package org.keycloak.connections.infinispan;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.manager.EmbeddedCacheManager;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import javax.naming.InitialContext;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultInfinispanConnectionProviderFactory implements InfinispanConnectionProviderFactory {
protected static final Logger logger = Logger.getLogger(DefaultInfinispanConnectionProviderFactory.class);
private Config.Scope config;
private EmbeddedCacheManager cacheManager;
private boolean containerManaged;
@Override
public InfinispanConnectionProvider create(KeycloakSession session) {
lazyInit();
return new DefaultInfinispanConnectionProvider(cacheManager);
}
@Override
public void close() {
if (cacheManager != null && !containerManaged) {
cacheManager.stop();
}
cacheManager = null;
}
@Override
public String getId() {
return "default";
}
@Override
public void init(Config.Scope config) {
this.config = config;
}
private void lazyInit() {
if (cacheManager == null) {
synchronized (this) {
if (cacheManager == null) {
String cacheContainer = config.get("cacheContainer");
if (cacheContainer != null) {
initContainerManaged(cacheContainer);
} else {
initEmbedded();
}
}
}
}
}
private void initContainerManaged(String cacheContainerLookup) {
try {
cacheManager = (EmbeddedCacheManager) new InitialContext().lookup(cacheContainerLookup);
containerManaged = true;
logger.debugv("Using container managed Infinispan cache container, lookup={1}", cacheContainerLookup);
} catch (Exception e) {
throw new RuntimeException("Failed to retrieve cache container", e);
}
}
private void initEmbedded() {
GlobalConfigurationBuilder gcb = new GlobalConfigurationBuilder();
boolean clustered = config.getBoolean("clustered", false);
boolean async = config.getBoolean("async", true);
if (clustered) {
gcb.transport().defaultTransport();
}
cacheManager = new DefaultCacheManager(gcb.build());
containerManaged = false;
logger.debug("Started embedded Infinispan cache container");
ConfigurationBuilder invalidationConfigBuilder = new ConfigurationBuilder();
if (clustered) {
invalidationConfigBuilder.clustering().cacheMode(async ? CacheMode.INVALIDATION_ASYNC : CacheMode.INVALIDATION_SYNC);
}
Configuration invalidationCacheConfiguration = invalidationConfigBuilder.build();
cacheManager.defineConfiguration(InfinispanConnectionProvider.REALM_CACHE_NAME, invalidationCacheConfiguration);
cacheManager.defineConfiguration(InfinispanConnectionProvider.USER_CACHE_NAME, invalidationCacheConfiguration);
ConfigurationBuilder sessionConfigBuilder = new ConfigurationBuilder();
if (clustered) {
String sessionsMode = config.get("sessionsMode", "distributed");
if (sessionsMode.equalsIgnoreCase("replicated")) {
sessionConfigBuilder.clustering().cacheMode(async ? CacheMode.REPL_ASYNC : CacheMode.REPL_SYNC);
} else if (sessionsMode.equalsIgnoreCase("distributed")) {
sessionConfigBuilder.clustering().cacheMode(async ? CacheMode.DIST_ASYNC : CacheMode.DIST_SYNC);
} else {
throw new RuntimeException("Invalid value for sessionsMode");
}
sessionConfigBuilder.clustering().hash()
.numOwners(config.getInt("sessionsOwners", 2))
.numSegments(config.getInt("sessionsSegments", 60)).build();
}
Configuration sessionCacheConfiguration = sessionConfigBuilder.build();
cacheManager.defineConfiguration(InfinispanConnectionProvider.SESSION_CACHE_NAME, sessionCacheConfiguration);
cacheManager.defineConfiguration(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME, sessionCacheConfiguration);
}
}
@@ -0,0 +1,18 @@
package org.keycloak.connections.infinispan;
import org.infinispan.Cache;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface InfinispanConnectionProvider extends Provider {
static final String REALM_CACHE_NAME = "realms";
static final String USER_CACHE_NAME = "users";
static final String SESSION_CACHE_NAME = "sessions";
static final String LOGIN_FAILURE_CACHE_NAME = "loginFailures";
<K, V> Cache<K, V> getCache(String name);
}
@@ -0,0 +1,9 @@
package org.keycloak.connections.infinispan;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface InfinispanConnectionProviderFactory extends ProviderFactory<InfinispanConnectionProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.connections.infinispan;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class InfinispanConnectionSpi implements Spi {
@Override
public String getName() {
return "connectionsInfinispan";
}
@Override
public Class<? extends Provider> getProviderClass() {
return InfinispanConnectionProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return InfinispanConnectionProviderFactory.class;
}
}
@@ -0,0 +1 @@
org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory
@@ -0,0 +1 @@
org.keycloak.connections.infinispan.InfinispanConnectionSpi
+72
View File
@@ -0,0 +1,72 @@
<?xml version="1.0"?>
<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>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-jpa-liquibase</artifactId>
<name>Keycloak Connections JPA Liquibase Updater</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-connections-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<configuration>
<changeLogFile>META-INF/jpa-changelog-master.xml</changeLogFile>
<url>${url}</url>
<driver>${driver}</driver>
<username>${username}</username>
<password>${password}</password>
<referenceUrl>${referenceUrl}</referenceUrl>
<referenceDriver>${driver}</referenceDriver>
<referenceUsername>${username}</referenceUsername>
<referencePassword>${password}</referencePassword>
</configuration>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<properties>
<username>sa</username>
<password></password>
<driver>org.h2.Driver</driver>
</properties>
</project>
@@ -0,0 +1,224 @@
package org.keycloak.connections.jpa.updater.liquibase;
import liquibase.Contexts;
import liquibase.Liquibase;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.changelog.RanChangeSet;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.core.DB2Database;
import liquibase.database.core.DerbyDatabase;
import liquibase.database.core.FirebirdDatabase;
import liquibase.database.core.H2Database;
import liquibase.database.core.HsqlDatabase;
import liquibase.database.core.InformixDatabase;
import liquibase.database.core.MSSQLDatabase;
import liquibase.database.core.MySQLDatabase;
import liquibase.database.core.OracleDatabase;
import liquibase.database.core.PostgresDatabase;
import liquibase.database.core.SQLiteDatabase;
import liquibase.database.core.SybaseASADatabase;
import liquibase.database.core.SybaseDatabase;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.logging.LogFactory;
import liquibase.logging.LogLevel;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.servicelocator.ServiceLocator;
import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
private static final Logger logger = Logger.getLogger(LiquibaseJpaUpdaterProvider.class);
private static final String CHANGELOG = "META-INF/jpa-changelog-master.xml";
@Override
public String getCurrentVersionSql() {
return "SELECT ID from DATABASECHANGELOG ORDER BY DATEEXECUTED DESC LIMIT 1";
}
@Override
public void update(Connection connection) {
logger.debug("Starting database update");
try {
Liquibase liquibase = getLiquibase(connection);
List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
if (!changeSets.isEmpty()) {
if (changeSets.get(0).getId().equals(FIRST_VERSION)) {
Statement statement = connection.createStatement();
try {
statement.executeQuery("SELECT id FROM REALM");
logger.infov("Updating database from {0} to {1}", FIRST_VERSION, changeSets.get(changeSets.size() - 1).getId());
liquibase.markNextChangeSetRan((Contexts) null);
} catch (SQLException e) {
logger.info("Initializing database schema");
}
} else {
if (logger.isDebugEnabled()) {
List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
logger.debugv("Updating database from {0} to {1}", ranChangeSets.get(ranChangeSets.size() - 1).getId(), changeSets.get(changeSets.size() - 1).getId());
} else {
logger.infov("Updating database");
}
}
liquibase.update((Contexts) null);
}
} catch (Exception e) {
throw new RuntimeException("Failed to update database", e);
}
logger.debug("Completed database update");
}
@Override
public void validate(Connection connection) {
try {
Liquibase liquibase = getLiquibase(connection);
liquibase.validate();
} catch (Exception e) {
throw new RuntimeException("Failed to validate database", e);
}
}
private Liquibase getLiquibase(Connection connection) throws Exception {
ServiceLocator sl = ServiceLocator.getInstance();
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
if (sl.getPackages().remove("liquibase.core")) {
sl.addPackageToScan("liquibase.core.xml");
}
if (sl.getPackages().remove("liquibase.parser")) {
sl.addPackageToScan("liquibase.parser.core.xml");
}
if (sl.getPackages().remove("liquibase.serializer")) {
sl.addPackageToScan("liquibase.serializer.core.xml");
}
sl.getPackages().remove("liquibase.ext");
sl.getPackages().remove("liquibase.sdk");
}
LogFactory.setInstance(new LogWrapper());
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
return new Liquibase(CHANGELOG, new ClassLoaderResourceAccessor(getClass().getClassLoader()), database);
}
@Override
public void close() {
}
private static class LogWrapper extends LogFactory {
private liquibase.logging.Logger logger = new liquibase.logging.Logger() {
@Override
public void setName(String name) {
}
@Override
public void setLogLevel(String level) {
}
@Override
public void setLogLevel(LogLevel level) {
}
@Override
public void setLogLevel(String logLevel, String logFile) {
}
@Override
public void severe(String message) {
LiquibaseJpaUpdaterProvider.logger.error(message);
}
@Override
public void severe(String message, Throwable e) {
LiquibaseJpaUpdaterProvider.logger.error(message, e);
}
@Override
public void warning(String message) {
LiquibaseJpaUpdaterProvider.logger.warn(message);
}
@Override
public void warning(String message, Throwable e) {
LiquibaseJpaUpdaterProvider.logger.warn(message, e);
}
@Override
public void info(String message) {
LiquibaseJpaUpdaterProvider.logger.debug(message);
}
@Override
public void info(String message, Throwable e) {
LiquibaseJpaUpdaterProvider.logger.debug(message, e);
}
@Override
public void debug(String message) {
LiquibaseJpaUpdaterProvider.logger.trace(message);
}
@Override
public LogLevel getLogLevel() {
if (LiquibaseJpaUpdaterProvider.logger.isTraceEnabled()) {
return LogLevel.DEBUG;
} else if (LiquibaseJpaUpdaterProvider.logger.isDebugEnabled()) {
return LogLevel.INFO;
} else {
return LogLevel.WARNING;
}
}
@Override
public void debug(String message, Throwable e) {
LiquibaseJpaUpdaterProvider.logger.trace(message, e);
}
@Override
public void setChangeLog(DatabaseChangeLog databaseChangeLog) {
}
@Override
public void setChangeSet(ChangeSet changeSet) {
}
@Override
public int getPriority() {
return 0;
}
};
@Override
public liquibase.logging.Logger getLog(String name) {
return logger;
}
@Override
public liquibase.logging.Logger getLog() {
return logger;
}
}
}
@@ -0,0 +1,31 @@
package org.keycloak.connections.jpa.updater.liquibase;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import org.keycloak.connections.jpa.updater.JpaUpdaterProviderFactory;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class LiquibaseJpaUpdaterProviderFactory implements JpaUpdaterProviderFactory {
@Override
public JpaUpdaterProvider create(KeycloakSession session) {
return new LiquibaseJpaUpdaterProvider();
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "liquibase";
}
}
@@ -0,0 +1,85 @@
package org.keycloak.connections.jpa.updater.liquibase.custom;
import liquibase.change.custom.CustomSqlChange;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.CustomChangeException;
import liquibase.exception.SetupException;
import liquibase.exception.ValidationErrors;
import liquibase.resource.ResourceAccessor;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.UpdateStatement;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.ArrayList;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class AddRealmCodeSecret implements CustomSqlChange {
private String confirmationMessage;
@Override
public SqlStatement[] generateStatements(Database database) throws CustomChangeException {
try {
StringBuilder sb = new StringBuilder();
sb.append("Generated codeSecret for realms: ");
Connection connection = ((JdbcConnection) (database.getConnection())).getWrappedConnection();
ArrayList<SqlStatement> statements = new ArrayList<SqlStatement>();
String correctedTableName = database.correctObjectName("REALM", Table.class);
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM REALM WHERE CODE_SECRET IS NULL");
while (resultSet.next()) {
String id = resultSet.getString(1);
UpdateStatement statement = new UpdateStatement(null, null, correctedTableName)
.addNewColumnValue("CODE_SECRET", KeycloakModelUtils.generateCodeSecret())
.setWhereClause("ID='" + id + "'");
statements.add(statement);
if (!resultSet.isFirst()) {
sb.append(", ");
}
sb.append(id);
}
if (!statements.isEmpty()) {
confirmationMessage = sb.toString();
}
}
return statements.toArray(new SqlStatement[statements.size()]);
} catch (Exception e) {
throw new CustomChangeException("Failed to add realm code secret", e);
}
}
@Override
public String getConfirmationMessage() {
return confirmationMessage;
}
@Override
public void setUp() throws SetupException {
}
@Override
public void setFileOpener(ResourceAccessor resourceAccessor) {
}
@Override
public ValidationErrors validate(Database database) {
return null;
}
}
@@ -0,0 +1,420 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.0.0.Final">
<createTable tableName="APPLICATION_DEFAULT_ROLES">
<column name="APPLICATION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="CLIENT">
<column name="DTYPE" type="VARCHAR(31)">
<constraints nullable="false"/>
</column>
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ALLOWED_CLAIMS_MASK" type="BIGINT"/>
<column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="FULL_SCOPE_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="NAME" type="VARCHAR(255)"/>
<column name="NOT_BEFORE" type="INT"/>
<column name="PUBLIC_CLIENT" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="SECRET" type="VARCHAR(255)"/>
<column name="BASE_URL" type="VARCHAR(255)"/>
<column name="BEARER_ONLY" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="MANAGEMENT_URL" type="VARCHAR(255)"/>
<column name="SURROGATE_AUTH_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="DIRECT_GRANTS_ONLY" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="CLIENT_SESSION">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ACTION" type="INT"/>
<column name="CLIENT_ID" type="VARCHAR(36)"/>
<column name="REDIRECT_URI" type="VARCHAR(255)"/>
<column name="STATE" type="VARCHAR(255)"/>
<column name="TIMESTAMP" type="INT"/>
<column name="SESSION_ID" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="CLIENT_SESSION_ROLE">
<column name="ROLE_ID" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="CLIENT_SESSION" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="COMPOSITE_ROLE">
<column name="COMPOSITE" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="CHILD_ROLE" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="CREDENTIAL">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="DEVICE" type="VARCHAR(255)"/>
<column name="HASH_ITERATIONS" type="INT"/>
<column name="SALT" type="BLOB(16)"/>
<column name="TYPE" type="VARCHAR(255)"/>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="USER_ID" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="EVENT_ENTITY">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="CLIENT_ID" type="VARCHAR(255)"/>
<column name="DETAILS_JSON" type="VARCHAR(2550)"/>
<column name="ERROR" type="VARCHAR(255)"/>
<column name="IP_ADDRESS" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="SESSION_ID" type="VARCHAR(255)"/>
<column name="TIME" type="BIGINT"/>
<column name="TYPE" type="VARCHAR(255)"/>
<column name="USER_ID" type="VARCHAR(255)"/>
</createTable>
<createTable tableName="FED_PROVIDERS">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="USERFEDERATIONPROVIDERS_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="KEYCLOAK_ROLE">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="APP_REALM_CONSTRAINT" type="VARCHAR(36)"/>
<column name="APPLICATION_ROLE" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="DESCRIPTION" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="APPLICATION" type="VARCHAR(36)"/>
<column name="REALM" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="REALM">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ACCESS_CODE_LIFESPAN" type="INT"/>
<column name="USER_ACTION_LIFESPAN" type="INT"/>
<column name="ACCESS_TOKEN_LIFESPAN" type="INT"/>
<column name="ACCOUNT_THEME" type="VARCHAR(255)"/>
<column name="ADMIN_THEME" type="VARCHAR(255)"/>
<column name="EMAIL_THEME" type="VARCHAR(255)"/>
<column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="EVENTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="EVENTS_EXPIRATION" type="BIGINT"/>
<column name="LOGIN_THEME" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)"/>
<column name="NOT_BEFORE" type="INT"/>
<column name="PASSWORD_CRED_GRANT_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="PASSWORD_POLICY" type="VARCHAR(255)"/>
<column name="PRIVATE_KEY" type="VARCHAR(2048)"/>
<column name="PUBLIC_KEY" type="VARCHAR(2048)"/>
<column name="REGISTRATION_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="REMEMBER_ME" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="RESET_PASSWORD_ALLOWED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="SOCIAL" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="SSL_REQUIRED" type="VARCHAR(255)"/>
<column name="SSO_IDLE_TIMEOUT" type="INT"/>
<column name="SSO_MAX_LIFESPAN" type="INT"/>
<column name="UPDATE_PROFILE_ON_SOC_LOGIN" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="VERIFY_EMAIL" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="MASTER_ADMIN_APP" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="REALM_APPLICATION">
<column name="APPLICATION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_ATTRIBUTE">
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_DEFAULT_ROLES">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_EVENTS_LISTENERS">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
</createTable>
<createTable tableName="REALM_REQUIRED_CREDENTIAL">
<column name="TYPE" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="FORM_LABEL" type="VARCHAR(255)"/>
<column name="INPUT" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="SECRET" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_SMTP_CONFIG">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_SOCIAL_CONFIG">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REDIRECT_URIS">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
</createTable>
<createTable tableName="SCOPE_MAPPING">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USERNAME_LOGIN_FAILURE">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="USERNAME" type="VARCHAR(200)">
<constraints nullable="false"/>
</column>
<column name="FAILED_LOGIN_NOT_BEFORE" type="INT"/>
<column name="LAST_FAILURE" type="BIGINT"/>
<column name="LAST_IP_FAILURE" type="VARCHAR(255)"/>
<column name="NUM_FAILURES" type="INT"/>
</createTable>
<createTable tableName="USER_ATTRIBUTE">
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USER_ENTITY">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="EMAIL" type="VARCHAR(255)"/>
<column name="EMAIL_CONSTRAINT" type="VARCHAR(255)"/>
<column name="EMAIL_VERIFIED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="FEDERATION_LINK" type="VARCHAR(255)"/>
<column name="FIRST_NAME" type="VARCHAR(255)"/>
<column name="LAST_NAME" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="TOTP" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="USERNAME" type="VARCHAR(255)"/>
</createTable>
<createTable tableName="USER_FEDERATION_CONFIG">
<column name="USER_FEDERATION_PROVIDER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USER_FEDERATION_PROVIDER">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="CHANGED_SYNC_PERIOD" type="INT"/>
<column name="DISPLAY_NAME" type="VARCHAR(255)"/>
<column name="FULL_SYNC_PERIOD" type="INT"/>
<column name="LAST_SYNC" type="INT"/>
<column name="PRIORITY" type="INT"/>
<column name="PROVIDER_NAME" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="USER_REQUIRED_ACTION">
<column name="ACTION" type="INT">
<constraints nullable="false"/>
</column>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USER_ROLE_MAPPING">
<column name="ROLE_ID" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USER_SESSION">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="AUTH_METHOD" type="VARCHAR(255)"/>
<column name="IP_ADDRESS" type="VARCHAR(255)"/>
<column name="LAST_SESSION_REFRESH" type="INT"/>
<column name="LOGIN_USERNAME" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="REMEMBER_ME" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="STARTED" type="INT"/>
<column name="USER_ID" type="VARCHAR(255)"/>
</createTable>
<createTable tableName="USER_SOCIAL_LINK">
<column name="SOCIAL_PROVIDER" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="SOCIAL_USER_ID" type="VARCHAR(255)"/>
<column name="SOCIAL_USERNAME" type="VARCHAR(255)"/>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="WEB_ORIGINS">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
</createTable>
<addPrimaryKey columnNames="REALM_ID, NAME" constraintName="CONSTRAINT_1" tableName="REALM_SOCIAL_CONFIG"/>
<addPrimaryKey columnNames="REALM_ID, USERNAME" constraintName="CONSTRAINT_17" tableName="USERNAME_LOGIN_FAILURE"/>
<addPrimaryKey columnNames="ACTION, USER_ID" constraintName="CONSTRAINT_2" tableName="USER_REQUIRED_ACTION"/>
<addPrimaryKey columnNames="SOCIAL_PROVIDER, USER_ID" constraintName="CONSTRAINT_3" tableName="USER_SOCIAL_LINK"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_4" tableName="EVENT_ENTITY"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_4A" tableName="REALM"/>
<addPrimaryKey columnNames="CLIENT_SESSION, ROLE_ID" constraintName="CONSTRAINT_5" tableName="CLIENT_SESSION_ROLE"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_57" tableName="USER_SESSION"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_5C" tableName="USER_FEDERATION_PROVIDER"/>
<addPrimaryKey columnNames="NAME, USER_ID" constraintName="CONSTRAINT_6" tableName="USER_ATTRIBUTE"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_7" tableName="CLIENT"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_8" tableName="CLIENT_SESSION"/>
<addPrimaryKey columnNames="CLIENT_ID, ROLE_ID" constraintName="CONSTRAINT_81" tableName="SCOPE_MAPPING"/>
<addPrimaryKey columnNames="NAME, REALM_ID" constraintName="CONSTRAINT_9" tableName="REALM_ATTRIBUTE"/>
<addPrimaryKey columnNames="REALM_ID, TYPE" constraintName="CONSTRAINT_92" tableName="REALM_REQUIRED_CREDENTIAL"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_A" tableName="KEYCLOAK_ROLE"/>
<addPrimaryKey columnNames="ROLE_ID, USER_ID" constraintName="CONSTRAINT_C" tableName="USER_ROLE_MAPPING"/>
<addPrimaryKey columnNames="REALM_ID, NAME" constraintName="CONSTRAINT_E" tableName="REALM_SMTP_CONFIG"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_F" tableName="CREDENTIAL"/>
<addPrimaryKey columnNames="USER_FEDERATION_PROVIDER_ID, NAME" constraintName="CONSTRAINT_F9" tableName="USER_FEDERATION_CONFIG"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_FB" tableName="USER_ENTITY"/>
<addUniqueConstraint columnNames="ROLE_ID" constraintName="UK_8AELWNIBJI49AVXSRTUF6XJOW" tableName="APPLICATION_DEFAULT_ROLES"/>
<addUniqueConstraint columnNames="REALM_ID,NAME" constraintName="UK_B71CJLBENV945RB6GCON438AT" tableName="CLIENT"/>
<addUniqueConstraint columnNames="USERFEDERATIONPROVIDERS_ID" constraintName="UK_DCCIRJLIPU1478VQC89DID88C" tableName="FED_PROVIDERS"/>
<addUniqueConstraint columnNames="REALM_ID,EMAIL_CONSTRAINT" constraintName="UK_DYKN684SL8UP1CRFEI6ECKHD7" tableName="USER_ENTITY"/>
<addUniqueConstraint columnNames="ROLE_ID" constraintName="UK_H4WPD7W4HSOOLNI3H0SW7BTJE" tableName="REALM_DEFAULT_ROLES"/>
<addUniqueConstraint columnNames="NAME,APP_REALM_CONSTRAINT" constraintName="UK_J3RWUVD56ONTGSUHOGM184WW2" tableName="KEYCLOAK_ROLE"/>
<addUniqueConstraint columnNames="REALM_ID" constraintName="UK_L5QGA3RFME47335JY8JXYXH3I" tableName="REALM_APPLICATION"/>
<addUniqueConstraint columnNames="NAME" constraintName="UK_ORVSDMLA56612EAEFIQ6WL5OI" tableName="REALM"/>
<addUniqueConstraint columnNames="REALM_ID,USERNAME" constraintName="UK_RU8TT6T700S9V50BU18WS5HA6" tableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_SESSION_ROLE" constraintName="FK_11B7SGQW18I532811V7O2DV76" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="REDIRECT_URIS" constraintName="FK_1BURS8PB4OUJ97H5WUPPAHV9F" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="USER_FEDERATION_PROVIDER" constraintName="FK_1FJ32F6PTOLW2QY60CD8N01E8" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="FED_PROVIDERS" constraintName="FK_213LYQ09FKXQ8K8NY8DY3737T" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_REQUIRED_CREDENTIAL" constraintName="FK_5HG65LYBEVAVKQFKI3KPONH9V" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_ATTRIBUTE" constraintName="FK_5HRM2VLF9QL5FU043KQEPOVBR" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_SOCIAL_LINK" constraintName="FK_68CJYS5UWM55UY823Y75XG4OM" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_REQUIRED_ACTION" constraintName="FK_6QJ3W1JW9CVAFHE19BWSIUVMD" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="REALM" baseTableName="KEYCLOAK_ROLE" constraintName="FK_6VYQFE4CN4WLQ8R6KT5VDSJ5C" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_SMTP_CONFIG" constraintName="FK_70EJ8XDXGXD0B9HH6180IRR0O" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="APPLICATION_ID" baseTableName="REALM_APPLICATION" constraintName="FK_71S3P0DIUXAWWQQSA528UBY2Q" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="APPLICATION_DEFAULT_ROLES" constraintName="FK_8AELWNIBJI49AVXSRTUF6XJOW" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_ATTRIBUTE" constraintName="FK_8SHXD6L3E9ATQUKACXGPFFPTW" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="COMPOSITE" baseTableName="COMPOSITE_ROLE" constraintName="FK_A63WVEKFTU8JO1PNJ81E7MCE2" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseColumnNames="SESSION_ID" baseTableName="CLIENT_SESSION" constraintName="FK_B4AO2VCVAT6UKAU74WBWTFQO1" referencedColumnNames="ID" referencedTableName="USER_SESSION"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_ROLE_MAPPING" constraintName="FK_C4FQV34P1MBYLLOXANG7B1Q3L" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="USERFEDERATIONPROVIDERS_ID" baseTableName="FED_PROVIDERS" constraintName="FK_DCCIRJLIPU1478VQC89DID88C" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_PROVIDER"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_DEFAULT_ROLES" constraintName="FK_EVUDB1PPW84OXFAX2DRS03ICC" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="CHILD_ROLE" baseTableName="COMPOSITE_ROLE" constraintName="FK_GR7THLLB9LU8Q4VQA4524JJY8" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="REALM_DEFAULT_ROLES" constraintName="FK_H4WPD7W4HSOOLNI3H0SW7BTJE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_EVENTS_LISTENERS" constraintName="FK_H846O4H0W8EPX5NXEV9F5Y69J" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_APPLICATION" constraintName="FK_L5QGA3RFME47335JY8JXYXH3I" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="WEB_ORIGINS" constraintName="FK_LOJPHO213XCX4WNKOG82SSRFY" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="APPLICATION_ID" baseTableName="APPLICATION_DEFAULT_ROLES" constraintName="FK_MAYLTS7KLWQW2H8M2B5JOYTKY" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="SCOPE_MAPPING" constraintName="FK_OUSE064PLMLR732LXJCN1Q5F1" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="SCOPE_MAPPING" constraintName="FK_P3RH9GRKU11KQFRS4FLTT7RNQ" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLIENT" constraintName="FK_P56CTINXXB9GSK57FO49F9TAC" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="CREDENTIAL" constraintName="FK_PFYR0GLASQYL0DEI3KL69R6V0" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addForeignKeyConstraint baseColumnNames="APPLICATION" baseTableName="KEYCLOAK_ROLE" constraintName="FK_PIMO5LE2C0RAL09FL8CM9WFW9" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="MASTER_ADMIN_APP" baseTableName="REALM" constraintName="FK_RSAF444KK6QRKMS7N56AIWQ5Y" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_SOCIAL_CONFIG" constraintName="FK_SV5I3C2TI7G0G922FGE683SOV" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="USER_FEDERATION_PROVIDER_ID" baseTableName="USER_FEDERATION_CONFIG" constraintName="FK_T13HPU1J94R2EBPEKR39X5EU5" referencedColumnNames="ID" referencedTableName="USER_FEDERATION_PROVIDER"/>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.1.0.Beta1">
<delete tableName="CLIENT_SESSION_ROLE"/>
<delete tableName="CLIENT_SESSION"/>
<delete tableName="USER_SESSION"/>
<createTable tableName="CLIENT_ATTRIBUTES">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(2048)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="CLIENT_SESSION_NOTE">
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="CLIENT_SESSION" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="APP_NODE_REGISTRATIONS">
<column name="APPLICATION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="INT"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
</createTable>
<addColumn tableName="CLIENT_SESSION">
<column name="AUTH_METHOD" type="VARCHAR(255)"/>
</addColumn>
<addColumn tableName="CLIENT">
<column name="PROTOCOL" type="VARCHAR(255)"/>
</addColumn>
<addColumn tableName="CLIENT_SESSION">
<column name="REALM_ID" type="VARCHAR(255)"/>
</addColumn>
<addColumn tableName="REALM">
<column name="CERTIFICATE" type="VARCHAR(2048)"/>
<column name="CODE_SECRET" type="VARCHAR(255)"/>
</addColumn>
<addColumn tableName="CLIENT">
<column name="NODE_REREG_TIMEOUT" type="INT" defaultValueNumeric="0"/>
</addColumn>
<addPrimaryKey columnNames="CLIENT_ID, NAME" constraintName="CONSTRAINT_3C" tableName="CLIENT_ATTRIBUTES"/>
<addPrimaryKey columnNames="CLIENT_SESSION, NAME" constraintName="CONSTRAINT_5E" tableName="CLIENT_SESSION_NOTE"/>
<addPrimaryKey columnNames="APPLICATION_ID, NAME" constraintName="CONSTRAINT_84" tableName="APP_NODE_REGISTRATIONS"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_ID" baseTableName="CLIENT_ATTRIBUTES" constraintName="FK3C47C64BEACCA966" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_SESSION" baseTableName="CLIENT_SESSION_NOTE" constraintName="FK5EDFB00FF51C2736" referencedColumnNames="ID" referencedTableName="CLIENT_SESSION"/>
<addForeignKeyConstraint baseColumnNames="APPLICATION_ID" baseTableName="APP_NODE_REGISTRATIONS" constraintName="FK8454723BA992F594" referencedColumnNames="ID" referencedTableName="CLIENT"/>
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.AddRealmCodeSecret"/>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.1.0.Final">
<renameColumn tableName="EVENT_ENTITY" oldColumnName="TIME" newColumnName="EVENT_TIME" columnDataType="BIGINT"/>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<include file="META-INF/jpa-changelog-1.0.0.Final.xml"/>
<include file="META-INF/jpa-changelog-1.1.0.Beta1.xml"/>
<include file="META-INF/jpa-changelog-1.1.0.Final.xml"/>
</databaseChangeLog>
@@ -0,0 +1 @@
org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProviderFactory
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,12 +1,20 @@
package org.keycloak.connections.jpa;
import org.hibernate.ejb.AvailableSettings;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import org.keycloak.models.KeycloakSession;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
@@ -15,13 +23,15 @@ import java.util.Map;
*/
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
private volatile EntityManagerFactory emf;
private Config.Scope config;
@Override
public JpaConnectionProvider create(KeycloakSession session) {
lazyInit();
lazyInit(session);
EntityManager em = emf.createEntityManager();
em = PersistenceExceptionConverter.create(em);
@@ -46,11 +56,17 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
this.config = config;
}
private void lazyInit() {
private void lazyInit(KeycloakSession session) {
if (emf == null) {
synchronized (this) {
if (emf == null) {
logger.debug("Initializing JPA connections");
Connection connection = null;
String unitName = config.get("unitName");
String databaseSchema = config.get("databaseSchema");
Map<String, Object> properties = new HashMap<String, Object>();
// Only load config from keycloak-server.json if unitName is not specified
@@ -83,19 +99,84 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
properties.put("hibernate.dialect", driverDialect);
}
String databaseSchema = config.get("databaseSchema", "validate");
if (databaseSchema != null) {
properties.put("hibernate.hbm2ddl.auto", databaseSchema);
if (databaseSchema.equals("development-update")) {
properties.put("hibernate.hbm2ddl.auto", "update");
databaseSchema = null;
} else if (databaseSchema.equals("development-validate")) {
properties.put("hibernate.hbm2ddl.auto", "validate");
databaseSchema = null;
}
}
properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
properties.put("hibernate.format_sql", config.getBoolean("formatSql", true));
}
if (databaseSchema != null) {
logger.trace("Updating database");
JpaUpdaterProvider updater = session.getProvider(JpaUpdaterProvider.class);
if (updater == null) {
throw new RuntimeException("Can't update database: JPA updater provider not found");
}
connection = getConnection();
if (databaseSchema.equals("update")) {
String currentVersion = null;
try {
ResultSet resultSet = connection.createStatement().executeQuery(updater.getCurrentVersionSql());
if (resultSet.next()) {
currentVersion = resultSet.getString(1);
}
} catch (SQLException e) {
}
if (currentVersion == null || !JpaUpdaterProvider.LAST_VERSION.equals(currentVersion)) {
updater.update(connection);
} else {
logger.debug("Database is up to date");
}
} else if (databaseSchema.equals("validate")) {
updater.validate(connection);
} else {
throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
}
logger.trace("Database update completed");
}
logger.trace("Creating EntityManagerFactory");
emf = Persistence.createEntityManagerFactory(unitName, properties);
logger.trace("EntityManagerFactory created");
// Close after creating EntityManagerFactory to prevent in-mem databases from closing
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.warn(e);
}
}
}
}
}
}
private Connection getConnection() {
try {
String dataSourceLookup = config.get("dataSource");
if (dataSourceLookup != null) {
DataSource dataSource = (DataSource) new InitialContext().lookup(dataSourceLookup);
return dataSource.getConnection();
} else {
Class.forName(config.get("driver"));
return DriverManager.getConnection(config.get("url"), config.get("user"), config.get("password"));
}
} catch (Exception e) {
throw new RuntimeException("Failed to connect to database", e);
}
}
}
@@ -0,0 +1,22 @@
package org.keycloak.connections.jpa.updater;
import org.keycloak.provider.Provider;
import java.sql.Connection;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface JpaUpdaterProvider extends Provider {
public String FIRST_VERSION = "1.0.0.Final";
public String LAST_VERSION = "1.1.0.Beta1";
public String getCurrentVersionSql();
public void update(Connection connection);
public void validate(Connection connection);
}
@@ -0,0 +1,9 @@
package org.keycloak.connections.jpa.updater;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface JpaUpdaterProviderFactory extends ProviderFactory<JpaUpdaterProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.connections.jpa.updater;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaUpdaterSpi implements Spi {
@Override
public String getName() {
return "connectionsJpaUpdater";
}
@Override
public Class<? extends Provider> getProviderClass() {
return JpaUpdaterProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return JpaUpdaterProviderFactory.class;
}
}
@@ -21,6 +21,7 @@
<!-- JpaUserSessionProvider -->
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionRoleEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.ClientSessionNoteEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UserSessionEntity</class>
<class>org.keycloak.models.sessions.jpa.entities.UsernameLoginFailureEntity</class>
@@ -1 +1,2 @@
org.keycloak.connections.jpa.JpaConnectionSpi
org.keycloak.connections.jpa.JpaConnectionSpi
org.keycloak.connections.jpa.updater.JpaUpdaterSpi
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -2,6 +2,7 @@ package org.keycloak.connections.mongo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.jboss.logging.Logger;
@@ -9,8 +10,10 @@ import org.keycloak.Config;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocationContext;
import org.keycloak.connections.mongo.updater.DefaultMongoUpdaterProvider;
import org.keycloak.models.KeycloakSession;
import java.lang.reflect.Method;
import java.util.Collections;
/**
@@ -64,22 +67,32 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
String host = config.get("host", ServerAddress.defaultHost());
int port = config.getInt("port", ServerAddress.defaultPort());
String dbName = config.get("db", "keycloak");
boolean clearOnStartup = config.getBoolean("clearOnStartup", false);
String user = config.get("user");
String password = config.get("password");
MongoClientOptions clientOptions = getClientOptions();
if (user != null && password != null) {
MongoCredential credential = MongoCredential.createMongoCRCredential(user, dbName, password.toCharArray());
client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential));
client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential), clientOptions);
} else {
client = new MongoClient(host, port);
client = new MongoClient(new ServerAddress(host, port), clientOptions);
}
this.db = client.getDB(dbName);
this.mongoStore = new MongoStoreImpl(db, clearOnStartup, getManagedEntities());
String databaseSchema = config.get("databaseSchema");
if (databaseSchema != null) {
if (databaseSchema.equals("update")) {
new DefaultMongoUpdaterProvider().update(db);
} else {
throw new RuntimeException("Invalid value for databaseSchema: " + databaseSchema);
}
}
logger.infof("Initialized mongo model. host: %s, port: %d, db: %s, clearOnStartup: %b", host, port, dbName, clearOnStartup);
this.mongoStore = new MongoStoreImpl(db, getManagedEntities());
logger.debugv("Initialized mongo model. host: %s, port: %d, db: %s", host, port, dbName);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -108,4 +121,43 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
return "default";
}
protected MongoClientOptions getClientOptions() {
MongoClientOptions.Builder builder = MongoClientOptions.builder();
checkIntOption("connectionsPerHost", builder);
checkIntOption("threadsAllowedToBlockForConnectionMultiplier", builder);
checkIntOption("maxWaitTime", builder);
checkIntOption("connectTimeout", builder);
checkIntOption("socketTimeout", builder);
checkBooleanOption("socketKeepAlive", builder);
checkBooleanOption("autoConnectRetry", builder);
if (config.getLong("maxAutoConnectRetryTime") != null) {
builder.maxAutoConnectRetryTime(config.getLong("maxAutoConnectRetryTime"));
}
return builder.build();
}
protected void checkBooleanOption(String optionName, MongoClientOptions.Builder builder) {
Boolean val = config.getBoolean(optionName);
if (val != null) {
try {
Method m = MongoClientOptions.Builder.class.getMethod(optionName, boolean.class);
m.invoke(builder, val);
} catch (Exception e) {
throw new IllegalStateException("Problem configuring boolean option " + optionName + " for mongo client. Ensure you used correct value true or false and if this option is supported by mongo driver", e);
}
}
}
protected void checkIntOption(String optionName, MongoClientOptions.Builder builder) {
Integer val = config.getInt(optionName);
if (val != null) {
try {
Method m = MongoClientOptions.Builder.class.getMethod(optionName, int.class);
m.invoke(builder, val);
} catch (Exception e) {
throw new IllegalStateException("Problem configuring int option " + optionName + " for mongo client. Ensure you used correct value (number) and if this option is supported by mongo driver", e);
}
}
}
}
@@ -1,26 +0,0 @@
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Target({TYPE})
@Documented
@Retention(RUNTIME)
@Inherited
public @interface MongoIndex {
String[] fields();
boolean unique() default false;
boolean sparse() default false;
}
@@ -1,22 +0,0 @@
package org.keycloak.connections.mongo.api;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Target({TYPE})
@Documented
@Retention(RUNTIME)
@Inherited
public @interface MongoIndexes {
MongoIndex[] value();
}
@@ -11,8 +11,6 @@ import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.api.MongoCollection;
import org.keycloak.connections.mongo.api.MongoEntity;
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
import org.keycloak.connections.mongo.api.MongoIndex;
import org.keycloak.connections.mongo.api.MongoIndexes;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.connections.mongo.api.context.MongoTask;
@@ -57,7 +55,7 @@ public class MongoStoreImpl implements MongoStore {
new ConcurrentHashMap<Class<?>, EntityInfo>();
public MongoStoreImpl(DB database, boolean clearCollectionsOnStartup, Class<?>[] managedEntityTypes) {
public MongoStoreImpl(DB database, Class<?>[] managedEntityTypes) {
this.database = database;
mapperRegistry = new MapperRegistry();
@@ -86,13 +84,6 @@ public class MongoStoreImpl implements MongoStore {
mapperRegistry.addAppObjectMapper(new MongoEntityMapper(this, mapperRegistry, type));
mapperRegistry.addDBObjectMapper(new BasicDBObjectMapper(this, mapperRegistry, type));
}
if (clearCollectionsOnStartup) {
// dropDatabase();
clearManagedCollections(managedEntityTypes);
}
initManagedCollections(managedEntityTypes);
}
protected void dropDatabase() {
@@ -100,63 +91,6 @@ public class MongoStoreImpl implements MongoStore {
logger.info("Database " + this.database.getName() + " dropped in MongoDB");
}
// Don't drop database, but just clear all data in managed collections (useful for export/import or during development)
protected void clearManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
DBCollection dbCollection = getDBCollectionForType(clazz);
if (dbCollection != null) {
dbCollection.remove(new BasicDBObject());
logger.debug("Collection " + dbCollection.getName() + " cleared from " + this.database.getName());
}
}
}
protected void initManagedCollections(Class<?>[] managedEntityTypes) {
for (Class<?> clazz : managedEntityTypes) {
EntityInfo entityInfo = getEntityInfo(clazz);
String dbCollectionName = entityInfo.getDbCollectionName();
if (dbCollectionName != null && !database.collectionExists(dbCollectionName)) {
DBCollection dbCollection = database.getCollection(dbCollectionName);
logger.debug("Created collection " + dbCollection.getName() + " in " + this.database.getName());
MongoIndex index = clazz.getAnnotation(MongoIndex.class);
if (index != null) {
createIndex(dbCollection, index);
}
MongoIndexes indexes = clazz.getAnnotation(MongoIndexes.class);
if (indexes != null) {
for (MongoIndex i : indexes.value()) {
createIndex(dbCollection, i);
}
}
}
}
}
protected void createIndex(DBCollection dbCollection, MongoIndex index) {
BasicDBObject fields = new BasicDBObject();
for (String f : index.fields()) {
fields.put(f, 1);
}
boolean unique = index.unique();
boolean sparse = index.sparse();
BasicDBObject options = new BasicDBObject();
if (unique) {
options.put("unique", unique);
}
if (sparse) {
options.put("sparse", sparse);
}
dbCollection.ensureIndex(fields, options);
logger.debug("Created index " + fields + "(options: " + options + ") on " + dbCollection.getName() + " in " + this.database.getName());
}
@Override
public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
Class<? extends MongoEntity> clazz = entity.getClass();
@@ -325,7 +259,7 @@ public class MongoStoreImpl implements MongoStore {
DBCollection dbCollection = getDBCollectionForType(type);
BasicDBObject dbQuery = new BasicDBObject("_id", id);
dbCollection.remove(dbQuery);
logger.info("Entity of type: " + type + ", id: " + id + " removed from MongoDB.");
//logger.debugf("Entity of type: %s , id: %s removed from MongoDB.", type, id);
context.addRemovedEntity(found);
return true;
@@ -341,7 +275,7 @@ public class MongoStoreImpl implements MongoStore {
} else {
DBCollection dbCollection = getDBCollectionForType(type);
dbCollection.remove(query);
logger.info("Removed " + foundObjects.size() + " entities of type: " + type + ", query: " + query);
//logger.debug("Removed %d" + foundObjects.size() + " entities of type: " + type + ", query: " + query);
for (MongoIdentifiableEntity found : foundObjects) {
context.addRemovedEntity(found);;
@@ -9,7 +9,7 @@ import org.keycloak.connections.mongo.api.types.MapperRegistry;
import org.keycloak.connections.mongo.impl.EntityInfo;
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
import org.keycloak.models.utils.reflection.Property;
import org.keycloak.models.utils.reflection.Types;
import org.keycloak.util.reflections.Types;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -8,7 +8,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* For now, there is support just for convert to Map<String, String>
* For now, there is support just for convert to Map<String, simpleType>
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@@ -18,10 +18,15 @@ public class BasicDBObjectToMapMapper implements Mapper<BasicDBObject, Map> {
public Map convertObject(MapperContext<BasicDBObject, Map> context) {
BasicDBObject dbObjectToConvert = context.getObjectToConvert();
HashMap<String, String> result = new HashMap<String, String>();
HashMap<String, Object> result = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : dbObjectToConvert.entrySet()) {
String key = entry.getKey();
String value = (String)entry.getValue();
Object value = entry.getValue();
// Workaround as manually inserted numbers into mongo may be treated as "Double"
if (value instanceof Double && context.getGenericTypes().get(1) == Integer.class) {
value = ((Double)value).intValue();
}
if (key.contains(MapMapper.DOT_PLACEHOLDER)) {
key = key.replaceAll(MapMapper.DOT_PLACEHOLDER, ".");
@@ -8,7 +8,7 @@ import java.util.Map;
import java.util.Set;
/**
* For now, we support just convert from Map<String, String>
* For now, we support just convert from Map<String, simpleType>
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
@@ -31,7 +31,7 @@ public class MapMapper<T extends Map> implements Mapper<T, BasicDBObject> {
Set<Map.Entry> entries = objectToConvert.entrySet();
for (Map.Entry entry : entries) {
String key = (String)entry.getKey();
String value = (String)entry.getValue();
Object value = entry.getValue();
if (key.contains(".")) {
key = key.replaceAll("\\.", DOT_PLACEHOLDER);
@@ -0,0 +1,103 @@
package org.keycloak.connections.mongo.updater;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import org.jboss.logging.Logger;
import org.keycloak.connections.mongo.updater.updates.Update;
import org.keycloak.connections.mongo.updater.updates.Update1_0_0_Final;
import org.keycloak.connections.mongo.updater.updates.Update1_1_0_Beta1;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
public static final Logger log = Logger.getLogger(DefaultMongoUpdaterProvider.class);
public static final String CHANGE_LOG_COLLECTION = "databaseChangeLog";
private Class<? extends Update>[] updates = new Class[]{
Update1_0_0_Final.class,
Update1_1_0_Beta1.class
};
@Override
public void update(DB db) {
log.debug("Starting database update");
try {
boolean changeLogExists = db.collectionExists(CHANGE_LOG_COLLECTION);
boolean realmExists = db.collectionExists("realms");
DBCollection changeLog = db.getCollection(CHANGE_LOG_COLLECTION);
List<String> executed = new LinkedList<String>();
if (!changeLogExists && realmExists) {
Update1_0_0_Final u = new Update1_0_0_Final();
executed.add(u.getId());
createLog(changeLog, u, 1);
} else if (changeLogExists) {
DBCursor cursor = changeLog.find().sort(new BasicDBObject("orderExecuted", 1));
while (cursor.hasNext()) {
executed.add((String) cursor.next().get("_id"));
}
}
List<Update> updatesToRun = new LinkedList<Update>();
for (Class<? extends Update> updateClass : updates) {
Update u = updateClass.newInstance();
if (!executed.contains(u.getId())) {
updatesToRun.add(u);
}
}
if (!updatesToRun.isEmpty()) {
if (executed.isEmpty()) {
log.info("Initializing database schema");
} else {
if (log.isDebugEnabled()) {
log.infov("Updating database from {0} to {1}", executed.get(executed.size() - 1), updatesToRun.get(updatesToRun.size() - 1).getId());
} else {
log.debugv("Updating database");
}
}
int order = executed.size();
for (Update u : updatesToRun) {
log.debugv("Executing updates for {0}", u.getId());
u.setLog(log);
u.setDb(db);
u.update();
createLog(changeLog, u, ++order);
log.debugv("Completed updates for {0}", u.getId());
}
}
} catch (Exception e) {
throw new RuntimeException("Failed to update database", e);
}
log.debug("Completed database update");
}
private void createLog(DBCollection changeLog, Update update, int orderExecuted) {
changeLog.insert(new BasicDBObject("_id", update.getId()).append("dateExecuted", new Date()).append("orderExecuted", orderExecuted));
}
@Override
public void close() {
}
}
@@ -0,0 +1,29 @@
package org.keycloak.connections.mongo.updater;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultMongoUpdaterProviderFactory implements MongoUpdaterProviderFactory {
@Override
public MongoUpdaterProvider create(KeycloakSession session) {
return new DefaultMongoUpdaterProvider();
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return "default";
}
}
@@ -0,0 +1,13 @@
package org.keycloak.connections.mongo.updater;
import com.mongodb.DB;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface MongoUpdaterProvider extends Provider {
public void update(DB db);
}
@@ -0,0 +1,9 @@
package org.keycloak.connections.mongo.updater;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface MongoUpdaterProviderFactory extends ProviderFactory<MongoUpdaterProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.connections.mongo.updater;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoUpdaterSpi implements Spi {
@Override
public String getName() {
return "connectionsMongoUpdater";
}
@Override
public Class<? extends Provider> getProviderClass() {
return MongoUpdaterProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return MongoUpdaterProviderFactory.class;
}
}
@@ -0,0 +1,62 @@
package org.keycloak.connections.mongo.updater.updates;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import org.jboss.logging.Logger;
import java.util.Arrays;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public abstract class Update {
protected DB db;
protected Logger log;
public abstract String getId();
public abstract void update() throws ClassNotFoundException;
protected DBCollection createCollection(String name) {
if (db.collectionExists(name)) {
throw new RuntimeException("Failed to create collection {0}: collection already exists");
}
DBCollection col = db.getCollection(name);
log.debugv("Created collection {0}", name);
return col;
}
protected void ensureIndex(String name, String field, boolean unique, boolean sparse) {
ensureIndex(name, new String[]{field}, unique, sparse);
}
protected void ensureIndex(String name, String[] fields, boolean unique, boolean sparse) {
DBCollection col = db.getCollection(name);
BasicDBObject o = new BasicDBObject();
for (String f : fields) {
o.append(f, 1);
}
col.ensureIndex(o, new BasicDBObject("unique", unique).append("sparse", sparse));
log.debugv("Created index {0}, fields={1}, unique={2}, sparse={3}", name, Arrays.toString(fields), unique, sparse);
}
protected void deleteEntries(String collection) {
db.getCollection(collection).remove(new BasicDBObject());
log.debugv("Deleted entries from {0}", collection);
}
public void setLog(Logger log) {
this.log = log;
}
public void setDb(DB db) {
this.db = db;
}
}
@@ -0,0 +1,44 @@
package org.keycloak.connections.mongo.updater.updates;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import org.keycloak.connections.mongo.updater.DefaultMongoUpdaterProvider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Update1_0_0_Final extends Update {
@Override
public String getId() {
return "1.0.0.Final";
}
@Override
public void update() throws ClassNotFoundException {
DBCollection realmsCollection = db.getCollection("realms");
realmsCollection.ensureIndex(new BasicDBObject("name", 1), new BasicDBObject("unique", true));
DefaultMongoUpdaterProvider.log.debugv("Created collection {0}", "realms");
createCollection("users");
ensureIndex("users", new String[] { "realmId", "username"}, true, false);
ensureIndex("users", "emailIndex", true, true);
createCollection("roles");
ensureIndex("roles", "nameIndex", true, false);
createCollection("applications");
ensureIndex("applications", new String[]{"realmId", "name"}, true, false);
createCollection("oauthClients");
ensureIndex("oauthClients", new String[] { "realmId", "name"}, true, false);
createCollection("userFailures");
createCollection("sessions");
createCollection("clientSessions");
}
}
@@ -0,0 +1,45 @@
package org.keycloak.connections.mongo.updater.updates;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
import org.keycloak.models.utils.KeycloakModelUtils;
import java.util.Arrays;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Update1_1_0_Beta1 extends Update {
@Override
public String getId() {
return "1.1.0.Beta1";
}
@Override
public void update() {
deleteEntries("clientSessions");
deleteEntries("sessions");
addRealmCodeSecret();
}
private void addRealmCodeSecret() {
DBCollection realms = db.getCollection("realms");
DBObject query = new QueryBuilder()
.and("codeSecret").is(null).get();
DBCursor objects = realms.find(query);
while (objects.hasNext()) {
DBObject object = objects.next();
object.put("codeSecret", KeycloakModelUtils.generateCodeSecret());
realms.save(object);
log.debugv("Added realm.codeSecret, id={0}", object.get("id"));
}
}
}
+3 -1
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
</parent>
<name>Connections Parent</name>
<description/>
@@ -14,6 +14,8 @@
<modules>
<module>jpa</module>
<module>jpa-liquibase</module>
<module>infinispan</module>
<module>mongo</module>
</modules>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -31,7 +31,7 @@ public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper>
@Override
public ObjectMapper getContext(Class<?> type) {
if (type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
if (type.getPackage() != null && type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
return null;
}
}
+42 -1
View File
@@ -4,18 +4,26 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-core</artifactId>
<name>Keycloak Core</name>
<packaging>jar</packaging>
<description/>
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
<keycloak.osgi.export>
org.keycloak.*
</keycloak.osgi.export>
<keycloak.osgi.import>
net.iharder;version=${base64.version},
*;resolution:=optional
</keycloak.osgi.import>
</properties>
<dependencies>
<dependency>
@@ -60,6 +68,39 @@
<target>${maven.compiler.target}</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>
@@ -1,5 +1,6 @@
package org.keycloak;
import org.keycloak.enums.RelativeUrlsUsed;
import org.keycloak.util.KeycloakUriBuilder;
import java.util.Map;
@@ -19,7 +20,7 @@ public class AbstractOAuthClient {
protected String authUrl;
protected String codeUrl;
protected String refreshUrl;
protected boolean relativeUrls;
protected RelativeUrlsUsed relativeUrlsUsed;
protected String scope;
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
protected String stateCookiePath;
@@ -101,12 +102,12 @@ public class AbstractOAuthClient {
this.publicClient = publicClient;
}
public boolean isRelativeUrls() {
return relativeUrls;
public RelativeUrlsUsed getRelativeUrlsUsed() {
return relativeUrlsUsed;
}
public void setRelativeUrls(boolean relativeUrls) {
this.relativeUrls = relativeUrls;
public void setRelativeUrlsUsed(RelativeUrlsUsed relativeUrlsUsed) {
this.relativeUrlsUsed = relativeUrlsUsed;
}
protected String stripOauthParametersFromRedirect(String uri) {
@@ -121,6 +121,17 @@ public class Config {
return v != null ? Boolean.parseBoolean(v) : defaultValue;
}
@Override
public Scope scope(String... scope) {
StringBuilder sb = new StringBuilder();
sb.append(prefix + ".");
for (String s : scope) {
sb.append(s);
sb.append(".");
}
return new SystemPropertiesScope(sb.toString());
}
}
/**
@@ -146,5 +157,7 @@ public class Config {
Boolean getBoolean(String key, Boolean defaultValue);
Scope scope(String... scope);
}
}
@@ -7,16 +7,16 @@ import java.security.Principal;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakPrincipal implements Principal, Serializable {
public class KeycloakPrincipal<T extends KeycloakSecurityContext> implements Principal, Serializable {
protected final String name;
protected final KeycloakSecurityContext context;
protected final T context;
public KeycloakPrincipal(String name, KeycloakSecurityContext context) {
public KeycloakPrincipal(String name, T context) {
this.name = name;
this.context = context;
}
public KeycloakSecurityContext getKeycloakSecurityContext() {
public T getKeycloakSecurityContext() {
return context;
}
@@ -2,7 +2,12 @@ package org.keycloak;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import org.keycloak.util.Base64Url;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
@@ -11,10 +16,12 @@ import java.io.Serializable;
*/
public class KeycloakSecurityContext implements Serializable {
protected String tokenString;
protected AccessToken token;
protected IDToken idToken;
protected String idTokenString;
// Don't store parsed tokens into HTTP session
protected transient AccessToken token;
protected transient IDToken idToken;
public KeycloakSecurityContext() {
}
@@ -40,4 +47,36 @@ public class KeycloakSecurityContext implements Serializable {
public String getIdTokenString() {
return idTokenString;
}
public String getRealm() {
// Assumption that issuer contains realm name
return token.getIssuer();
}
// SERIALIZATION
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
token = parseToken(tokenString, AccessToken.class);
idToken = parseToken(idTokenString, IDToken.class);
}
// Just decode token without any verifications
private <T> T parseToken(String encoded, Class<T> clazz) throws IOException {
if (encoded == null)
return null;
String[] parts = encoded.split("\\.");
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
byte[] bytes = Base64Url.decode(parts[1]);
return JsonSerialization.readValue(bytes, clazz);
}
}
@@ -35,7 +35,7 @@ public class RSATokenVerifier {
if (user == null) {
throw new VerificationException("Token user was null.");
}
if (!realm.equals(token.getAudience())) {
if (!realm.equals(token.getIssuer())) {
throw new VerificationException("Token audience doesn't match domain.");
}
@@ -1,21 +0,0 @@
package org.keycloak.adapters;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AdapterConstants {
// URL endpoints
public static final String K_LOGOUT = "k_logout";
public static final String K_VERSION = "k_version";
public static final String K_PUSH_NOT_BEFORE = "k_push_not_before";
public static final String K_GET_USER_STATS = "k_get_user_stats";
public static final String K_GET_SESSION_STATS = "k_get_session_stats";
public static final String K_QUERY_BEARER_TOKEN = "k_query_bearer_token";
// This param name is defined again in Keycloak Subsystem class
// org.keycloak.subsystem.extensionKeycloakAdapterConfigDeploymentProcessor. We have this value in
// two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
}
@@ -0,0 +1,32 @@
package org.keycloak.constants;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface AdapterConstants {
// URL endpoints
public static final String K_LOGOUT = "k_logout";
public static final String K_VERSION = "k_version";
public static final String K_PUSH_NOT_BEFORE = "k_push_not_before";
public static final String K_TEST_AVAILABLE = "k_test_available";
public static final String K_QUERY_BEARER_TOKEN = "k_query_bearer_token";
// This param name is defined again in Keycloak Subsystem class
// org.keycloak.subsystem.extensionKeycloakAdapterConfigDeploymentProcessor. We have this value in
// two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
String AUTH_DATA_PARAM_NAME = "org.keycloak.json.adapterConfig";
// Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains ID of HttpSession on adapter
public static final String APPLICATION_SESSION_STATE = "application_session_state";
// Attribute passed in codeToToken request from adapter to Keycloak and saved in ClientSession. Contains hostname of adapter where HttpSession is served
public static final String APPLICATION_SESSION_HOST = "application_session_host";
// Attribute passed in registerNode request for register new application cluster node once he joined cluster
public static final String APPLICATION_CLUSTER_HOST = "application_cluster_host";
// Cookie used on adapter side to store token info. Used only when tokenStore is 'COOKIE'
public static final String KEYCLOAK_ADAPTER_STATE_COOKIE = "KEYCLOAK_ADAPTER_STATE";
}
@@ -0,0 +1,10 @@
package org.keycloak.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class GenericConstants {
public static final String PROTOCOL_CLASSPATH = "classpath:";
}
@@ -1,4 +1,4 @@
package org.keycloak;
package org.keycloak.constants;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -6,12 +6,14 @@ package org.keycloak;
*/
public interface ServiceUrlConstants {
public static final String TOKEN_SERVICE_LOGIN_PATH = "/realms/{realm-name}/tokens/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/realms/{realm-name}/tokens/access/codes";
public static final String TOKEN_SERVICE_REFRESH_PATH = "/realms/{realm-name}/tokens/refresh";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/tokens/logout";
public static final String TOKEN_SERVICE_DIRECT_GRANT_PATH = "/realms/{realm-name}/tokens/grants/access";
public static final String TOKEN_SERVICE_LOGIN_PATH = "/realms/{realm-name}/protocol/openid-connect/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/realms/{realm-name}/protocol/openid-connect/access/codes";
public static final String TOKEN_SERVICE_REFRESH_PATH = "/realms/{realm-name}/protocol/openid-connect/refresh";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/protocol/openid-connect/logout";
public static final String TOKEN_SERVICE_DIRECT_GRANT_PATH = "/realms/{realm-name}/protocol/openid-connect/grants/access";
public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
public static final String REALM_INFO_PATH = "/realms/{realm-name}";
public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/register-node";
public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "/realms/{realm-name}/clients-managements/unregister-node";
}
@@ -0,0 +1,36 @@
package org.keycloak.enums;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public enum RelativeUrlsUsed {
/**
* Always use relative URI and resolve them later based on browser HTTP request
*/
ALL_REQUESTS,
/**
* Use relative Uris just for browser requests and resolve those based on browser HTTP requests.
* Backend request (like refresh token request, codeToToken request etc) will use the URI based on current hostname
*/
BROWSER_ONLY,
/**
* Relative Uri not used. Configuration contains absolute URI
*/
NEVER;
public boolean useRelative(boolean isBrowserReq) {
switch (this) {
case ALL_REQUESTS:
return true;
case NEVER:
return false;
case BROWSER_ONLY:
return isBrowserReq;
default:
return true;
}
}
}
@@ -0,0 +1,9 @@
package org.keycloak.enums;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public enum TokenStore {
SESSION,
COOKIE
}
@@ -58,81 +58,148 @@ public class JWSBuilder {
}
}
protected String encode(Algorithm alg, byte[] data, byte[] signature) {
StringBuffer encoding = new StringBuffer();
encoding.append(encodeHeader(alg));
protected String encodeAll(StringBuffer encoding, byte[] signature) {
encoding.append('.');
encoding.append(Base64Url.encode(data));
encoding.append('.');
if (alg != Algorithm.none) {
if (signature != null) {
encoding.append(Base64Url.encode(signature));
}
return encoding.toString();
}
protected void encode(Algorithm alg, byte[] data, StringBuffer encoding) {
encoding.append(encodeHeader(alg));
encoding.append('.');
encoding.append(Base64Url.encode(data));
}
protected byte[] marshalContent() {
return contentBytes;
}
public class EncodingBuilder {
public String none() {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
return encode(Algorithm.none, data, null);
encode(Algorithm.none, data, buffer);
return encodeAll(buffer, null);
}
public String rsa256(PrivateKey privateKey) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = RSAProvider.sign(data, Algorithm.RS256, privateKey);
return encode(Algorithm.RS256, data, signature);
encode(Algorithm.RS256, data, buffer);
byte[] signature = null;
try {
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS256, privateKey);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String rsa384(PrivateKey privateKey) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = RSAProvider.sign(data, Algorithm.RS384, privateKey);
return encode(Algorithm.RS384, data, signature);
encode(Algorithm.RS384, data, buffer);
byte[] signature = null;
try {
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS384, privateKey);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String rsa512(PrivateKey privateKey) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = RSAProvider.sign(data, Algorithm.RS512, privateKey);
return encode(Algorithm.RS512, data, signature);
encode(Algorithm.RS512, data, buffer);
byte[] signature = null;
try {
signature = RSAProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.RS512, privateKey);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac256(byte[] sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
return encode(Algorithm.HS256, data, signature);
encode(Algorithm.HS256, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac384(byte[] sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
return encode(Algorithm.HS384, data, signature);
encode(Algorithm.HS384, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac512(byte[] sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
return encode(Algorithm.HS512, data, signature);
encode(Algorithm.HS512, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac256(SecretKey sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS256, sharedSecret);
return encode(Algorithm.HS256, data, signature);
encode(Algorithm.HS256, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS256, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac384(SecretKey sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS384, sharedSecret);
return encode(Algorithm.HS384, data, signature);
encode(Algorithm.HS384, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS384, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
public String hmac512(SecretKey sharedSecret) {
StringBuffer buffer = new StringBuffer();
byte[] data = marshalContent();
byte[] signature = HMACProvider.sign(data, Algorithm.HS512, sharedSecret);
return encode(Algorithm.HS512, data, signature);
encode(Algorithm.HS512, data, buffer);
byte[] signature = null;
try {
signature = HMACProvider.sign(buffer.toString().getBytes("UTF-8"), Algorithm.HS512, sharedSecret);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return encodeAll(buffer, signature);
}
}
}
@@ -15,6 +15,7 @@ public class JWSInput {
String encodedHeader;
String encodedContent;
String encodedSignature;
String encodedSignatureInput;
JWSHeader header;
byte[] content;
byte[] signature;
@@ -26,6 +27,7 @@ public class JWSInput {
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
encodedHeader = parts[0];
encodedContent = parts[1];
encodedSignatureInput = encodedHeader + '.' + encodedContent;
try {
content = Base64Url.decode(encodedContent);
if (parts.length > 2) {
@@ -55,6 +57,9 @@ public class JWSInput {
public String getEncodedSignature() {
return encodedSignature;
}
public String getEncodedSignatureInput() {
return encodedSignatureInput;
}
public JWSHeader getHeader() {
return header;
@@ -74,7 +74,7 @@ public class HMACProvider {
public static boolean verify(JWSInput input, byte[] sharedSecret) {
try {
byte[] signature = sign(input.getContent(), input.getHeader().getAlgorithm(), sharedSecret);
byte[] signature = sign(input.getEncodedSignatureInput().getBytes("UTF-8"), input.getHeader().getAlgorithm(), sharedSecret);
String x = Base64Url.encode(signature);
return x.equals(input.getEncodedSignature());
} catch (Exception e) {
@@ -49,7 +49,7 @@ public class RSAProvider {
try {
Signature verifier = getSignature(input.getHeader().getAlgorithm());
verifier.initVerify(publicKey);
verifier.update(input.getContent());
verifier.update(input.getEncodedSignatureInput().getBytes("UTF-8"));
return verifier.verify(input.getSignature());
} catch (Exception e) {
throw new RuntimeException(e);
@@ -3,6 +3,7 @@ package org.keycloak.representations;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -13,7 +14,7 @@ import java.util.Set;
* @version $Revision: 1 $
*/
public class AccessToken extends IDToken {
public static class Access {
public static class Access implements Serializable {
@JsonProperty("roles")
protected Set<String> roles;
@JsonProperty("verify_caller")
@@ -15,6 +15,9 @@ public class AccessTokenResponse {
@JsonProperty("expires_in")
protected long expiresIn;
@JsonProperty("refresh_expires_in")
protected long refreshExpiresIn;
@JsonProperty("refresh_token")
protected String refreshToken;
@@ -46,6 +49,14 @@ public class AccessTokenResponse {
this.expiresIn = expiresIn;
}
public long getRefreshExpiresIn() {
return refreshExpiresIn;
}
public void setRefreshExpiresIn(long refreshExpiresIn) {
this.refreshExpiresIn = refreshExpiresIn;
}
public String getRefreshToken() {
return refreshToken;
}
@@ -0,0 +1,60 @@
package org.keycloak.representations.adapters.action;
import java.util.ArrayList;
import java.util.List;
/**
* Result of the "global" request (like push notBefore or logoutAll), which is send to all cluster nodes
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class GlobalRequestResult {
private List<String> successRequests;
private List<String> failedRequests;
public void addSuccessRequest(String reqUri) {
if (successRequests == null) {
successRequests = new ArrayList<String>();
}
successRequests.add(reqUri);
}
public void addFailedRequest(String reqUri) {
if (failedRequests == null) {
failedRequests = new ArrayList<String>();
}
failedRequests.add(reqUri);
}
public void addAllSuccessRequests(List<String> reqUris) {
if (successRequests == null) {
successRequests = new ArrayList<String>();
}
successRequests.addAll(reqUris);
}
public void addAllFailedRequests(List<String> reqUris) {
if (failedRequests == null) {
failedRequests = new ArrayList<String>();
}
failedRequests.addAll(reqUris);
}
public void addAll(GlobalRequestResult merged) {
if (merged.getSuccessRequests() != null && merged.getSuccessRequests().size() > 0) {
addAllSuccessRequests(merged.getSuccessRequests());
}
if (merged.getFailedRequests() != null && merged.getFailedRequests().size() > 0) {
addAllFailedRequests(merged.getFailedRequests());
}
}
public List<String> getSuccessRequests() {
return successRequests;
}
public List<String> getFailedRequests() {
return failedRequests;
}
}
@@ -1,40 +1,25 @@
package org.keycloak.representations.adapters.action;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class LogoutAction extends AdminAction {
public static final String LOGOUT = "LOGOUT";
protected String user;
private String session;
protected List<String> adapterSessionIds;
protected int notBefore;
public LogoutAction() {
}
public LogoutAction(String id, int expiration, String resource, String user, String session, int notBefore) {
public LogoutAction(String id, int expiration, String resource, List<String> adapterSessionIds, int notBefore) {
super(id, expiration, resource, LOGOUT);
this.user = user;
this.session = session;
this.adapterSessionIds = adapterSessionIds;
this.notBefore = notBefore;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
public int getNotBefore() {
return notBefore;
@@ -44,6 +29,10 @@ public class LogoutAction extends AdminAction {
this.notBefore = notBefore;
}
public List<String> getAdapterSessionIds() {
return adapterSessionIds;
}
@Override
public boolean validate() {
return LOGOUT.equals(action);
@@ -1,37 +0,0 @@
package org.keycloak.representations.adapters.action;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SessionStats {
protected int activeSessions;
protected int activeUsers;
protected Map<String, UserStats> users;
public int getActiveSessions() {
return activeSessions;
}
public void setActiveSessions(int activeSessions) {
this.activeSessions = activeSessions;
}
public int getActiveUsers() {
return activeUsers;
}
public void setActiveUsers(int activeUsers) {
this.activeUsers = activeUsers;
}
public Map<String, UserStats> getUsers() {
return users;
}
public void setUsers(Map<String, UserStats> users) {
this.users = users;
}
}
@@ -1,35 +0,0 @@
package org.keycloak.representations.adapters.action;
/**
* Query session stats.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SessionStatsAction extends AdminAction {
public static final String SESSION_STATS = "SESSION_STATS";
protected boolean listUsers;
public SessionStatsAction() {
}
public SessionStatsAction(String id, int expiration, String resource) {
super(id, expiration, resource, SESSION_STATS);
}
public boolean isListUsers() {
return listUsers;
}
public void setListUsers(boolean listUsers) {
this.listUsers = listUsers;
}
@Override
public boolean validate() {
return SESSION_STATS.equals(action);
}
}
@@ -0,0 +1,22 @@
package org.keycloak.representations.adapters.action;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class TestAvailabilityAction extends AdminAction {
public static final String TEST_AVAILABILITY = "TEST_AVAILABILITY";
public TestAvailabilityAction() {
}
public TestAvailabilityAction(String id, int expiration, String resource) {
super(id, expiration, resource, TEST_AVAILABILITY);
}
@Override
public boolean validate() {
return TEST_AVAILABILITY.equals(action);
}
}
@@ -1,26 +0,0 @@
package org.keycloak.representations.adapters.action;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserStats {
protected boolean loggedIn;
protected long whenLoggedIn;
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public long getWhenLoggedIn() {
return whenLoggedIn;
}
public void setWhenLoggedIn(long whenLoggedIn) {
this.whenLoggedIn = whenLoggedIn;
}
}
@@ -1,31 +0,0 @@
package org.keycloak.representations.adapters.action;
/**
* Query session stats.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserStatsAction extends AdminAction {
public static final String USER_STATS = "USER_STATS";
protected String user;
public UserStatsAction() {
}
public UserStatsAction(String id, int expiration, String resource, String user) {
super(id, expiration, resource, USER_STATS);
this.user = user;
}
public String getUser() {
return user;
}
@Override
public boolean validate() {
return USER_STATS.equals(action);
}
}
@@ -10,13 +10,15 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
* @version $Revision: 1 $
*/
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-required",
"resource", "credentials",
"resource", "public-client", "credentials",
"use-resource-role-mappings",
"enable-cors", "cors-max-age", "cors-allowed-methods",
"expose-token", "bearer-only",
"connection-pool-size",
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
"client-keystore", "client-keystore-password", "client-key-password"
"client-keystore", "client-keystore-password", "client-key-password",
"auth-server-url-for-backend-requests", "always-refresh-token",
"register-node-at-startup", "register-node-period", "token-store", "principal-attribute"
})
public class AdapterConfig extends BaseAdapterConfig {
@@ -36,6 +38,18 @@ public class AdapterConfig extends BaseAdapterConfig {
protected String clientKeyPassword;
@JsonProperty("connection-pool-size")
protected int connectionPoolSize = 20;
@JsonProperty("auth-server-url-for-backend-requests")
protected String authServerUrlForBackendRequests;
@JsonProperty("always-refresh-token")
protected boolean alwaysRefreshToken = false;
@JsonProperty("register-node-at-startup")
protected boolean registerNodeAtStartup = false;
@JsonProperty("register-node-period")
protected int registerNodePeriod = -1;
@JsonProperty("token-store")
protected String tokenStore;
@JsonProperty("principal-attribute")
protected String principalAttribute;
public boolean isAllowAnyHostname() {
return allowAnyHostname;
@@ -101,4 +115,51 @@ public class AdapterConfig extends BaseAdapterConfig {
this.connectionPoolSize = connectionPoolSize;
}
public String getAuthServerUrlForBackendRequests() {
return authServerUrlForBackendRequests;
}
public void setAuthServerUrlForBackendRequests(String authServerUrlForBackendRequests) {
this.authServerUrlForBackendRequests = authServerUrlForBackendRequests;
}
public boolean isAlwaysRefreshToken() {
return alwaysRefreshToken;
}
public void setAlwaysRefreshToken(boolean alwaysRefreshToken) {
this.alwaysRefreshToken = alwaysRefreshToken;
}
public boolean isRegisterNodeAtStartup() {
return registerNodeAtStartup;
}
public void setRegisterNodeAtStartup(boolean registerNodeAtStartup) {
this.registerNodeAtStartup = registerNodeAtStartup;
}
public int getRegisterNodePeriod() {
return registerNodePeriod;
}
public void setRegisterNodePeriod(int registerNodePeriod) {
this.registerNodePeriod = registerNodePeriod;
}
public String getTokenStore() {
return tokenStore;
}
public void setTokenStore(String tokenStore) {
this.tokenStore = tokenStore;
}
public String getPrincipalAttribute() {
return principalAttribute;
}
public void setPrincipalAttribute(String principalAttribute) {
this.principalAttribute = principalAttribute;
}
}
@@ -16,7 +16,7 @@ import java.util.Map;
"resource", "public-client", "credentials",
"use-resource-role-mappings",
"enable-cors", "cors-max-age", "cors-allowed-methods",
"expose-token", "bearer-only"})
"expose-token", "bearer-only", "enable-basic-auth"})
public class BaseAdapterConfig extends BaseRealmConfig {
@JsonProperty("resource")
protected String resource;
@@ -34,6 +34,8 @@ public class BaseAdapterConfig extends BaseRealmConfig {
protected boolean exposeToken;
@JsonProperty("bearer-only")
protected boolean bearerOnly;
@JsonProperty("enable-basic-auth")
protected boolean enableBasicAuth;
@JsonProperty("public-client")
protected boolean publicClient;
@JsonProperty("credentials")
@@ -97,12 +99,20 @@ public class BaseAdapterConfig extends BaseRealmConfig {
}
public boolean isBearerOnly() {
return bearerOnly;
}
return bearerOnly;
}
public void setBearerOnly(boolean bearerOnly) {
this.bearerOnly = bearerOnly;
}
this.bearerOnly = bearerOnly;
}
public boolean isEnableBasicAuth() {
return enableBasicAuth;
}
public void setEnableBasicAuth(boolean enableBasicAuth) {
this.enableBasicAuth = enableBasicAuth;
}
public Map<String, String> getCredentials() {
return credentials;
@@ -1,6 +1,7 @@
package org.keycloak.representations.idm;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -21,8 +22,11 @@ public class ApplicationRepresentation {
protected Integer notBefore;
protected Boolean bearerOnly;
protected Boolean publicClient;
protected String protocol;
protected Map<String, String> attributes;
protected Boolean fullScopeAllowed;
protected Integer nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes;
public String getId() {
return id;
@@ -143,4 +147,36 @@ public class ApplicationRepresentation {
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
this.fullScopeAllowed = fullScopeAllowed;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public Integer getNodeReRegistrationTimeout() {
return nodeReRegistrationTimeout;
}
public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
this.nodeReRegistrationTimeout = nodeReRegistrationTimeout;
}
public Map<String, Integer> getRegisteredNodes() {
return registeredNodes;
}
public void setRegisteredNodes(Map<String, Integer> registeredNodes) {
this.registeredNodes = registeredNodes;
}
}
@@ -1,6 +1,7 @@
package org.keycloak.representations.idm;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -16,6 +17,8 @@ public class OAuthClientRepresentation {
protected ClaimRepresentation claims;
protected Integer notBefore;
protected Boolean publicClient;
protected String protocol;
protected Map<String, String> attributes;
protected Boolean directGrantsOnly;
protected Boolean fullScopeAllowed;
@@ -108,4 +111,19 @@ public class OAuthClientRepresentation {
this.fullScopeAllowed = fullScopeAllowed;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
}
@@ -43,6 +43,8 @@ public class RealmRepresentation {
protected String privateKey;
protected String publicKey;
protected String certificate;
protected String codeSecret;
protected RolesRepresentation roles;
protected List<String> defaultRoles;
protected Set<String> requiredCredentials;
@@ -60,8 +62,8 @@ public class RealmRepresentation {
protected String accountTheme;
protected String adminTheme;
protected String emailTheme;
protected boolean eventsEnabled;
protected long eventsExpiration;
protected Boolean eventsEnabled;
protected Long eventsExpiration;
protected List<String> eventsListeners;
public String getId() {
@@ -220,6 +222,22 @@ public class RealmRepresentation {
this.publicKey = publicKey;
}
public String getCertificate() {
return certificate;
}
public void setCertificate(String certificate) {
this.certificate = certificate;
}
public String getCodeSecret() {
return codeSecret;
}
public void setCodeSecret(String codeSecret) {
this.codeSecret = codeSecret;
}
public Boolean isPasswordCredentialGrantAllowed() {
return passwordCredentialGrantAllowed;
}
@@ -436,7 +454,7 @@ public class RealmRepresentation {
this.failureFactor = failureFactor;
}
public boolean isEventsEnabled() {
public Boolean isEventsEnabled() {
return eventsEnabled;
}
@@ -444,7 +462,7 @@ public class RealmRepresentation {
this.eventsEnabled = eventsEnabled;
}
public long getEventsExpiration() {
public Long getEventsExpiration() {
return eventsExpiration;
}
@@ -15,7 +15,7 @@ public class UserSessionRepresentation {
private String ipAddress;
private long start;
private long lastAccess;
private Set<String> applications = new HashSet<String>();
private Map<String, String> applications = new HashMap<String, String>();
private Map<String, String> clients = new HashMap<String, String>();
public String getId() {
@@ -58,11 +58,11 @@ public class UserSessionRepresentation {
this.lastAccess = lastAccess;
}
public Set<String> getApplications() {
public Map<String, String> getApplications() {
return applications;
}
public void setApplications(Set<String> applications) {
public void setApplications(Map<String, String> applications) {
this.applications = applications;
}
+66
View File
@@ -0,0 +1,66 @@
package org.keycloak.util;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.x509.X509V1CertificateGenerator;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import javax.security.auth.x500.X500Principal;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CertificateUtils {
static {
BouncyIntegration.init();
}
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert, String subject) throws Exception {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X500Principal subjectName = new X500Principal("CN=" + subject);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
certGen.setSerialNumber(serialNumber);
certGen.setIssuerDN(caCert.getSubjectX500Principal());
certGen.setNotBefore(new Date(System.currentTimeMillis() - 100000));
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
certGen.setNotAfter(calendar.getTime());
certGen.setSubjectDN(subjectName);
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,
new AuthorityKeyIdentifierStructure(caCert));
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
new SubjectKeyIdentifierStructure(keyPair.getPublic()));
X509Certificate cert = certGen.generate(caPrivateKey, "BC"); // note: private key of CA
return cert;
}
public static X509Certificate generateV1SelfSignedCertificate(KeyPair keyPair, String subject) throws Exception {
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
X500Principal subjectPrincipal = new X500Principal("CN=" + subject);
certGen.setSerialNumber(serialNumber);
certGen.setIssuerDN(subjectPrincipal);
certGen.setNotBefore(new Date(System.currentTimeMillis() - 100000));
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
certGen.setNotAfter(calendar.getTime());
certGen.setSubjectDN(subjectPrincipal);
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
X509Certificate cert = certGen.generate(keyPair.getPrivate(), "BC");
return cert;
}
}
@@ -0,0 +1,74 @@
package org.keycloak.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class HostUtils {
// Best effort to find the most proper hostname of this server.
public static String getHostName() {
return getHostNameImpl().trim().toLowerCase();
}
public static String getIpAddress() {
try {
String hostname = getHostName();
return InetAddress.getByName(hostname).getHostAddress();
} catch (UnknownHostException uhe) {
throw new IllegalStateException(uhe);
}
}
private static String getHostNameImpl() {
// Return bind address if available
String bindAddr = System.getProperty("jboss.bind.address");
if (bindAddr != null && !bindAddr.trim().equals("0.0.0.0")) {
return bindAddr;
}
// Fallback to qualified name
String qualifiedHostName = System.getProperty("jboss.qualified.host.name");
if (qualifiedHostName != null) {
return qualifiedHostName;
}
// If not on jboss env, let's try other possible fallbacks
// POSIX-like OSes including Mac should have this set
qualifiedHostName = System.getenv("HOSTNAME");
if (qualifiedHostName != null) {
return qualifiedHostName;
}
// Certain versions of Windows
qualifiedHostName = System.getenv("COMPUTERNAME");
if (qualifiedHostName != null) {
return qualifiedHostName;
}
try {
return NetworkUtils.canonize(getLocalHost().getHostName());
} catch (UnknownHostException uhe) {
uhe.printStackTrace();
return "unknown-host.unknown-domain";
}
}
/**
* Methods returns InetAddress for localhost
*
* @return InetAddress of the localhost
* @throws UnknownHostException if localhost could not be resolved
*/
private static InetAddress getLocalHost() throws UnknownHostException {
InetAddress addr;
try {
addr = InetAddress.getLocalHost();
} catch (ArrayIndexOutOfBoundsException e) { //this is workaround for mac osx bug see AS7-3223 and JGRP-1404
addr = InetAddress.getByName(null);
}
return addr;
}
}
@@ -17,6 +17,7 @@ import java.io.OutputStream;
public class JsonSerialization {
public static final ObjectMapper mapper = new ObjectMapper();
public static final ObjectMapper prettyMapper = new ObjectMapper();
public static final ObjectMapper sysPropertiesAwareMapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
static {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
@@ -46,7 +47,15 @@ public class JsonSerialization {
}
public static <T> T readValue(InputStream bytes, Class<T> type) throws IOException {
return mapper.readValue(bytes, type);
return readValue(bytes, type, false);
}
public static <T> T readValue(InputStream bytes, Class<T> type, boolean replaceSystemProperties) throws IOException {
if (replaceSystemProperties) {
return sysPropertiesAwareMapper.readValue(bytes, type);
} else {
return mapper.readValue(bytes, type);
}
}
@@ -2,18 +2,22 @@ package org.keycloak.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import org.keycloak.constants.GenericConstants;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeystoreUtil {
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
File truststoreFile = new File(filename);
FileInputStream trustStream = new FileInputStream(truststoreFile);
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStream = (filename.startsWith(GenericConstants.PROTOCOL_CLASSPATH))
?KeystoreUtil.class.getResourceAsStream(filename.replace(GenericConstants.PROTOCOL_CLASSPATH, ""))
:new FileInputStream(new File(filename));
trustStore.load(trustStream, password.toCharArray());
trustStream.close();
return trustStore;
@@ -0,0 +1,446 @@
package org.keycloak.util;
/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Locale;
/**
* Utility methods related to networking.
*
* @author Brian Stansberry (c) 2011 Red Hat Inc.
*/
public class NetworkUtils {
private static final int MAX_GROUP_LENGTH = 4;
private static final int IPV6_LEN = 8;
private static final boolean can_bind_to_mcast_addr; // are we running on Linux ?
static {
can_bind_to_mcast_addr = checkForLinux() || checkForSolaris() || checkForHp();
}
public static String formatPossibleIpv6Address(String address) {
if(address == null) {
return null;
}
String ipv6Address;
if (address.startsWith("[") && address.endsWith("]")) {
ipv6Address = address.substring(0, address.lastIndexOf(']')).substring(1);
} else {
ipv6Address = address;
}
// Definitely not an IPv6, return untouched input.
if (!mayBeIPv6Address(ipv6Address)) {
return ipv6Address;
}
return '[' + canonize(ipv6Address) + ']';
}
/**
* <p>Convert IPv6 adress into RFC 5952 form.
* E.g. 2001:db8:0:1:0:0:0:1 -> 2001:db8:0:1::1</p>
*
* <p>Method is null safe, and if IPv4 address or host name is passed to the
* method it is returned wihout any processing.</p>
*
* <p>Method also supports IPv4 in IPv6 (e.g. 0:0:0:0:0:ffff:192.0.2.1 ->
* ::ffff:192.0.2.1), and zone ID (e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
* -> fe80::f0f0:c0c0:1919:1234%4).</p>
*
* @param ipv6Address String representing valid IPv6 address.
* @return String representing IPv6 in canonical form.
* @throws IllegalArgumentException if IPv6 format is unacceptable.
*/
public static String canonize(String ipv6Address) throws IllegalArgumentException {
if (ipv6Address == null) {
return null;
}
// Definitely not an IPv6, return untouched input.
if (!mayBeIPv6Address(ipv6Address)) {
return ipv6Address;
}
// Length without zone ID (%zone) or IPv4 address
int ipv6AddressLength = ipv6Address.length();
if (isIPv4AddressInIPv6(ipv6Address)) {
// IPv4 in IPv6
// e.g. 0:0:0:0:0:FFFF:127.0.0.1
int lastColonPos = ipv6Address.lastIndexOf(":");
int lastColonsPos = ipv6Address.lastIndexOf("::");
if (lastColonsPos >= 0 && lastColonPos == lastColonsPos + 1) {
// IPv6 part ends with two consecutive colons, last colon is part of IPv6 format.
// e.g. ::127.0.0.1
ipv6AddressLength = lastColonPos + 1;
} else {
// IPv6 part ends with only one colon, last colon is not part of IPv6 format.
// e.g. ::FFFF:127.0.0.1
ipv6AddressLength = lastColonPos;
}
} else if (ipv6Address.contains(":") && ipv6Address.contains("%")) {
// Zone ID
// e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
ipv6AddressLength = ipv6Address.lastIndexOf("%");
}
StringBuilder result = new StringBuilder();
char [][] groups = new char[IPV6_LEN][MAX_GROUP_LENGTH];
int groupCounter = 0;
int charInGroupCounter = 0;
// Index of the current zeroGroup, -1 means not found.
int zeroGroupIndex = -1;
int zeroGroupLength = 0;
// maximum length zero group, if there is more then one, then first one
int maxZeroGroupIndex = -1;
int maxZeroGroupLength = 0;
boolean isZero = true;
boolean groupStart = true;
/*
* Two consecutive colons, initial expansion.
* e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1
*/
StringBuilder expanded = new StringBuilder(ipv6Address);
int colonsPos = ipv6Address.indexOf("::");
int length = ipv6AddressLength;
int change = 0;
if (colonsPos >= 0 && colonsPos < ipv6AddressLength - 2) {
int colonCounter = 0;
for (int i = 0; i < ipv6AddressLength; i++) {
if (ipv6Address.charAt(i) == ':') {
colonCounter++;
}
}
if (colonsPos == 0) {
expanded.insert(0, "0");
change = change + 1;
}
for (int i = 0; i < IPV6_LEN - colonCounter; i++) {
expanded.insert(colonsPos + 1, "0:");
change = change + 2;
}
if (colonsPos == ipv6AddressLength - 2) {
expanded.setCharAt(colonsPos + change + 1, '0');
} else {
expanded.deleteCharAt(colonsPos + change + 1);
change = change - 1;
}
length = length + change;
}
// Processing one char at the time
for (int charCounter = 0; charCounter < length; charCounter++) {
char c = expanded.charAt(charCounter);
if (c >= 'A' && c <= 'F') {
c = (char) (c + 32);
}
if (c != ':') {
groups[groupCounter][charInGroupCounter] = c;
if (!(groupStart && c == '0')) {
++charInGroupCounter;
groupStart = false;
}
if (c != '0') {
isZero = false;
}
}
if (c == ':' || charCounter == (length - 1)) {
// We reached end of current group
if (isZero) {
++zeroGroupLength;
if (zeroGroupIndex == -1) {
zeroGroupIndex = groupCounter;
}
}
if (!isZero || charCounter == (length - 1)) {
// We reached end of zero group
if (zeroGroupLength > maxZeroGroupLength) {
maxZeroGroupLength = zeroGroupLength;
maxZeroGroupIndex = zeroGroupIndex;
}
zeroGroupLength = 0;
zeroGroupIndex = -1;
}
++groupCounter;
charInGroupCounter = 0;
isZero = true;
groupStart = true;
}
}
int numberOfGroups = groupCounter;
// Output results
for (groupCounter = 0; groupCounter < numberOfGroups; groupCounter++) {
if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex
|| groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) {
for (int j = 0; j < MAX_GROUP_LENGTH; j++) {
if (groups[groupCounter][j] != 0) {
result.append(groups[groupCounter][j]);
}
}
if (groupCounter < (numberOfGroups - 1)
&& (groupCounter != maxZeroGroupIndex - 1
|| maxZeroGroupLength <= 1)) {
result.append(':');
}
} else if (groupCounter == maxZeroGroupIndex) {
result.append("::");
}
}
// Solve problem with three colons in IPv4 in IPv6 format
// e.g. 0:0:0:0:0:0:127.0.0.1 -> :::127.0.0.1 -> ::127.0.0.1
int resultLength = result.length();
if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length()
&& ipv6Address.charAt(ipv6AddressLength) == ':') {
result.delete(resultLength - 1, resultLength);
}
/*
* Append IPv4 from IPv4-in-IPv6 format or Zone ID
*/
for (int i = ipv6AddressLength; i < ipv6Address.length(); i++) {
result.append(ipv6Address.charAt(i));
}
return result.toString();
}
/**
* Heuristic check if string might be an IPv6 address.
*
* @param input Any string or null
* @return true, if input string contains only hex digits and at least two colons, before '.' or '%' character.
*/
private static boolean mayBeIPv6Address(String input) {
if (input == null) {
return false;
}
boolean result = false;
int colonsCounter = 0;
int length = input.length();
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == '.' || c == '%') {
// IPv4 in IPv6 or Zone ID detected, end of checking.
break;
}
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|| (c >= 'A' && c <= 'F') || c == ':')) {
return false;
} else if (c == ':') {
colonsCounter++;
}
}
if (colonsCounter >= 2) {
result = true;
}
return result;
}
/**
* Check if it is an IPv4 in IPv6 format.
* e.g. 0:0:0:0:0:FFFF:127.0.0.1
*
* @param ipv6Address the address
* @return true, if input string is an IPv4 address in IPv6 format.
*/
private static boolean isIPv4AddressInIPv6(String ipv6Address) {
return (ipv6Address.contains(":") && ipv6Address.contains("."));
}
/**
* Formats input address. For IPV4 returns simply host address, for IPV6 formats address according to <a
* href="http://tools.ietf.org/html/rfc5952">RFC5952</a> rules. It does not embed IPV6 address in '[', ']', since those are part of IPV6 URI literal.
*
* @param inet
* @return
*/
public static String formatAddress(InetAddress inet){
if(inet == null){
throw new NullPointerException();
}
if(inet instanceof Inet4Address){
return inet.getHostAddress();
} else if (inet instanceof Inet6Address){
byte[] byteRepresentation = inet.getAddress();
int[] hexRepresentation = new int[IPV6_LEN];
for(int i=0;i < hexRepresentation.length;i++){
hexRepresentation[i] = ( byteRepresentation[2*i] & 0xFF) << 8 | ( byteRepresentation[2*i+1] & 0xFF );
}
compactLongestZeroSequence(hexRepresentation);
return formatAddress6(hexRepresentation);
} else {
return inet.getHostAddress();
}
}
/**
* Converts socket address into string literal, which has form: 'address:port'. Example:<br>
* <ul>
* <li>127.0.0.1:8080</li>
* <li>dns.name.com:8080</li>
* <li>[0fe:1::20]:8080</li>
* <li>[::1]:8080</li>
* </ul>
* @param inet
* @return
*/
public static String formatAddress(InetSocketAddress inet){
if(inet == null){
throw new NullPointerException();
}
StringBuilder result = new StringBuilder();
if(inet.isUnresolved()){
result.append(inet.getHostName());
}else{
result.append(formatPossibleIpv6Address(formatAddress(inet.getAddress())));
}
result.append(":").append(inet.getPort());
return result.toString();
}
/**
* Converts IPV6 int[] representation into valid IPV6 string literal. Sequence of '-1' values are converted into '::'.
* @param hexRepresentation
* @return
*/
private static String formatAddress6(int[] hexRepresentation){
if(hexRepresentation == null){
throw new NullPointerException();
}
if(hexRepresentation.length != IPV6_LEN){
throw new IllegalArgumentException();
}
StringBuilder stringBuilder = new StringBuilder();
boolean inCompressedSection = false;
for(int i = 0;i<hexRepresentation.length;i++){
if(hexRepresentation[i] == -1){
if(!inCompressedSection){
inCompressedSection = true;
if(i == 0){
stringBuilder.append("::");
} else {
stringBuilder.append(':');
}
}
} else {
inCompressedSection = false;
stringBuilder.append(Integer.toHexString(hexRepresentation[i]));
if(i+1<hexRepresentation.length){
stringBuilder.append(":");
}
}
}
return stringBuilder.toString();
}
public static boolean isBindingToMulticastDressSupported() {
return can_bind_to_mcast_addr;
}
private static void compactLongestZeroSequence(int[] hexRepresentatoin){
int bestRunStart = -1;
int bestRunLen = -1;
boolean inRun = false;
int runStart = -1;
for(int i=0;i<hexRepresentatoin.length;i++){
if(hexRepresentatoin[i] == 0){
if(!inRun){
runStart = i;
inRun = true;
}
} else {
if(inRun){
inRun = false;
int runLen = i - runStart;
if(bestRunLen < 0){
bestRunStart = runStart;
bestRunLen = runLen;
} else {
if(runLen > bestRunLen){
bestRunStart = runStart;
bestRunLen = runLen;
}
}
}
}
}
if(bestRunStart >=0){
Arrays.fill(hexRepresentatoin, bestRunStart, bestRunStart + bestRunLen, -1);
}
}
private static boolean checkForLinux() {
return checkForPresence("os.name", "linux");
}
private static boolean checkForHp() {
return checkForPresence("os.name", "hp");
}
private static boolean checkForSolaris() {
return checkForPresence("os.name", "sun");
}
private static boolean checkForWindows() {
return checkForPresence("os.name", "win");
}
public static boolean checkForMac() {
return checkForPresence("os.name", "mac");
}
private static boolean checkForPresence(final String key, final String value) {
final String tmp = System.getProperty(key, value);
try {
return tmp != null && tmp.trim().toLowerCase(Locale.ENGLISH).startsWith(value);
} catch (Throwable t) {
return false;
}
}
// No instantiation
private NetworkUtils() {
}
}
@@ -1,4 +1,4 @@
package org.keycloak.services.util;
package org.keycloak.util;
import java.io.Serializable;
import java.text.DateFormat;
@@ -122,20 +122,23 @@ public class ServerCookie implements Serializable {
private final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
private final static DateFormat oldCookieFormat = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
private final static DateFormat OLD_COOKIE_FORMAT = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
static{
OLD_COOKIE_FORMAT.setTimeZone(GMT_ZONE);
}
public static String formatOldCookie(Date d) {
String ocf = null;
synchronized (oldCookieFormat) {
ocf = oldCookieFormat.format(d);
synchronized (OLD_COOKIE_FORMAT) {
ocf = OLD_COOKIE_FORMAT.format(d);
}
return ocf;
}
public static void formatOldCookie(Date d, StringBuffer sb,
FieldPosition fp) {
synchronized (oldCookieFormat) {
oldCookieFormat.format(d, sb, fp);
synchronized (OLD_COOKIE_FORMAT) {
OLD_COOKIE_FORMAT.format(d, sb, fp);
}
}
@@ -0,0 +1,51 @@
package org.keycloak.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.io.IOContext;
import org.codehaus.jackson.map.MappingJsonFactory;
import org.codehaus.jackson.util.JsonParserDelegate;
/**
* Provides replacing of system properties for parsed values
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SystemPropertiesJsonParserFactory extends MappingJsonFactory {
@Override
protected JsonParser _createJsonParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException {
JsonParser delegate = super._createJsonParser(data, offset, len, ctxt);
return new SystemPropertiesAwareJsonParser(delegate);
}
@Override
protected JsonParser _createJsonParser(Reader r, IOContext ctxt) throws IOException {
JsonParser delegate = super._createJsonParser(r, ctxt);
return new SystemPropertiesAwareJsonParser(delegate);
}
@Override
protected JsonParser _createJsonParser(InputStream in, IOContext ctxt) throws IOException {
JsonParser delegate = super._createJsonParser(in, ctxt);
return new SystemPropertiesAwareJsonParser(delegate);
}
public static class SystemPropertiesAwareJsonParser extends JsonParserDelegate {
public SystemPropertiesAwareJsonParser(JsonParser d) {
super(d);
}
@Override
public String getText() throws IOException {
String orig = super.getText();
return StringPropertyReplacer.replaceProperties(orig);
}
}
}
@@ -7,12 +7,18 @@ import java.util.Date;
*/
public class Time {
private static int offset;
public static int currentTime() {
return (int) (System.currentTimeMillis() / 1000);
return ((int) (System.currentTimeMillis() / 1000)) + offset;
}
public static Date toDate(int time) {
return new Date(((long) time ) * 1000);
}
public static void setOffset(int offset) {
Time.offset = offset;
}
}
+50
View File
@@ -1,12 +1,17 @@
package org.keycloak.util;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UriUtils {
private static final Pattern originPattern = Pattern.compile("(http://|https://)[\\w-]+(\\.[\\w-]+)*(:[\\d]{2,5})?");
public static String getOrigin(URI uri) {
return getOrigin(uri.toString());
}
@@ -16,4 +21,49 @@ public class UriUtils {
return u.substring(0, u.indexOf('/', 8));
}
public static boolean isOrigin(String url) {
return originPattern.matcher(url).matches();
}
public static MultivaluedHashMap<String, String> decodeQueryString(String queryString) {
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
if (queryString == null || queryString.equals("")) return map;
String[] params = queryString.split("&");
for (String param : params)
{
if (param.indexOf('=') >= 0)
{
String[] nv = param.split("=", 2);
try
{
String name = URLDecoder.decode(nv[0], "UTF-8");
String val = nv.length > 1 ? nv[1] : "";
map.add(name, URLDecoder.decode(val, "UTF-8"));
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
else
{
try
{
String name = URLDecoder.decode(param, "UTF-8");
map.add(name, "");
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
}
return map;
}
public static String stripQueryParam(String url, String name){
return url.replaceFirst("[\\?&]"+name+"=[^&]*$|"+name+"=[^&]*&", "");
}
}
@@ -1,4 +1,4 @@
package org.keycloak.models.utils.reflection;
package org.keycloak.util.reflections;
import java.beans.Introspector;
import java.io.Serializable;
@@ -1,4 +1,4 @@
package org.keycloak.models.utils.reflection;
package org.keycloak.util.reflections;
import java.lang.reflect.AccessibleObject;
import java.security.PrivilegedAction;
@@ -1,4 +1,4 @@
package org.keycloak.models.utils.reflection;
package org.keycloak.util.reflections;
import java.lang.reflect.Type;
@@ -0,0 +1,33 @@
package org.keycloak;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class JsonParserTest {
@Test
public void testParsingSystemProps() throws IOException {
System.setProperty("my.host", "foo");
System.setProperty("con.pool.size", "200");
System.setProperty("allow.any.hostname", "true");
InputStream is = getClass().getClassLoader().getResourceAsStream("keycloak.json");
AdapterConfig config = JsonSerialization.readValue(is, AdapterConfig.class, true);
Assert.assertEquals("http://foo:8080/auth", config.getAuthServerUrl());
Assert.assertEquals("external", config.getSslRequired());
Assert.assertEquals("angular-product${non.existing}", config.getResource());
Assert.assertTrue(config.isPublicClient());
Assert.assertTrue(config.isAllowAnyHostname());
Assert.assertEquals(100, config.getCorsMaxAge());
Assert.assertEquals(200, config.getConnectionPoolSize());
}
}
@@ -72,7 +72,7 @@ public class RSAVerifierTest {
token = new AccessToken();
token.subject("CN=Client")
.audience("domain")
.issuer("domain")
.addAccess("service").addRole("admin");
}
@@ -213,7 +213,7 @@ public class RSAVerifierTest {
public void testTokenAuth() throws Exception {
token = new AccessToken();
token.subject("CN=Client")
.audience("domain")
.issuer("domain")
.addAccess("service").addRole("admin").verifyCaller(true);
String encoded = new JWSBuilder()
@@ -1,13 +1,18 @@
package org.keycloak;
import junit.framework.Assert;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import org.keycloak.util.JsonSerialization;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -18,10 +23,7 @@ import java.security.KeyPairGenerator;
public class SkeletonKeyTokenTest {
@Test
public void testToken() throws Exception {
AccessToken token = new AccessToken();
token.id("111");
token.addAccess("foo").addRole("admin");
token.addAccess("bar").addRole("user");
AccessToken token = createSimpleToken();
String json = JsonSerialization.writeValueAsString(token);
token = JsonSerialization.readValue(json, AccessToken.class);
@@ -34,7 +36,7 @@ public class SkeletonKeyTokenTest {
@Test
public void testRSA() throws Exception {
AccessToken token = new AccessToken();
AccessToken token = createSimpleToken();
token.id("111");
token.addAccess("foo").addRole("admin");
token.addAccess("bar").addRole("user");
@@ -51,4 +53,59 @@ public class SkeletonKeyTokenTest {
Assert.assertEquals("111", token.getId());
Assert.assertTrue(RSAProvider.verify(input, keyPair.getPublic()));
}
@Test
public void testSerialization() throws Exception {
AccessToken token = createSimpleToken();
IDToken idToken = new IDToken();
idToken.setEmail("joe@email.cz");
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
String encoded = new JWSBuilder()
.jsonContent(token)
.rsa256(keyPair.getPrivate());
String encodedIdToken = new JWSBuilder()
.jsonContent(idToken)
.rsa256(keyPair.getPrivate());
KeycloakSecurityContext ctx = new KeycloakSecurityContext(encoded, token, encodedIdToken, idToken);
KeycloakPrincipal principal = new KeycloakPrincipal("joe", ctx);
// Serialize
ByteArrayOutputStream bso = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bso);
oos.writeObject(principal);
oos.close();
// Deserialize
byte[] bytes = bso.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
principal = (KeycloakPrincipal)ois.readObject();
ctx = principal.getKeycloakSecurityContext();
token = ctx.getToken();
idToken = ctx.getIdToken();
System.out.println("Size of serialized principal: " + bytes.length);
Assert.assertEquals(encoded, ctx.getTokenString());
Assert.assertEquals(encodedIdToken, ctx.getIdTokenString());
Assert.assertEquals("111", token.getId());
Assert.assertEquals("111", token.getId());
Assert.assertTrue(token.getResourceAccess("foo").isUserInRole("admin"));
Assert.assertTrue(token.getResourceAccess("bar").isUserInRole("user"));
Assert.assertEquals("joe@email.cz", idToken.getEmail());
Assert.assertEquals("acme", ctx.getRealm());
ois.close();
}
private AccessToken createSimpleToken() {
AccessToken token = new AccessToken();
token.id("111");
token.issuer("acme");
token.addAccess("foo").addRole("admin");
token.addAccess("bar").addRole("user");
return token;
}
}
@@ -0,0 +1,58 @@
package org.keycloak.util;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class UriUtilsTest {
@Test
public void testOrigins() {
assertValid("http://test");
assertValid("http://test:8080");
assertValid("https://test");
assertValid("http://test.com");
assertValid("https://test.com");
assertValid("https://test.com:8080");
assertValid("http://sub.test.com");
assertValid("https://sub.test.com");
assertValid("https://sub.test.com:8080");
assertValid("http://192.168.123.123");
assertValid("https://192.168.123.123");
assertValid("https://192.168.123.123:8080");
assertValid("https://sub-sub.test.com");
assertValid("https://sub.test-test.com");
assertInvalid("https://test/");
assertInvalid("{");
assertInvalid("https://{}");
assertInvalid("https://)");
assertInvalid("http://test:test");
assertInvalid("http://test:8080:8080");
}
public void assertValid(String origin) {
assertTrue(UriUtils.isOrigin(origin));
}
public void assertInvalid(String origin) {
assertFalse(UriUtils.isOrigin(origin));
}
@Test
public void testStripQueryParam(){
assertEquals("http://localhost",UriUtils.stripQueryParam("http://localhost?login_hint=michael","login_hint"));
assertEquals("http://localhost",UriUtils.stripQueryParam("http://localhost?login_hint=michael@me.com","login_hint"));
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?param=test&login_hint=michael","login_hint"));
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?param=test&login_hint=michael@me.com","login_hint"));
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?login_hint=michael&param=test","login_hint"));
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?login_hint=michael@me.com&param=test","login_hint"));
assertEquals("http://localhost?pre=test&param=test",UriUtils.stripQueryParam("http://localhost?pre=test&login_hint=michael&param=test","login_hint"));
assertEquals("http://localhost?pre=test&param=test",UriUtils.stripQueryParam("http://localhost?pre=test&login_hint=michael@me.com&param=test","login_hint"));
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"auth-server-url" : "http://${my.host}:8080/auth",
"ssl-required" : "external",
"resource" : "angular-product${non.existing}",
"public-client" : true,
"allow-any-hostname": "${allow.any.hostname}",
"cors-max-age": 100,
"connection-pool-size": "${con.pool.size}"
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+49 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -26,6 +26,16 @@
<artifactId>keycloak-connections-jpa</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-connections-jpa-liquibase</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-connections-infinispan</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
@@ -46,6 +56,16 @@
<artifactId>keycloak-model-sessions-mongo</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-infinispan</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-invalidation-cache-infinispan</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-jpa</artifactId>
@@ -123,6 +143,17 @@
<version>${project.version}</version>
</dependency>
<!-- saml -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-protocol</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-federation</artifactId>
</dependency>
<!-- mongo -->
<dependency>
<groupId>org.keycloak</groupId>
@@ -153,6 +184,23 @@
<dependency>
<groupId>de.idyl</groupId>
<artifactId>winzipaes</artifactId>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
+5 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -24,6 +24,10 @@
<groupId>net.iharder</groupId>
<artifactId>base64</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core-jaxrs</artifactId>
+22 -43
View File
@@ -21,6 +21,9 @@
<excludes>
<exclude>**/*.sh</exclude>
<exclude>welcome-content/*</exclude>
<exclude>**/modules/system/layers/base/org/picketlink/**</exclude>
<exclude>**/modules/system/layers/base/org/jboss/as/cli/**</exclude>
<exclude>**/modules/system/layers/base/org/jboss/aesh/**</exclude>
</excludes>
</fileSet>
<fileSet>
@@ -32,14 +35,15 @@
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>${project.build.directory}/unpacked/deployments</directory>
<outputDirectory>keycloak/standalone/deployments</outputDirectory>
<excludes>
<exclude>keycloak-ds.xml</exclude>
</excludes>
<directory>${project.build.directory}/unpacked/modules</directory>
<outputDirectory>keycloak/modules/system/layers/base</outputDirectory>
<includes>
<include>org/picketlink/**</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/unpacked/deployments/auth-server.war/WEB-INF/classes/META-INF</directory>
<directory>${project.build.directory}/unpacked/deployments/auth-server.war/WEB-INF/classes/META-INF
</directory>
<outputDirectory>keycloak/standalone/configuration</outputDirectory>
<includes>
<include>keycloak-server.json</include>
@@ -53,48 +57,23 @@
<directory>${project.build.directory}/unpacked/adapter</directory>
<outputDirectory>keycloak</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}/unpacked/js-adapter</directory>
<outputDirectory>adapters/js-adapter</outputDirectory>
<includes>
<include>**/*.js</include>
<include>**/*.html</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/welcome-content</directory>
<outputDirectory>keycloak/welcome-content</outputDirectory>
<includes>
<include>*.*</include>
</includes>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<useTransitiveDependencies>false</useTransitiveDependencies>
<includes>
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
</includes>
<outputDirectory>adapters</outputDirectory>
</dependencySet>
</dependencySets>
<!--
<moduleSets>
<moduleSet>
<useAllReactorProjects>true</useAllReactorProjects>
<includes>
<include>org.keycloak:keycloak-wildfly-adapter-dist</include>
</includes>
<binaries>
<outputDirectory>adapters</outputDirectory>
<attachmentClassifier>zip</attachmentClassifier>
<includeDependencies>false</includeDependencies>
<unpack>false</unpack>
</binaries>
</moduleSet>
</moduleSets>
-->
<files>
<file>
<source>src/main/themes/README.txt</source>
<outputDirectory>keycloak/standalone/configuration/themes</outputDirectory>
</file>
<file>
<source>src/main/providers/README.txt</source>
<outputDirectory>keycloak/standalone/configuration/providers</outputDirectory>
</file>
</files>
</assembly>
+44 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-final</version>
<version>1.1.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@@ -26,6 +26,42 @@
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat8-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jetty81-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jetty91-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jetty92-adapter-dist</artifactId>
<version>${project.version}</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-eap6-adapter-dist</artifactId>
@@ -90,6 +126,13 @@
<outputDirectory>${project.build.directory}/unpacked/js-adapter</outputDirectory>
<includes>*.js</includes>
</artifactItem>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jboss-modules</artifactId>
<version>${project.version}</version>
<type>zip</type>
<outputDirectory>${project.build.directory}/unpacked/modules</outputDirectory>
</artifactItem>
</artifactItems>
<excludes>**/welcome-content/*</excludes>
</configuration>
@@ -0,0 +1,2 @@
Any provider implementation jars and libraries in this folder will be loaded by Keycloak. See the providers
section in the documentation for more details.
Loaded 100 of 1220 files, more files were not shown because too many files have changed in this diff. Show more