Compare commits

...
1323 Commits
Author SHA1 Message Date
keycloak-bot fb0519c3a0 Set version to 1.6.1.Final 2015-10-27 11:40:37 +00:00
Marek Posolda 145ae5a740 Merge pull request #1781 from mposolda/1.6.x
KEYCLOAK-2005 Fixed migration to take less time. Added UserProvider.g…
2015-10-26 14:12:55 +01:00
mposolda 534a1a336c KEYCLOAK-2005 Fixed migration to take less time. Added UserProvider.grantToAllUsers 2015-10-26 11:12:31 +01:00
Marek Posolda fc5d1bea1d Merge pull request #1774 from mposolda/1.6.x
Migration and other fixes
2015-10-23 23:41:42 +02:00
mposolda 91dd570ecc KEYCLOAK-2011 2015-10-23 22:05:27 +02:00
mposolda e3b3381f07 KEYCLOAK-2007 Migration upgrade for 1.6.1 2015-10-23 17:02:58 +02:00
mposolda 2e6d884153 KEYCLOAK-1983 Fix Oracle and Sybase 2015-10-23 12:06:26 +02:00
mposolda 64582ad8fb KEYCLOAK-1999 KC server doesn't start on EAP 6.4 in local mode on PostgreSQL 2015-10-23 11:26:52 +02:00
mposolda 966fba8cd7 KEYCLOAK-1981 Migration fix of create-client 2015-10-23 11:24:18 +02:00
mposolda f29332be96 KEYCLOAK-1987 Minor fixes in fuse demo 2015-10-23 11:23:05 +02:00
Stian Thorgersen 06a9c7e35d Version bump 2015-10-23 10:09:22 +02:00
Stian Thorgersen 08a5c790b2 Fix parent in dockbook modules 2015-10-20 11:11:57 +02:00
Stian Thorgersen 538dc2da2c Fix saml examples not excluded from deploy 2015-10-20 09:27:07 +02:00
Marko Strukelj 6b1287a553 KEYCLOAK-1988 Loader constraint violation in multi-tenant example 2015-10-19 22:11:31 +02:00
Stian Thorgersen 256ca2b665 Merge pull request #1756 from stianst/master
KEYCLOAK-1977
2015-10-19 08:47:21 +02:00
Stian Thorgersen e4412523d4 Merge pull request #1754 from vramik/migration-kc15
arquillian-testsuite add migration-kc15
2015-10-19 08:44:51 +02:00
Stian Thorgersen 073d82b367 KEYCLOAK-1977 2015-10-19 08:43:34 +02:00
Stian Thorgersen 484c5ebb15 Merge pull request #1755 from stianst/master
Tweak authentication flow page a bit
2015-10-19 08:42:22 +02:00
vramik 4c33704c56 add support for migration kc1.5.1 2015-10-18 16:01:26 +02:00
Marek Posolda 511763d4bc Merge pull request #1753 from mposolda/master
KEYCLOAK-1952 Migration fix. Change some INFO messages to DEBUG/TRACE
2015-10-17 10:02:55 +02:00
mposolda 605c80a68d KEYCLOAK-1952 Migration fix. Change some INFO messages to DEBUG/TRACE 2015-10-16 20:51:40 +02:00
Marek Posolda 2325143803 Merge pull request #1751 from mposolda/master
KEYCLOAK-1972 docs and export/import fixes for offline tokens. DB fixes
2015-10-16 19:58:41 +02:00
mposolda 9cc5ca3ce4 KEYCLOAK-1972 docs and export/import fixes for offline tokens. DB fixes 2015-10-16 19:09:52 +02:00
Marek Posolda d13c120b6c Merge pull request #1750 from mposolda/master
KEYCLOAK-1929 Change package names. Fix Fuse demo
2015-10-16 17:35:14 +02:00
mposolda 9942c7b519 Fix integration-arquillian 2015-10-16 16:57:28 +02:00
mposolda 4587fd23b6 KEYCLOAK-1929 Change package names. Fix Fuse demo 2015-10-16 16:30:42 +02:00
Stian Thorgersen c21b56d596 Merge pull request #1748 from stianst/tweak-auth-page
Tweak authentication flow page a bit
2015-10-16 14:54:51 +02:00
Stian Thorgersen 4ee5c32b1e Merge pull request #1745 from stianst/kc-1969
KEYCLOAK-1969
2015-10-16 14:54:09 +02:00
Stian Thorgersen 6386d95904 Tweak authentication flow page a bit 2015-10-16 14:04:57 +02:00
Stian Thorgersen f99395aebe Merge pull request #1746 from mhajas/master
KEYCLOAK-1865 - Stabilize some integration-arquillian tests
2015-10-16 14:04:04 +02:00
Stian Thorgersen 82a7173dba Merge pull request #1747 from stianst/kc-1975
KEYCLOAK-1975
2015-10-16 14:03:47 +02:00
Stian Thorgersen 2bf6f4b0fd Tweak authentication flow page a bit 2015-10-16 14:03:30 +02:00
Stian Thorgersen d8e90028af Merge pull request #1744 from stianst/kc-1973
KEYCLOAK-1973 Clear user from authentication context is password is n…
2015-10-16 12:52:46 +02:00
Stian Thorgersen d2afb4892a KEYCLOAK-1975
Increase/decrease flow priority doesn't work
2015-10-16 12:52:07 +02:00
Stian Thorgersen eb9f69eee0 KEYCLOAK-1969
Admin console displays Clients flow page when execution or execution flow is created.
2015-10-16 12:23:41 +02:00
mhajas 39f985e04a Clean code 2015-10-16 12:09:35 +02:00
mhajas 41a51d924b Merge remote-tracking branch 'upstream/master' 2015-10-16 12:03:03 +02:00
mhajas ce996f6a41 Fix PasswordPolicyTest stability 2015-10-16 11:33:11 +02:00
mhajas 244848afc4 Fix events tests stability 2015-10-16 11:31:45 +02:00
Stian Thorgersen 2910db5595 KEYCLOAK-1973 Clear user from authentication context is password is not valid 2015-10-16 11:24:45 +02:00
Stian Thorgersen a6556a49c2 Merge pull request #1738 from gerbermichi/locale
KEYCLOAK-1962 update realm overwrites supported locales with empty list
2015-10-16 10:21:20 +02:00
Bill Burke e4961056db Merge pull request #1743 from patriot1burke/master
KEYCLOAK-1941
2015-10-15 20:41:35 -04:00
Bill Burke c8eee38471 Merge pull request #1742 from patriot1burke/master
KEYCLOAK-1954
2015-10-15 20:41:12 -04:00
Bill Burke 1e4b3fc3b6 KEYCLOAK-1941 2015-10-15 20:26:20 -04:00
Bill Burke 14426f26f2 KEYCLOAK-1954 2015-10-15 20:05:44 -04:00
Bill Burke 19ad846306 Merge pull request #1741 from patriot1burke/master
KEYCLOAK-1960
2015-10-15 19:33:55 -04:00
Bill Burke 235ffb2ff6 KEYCLOAK-1960 2015-10-15 18:56:56 -04:00
Bill Burke 181fdeb0d0 KEYCLOAK-1960 2015-10-15 18:54:57 -04:00
Bill Burke 8674578d0d Merge pull request #1730 from patriot1burke/master
KEYCLOAK-1908
2015-10-15 18:32:57 -04:00
Bill Burke 9cf4186eb2 fix arquillian test 2015-10-15 17:56:51 -04:00
Marek Posolda 92ed01a61b Merge pull request #1740 from mposolda/master
Offline tokens fixes & improvements
2015-10-15 23:15:50 +02:00
Bill Burke 99028e9cab Merge remote-tracking branch 'upstream/master' 2015-10-15 16:30:35 -04:00
Bill Burke 20f18eec15 support browser refresh 2015-10-15 16:30:21 -04:00
mposolda 67435791ed KEYCLOAK-1961 revokeRefreshToken support for offline tokens and other fixes 2015-10-15 22:30:17 +02:00
mposolda b4520baee5 KEYCLOAK-1959 Role offline_access was effective only when explicitly added to user 2015-10-15 22:30:17 +02:00
mposolda 802a39b1ce KEYCLOAK-904 Offline session idle timeout + admin console 2015-10-15 22:30:17 +02:00
Stian Thorgersen 229b964867 Merge pull request #1739 from mstruk/cli
KEYCLOAK-1849 Overlay installation scripts not working
2015-10-15 16:26:44 +02:00
mhajas b413bcb41d Unignored test 2015-10-15 14:57:58 +02:00
Marko Strukelj 0c39e30241 KEYCLOAK-1849 Overlay installation scripts not working
- fix unsupported dependency 'org.infinispan:main' warning
2015-10-15 13:46:38 +02:00
Marko Strukelj 11a8d3842e KEYCLOAK-1849 Overlay installation scripts not working 2015-10-15 13:46:38 +02:00
mhajas 2c460c3adc Test password policies using REST 2015-10-15 12:44:27 +02:00
Vlasta Ramik aaddaa6c25 Merge remote-tracking branch 'upstream/master' 2015-10-15 12:30:17 +02:00
Stian Thorgersen 96099e0798 Merge pull request #1732 from stianst/master
KEYCLOAK-1961
2015-10-15 10:57:23 +02:00
Stian Thorgersen e582de2837 KEYCLOAK-1961
Same token can be used multiple times to obtain access token
2015-10-15 09:11:18 +02:00
Stian Thorgersen e1fc863421 Merge pull request #1719 from gautric/french-i18n
French i18n
2015-10-15 08:54:26 +02:00
Stian Thorgersen 7de4051c9b Merge pull request #1737 from thomasdarimont/issue/KEYCLOAK-1918
KEYCLOAK-1918 - Add description field to client definition.
2015-10-15 08:53:47 +02:00
Stian Thorgersen 5b7b5b1b60 Merge pull request #1736 from stianst/test
Add test to make sure expired password is checked on direct grant
2015-10-15 08:53:28 +02:00
Michael Gerber f8effaee58 return null instead of an empty set. 2015-10-15 08:19:18 +02:00
Stian Thorgersen bf7d43fffb Add test to make sure expired password is checked on direct grant 2015-10-15 08:03:54 +02:00
Thomas Darimont 870702fd81 KEYCLOAK-1918 - Add description field to client definition.
Introduced description field with support for i18n for more descriptive client information.
Applications can use the description to display a "slightly" longer gist of
what the client / application is about, especially useful for tooltips.

The description is currently limited to 255 characters.
2015-10-15 07:33:38 +02:00
Stian Thorgersen 2a3e5fa7a4 Merge pull request #1733 from stianst/add-user-to-email-templates
KEYCLOAK-1965
2015-10-15 06:50:51 +02:00
Stian Thorgersen 90063cafec KEYCLOAK-1965
Include the user resource in the attribute map used by email provider freemarker
2015-10-14 20:29:15 +02:00
Stian Thorgersen 2b6fcc05e1 Merge pull request #1731 from stianst/master
Fix docbook
2015-10-14 20:15:54 +02:00
Stian Thorgersen f585ed5582 Fix docbook 2015-10-14 20:15:35 +02:00
Stian Thorgersen 192387047f Merge pull request #1728 from stianst/master
KEYCLOAK-1930
2015-10-14 20:15:00 +02:00
Bill Burke 78664e2571 Merge remote-tracking branch 'upstream/master' 2015-10-14 11:50:02 -04:00
Bill Burke bc71739fb2 Merge pull request #1729 from patriot1burke/master
KEYCLOAK-1839
2015-10-14 11:49:41 -04:00
Bill Burke 5563118d79 KEYCLOAK-1908 2015-10-14 11:49:36 -04:00
Bill Burke aadd63e2b0 Merge remote-tracking branch 'upstream/master' 2015-10-14 10:51:14 -04:00
Bill Burke 59d548228a KEYCLOAK-1839 2015-10-14 10:50:53 -04:00
Marek Posolda 68c3f2f65b Merge pull request #1726 from mposolda/master
KEYCLOAK-904 Offline tokens storage changes. Added UserSessionPersisterProvider . offline sessions preloaded to cache at startup
2015-10-14 14:24:54 +02:00
Stian Thorgersen b54bb25121 KEYCLOAK-1930 2015-10-14 14:22:10 +02:00
Stian Thorgersen 7f65a2be16 Merge pull request #1727 from stianst/master
Disable cli install scripts for overlay
2015-10-14 13:53:23 +02:00
Stian Thorgersen b907f8f92c Disable cli install scripts 2015-10-14 13:52:36 +02:00
Stian Thorgersen 3381ed50d1 KEYCLOAK-1930 2015-10-14 12:36:25 +02:00
mposolda c2c2b835b2 Unable to compile on JDK 7 2015-10-14 11:23:10 +02:00
mposolda f92fe6bea9 KEYCLOAK-904 Offline tokens storage changes. Added UserSessionPersisterProvider . offline sessions preloaded to cache at startup 2015-10-14 11:07:44 +02:00
Stian Thorgersen 6aa029784a Merge pull request #1724 from stianst/master
KEYCLOAK-1849 KEYCLOAK-1958 Fix install scripts for overlays
2015-10-14 09:31:07 +02:00
Stian Thorgersen 325072c74d KEYCLOAK-1849 KEYCLOAK-1958 Fix install scripts for overlays 2015-10-14 09:24:06 +02:00
Stian Thorgersen 1e48143db0 Merge pull request #1723 from stianst/master
KEYCLOAK-1877
2015-10-14 09:23:35 +02:00
Stian Thorgersen 8c72ef2980 KEYCLOAK-1877
Empty bubble in admin event types select box
2015-10-14 07:22:56 +02:00
Stian Thorgersen e7febbd5a5 Merge pull request #1700 from kodemaniak/master
URI based configuration of MongoDB to support Replica Sets
2015-10-14 07:07:03 +02:00
Stian Thorgersen d9211d6bc9 Merge pull request #1718 from lkubik/capitalizeAllLetters
KEYCLOAK-1945
2015-10-14 06:53:24 +02:00
Stian Thorgersen 8121a9391f Merge pull request #1721 from stianst/master
KEYCLOAK-1883
2015-10-14 06:49:23 +02:00
Stian Thorgersen 65b05fd4e4 Merge pull request #1722 from ssilvert/catch-missing-bundle-keys
Catch missing bundle keys
2015-10-14 06:38:40 +02:00
Stan Silvert 940c9f8bf1 KEYCLOAK-1933 Validate resource bundles for admin console 2015-10-13 18:25:14 -04:00
Stian Thorgersen c85e0248dd KEYCLOAK-1883
Improve setting of users locale
2015-10-13 19:47:10 +02:00
Stian Thorgersen 2ec143a3ba Fix tests 2015-10-13 13:17:46 +02:00
Stian Thorgersen a279ff3d7f Merge pull request #1717 from stianst/master
KEYCLOAK-1947 Add tests without client secret
2015-10-13 10:36:42 +02:00
gautric 128c26043b [KEYCLOAK-1903] Add French language support, cross link with other translation 2015-10-13 10:08:34 +02:00
gautric fe9b5a6588 Merge remote-tracking branch 'keycloak/master' into french-i18n 2015-10-13 10:02:04 +02:00
Lukas Kubik 0f93e72b02 KEYCLOAK-1945
Change capitalize function behavior
2015-10-13 09:18:54 +02:00
Stian Thorgersen bdba5ff8b1 KEYCLOAK-1947 Add tests without client secret 2015-10-13 09:02:09 +02:00
Stian Thorgersen 7071161a7c Merge pull request #1716 from stianst/master
KEYCLOAK-1865
2015-10-13 09:00:29 +02:00
Stian Thorgersen 672103e363 KEYCLOAK-1865
Failing tests in testsuite/integration-arquillian
2015-10-13 09:00:12 +02:00
Stian Thorgersen f579d7ffe9 Merge pull request #1715 from stianst/fix-email-removed-profile
KEYCLOAK-1823
2015-10-13 08:58:58 +02:00
Stian Thorgersen d1f0b353e8 Merge pull request #1714 from stianst/master
KEYCLOAK-1335
2015-10-13 08:26:50 +02:00
Stian Thorgersen ef56dca050 KEYCLOAK-1823
Annoying behaviour of validations in user registration form
2015-10-13 08:14:39 +02:00
Stian Thorgersen 07c3772b08 KEYCLOAK-1823
Annoying behaviour of validations in user registration form
2015-10-13 07:36:20 +02:00
Stian Thorgersen 85a886da18 KEYCLOAK-1823
Annoying behaviour of validations in user registration form
2015-10-13 07:30:31 +02:00
Stian Thorgersen 4ce93171ba KEYCLOAK-1335
Slow startup in OpenStack
2015-10-13 07:00:47 +02:00
Stian Thorgersen c987d57b9e Merge pull request #1713 from girirajsharma/master
[KEYCLOAK-1923] It's possible to create new authentication flow with empty name
2015-10-13 06:49:24 +02:00
Stian Thorgersen a416327124 Merge pull request #1712 from gautric/french-i18n
[KEYCLOAK-1903] Add French language support, add and fix some translations
2015-10-13 06:49:05 +02:00
girirajsharma 285ef50341 [KEYCLOAK-1923] It's possible to create new authentication flow with empty name 2015-10-13 00:29:08 +05:30
Stian Thorgersen 0d22074826 Merge pull request #1711 from stianst/remove-zip-export
KEYCLOAK-1944
2015-10-12 19:38:32 +02:00
gautric b76fb68ff7 [KEYCLOAK-1903] Add French language support, 2xSimpleQuote correction 2015-10-12 19:32:04 +02:00
gautric f03128f5ed [KEYCLOAK-1903] Add French language support, 2xSimpleQuote correction 2015-10-12 19:31:07 +02:00
gautric 8fb05bacd1 [KEYCLOAK-1903] Add French language support, correct accent 2015-10-12 19:29:09 +02:00
gautric f8842b3df1 [KEYCLOAK-1903] Add French language support. add and fixes some translation 2015-10-12 19:25:31 +02:00
gautric b376d1fb6d Some fixes into "fr" messages 2015-10-12 16:52:14 +02:00
gautric d4e0901599 Merge remote-tracking branch 'keycloak/master' into french-i18n 2015-10-12 16:27:18 +02:00
Vlasta Ramik 217c359530 Merge remote-tracking branch 'upstream/master' 2015-10-12 15:35:04 +02:00
Stian Thorgersen 4fbf6841be KEYCLOAK-1944
Remove winzipaes import/export provider
2015-10-12 14:43:52 +02:00
Stian Thorgersen 2deb20a2c9 Merge pull request #1710 from stianst/master
Fix for issue introduced by fixing KEYCLOAK-1931
2015-10-12 14:03:57 +02:00
Stian Thorgersen 20b92c410f Fix for issue introduced by fixing KEYCLOAK-1931 2015-10-12 14:03:38 +02:00
Vlasta Ramik 1d829a8365 Merge remote-tracking branch 'upstream/master' 2015-10-12 13:55:36 +02:00
Stian Thorgersen 10b4bd24a4 Merge pull request #1706 from girirajsharma/Patch-Keycloak-1931
[KEYCLOAK-1931] UI doesn't reflect when flow is deleted.
2015-10-12 13:48:45 +02:00
Stian Thorgersen 788501f13d Merge pull request #1704 from AOEpeople/KEYCLOAK-1910
KEYCLOAK-1910, added same fix for registrations endpoint
2015-10-12 13:36:02 +02:00
Carsten Saathoff 345bea50b6 Added documentation about the mongodb:// URI based configuration and how to use a MongoDB replica set. 2015-10-12 13:04:48 +02:00
gautric ab7bfa6d90 Merge remote-tracking branch 'keycloak/master' 2015-10-12 11:45:08 +02:00
Stian Thorgersen 4f7979d9fc Merge pull request #1707 from stianst/client-reg
Refactored client registration service
2015-10-12 11:15:19 +02:00
Stian Thorgersen 286458b94a Merge pull request #1709 from stianst/fix-test-timeouts
Disable failing tests
2015-10-12 10:51:17 +02:00
Stian Thorgersen 61a8c422df Disable failing tests 2015-10-12 09:39:57 +02:00
Stian Thorgersen baaf445727 Merge pull request #1678 from gautric/master
[KEYCLOAK-1903] Add French language support
2015-10-12 08:49:44 +02:00
Stian Thorgersen 2faf0eccdb Refactored client registration service 2015-10-12 08:31:39 +02:00
girirajsharma 639b5b617b [KEYCLOAK-1931] UI doesn't reflect when flow is deleted 2015-10-11 12:42:07 +05:30
girirajsharma 115663a32d [KEYCLOAK-1932] Unable to create flow named exactly the same as removed NON-top level flow 2015-10-11 12:42:07 +05:30
Sebastian Rose b277afa6d9 KEYCLOAK-1910, added same fix for registrations endpoint 2015-10-10 10:40:16 +02:00
Bill Burke 960cd8c822 Merge pull request #1703 from patriot1burke/master
filter docs
2015-10-09 19:02:47 -04:00
Bill Burke 4acc69c604 Merge pull request #1702 from patriot1burke/master
SAML and OIDC Servlet Filter SP
2015-10-09 19:02:18 -04:00
Bill Burke 0230e008c5 filter docs 2015-10-09 18:49:15 -04:00
Bill Burke 382b8d60d0 Merge remote-tracking branch 'upstream/master' 2015-10-09 18:11:53 -04:00
Bill Burke 0ad29c9737 node registration 2015-10-09 18:11:38 -04:00
Bill Burke 9ced56d8d7 saml and oidc filters 2015-10-09 18:07:50 -04:00
Carsten Saathoff eb197c46f7 Setting operational attributes for mongo also when configured via URI. 2015-10-09 15:06:22 +02:00
Stian Thorgersen 63947cd37a Merge pull request #1698 from stianst/master
Renamed 'Keycloak Version to Server Version' on server info page
2015-10-09 13:59:29 +02:00
Stian Thorgersen 938ce9612c Renamed 'Keycloak Version to Server Version' on server info page 2015-10-09 13:59:12 +02:00
Stian Thorgersen d6119c04d6 Merge pull request #1697 from stianst/master
KEYCLOAK-1859 Invalid "Go to the home page" link on the "Resource not…
2015-10-09 13:45:44 +02:00
Stian Thorgersen 14646781ad KEYCLOAK-1859 Invalid "Go to the home page" link on the "Resource not found" page 2015-10-09 13:45:20 +02:00
vramik 1b41832946 fixed verifyEmail test 2015-10-09 13:43:16 +02:00
Stian Thorgersen 57d0bac96a Merge pull request #1696 from stianst/fix-admin-console-not-loading-properly
KEYCLOAK-1876 Some admin console pages don't load properly when accessed via URL
2015-10-09 11:11:03 +02:00
Stian Thorgersen 2ca3ce2dba Merge pull request #1693 from stianst/fix-umlats
KEYCLOAK-1739 User registration form is not able to process diacritics
2015-10-09 10:36:17 +02:00
Stian Thorgersen e5d404fdb3 Remove unused import 2015-10-09 09:54:39 +02:00
Stian Thorgersen 8829fe8658 KEYCLOAK-1739 User registration form is not able to process diacritics 2015-10-09 09:52:25 +02:00
Stian Thorgersen 9ccb0b1f65 Merge pull request #1692 from stianst/fix-json-includes-null
KEYCLOAK-1896 Search for users returns null values
2015-10-09 09:50:30 +02:00
Stian Thorgersen 7bb70f2d00 Merge pull request #1681 from mstruk/i18n
KEYCLOAK-1152 Internationalization support for admin console
2015-10-09 09:50:20 +02:00
Stian Thorgersen 3ab7edbbcd Merge pull request #1695 from stianst/fix-undertow-start
KEYCLOAK-1935 Stop KeycloakServer if Undertow fails to start
2015-10-09 09:49:34 +02:00
Stian Thorgersen d4060cce92 KEYCLOAK-1876 Some admin console pages don't load properly when accessed via URL 2015-10-09 09:44:00 +02:00
Stian Thorgersen 1342904fae KEYCLOAK-1935 Stop KeycloakServer if Undertow fails to start 2015-10-09 09:03:48 +02:00
Stian Thorgersen fc0a3c3e73 Merge pull request #1694 from stianst/master
Fix docbook parent pom artifactId
2015-10-09 08:54:15 +02:00
Stian Thorgersen 756a9f095c Fix docbook parent pom artifactId 2015-10-09 08:53:57 +02:00
Stian Thorgersen 021e48d6d6 Merge pull request #1689 from AOEpeople/KEYCLOAK-1927
KEYCLOAK-1927
2015-10-09 07:06:51 +02:00
Bill Burke 91f78c61b7 Merge pull request #1691 from patriot1burke/master
SAML SP Servlet Filter
2015-10-08 20:50:55 -04:00
Bill Burke d39aee0a72 Merge remote-tracking branch 'upstream/master' 2015-10-08 16:19:56 -04:00
Bill Burke 7c600e2f4b SAML SP Filter 2015-10-08 16:19:43 -04:00
Stan Silvert 14079b950a KEYCLOAK-1933: Validate resource bundles for admin console 2015-10-08 15:23:27 -04:00
Sebastian Rose 173c112f8e KEYCLOAK-1927 2015-10-08 20:34:08 +02:00
Stian Thorgersen 67d8ca0207 KEYCLOAK-1896 Search for users returns null values 2015-10-08 20:15:53 +02:00
Marko Strukelj e690f4e645 KEYCLOAK-1152 Internationalization support for admin console
- Added custom mapper fields localization
2015-10-08 17:11:06 +02:00
Stian Thorgersen 4c554b4af6 Merge pull request #1687 from stianst/client-reg2
KEYCLOAK-1749 Client registration service and client java api
2015-10-08 15:48:58 +02:00
Marko Strukelj 3aee5eeecf KEYCLOAK-1152 Internationalization support for admin console
- Added i18n to 'clients', and 'identity providers' sections
2015-10-08 15:31:03 +02:00
Stian Thorgersen 366a1629e5 KEYCLOAK-1749 Client registration service and client java api 2015-10-08 11:55:42 +02:00
Stian Thorgersen 7fec1677ee Merge pull request #1679 from lkrzyzanek/KEYCLOAK-1904
Add 'register' and 'createRegisterUrl' methods to Javascript Adapter API
2015-10-08 11:51:18 +02:00
Carsten Saathoff 8e391ffa4e After rebase to upstream: Merge branch 'master' of github.com:kodemaniak/keycloak 2015-10-08 10:45:36 +02:00
Carsten Saathoff d65ce5d1d4 Added configuration via mongodb:// uri to mongo provider factory. 2015-10-08 10:44:49 +02:00
Carsten Saathoff 6741dffe38 Added configuration via mongodb:// uri to mongo provider factory. 2015-10-08 10:02:36 +02:00
Stian Thorgersen 894af03323 Merge pull request #1680 from ssilvert/i18n-in-java
KEYCLOAK-1152 i18n for text hard-coded in java source
2015-10-08 06:47:10 +02:00
Bill Burke 80dea9c0bd Merge pull request #1682 from patriot1burke/master
SAML eap adapter and docs
2015-10-07 21:00:33 -04:00
Bill Burke 0b83325470 cleanup 2015-10-07 16:30:42 -04:00
Bill Burke 368ea64b51 Merge remote-tracking branch 'upstream/master' 2015-10-07 16:21:13 -04:00
Bill Burke 450e031da9 saml adapter docs 2015-10-07 16:20:59 -04:00
Marek Posolda 1796a45a68 Merge pull request #1677 from mkdgit/Customized_LDAP_filter_1_6
KEYCLOAK-1906 : Customized LDAP filter
2015-10-07 22:05:30 +02:00
Stan Silvert c9437595b7 KEYCLOAK-1152 i18n for text hard-coded in java source
(ProtocolMapperUtils)
2015-10-07 11:34:34 -04:00
Bill Burke a1b315adbd Merge remote-tracking branch 'upstream/master' 2015-10-07 10:19:26 -04:00
Bill Burke 1781588597 as7/eap saml adapter 2015-10-07 10:19:15 -04:00
Libor Krzyzanek f29aff4bed Add 'register' and 'createRegisterUrl' methods to Javascript Adapter API. fixes #KEYCLOAK-1904 2015-10-07 13:53:25 +02:00
Stian Thorgersen ac91839e69 Merge pull request #1663 from thomasdarimont/issue/KEYCLOAK-1893
KEYCLOAK-1893 - Allow to configure OTP period in admin console.
2015-10-07 09:35:59 +02:00
Stian Thorgersen 9c0c8e37b6 Merge pull request #1676 from Smartling/KEYCLOAK-1901
KEYCLOAK-1901: Add a Keycloak client builder
2015-10-07 09:06:19 +02:00
Bill Burke d40237b08d saml adapters docs/dist 2015-10-06 15:56:44 -04:00
gautric 59527e12f0 [KEYCLOAK-1903] Add French language support, few fixes 2015-10-06 20:01:04 +02:00
gautric 6d0483667f [KEYCLOAK-1903] Add French language support 2015-10-06 18:09:36 +02:00
gautric dcf8747d7e Merge remote-tracking branch 'keycloak/master' 2015-10-06 16:32:11 +02:00
Stian Thorgersen 7a3b4823b0 Merge pull request #1662 from Smartling/KEYCLOAK-1892
WrappedHttpServletRequest may throw an exception returning cookies
2015-10-06 14:58:54 +02:00
Stian Thorgersen 64ecc3b153 Merge pull request #1672 from ssilvert/KEYCLOAK-1882-add-locale-mapper-on-new-realm
KEYCLOAK-1882 Also add locale mapper when new realm is created.
2015-10-06 14:58:27 +02:00
Stian Thorgersen cc41a1fd78 Merge pull request #1656 from gerbermichi/import2
swap import and migrate order (KEYCLOAK-1884)
2015-10-06 12:05:59 +02:00
gautric 255b1cb3bf Merge remote-tracking branch 'keycloak/master' 2015-10-06 10:25:23 +02:00
Michal Drela a1bb202bd4 Customized LDAP filter 2015-10-06 10:01:29 +02:00
Scott Rossillo 332e3f6099 KEYCLOAK-1901: Add a Keycloak client builder
Adds support for creating a Keycloak client using the builder
pattern and supports customizing the underlying ResteasyClient
used for connecting to the Keycloak server.
2015-10-05 14:56:38 -04:00
Bill Burke 6b41d79058 Merge pull request #1675 from patriot1burke/master
saml adapter doc module
2015-10-05 13:34:53 -04:00
Bill Burke 3b4b5c11e6 Merge remote-tracking branch 'upstream/master' 2015-10-05 13:33:55 -04:00
Bill Burke 0c9e764e11 move docs 2015-10-05 13:33:38 -04:00
Marek Posolda 00cbc22d8b Merge pull request #1674 from girirajsharma/master
[KEYCLOAK-1864] No names for required actions
2015-10-05 08:56:26 +02:00
girirajsharma 0a3de09b5a [KEYCLOAK-1864] No names for required actions 2015-10-04 23:44:44 +05:30
Bill Burke 4e0ad5ac0b Merge pull request #1673 from patriot1burke/master
saml adapter schema and simplifications
2015-10-02 21:16:34 -04:00
Bill Burke 72256fd6ac Merge remote-tracking branch 'upstream/master' 2015-10-02 18:40:05 -04:00
Bill Burke d06237a3fd saml adapter schema and simplifications 2015-10-02 18:39:50 -04:00
Stan Silvert 28fad68486 KEYCLOAK-1882 Also add locale mapper when new realm is created. 2015-10-02 15:01:39 -04:00
Stian Thorgersen 53b86cbace Merge pull request #1671 from stianst/master
KEYCLOAK-1882 Add locale mapper to admin console clients during migra…
2015-10-02 15:09:43 +02:00
Stian Thorgersen a53aebcddf KEYCLOAK-1882 Add locale mapper to admin console clients during migration 2015-10-02 13:43:41 +02:00
Marek Posolda af307c695a Merge pull request #1670 from mposolda/master
KEYCLOAK-1856 KEYCLOAK-1860 Fix onoffswitchvalue directive
2015-10-02 11:58:04 +02:00
mposolda 7816f053a6 KEYCLOAK-1856 KEYCLOAK-1860 Fix onoffswitchvalue directive 2015-10-02 11:09:54 +02:00
Bill Burke ed54ba9064 Merge pull request #1669 from patriot1burke/master
keycloak-common
2015-10-01 16:03:20 -04:00
Bill Burke 8acdaf462b fix arquillian 2015-10-01 15:14:16 -04:00
Bill Burke c5efd34a46 Merge remote-tracking branch 'upstream/master' 2015-10-01 14:28:04 -04:00
Bill Burke 75343986b0 keycloak-common 2015-10-01 14:27:51 -04:00
Stian Thorgersen 424d357c9c Merge pull request #1668 from vramik/master
arquillian-testsuite: fixed org.keycloak.services.ForbiddenException in test log
2015-10-01 16:35:29 +02:00
Stian Thorgersen 56116038d6 Merge pull request #1667 from stianst/fb-fix
KEYCLOAK-1894 Fix login with Facebook missing profile details
2015-10-01 13:37:57 +02:00
Stian Thorgersen c76da8f3b8 Merge pull request #1666 from stianst/migration-fix
Fix db migration not running as latest jpa version wasn't updated
2015-10-01 13:37:49 +02:00
Stian Thorgersen 589eb3206e KEYCLOAK-1894 Fix login with Facebook missing profile details 2015-10-01 11:54:14 +02:00
Stian Thorgersen 5419ec32e4 Fix db migration not running as latest jpa version wasn't updated 2015-10-01 09:01:06 +02:00
Stian Thorgersen c9e0a7a97d Merge pull request #1657 from stianst/zxing
KEYCLOAK-1888
2015-10-01 08:07:43 +02:00
Bill Burke 5b5f99fdfe Merge pull request #1665 from patriot1burke/master
saml wildfly sp/dist
2015-09-30 17:41:41 -04:00
Bill Burke d3bd0a67a7 saml example docs 2015-09-30 16:51:21 -04:00
Bill Burke 2a36185419 Merge remote-tracking branch 'upstream/master' 2015-09-30 16:36:42 -04:00
Bill Burke 76e3c6394c saml sp distro 2015-09-30 16:36:21 -04:00
Thomas Darimont 9e15b20591 KEYCLOAK-1893 - Allow to configure OTP period in admin console.
Added input form that allows to specify the OTP token period
in the `OTP Policy` section of the `Authentication` settings.

Since the value is already backed by the provided `otpPolicyPeriod`
field in the `RealmRepresentation` class we only needed to show the value
in the admin ui.
2015-09-30 21:07:06 +02:00
Scott Rossillo 05bd51ac1c WrappedHttpServletRequest may throw an exception returning cookies
HttpServletRequest.getCookies() may return null
2015-09-30 14:31:15 -04:00
Bill Burke d648ba73de wildfly saml distro 2015-09-30 11:56:21 -04:00
Marek Posolda c6b34f32a1 Merge pull request #1660 from mposolda/master
Fixes
2015-09-30 17:16:44 +02:00
Stian Thorgersen 974c0a50e7 Merge pull request #1659 from stianst/liquibase
KEYCLOAK-1890
2015-09-30 17:05:30 +02:00
Bill Burke 07d3b26722 Merge remote-tracking branch 'upstream/master' 2015-09-30 11:01:55 -04:00
Bill Burke 510b03476f saml distro 2015-09-30 11:01:45 -04:00
mposolda 4f6d3c8dca KEYCLOAK-1815 Reduce info logging 2015-09-30 16:35:56 +02:00
mposolda 95fe2fe74b KEYCLOAK-904 offline tokens - migration 2015-09-30 16:35:56 +02:00
Stian Thorgersen e937216cf7 KEYCLOAK-1888
Upgrade ZXing dependency
2015-09-30 15:03:02 +02:00
Stian Thorgersen fd8d93663e KEYCLOAK-1890
Upgrade to Liquibase 3.4.1
2015-09-30 15:02:30 +02:00
Stian Thorgersen a048cfc102 Fix merge error 2015-09-30 15:00:35 +02:00
Stian Thorgersen 272272634d KEYCLOAK-1889
Upgrade FreeMarker dependency
2015-09-30 14:58:02 +02:00
Stian Thorgersen 01947f46b9 Merge pull request #1655 from stianst/twitter4j
KEYCLOAK-1887 Upgrade Twitter4j dependency
2015-09-30 14:49:24 +02:00
Bill Burke 5ec73a81e9 Merge pull request #1651 from patriot1burke/master
wf saml adapter first iter
2015-09-30 08:39:45 -04:00
vramik 4cba764ac3 add view-realm role to test user for test realm to avoid org.keycloak.services.ForbiddenException in test log 2015-09-30 14:23:24 +02:00
Stian Thorgersen 84b9963609 Merge pull request #1654 from stianst/master
Set product name/version in keycloak-paren pom
2015-09-30 14:21:39 +02:00
Stian Thorgersen 99c216635f KEYCLOAK-1887
Upgrade Twitter4j dependency
2015-09-30 14:08:21 +02:00
Stian Thorgersen 25a6fcc382 Set product name/version in keycloak-paren pom 2015-09-30 13:41:37 +02:00
Michael Gerber acefd3cacd swap import and migrate order 2015-09-30 13:31:22 +02:00
Marek Posolda 15a5c87cc5 Merge pull request #1653 from mposolda/master
KEYCLOAK-904 offline tokens - example, refactoring, polishing
2015-09-30 12:37:18 +02:00
mposolda 3044138e10 Fix compilation errors 2015-09-30 10:51:53 +02:00
mposolda 6fbb8ccf71 KEYCLOAK-904 Offline tokens - model changes, admin console, export/import, docs 2015-09-30 10:51:36 +02:00
mposolda 018866aa81 KEYCLOAK-904 Offline portal example added 2015-09-30 09:23:23 +02:00
Bill Burke 18b2b572ac fix compilation errors 2015-09-29 20:38:10 -04:00
Bill Burke d9e67aa5ee Merge remote-tracking branch 'upstream/master' 2015-09-29 20:26:16 -04:00
Bill Burke e675ce44d5 Merge remote-tracking branch 'upstream/master' 2015-09-29 20:25:28 -04:00
Bill Burke df46a8ea0d Merge pull request #1647 from patriot1burke/master
tomcat 7 and 8 SAML adapter tests
2015-09-29 20:25:19 -04:00
Bill Burke e277d5b55e wf saml adapter 2015-09-29 20:24:59 -04:00
Stian Thorgersen 4bd1d899db Merge pull request #1618 from ssilvert/i18n
KEYCLOAK-1152: i18n using angular-translate
2015-09-29 14:57:24 +02:00
Stian Thorgersen 3e3d92c2e4 Merge pull request #1650 from stianst/client-reg2
KEYCLOAK-1868 Import clients through admin console
2015-09-29 14:12:59 +02:00
Stian Thorgersen 55deedd3b8 KEYCLOAK-1868 Import clients through admin console
KEYCLOAK-1869 Add root url to clients that should be used to resolve relative urls
2015-09-29 12:16:05 +02:00
Stian Thorgersen 8b6251eb23 Merge pull request #1649 from eugene-chow/master
Updated documentation for "Server Installation > Installing Keycloak Server as Root Context"
2015-09-29 08:59:54 +02:00
Stian Thorgersen 35919da0a4 Merge pull request #1645 from mhajas/master
Arquillian testsuite refactoring
2015-09-29 08:59:09 +02:00
Eugene Chow ec018d2739 Updated documentation for "Server Installation > Installing Keycloak Server as Root Context" to work with Keycloak 1.5 2015-09-29 10:32:16 +08:00
Bill Burke b1a23a13d6 jetty saml fixes 2015-09-28 16:30:03 -04:00
Bill Burke 3ebbe96786 Merge remote-tracking branch 'upstream/master' 2015-09-28 16:05:22 -04:00
Bill Burke cfaa4c60c9 jetty saml adapter 2015-09-28 16:05:07 -04:00
Stian Thorgersen e104450fc8 Merge pull request #1648 from girirajsharma/master
[KEYCLOAK-1880] Admin API Doesn't Detect Null Client
2015-09-28 09:06:26 +02:00
girirajsharma c22b0f4da8 [KEYCLOAK-1880] Admin API Doesn't Detect Null Client 2015-09-27 14:57:16 +05:30
Stan Silvert 302d0b58cc Get locale from token via builtin mapper. 2015-09-26 20:11:06 -04:00
Bill Burke 72999f0acb fix tomcat test shutdown 2015-09-25 17:32:19 -04:00
Bill Burke a942322d99 Merge pull request #1646 from patriot1burke/master
tomcat 6 saml adapter
2015-09-25 15:51:37 -04:00
Bill Burke 8902502c4d tomcat8 saml tests 2015-09-25 15:49:40 -04:00
Bill Burke 8d19741f53 tomcat 7 saml adapter 2015-09-25 15:45:16 -04:00
Bill Burke e60549d764 fix poms 2015-09-25 15:17:51 -04:00
Bill Burke 0a42a28eeb Merge remote-tracking branch 'upstream/master' 2015-09-25 15:12:34 -04:00
Bill Burke 88355d7eb4 tomcat6 adapter 2015-09-25 15:12:14 -04:00
mhajas 67db5917ac Merge remote-tracking branch 'upstream/master' 2015-09-25 09:30:58 +02:00
mhajas 8f1daf5d77 Refactoring 2015-09-25 09:10:17 +02:00
Stian Thorgersen 6d5e3b2a17 Merge pull request #1643 from stianst/master
KEYCLOAK-1878
2015-09-25 07:37:23 +02:00
Stian Thorgersen 75c0d5089f KEYCLOAK-1878
Add Base64 to Keycloak core
2015-09-25 07:02:25 +02:00
Tomas Kyjovsky 5b1fcbfc51 Merge pull request #1642 from tkyjovsk/master
FIxed compilation error of arquillian tests by adding keycloak-adapte…
2015-09-24 22:46:29 +02:00
Tomas Kyjovsky 0c80255f3a FIxed compilation error of arquillian tests by adding keycloak-adapter-spi dependency. 2015-09-24 21:57:02 +02:00
Stan Silvert 121f8e9174 Converted some more pages to user ng-translate. 2015-09-24 15:35:37 -04:00
Bill Burke c1cb50b39f Merge pull request #1641 from patriot1burke/master
initial saml sp adapter
2015-09-24 14:23:05 -04:00
Bill Burke 791a740f32 Merge remote-tracking branch 'upstream/master' 2015-09-24 12:05:24 -04:00
Bill Burke 546cdd7d8f fix modules for refactor 2015-09-24 12:05:12 -04:00
Stian Thorgersen 8ef6602f82 Merge pull request #1640 from stianst/master
Removed unused netty dependency from keycloak parent
2015-09-24 09:16:33 +02:00
Stian Thorgersen 2938759db4 Removed unused files from common/lib theme 2015-09-24 08:37:01 +02:00
Stian Thorgersen f7bcca8553 Removed unused netty dependency from keycloak parent 2015-09-24 08:05:34 +02:00
Stian Thorgersen 4eaf893492 Merge pull request #1610 from raehalme/KEYCLOAK-1828
KEYCLOAK-1828 attemptAuthentication throws KeycloakAuthenticationException if authentication fails
2015-09-24 06:32:27 +02:00
Stian Thorgersen 0ba6ab198a Merge pull request #1611 from raehalme/KEYCLOAK-1829
KEYCLOAK-1829 unsuccessfulAuthentication now returns HTTP response status 401 instead of 403
2015-09-24 06:31:33 +02:00
Bill Burke 49a530f2b4 merge 2015-09-23 21:13:42 -04:00
Bill Burke c14d3d7963 merge conflicts 2015-09-23 21:01:47 -04:00
Bill Burke fe26d6ecec more 2015-09-23 20:54:27 -04:00
Bill Burke 35a00b449d all tests 2015-09-23 20:45:20 -04:00
Bill Burke 1e9c09d23a more complete 2015-09-23 17:54:16 -04:00
Stian Thorgersen ec4f8a7f15 Merge pull request #1639 from stianst/master
Make it possible to set hibernate spec artifact id with a property in…
2015-09-23 20:36:58 +02:00
Stian Thorgersen d109bf7b56 Updated release process to use maven release plugin 2015-09-23 15:50:25 +02:00
Stian Thorgersen 4625ab917d Merge pull request #1636 from vramik/master
arquillian-testsuite: Suppress error from GreenMail on shutdown, login settings test coverage
2015-09-23 15:37:12 +02:00
Stian Thorgersen 7d239f8990 Make it possible to set hibernate spec artifact id with a property in parent pom 2015-09-23 15:36:40 +02:00
Marek Posolda 22f7efd977 Merge pull request #1638 from mposolda/master
KEYCLOAK-904 Consents support. Added scopeParamRequired flag to RoleM…
2015-09-23 15:30:36 +02:00
mposolda 2a349673b9 Fix integration-arquillian 2015-09-23 14:47:20 +02:00
Vlasta Ramik 361019fc6a Merge remote-tracking branch 'upstream/master' 2015-09-23 13:07:48 +02:00
vramik abb099745f added test coverage of login settings 2015-09-23 13:07:30 +02:00
mposolda 046edbbd54 KEYCLOAK-904 Consents support. Added scopeParamRequired flag to RoleModel 2015-09-23 12:52:47 +02:00
Stian Thorgersen 8cc4c8c5e2 Merge pull request #1635 from stianst/realm-import
KEYCLOAK-1866
2015-09-23 11:45:56 +02:00
Vlasta Ramik d2d3a3f216 Merge remote-tracking branch 'upstream/master' 2015-09-23 11:23:57 +02:00
vramik cbf5c920ea Suppress error from GreenMail on shutdown 2015-09-23 11:21:48 +02:00
Stian Thorgersen 7ac1d1f14c KEYCLOAK-1866
Allow changing name and view details of imported realm
2015-09-23 11:08:53 +02:00
vramik e811b87679 moved smtp server configuration to suiteContext 2015-09-23 10:50:49 +02:00
Stian Thorgersen d08fca4e0a Merge pull request #1625 from girirajsharma/master
[KEYCLOAK-1787] Confirming password policy values with ENTER key deletes the first item in the table.
2015-09-23 08:33:07 +02:00
Stian Thorgersen 30aa41a2ee Merge pull request #1633 from stianst/update-username
KEYCLOAK-1857 Allow users to edit username on first login
2015-09-23 08:26:03 +02:00
Stian Thorgersen 9d8d690100 KEYCLOAK-1857 Prefill update profile form with username from user or formdata 2015-09-23 07:43:38 +02:00
dcampagna 43541d3028 Show error when username already exists (KEYCLOAK-1857) 2015-09-23 07:43:38 +02:00
dcampagna 880e831e71 Removed comment (KEYCLOAK-1857) 2015-09-23 07:43:38 +02:00
dcampagna fe2278b320 Fix broken tests (KEYCLOAK-1857) 2015-09-23 07:43:38 +02:00
dcampagna f7a8bbbcc8 Allow username change at first login (KEYCLOAK-1857) 2015-09-23 07:43:38 +02:00
dcampagna fde4bc99aa Allow username change at first login (KEYCLOAK-1849) 2015-09-23 07:43:38 +02:00
Bill Burke cc9d6d0cf7 saml undertow sp 2015-09-22 20:27:08 -04:00
Marek Posolda b17bbc9b86 Merge pull request #1634 from pdrozd/sync-ldap-sleep
Added configurable sleep time
2015-09-22 16:18:45 +02:00
Pavel Drozd d4c5349e1a Added configurable sleep time 2015-09-22 15:29:21 +02:00
Bill Burke 2865a3c047 Merge pull request #1626 from dbarentine/master
KEYCLOAK-1861 Allow setting of signature algorithm when signing SAML …
2015-09-22 08:37:46 -04:00
Marek Posolda 522fc7412c Merge pull request #1632 from mposolda/master
KEYCLOAK-904 Offline tokens - step 1
2015-09-21 12:06:33 +02:00
mposolda 7ec3f86efb KEYCLOAK-904 Offline tokens 2015-09-21 10:28:30 +02:00
mposolda c11539cccb docs and javadoc fixes 2015-09-21 10:13:41 +02:00
Stian Thorgersen 09488b8df3 Merge pull request #1629 from tkyjovsk/master-squashed
Updates and refactoring of arquillian testsuite.
2015-09-18 15:12:12 +02:00
Tomas Kyjovsky e16cc493d2 Updates and refactoring of arquillian testsuite. 2015-09-18 14:27:28 +02:00
Stian Thorgersen 379fc8961e Merge pull request #1628 from stianst/master
Configure maven release plugin
2015-09-18 13:24:31 +02:00
Stian Thorgersen 43114f176b Configure maven release plugin 2015-09-18 13:23:54 +02:00
Stian Thorgersen f01d959f7c Merge pull request #1624 from tkyjovsk/serial-versions
Removed occurences of serialVersionUID from all classes.
2015-09-18 13:03:37 +02:00
Stian Thorgersen 28f4409768 Merge pull request #1623 from mstruk/asciidoc
KEYCLOAK-1241 Can't build release with Java 8
2015-09-18 13:03:02 +02:00
Stian Thorgersen 364aecda2a Merge pull request #1627 from stianst/master
KEYCLOAK-1858
2015-09-18 13:02:38 +02:00
Stian Thorgersen 9bfbac6be5 KEYCLOAK-1858
JavaDoc aggregate fails during release if build not already executed
2015-09-18 10:11:51 +02:00
Dane Barentine db20fd9eeb KEYCLOAK-1861 Allow setting of signature algorithm when signing SAML AuthnRequests to IDPs 2015-09-17 15:55:59 -07:00
Giriraj Sharma 53a198fde8 [KEYCLOAK-1787] Confirming password policy values with ENTER key deletes the first item in table 2015-09-17 23:56:17 +05:30
Bill Burke 861a13501a merge 2015-09-17 14:25:16 -04:00
Bill Burke 0f24bd2ea4 merge 2015-09-17 14:06:33 -04:00
Bill Burke 9dc54815eb Merge pull request #1616 from dbarentine/master
Bug fixes
2015-09-17 14:01:13 -04:00
Bill Burke cb8ca619ae saml sp 2015-09-17 14:00:57 -04:00
Tomas Kyjovsky ac91deac96 Removed occurences of serialVersionUID from all classes. 2015-09-17 17:27:39 +02:00
Marko Strukelj 71e2be5d3d KEYCLOAK-1241 Can't build release with Java 8
- Fix Null title in some build environments
2015-09-17 14:10:15 +02:00
Stian Thorgersen 4878073867 Merge pull request #1587 from mstruk/asciidoc
KEYCLOAK-1241 Can't build release with Java 8
2015-09-17 09:06:22 +02:00
Stian Thorgersen dc327ddddb Merge pull request #1621 from stianst/master
KEYCLOAK-1854
2015-09-17 08:36:08 +02:00
Stian Thorgersen e6467403ef Merge pull request #1600 from cfsnyder/master
KEYCLOAK-1807 Fix bug with commas in regex password policies
2015-09-17 08:26:56 +02:00
Stian Thorgersen cf0fab2d66 Merge pull request #1620 from lkubik/unifyJetty8Versions
Unify jetty 8.1 artifacts version with fabric8-bom-1.2.0.redhat-133.pom
2015-09-17 08:23:22 +02:00
Stian Thorgersen 2eaa03539c KEYCLOAK-1854
NPE in SystemInfoRepresentation if user.country or user.language not set
2015-09-17 07:38:37 +02:00
Lukas Kubik b7e49dc88d Unify jetty 8.1 artifacts version with fabric8-bom-1.2.0.redhat-133.pom 2015-09-16 17:14:29 +02:00
Marek Posolda ca05455aa0 Merge pull request #1619 from mstruk/kerberos
KEYCLOAK-1852 Improve Kerberos example documentation
2015-09-16 15:08:50 +02:00
Stian Thorgersen 7ae3eb8321 Merge pull request #1615 from ssilvert/breadcrumbs
Fix breadcrumbs.
2015-09-16 14:16:14 +02:00
Stan Silvert ae54babbbb Update client-credentials-jwt-key-import.html 2015-09-16 07:40:30 -04:00
Stan Silvert a8378fe84b Update client-credentials-jwt-key-export.html 2015-09-16 07:40:14 -04:00
Stian Thorgersen 85df0b6a67 Merge pull request #1613 from raehalme/KEYCLOAK-1832
KEYCLOAK-1832 Added check for null authentication on the logout method
2015-09-16 13:34:51 +02:00
Marko Strukelj 95967b9c79 KEYCLOAK-1852 Improve Kerberos example documentation and user experience 2015-09-16 12:22:56 +02:00
Marko Strukelj 8396b999a2 KEYCLOAK-1241 Can't build release with Java 8
- Speed up build by only building REST API doc during -Pjboss-release
2015-09-16 11:53:53 +02:00
Marko Strukelj 3bbe82057c KEYCLOAK-1241 Can't build release with Java 8
- Improve javadoc comments for new REST API documentation generation
2015-09-15 21:22:43 +02:00
Marko Strukelj 0c49fce78f KEYCLOAK-1241 Can't build release with Java 8 2015-09-15 21:22:43 +02:00
Stian Thorgersen f9af8ba1a0 Merge pull request #1614 from stianst/master
Fixes
2015-09-15 13:40:04 +02:00
Dane Barentine 80f91b5fa5 KEYCLOAK-1848 Fix consuming of metadata when EntityDescriptor includes multiple Descriptors 2015-09-14 15:04:54 -07:00
Dane Barentine 6478e8f5c7 KEYCLOAK-1847 Per SAML Spec 3.4.4.1 SigAlg in redirect binding should be URI not Java signature algorithm 2015-09-14 15:02:27 -07:00
Dane Barentine 55dc42e147 KEYCLOAK-1491 AttributeStatement must contain one or more attribute or encryptedattribute statements 2015-09-14 15:00:41 -07:00
Dane Barentine f55ab0d689 KEYCLOAK-1846 Per SAML spec 6.2 Encrypting assertions must happen after the assertions are signed 2015-09-14 15:00:41 -07:00
Dane Barentine fe79c9b01e KEYCLOAK-1845 Fixed relative path error which was omitting the themes on the EAP overlay 2015-09-14 14:58:56 -07:00
Dane Barentine 6291e90f9c KEYCLOAK-1844 Login endpoint needs to handle POST as well for SAML clients using HTTP-POST binding 2015-09-14 14:57:38 -07:00
Stan Silvert a32fefb597 Fix breadcrumbs. 2015-09-14 14:28:32 -04:00
Cory Snyder 3e04d045ee KEYCLOAK-1807 Fix bug with commas in regex password policies by using alternate way to declare multiple regex patterns 2015-09-11 11:00:31 -04:00
Stian Thorgersen fb4645a3dc KEYCLOAK-1833 Fix error messages for identity brokering 2015-09-10 21:15:55 +02:00
Thomas Raehalme e0eac89e5a Added check for null authentication on the logout method. 2015-09-10 12:30:07 +03:00
Thomas Raehalme 90d34bfd06 unsuccessfulAuthentication now returns HTTP response status 401 instead of 403. 2015-09-09 18:31:25 +03:00
Thomas Raehalme e58b5762f3 attemptAuthentication now throws KeycloakAuthenticationException if authentication fails.
Also authenticationFailureHandler is by default set to SimpleUrlAuthenticationFailureHandler
with default login url set to /sso/login.
2015-09-09 15:45:13 +03:00
Stian Thorgersen 3fd4d23bed Version bump 2015-09-09 11:27:21 +02:00
Marek Posolda 1c38bb7158 Merge pull request #1609 from mposolda/master
KEYCLOAK-1824 ClientIdAndSecretCredentialsProvider not found when dep…
2015-09-08 23:45:04 +02:00
mposolda 149ef706dd KEYCLOAK-1824 ClientIdAndSecretCredentialsProvider not found when deploying Fuse examples 2015-09-08 22:55:43 +02:00
Stan Silvert 75bd8d4627 Load admin messages through Themes. 2015-09-08 15:22:50 -04:00
Marek Posolda f1c40dd345 Merge pull request #1608 from mposolda/master
KEYCLOAK-1826
2015-09-08 21:01:52 +02:00
mposolda 6225ccfc06 KEYCLOAK-1826 2015-09-08 21:00:42 +02:00
Marek Posolda 34de631b2a Merge pull request #1607 from mposolda/master
KEYCLOAK-1821 KEYCLOAK-1825 Migration and export/import of clientAuth…
2015-09-08 20:28:04 +02:00
mposolda 86f0092622 KEYCLOAK-1821 KEYCLOAK-1825 Migration and export/import of clientAuthFlow + resetCredentialsFlow 2015-09-08 19:53:35 +02:00
Stan Silvert e455cbf319 Add new getMessages() method to Theme interface. 2015-09-08 13:28:17 -04:00
Stan Silvert cee2d69718 Update for use with Angualr 1.4 anti-watch feature. Also, limit sanitize
to params.  This avoids issue with Unicode.
2015-09-08 12:57:22 -04:00
Stan Silvert ff17123123 i18n for onoffswitch 2015-09-08 12:57:21 -04:00
Stan Silvert e118a06a09 Bundles now read from base theme instead of from classpath. Bundle names
no longer hard-coded.
2015-09-08 12:57:20 -04:00
Stan Silvert 4898d74c6d KEYCLOAK-1152 Initial commit for i18n support 2015-09-08 12:57:19 -04:00
Marek Posolda 76f3842dad Merge pull request #1606 from mposolda/master
Fix service-account demo app on EAP 6.4
2015-09-08 17:22:29 +02:00
mposolda d818ebdd9e Fix service-account demo app on EAP 6.4 2015-09-08 16:41:27 +02:00
Stian Thorgersen 4d90898dd9 Merge pull request #1605 from stianst/master
KEYCLOAK-1818
2015-09-08 09:56:06 +02:00
Stian Thorgersen 298b9e01d8 KEYCLOAK-1818
Authenticator example doesn't work when deployed as a module
2015-09-08 09:55:45 +02:00
Marek Posolda d0b08cacd8 Merge pull request #1604 from mposolda/master
KEYCLOAK-1811 Pluggable client authentication config through adapter …
2015-09-08 00:12:49 +02:00
mposolda 050c65a520 KEYCLOAK-1811 Pluggable client authentication config through adapter subsystem 2015-09-07 23:30:08 +02:00
Bill Burke be0c359160 adapter refactor 2015-09-07 10:27:57 -04:00
Bill Burke 3f792030d3 adapter refactor 2015-09-07 10:26:25 -04:00
Stian Thorgersen 5c2fc1120b Merge pull request #1603 from stianst/master
KEYCLOAK-1816
2015-09-07 13:32:29 +02:00
Stian Thorgersen 3d2acbe780 KEYCLOAK-1816
LocaleHelper prints info 'Locale en is not supported'
2015-09-07 13:02:52 +02:00
Stian Thorgersen bce0e0ea90 Merge pull request #1602 from stianst/master
Fixes
2015-09-07 10:36:48 +02:00
Stian Thorgersen 931102ff26 KEYCLOAK-1808
Revoke Grant button should disappear
2015-09-07 10:08:32 +02:00
Stian Thorgersen 5a3938d12f KEYCLOAK-1806
oauth-client example fails if you say no to grant
2015-09-07 09:59:32 +02:00
Stian Thorgersen dca1751a63 KEYCLOAK-1812 View user attributes in admin console doesn't work 2015-09-07 09:40:34 +02:00
Stian Thorgersen f6ec9af61e KEYCLOAK-1805
address theme causes exception for login theme
2015-09-07 09:33:34 +02:00
Stian Thorgersen 64f2f84ffa Merge pull request #1599 from stianst/master
KEYCLOAK-1804
2015-09-07 08:51:01 +02:00
Marek Posolda 5df5e53f11 Merge pull request #1601 from mposolda/master
KEYCLOAK-1799 Download adapter JSON config with proper adapter
2015-09-07 08:36:53 +02:00
mposolda 81f4c50574 KEYCLOAK-1799 Download adapter JSON config with proper adapter 2015-09-04 22:23:01 +02:00
Marek Posolda 2550d16127 Merge pull request #1598 from mposolda/master
KEYCLOAK-1801 Additional fix and cleanup
2015-09-04 22:21:37 +02:00
Bill Burke 333ad0efac refactor adapters 2015-09-04 15:56:28 -04:00
Stian Thorgersen f3675681c3 KEYCLOAK-1804
Replace -snapshot with startup time in resource urls
2015-09-04 16:55:32 +02:00
Stian Thorgersen 28de8dc5b7 Merge pull request #1597 from mstruk/KEYCLOAK-1779
KEYCLOAK-1779 NPE due to missing web.xml/jboss-web.xml
2015-09-04 16:14:55 +02:00
mposolda 35e63a9398 KEYCLOAK-1801 Additional fix and cleanup 2015-09-04 15:19:43 +02:00
Stian Thorgersen f23f1cc813 Merge pull request #1596 from stianst/master
KEYCLOAK-1803
2015-09-04 14:22:07 +02:00
Marko Strukelj b0095154d1 KEYCLOAK-1779 NPE due to missing web.xml/jboss-web.xml
- improved code readability and npe fix
2015-09-04 14:18:57 +02:00
Stian Thorgersen 79ea9ed314 KEYCLOAK-1803
On/off switches in mappers doesn't work
2015-09-04 14:17:30 +02:00
Marek Posolda 413db0dce1 Merge pull request #1595 from mposolda/master
Add 'Testsuite' prefix to the dummy providers used for testing only
2015-09-04 13:53:10 +02:00
William DeCoste e6745532ce KEYCLOAK-1779 2015-09-04 13:52:25 +02:00
Stian Thorgersen 59da0f90f8 Merge pull request #1594 from stianst/master
KEYCLOAK-1801
2015-09-04 13:37:32 +02:00
mposolda 76f0f52ee3 Add 'Testsuite' prefix to the dummy providers used for testing only 2015-09-04 13:17:20 +02:00
Stian Thorgersen 73c230f1ca KEYCLOAK-1801
Suggestions to improving client credentials tab
2015-09-04 12:55:25 +02:00
Marek Posolda ddee72c756 Merge pull request #1593 from mposolda/master
KEYCLOAK-1802
2015-09-04 12:46:15 +02:00
mposolda 6318964374 KEYCLOAK-1802 2015-09-04 12:21:45 +02:00
Stian Thorgersen 853f1af40d Merge pull request #1592 from stianst/master
KEYCLOAK-1794 Admin console issues with kc-provider-config directive
2015-09-04 11:43:30 +02:00
Stian Thorgersen d429b2151a KEYCLOAK-1800
Save buttons not aligned correctly on otp-policy and flow-bindings pages
2015-09-04 10:14:55 +02:00
Stian Thorgersen b223e1a7af KEYCLOAK-1794 Admin console issues with kc-provider-config directive 2015-09-04 09:59:48 +02:00
Stian Thorgersen c806b8911e Merge pull request #1590 from stianst/master
KEYCLOAK-1796 Tabs on Keycloak identity provider shown twice
2015-09-04 08:59:16 +02:00
Stian Thorgersen 9f30a51925 KEYCLOAK-1796 Tabs on Keycloak identity provider shown twice 2015-09-04 08:32:00 +02:00
Stian Thorgersen a8b7129269 Merge pull request #1585 from stianst/master
KEYCLOAK-1793 Remove cancel button on login and login-totp
2015-09-04 08:19:27 +02:00
Stian Thorgersen 991b0e8ee2 Merge pull request #1586 from suchabar/bsuchano-branch
My first PR - addition of extra info to Readme file
2015-09-04 08:19:12 +02:00
Marek Posolda e9d1475475 Merge pull request #1588 from mposolda/master
KEYCLOAK-1795 Add just one clientAuthenticatorType per client
2015-09-04 00:35:25 +02:00
mposolda bc189554aa KEYCLOAK-1795 Add just one clientAuthenticatorType per client 2015-09-04 00:09:54 +02:00
suchabar d0f26ae4cf Edited Readme file 2015-09-03 20:46:34 +02:00
suchabar ab6d247ef1 Edited Readme file 2015-09-03 20:43:16 +02:00
Stian Thorgersen fcc82a47e4 KEYCLOAK-1793 Remove cancel button on login and login-totp 2015-09-03 20:21:56 +02:00
Marek Posolda 25e53db96f Merge pull request #1584 from mposolda/master
KEYCLOAK-1760 KEYCLOAK-1697 DB fixes
2015-09-03 12:23:31 +02:00
mposolda 89660d06e5 KEYCLOAK-1697 Fix UserProvider.searchForUsersByAttribute 2015-09-03 11:47:24 +02:00
mposolda 493fd0ad6a KEYCLOAK-1760 Fix DB issues when schema option defined 2015-09-03 11:47:24 +02:00
Stian Thorgersen 11422524f3 Merge pull request #1583 from stianst/master
KEYCLOAK-1497 Success message is not displayed when assigning roles
2015-09-03 09:29:24 +02:00
Stian Thorgersen 957214ed78 KEYCLOAK-1497 Success message is not displayed when assigning roles 2015-09-03 08:52:05 +02:00
Bill Burke f013cca3b8 Merge pull request #1582 from patriot1burke/master
KEYCLOAK-1792
2015-09-02 18:00:35 -04:00
Bill Burke a1cfc0a0ff KEYCLOAK-1792 2015-09-02 17:17:57 -04:00
Bill Burke e8b3b3acf3 Merge pull request #1581 from patriot1burke/master
client session required actions
2015-09-02 17:10:20 -04:00
Bill Burke 0cfb03be03 Merge remote-tracking branch 'upstream/master' 2015-09-02 16:30:35 -04:00
Bill Burke 7d4b93e01e client session required actions 2015-09-02 16:30:16 -04:00
Marek Posolda 2f3793805b Merge pull request #1579 from mposolda/master
MSSQL Fix
2015-09-02 16:59:36 +02:00
mposolda a310c13d32 MSSQL Fix 2015-09-02 16:25:38 +02:00
Stian Thorgersen 38a721425d Merge pull request #1578 from stianst/master
KEYCLOAK-1791 Exception on logout on EAP 6.4 overlay
2015-09-02 15:25:45 +02:00
Marek Posolda dfc34d99c5 Merge pull request #1577 from mposolda/master
KEYCLOAK-1789 KEYCLOAK-1759 Export/import fixes
2015-09-02 14:49:23 +02:00
Stian Thorgersen 6c58fd03a4 KEYCLOAK-1791 Exception on logout on EAP 6.4 overlay 2015-09-02 14:40:43 +02:00
mposolda 5b9d1286cc KEYCLOAK-1789 KEYCLOAK-1759 Export/import fixes 2015-09-02 12:03:16 +02:00
Stian Thorgersen d9e330802c Merge pull request #1576 from jean-merelis/master
aligning translation pt-br with master
2015-09-02 09:25:28 +02:00
Stian Thorgersen 085de8a069 Merge pull request #1571 from ssilvert/ng-upgrade-fix-conflicts
KEYCLOAK-1781: Upgrade AngularJS to version 1.4.4
2015-09-02 09:24:26 +02:00
jean 5af4c63a3e aligning translation pt-br with master 2015-09-01 13:53:01 -03:00
Stian Thorgersen 5177365c28 Merge pull request #1574 from stianst/master
Fix loading resources from theme
2015-09-01 14:06:18 +02:00
Marek Posolda 4df5ff3004 Merge pull request #1573 from mposolda/master
KEYCLOAK-1780 documentation + Generic client authentication screen
2015-09-01 13:58:04 +02:00
Stian Thorgersen 00f6841dc7 Fix loading resources from theme 2015-09-01 13:39:35 +02:00
mposolda be8394158f KEYCLOAK-1780 documentation + Generic client authentication screen 2015-09-01 13:17:14 +02:00
Bill Burke fbf62b2a63 Merge pull request #1572 from patriot1burke/master
more mappers
2015-08-31 20:48:55 -04:00
Bill Burke a047fb947b docs 2015-08-31 16:24:09 -04:00
Bill Burke eec3a3d5c3 more mappers 2015-08-31 16:23:17 -04:00
Stan Silvert 9387de1d1a KEYCLOAK-1781: Upgrade AngularJS to version 1.4.4 2015-08-31 15:09:55 -04:00
Bill Burke b9c90f128a Merge pull request #1570 from patriot1burke/master
KEYCLOAK-1726
2015-08-31 14:46:38 -04:00
Bill Burke 5699efc0f5 KEYCLOAK-1726 2015-08-31 14:46:14 -04:00
Bill Burke 6ead008bf4 Merge pull request #1569 from patriot1burke/master
KEYCLOAK-1721
2015-08-31 13:18:08 -04:00
Bill Burke 34e52839f7 KEYCLOAK-1721 2015-08-31 13:17:45 -04:00
Bill Burke bd54e1c60c Merge pull request #1568 from patriot1burke/master
docs
2015-08-31 10:55:25 -04:00
Bill Burke 03006522e2 docs 2015-08-31 10:54:57 -04:00
Bill Burke 7492ae2990 Merge pull request #1567 from patriot1burke/master
refactor recover password
2015-08-31 10:53:29 -04:00
Bill Burke 6edf890699 Merge pull request #1549 from ahus1/ahus1_jetty_contenttype
KEYCLOAK-1776 / JettySessionTokenStore sets content type on restoring form values
2015-08-31 10:34:16 -04:00
Bill Burke 43fd24f02b Merge remote-tracking branch 'upstream/master' 2015-08-31 10:13:55 -04:00
Bill Burke 22ebb81650 refactor recover password 2015-08-31 10:13:42 -04:00
Bill Burke fd074278f7 Merge pull request #1566 from bdecoste/master
KEYCLOAK-1783
2015-08-30 08:50:47 -04:00
William DeCoste ad497a66cd KEYCLOAK-1783 2015-08-29 08:57:04 -07:00
Bill Burke 41275b0e91 Merge pull request #1564 from patriot1burke/master
KEYCLOAK-1375
2015-08-27 14:56:53 -04:00
Bill Burke b82502af1d KEYCLOAK-1375 2015-08-27 14:15:47 -04:00
Bill Burke 43f2199d46 Merge pull request #1561 from velias/KEYCLOAK-1739
KEYCLOAK-1739 - correct handling of diacritics from http request in KeycloakServer
2015-08-27 09:06:42 -04:00
Bill Burke d44541fc9e Merge pull request #1560 from girirajsharma/master
[KEYCLOAK-1767] Clients table is unsorted
2015-08-27 09:06:05 -04:00
Bill Burke 24147a3d84 Merge pull request #1562 from velias/KEYCLOAK-1741
KEYCLOAK-1741 - Login form keeps "Username or email" field value after reshown due validation error
2015-08-27 09:05:40 -04:00
Vlastimil Elias 244d879d00 KEYCLOAK-1741 - Login form keeps "Username or email" field value after
reshown due validation error
2015-08-26 15:39:41 +02:00
Vlastimil Elias f5f67a629e KEYCLOAK-1739 - correct handling of diacritics from http request in
KeycloakServer
2015-08-26 14:58:37 +02:00
Alexander Schwartz aad1d57502 KEYCLOAK-1776 / check content type on form submit 2015-08-25 17:35:10 +02:00
giriraj sharma cf75c2378f [KEYCLOAK-1767] Clients table is unsorted 2015-08-23 21:03:06 +05:30
Bill Burke 3a64c4d582 Merge pull request #1543 from raehalme/KEYCLOAK-1775
KEYCLOAK-1775 Basic auth no longer redirects on Spring Security
2015-08-21 21:06:00 -04:00
Bill Burke d36376ffcd Merge pull request #1559 from patriot1burke/master
totp and profile refactor
2015-08-21 20:59:51 -04:00
Bill Burke 434197c10d Merge remote-tracking branch 'upstream/master' 2015-08-21 18:30:52 -04:00
Bill Burke d4af694c6f refactor profile and totp update 2015-08-21 18:30:39 -04:00
Bill Burke f245b67036 totp refactor 2015-08-21 17:53:26 -04:00
Bill Burke 945673c7da Merge pull request #1558 from patriot1burke/master
refactor update password
2015-08-21 17:27:42 -04:00
Bill Burke c25967bd61 fix 2015-08-21 17:01:29 -04:00
Bill Burke 165fba6b9c refactor update password 2015-08-21 15:17:01 -04:00
Marek Posolda 76209dd899 Merge pull request #1555 from mposolda/master
KEYCLOAK-1295 Fixes and javadoc
2015-08-21 20:41:21 +02:00
Bill Burke 8c8cc53989 Merge pull request #1556 from patriot1burke/master
document bypassing CORS
2015-08-21 13:26:44 -04:00
Bill Burke 6f463196ef Merge pull request #1554 from patriot1burke/master
adapter fixes
2015-08-21 13:21:02 -04:00
mposolda b0e2624343 KEYCLOAK-1295 Fixes and javadoc 2015-08-21 19:00:31 +02:00
Bill Burke 99fda3a7cb document bypassing CORS 2015-08-21 11:43:13 -04:00
Bill Burke 457039d7ba fix NPE in adapter for invalid cors requests 2015-08-21 11:29:38 -04:00
Bill Burke eb4ffbca29 co-existence of bearer and basic auth 2015-08-21 11:02:56 -04:00
Marek Posolda c9afe8fcc4 Merge pull request #1553 from mposolda/master
KEYCLOAK-1295 Adapter support. Fixes
2015-08-21 09:20:49 +02:00
mposolda d8d6348f67 KEYCLOAK-1295 Adapter support. Fixes 2015-08-21 08:26:12 +02:00
mposolda 87f7ec5909 KEYCLOAK-1561 LDAPDn.getParentDn() return value is not a DN 2015-08-21 08:26:12 +02:00
mposolda 18583eb6ed Fix mongo 2015-08-21 08:26:12 +02:00
Bill Burke b9d0219f04 Merge pull request #1552 from patriot1burke/master
change reset password
2015-08-20 18:52:07 -04:00
Bill Burke d9cb1fc4a9 Merge remote-tracking branch 'upstream/master' 2015-08-20 17:43:54 -04:00
Bill Burke 1654be0a85 change reset password 2015-08-20 17:43:37 -04:00
Stian Thorgersen d5944163d6 Merge pull request #1551 from stianst/master
KEYCLOAK-1761 Remove address from registration and account management
2015-08-20 17:19:47 +02:00
Stian Thorgersen 5ca3a48094 KEYCLOAK-1723 Allow aud to be single field or array 2015-08-20 15:55:52 +02:00
Stian Thorgersen 1fb3d7cd3b KEYCLOAK-1161
web.xml example in the doc is incorrect
2015-08-20 13:40:35 +02:00
Stian Thorgersen f827b2dc0d KEYCLOAK-1130
security-deployment vs. secure-deployment in the documentation
2015-08-20 13:37:50 +02:00
Stian Thorgersen 0295824923 KEYCLOAK-1747
Deal with time inconsistency in keycloak.js
2015-08-20 13:29:32 +02:00
Stian Thorgersen 8fee0c946b Merge pull request #1550 from mstruk/KEYCLOAK-1777
KEYCLOAK-1777 Column \"USERFEDERA0_.REALMENTITY_ID\" not found ...
2015-08-20 12:26:13 +02:00
Stian Thorgersen bd13b8a5fe KEYCLOAK-1761 Remove address from registration and account management
KEYCLOAK-1762 Add example theme that adds address fields to registration, account management and admin console
2015-08-20 12:25:26 +02:00
Stian Thorgersen 743ea95a78 Upgraded instructions to upgrade OpenShift cartridge 2015-08-19 15:56:44 +02:00
Marko Strukelj 2998a0fa35 KEYCLOAK-1777 Column \"USERFEDERA0_.REALMENTITY_ID\" not found on Wildfly 10.0.0.Beta1 2015-08-18 18:10:39 +02:00
Alexander Schwartz 7b0a3989e2 JettySessionTokenStore sets content type on restoring form values
Closes: KEYCLOAK-1776
2015-08-18 15:32:27 +02:00
Stian Thorgersen 06fcb7595a Merge pull request #1548 from stianst/master
Updated Docker hub release instructions
2015-08-18 15:21:53 +02:00
Stian Thorgersen bd3c4d4215 Updated Docker hub release instructions 2015-08-18 15:21:32 +02:00
Stian Thorgersen b969d9edfa Merge pull request #1547 from cainj13/master
add missing tag start type to sample jboss configuration in docbook
2015-08-18 14:46:38 +02:00
Josh Cain 3ef0fb63a9 add missing tag start type to sample jboss configuration in docbook 2015-08-18 08:43:28 -04:00
Stian Thorgersen bf706a9191 Merge pull request #1546 from stianst/master
Updated release process docs
2015-08-18 14:42:55 +02:00
Stian Thorgersen 26be615a80 Updated release process to include updating openshit cartridge and docker images 2015-08-18 14:10:13 +02:00
Stian Thorgersen 81928eb61a Updated release process docs 2015-08-18 13:48:21 +02:00
Marek Posolda 126f517520 Merge pull request #1545 from mposolda/master
KEYCLOAK-1295 pluggable client authentication. Support authenticate c…
2015-08-18 10:54:01 +02:00
mposolda 7028496601 KEYCLOAK-1295 pluggable client authentication. Support authenticate clients with signed JWT 2015-08-17 23:21:23 +02:00
Thomas Raehalme 3a4897c7d2 Separated the error message for Bearer token and Basic authentication failures. 2015-08-17 22:36:59 +03:00
Thomas Raehalme b3f142d715 KeycloakAuthenticationProcessingFilter now handles Basic Authentication the same way as Bearer token. 2015-08-17 18:05:49 +03:00
Stian Thorgersen a4e16ca9c7 Merge pull request #1540 from ssilvert/master
Fix typos in doc.
2015-08-17 10:09:19 +02:00
Bill Burke 57176dee75 Merge pull request #1542 from patriot1burke/master
oops, .info messages
2015-08-16 17:28:30 -04:00
Bill Burke f87ba8a3a9 oops, .info messages 2015-08-16 17:28:07 -04:00
Bill Burke 8c0b33f902 Merge pull request #1541 from patriot1burke/master
reset password refactor
2015-08-16 17:26:49 -04:00
Bill Burke 51e927adf7 Merge remote-tracking branch 'upstream/master' 2015-08-16 16:41:08 -04:00
Bill Burke bf4b681506 tests 2015-08-16 16:40:39 -04:00
Bill Burke 3c88d2cc18 finish refactor 2015-08-16 15:38:00 -04:00
Bill Burke c7b5975ac1 reset password refactor 2015-08-16 15:20:16 -04:00
Stan Silvert 09901997c1 Fix typos in doc. 2015-08-16 14:59:31 -04:00
Bill Burke c0f3d851db reset password refactor/flow 2015-08-16 12:23:15 -04:00
Bill Burke 98b6344f03 Merge pull request #1539 from patriot1burke/master
fix holes
2015-08-15 11:37:20 -04:00
Bill Burke e4b6e4c167 Merge pull request #1523 from velias/KEYCLOAK-1731
KEYCLOAK-1731 - patched user attribute handling for update profile action
2015-08-15 11:30:22 -04:00
Bill Burke d6983e829a Merge remote-tracking branch 'upstream/master' 2015-08-15 10:39:44 -04:00
Bill Burke 374a2ad957 fix holes 2015-08-15 10:39:33 -04:00
Bill Burke 52fd2d7e75 Merge pull request #1538 from patriot1burke/master
refactor auth-spi, auth demo, and docs
2015-08-14 15:14:00 -04:00
Bill Burke 25bb0ade1b Merge remote-tracking branch 'upstream/master' 2015-08-14 14:39:10 -04:00
Bill Burke 6d7be80930 refactor auth-spi, auth demo, and docs 2015-08-14 14:38:59 -04:00
Bill Burke 1f13f6372a register required action 2015-08-14 12:03:37 -04:00
Bill Burke 39fcd84d53 Merge pull request #1537 from patriot1burke/master
auth spi docs and refactor
2015-08-14 08:53:21 -04:00
Bill Burke d11a83d6e2 stuff 2015-08-13 15:32:58 -04:00
Bill Burke 1978e23cfd Merge pull request #1536 from patriot1burke/master
auth spi docs and refactor
2015-08-13 13:47:24 -04:00
Bill Burke 4cc1a774df Merge remote-tracking branch 'upstream/master' 2015-08-13 13:02:27 -04:00
Bill Burke 8a23463328 auth spi refactor and doco 2015-08-13 11:28:11 -04:00
Stian Thorgersen fad2913665 Merge pull request #1535 from stianst/master
Remove user session entities from persistence.xml
2015-08-13 13:38:59 +02:00
Stian Thorgersen c4c27973f3 Remove user session entities from persistence.xml 2015-08-13 10:33:18 +02:00
Stian Thorgersen 2ae733bd07 Merge pull request #1534 from stianst/master
KEYCLOAK-1703 Remove jpa and mongo user session providers
2015-08-13 10:32:25 +02:00
Stian Thorgersen 7665b9f81e KEYCLOAK-1703 Remove jpa and mongo user session providers 2015-08-13 08:57:37 +02:00
Stian Thorgersen 248322c748 Merge pull request #1533 from stianst/master
KEYCLOAK-1702 Removed mem and none realm and user cache
2015-08-13 08:24:13 +02:00
Bill Burke 523bdd5ec9 doco 2015-08-12 20:37:51 -04:00
Stian Thorgersen a8ad00156b KEYCLOAK-1702 Removed mem and none realm and user cache 2015-08-12 16:55:23 +02:00
Stian Thorgersen 8f820713fa Merge pull request #1530 from lkubik/multipleDependencyDeclaration
Remove multiple declaration of jboss-logging dependency
2015-08-12 13:00:54 +02:00
Stian Thorgersen fc7d4b072c Merge pull request #1526 from mstruk/WF10
KEYCLOAK-1745 Keycloak fails to start on Wildfly 10.0.0.Alpha6
2015-08-12 11:51:11 +02:00
Bill Burke 1801526f65 auth spi doco 2015-08-11 17:44:06 -04:00
Bill Burke 58e37b6a3f Merge pull request #1532 from patriot1burke/master
refactor requiredactions, start doco
2015-08-11 13:52:07 -04:00
Bill Burke 0bd9cad6ad Merge remote-tracking branch 'upstream/master' 2015-08-11 13:04:51 -04:00
Bill Burke bcc2c893ef refactor requiredactions, start doco 2015-08-11 13:04:40 -04:00
Lukas Kubik ac71bbd4b5 Remove multiple declaration of jboss-logging dependency from testsuit/tomcat6/pom.xml 2015-08-10 15:16:28 +02:00
Stian Thorgersen ae94b30066 Merge pull request #1529 from grange74/KEYCLOAK-1724
KEYCLOAK-1724: Removed second security-constraint as it stops Tomcat from redirecting to Keycloak
2015-08-10 15:11:01 +02:00
nick.grange b3c307affe Removed second security-constraint as it seems to stop Tomcat from
redirecting users that aren’t logged in to Keycloak. Also added missing
tag start.
2015-08-10 22:27:52 +10:00
Bill Burke 03d3f4229e Merge pull request #1528 from patriot1burke/master
auth spi javadoc
2015-08-09 15:51:55 -04:00
Bill Burke c627b83cc5 Merge remote-tracking branch 'upstream/master' 2015-08-09 15:06:37 -04:00
Bill Burke 5469db311d document auth spi 2015-08-09 15:06:24 -04:00
Bill Burke 75793a36cf Merge pull request #1527 from patriot1burke/master
binding custom flows
2015-08-07 21:26:46 -04:00
Bill Burke d68603e4ea Merge remote-tracking branch 'upstream/master' 2015-08-07 19:00:19 -04:00
Bill Burke 33e402e7be binding custom flows 2015-08-07 19:00:07 -04:00
Marko Strukelj 375dce14e6 KEYCLOAK-1745 Keycloak fails to start on Wildfly 10.0.0.Alpha6 2015-08-07 14:56:14 +02:00
Bill Burke 08ae3aee50 Merge pull request #1525 from patriot1burke/master
hotp and otp policy
2015-08-06 17:43:46 -04:00
Bill Burke 1ad7d4f1d8 Merge remote-tracking branch 'upstream/master' 2015-08-06 16:55:16 -04:00
Bill Burke f9e8f1f7b7 hotp 2015-08-06 16:54:59 -04:00
Marek Posolda fa0b45625c Merge pull request #1524 from mposolda/master
Minor clustering improvements
2015-08-06 18:05:40 +02:00
mposolda c5459b2614 Update docker-cluster to keycloak 1.4 2015-08-06 17:29:08 +02:00
mposolda 8232773d97 Log more details about possible error in UserInfoEndpoint 2015-08-06 17:28:35 +02:00
Bill Burke 53b752ccfe Merge remote-tracking branch 'upstream/master' 2015-08-05 20:40:02 -04:00
Bill Burke 07efba364e hotp 2015-08-05 20:39:47 -04:00
Vlastimil Elias 2e52d8ea7a KEYCLOAK-1731 - patched user attribute handling for
login-update-profile.ftl form. Relevant tests added. Tests for user
attributes handling from register.ftl also added.
2015-08-05 17:07:21 +02:00
Marek Posolda a46a7a42a1 Merge pull request #1522 from mposolda/master
Clustering docs and distribution fixes
2015-08-05 13:34:39 +02:00
mposolda 060a193b48 KEYCLOAK-1732 Fix standalone.xml in demo distribution 2015-08-05 13:33:11 +02:00
mposolda 06ee06ae50 Update clustering docs as infinispan is default provider now 2015-08-05 13:32:40 +02:00
Marek Posolda 17a5a9f033 Merge pull request #1521 from mposolda/master
KEYCLOAK-1595 Don't send 401 from AuthorizeClientUtil if public clien…
2015-08-04 16:01:17 +02:00
mposolda e27a754f5f KEYCLOAK-1595 Don't send 401 from AuthorizeClientUtil if public client sent client_id parameter together with Authorization: Negotiate 2015-08-04 15:22:03 +02:00
Bill Burke 61d5ba6a92 Merge pull request #1520 from patriot1burke/master
fix javascript flo bug
2015-08-04 09:04:18 -04:00
Bill Burke eff0054b4a fix bug 2015-08-04 09:03:49 -04:00
Marek Posolda 99cd6c7383 Merge pull request #1519 from mposolda/master
LDAP & migration fixes
2015-08-04 14:14:56 +02:00
mposolda 5087392162 KEYCLOAK-1725 Fix migration from 1.1.0.Final on Oracle 2015-08-04 13:21:09 +02:00
mposolda 7474a31d95 KEYCLOAK-1562 better error reporting when missing UUID on ldap user record 2015-08-04 13:21:09 +02:00
mposolda a0197bc9da KEYCLOAK-1728 NPE during LDAP sync when some LDAP user doesn't have username 2015-08-04 13:21:09 +02:00
Bill Burke 3b2e679aed Merge pull request #1518 from patriot1burke/master
auth flow editing
2015-08-03 19:26:11 -04:00
Bill Burke 75d69a1ec1 Merge pull request #1516 from pfiled/proxy-header-inject-bug
Populate the KEYCLOAK_USERNAME header
2015-08-03 18:59:32 -04:00
Bill Burke 930fc66ebf flow editing 2015-08-03 18:58:14 -04:00
Bill Burke 04d3d26cb1 refactor execution model 2015-08-03 09:52:56 -04:00
Bill Burke de940ccff9 auth flow editing 2015-08-02 19:03:33 -04:00
Daniel Pfile aedc54cc89 Populate the KEYCLOAK_USERNAME header, this fixes the authenticate and roles-allowed constraints in the proxy. 2015-07-30 16:24:16 -05:00
Stian Thorgersen de3a776b9a Merge pull request #1515 from stianst/master
KEYCLOAK-1702 KEYCLOAK-1703 Make Infinispan default user session and …
2015-07-29 13:07:09 +02:00
Stian Thorgersen 5d6cc61d4d KEYCLOAK-1702 KEYCLOAK-1703 Remove mem user session provider 2015-07-29 12:02:27 +02:00
Stian Thorgersen f32b38cdbc KEYCLOAK-1702 KEYCLOAK-1703 Make Infinispan default user session and cache provider 2015-07-29 10:08:15 +02:00
Stian Thorgersen f3bfb06dec Version bump 2015-07-28 10:20:40 +02:00
Stian Thorgersen 630597746e Merge pull request #1514 from stianst/master
KEYCLOAK-1714 Add @JsonIgnoreProperties(ignoreUnknown = true) to JWSH…
2015-07-28 10:15:09 +02:00
Stian Thorgersen f98036296c KEYCLOAK-1716 NPE importing with empty database 2015-07-28 09:46:03 +02:00
Stian Thorgersen bf1f867f23 KEYCLOAK-1715 Cordova example doesn't work on Cordova 5.x 2015-07-28 08:36:01 +02:00
Stian Thorgersen 8215a85930 KEYCLOAK-1549
Migration for multiple attributes and LDAP mappers
2015-07-28 07:46:29 +02:00
Stian Thorgersen 10a5686955 KEYCLOAK-1714 Add @JsonIgnoreProperties(ignoreUnknown = true) to JWSHeader 2015-07-28 07:30:10 +02:00
Bill Burke 2e3c7a3acf Merge pull request #1512 from patriot1burke/master
canonicalization config
2015-07-27 15:33:27 -04:00
Bill Burke 06713da67b Merge remote-tracking branch 'upstream/master' 2015-07-27 11:57:21 -04:00
Bill Burke 46fb1b6582 canonicalization config 2015-07-27 11:57:08 -04:00
Stian Thorgersen 1b3f98db1e Merge pull request #1511 from stianst/master
UserInfo fix
2015-07-27 17:01:41 +02:00
Stian Thorgersen a190cdd8f2 KEYCLOAK-1712 Admin client example not working 2015-07-27 16:01:48 +02:00
Stian Thorgersen 8e25369001 KEYCLOAK-1711 Add get user info to js-console example 2015-07-27 15:43:52 +02:00
Stian Thorgersen 8d90ad816a KEYCLOAK-1710 UserInfoEndpoint throws NPE if user session is not found 2015-07-27 15:43:52 +02:00
Stian Thorgersen da9e42cb21 Merge pull request #1510 from stianst/master
KEYCLOAK-1709 Add standalone-keycloak-ha.xml to server overlays
2015-07-27 14:32:00 +02:00
Stian Thorgersen cbab3ff0d0 KEYCLOAK-1709 Add standalone-keycloak-ha.xml to server overlays 2015-07-27 14:31:40 +02:00
Stian Thorgersen 210b570c89 Merge pull request #1509 from stianst/master
Admin console fixes
2015-07-27 13:31:16 +02:00
Stian Thorgersen a2203df6a3 KEYCLOAK-1705 Logo not changed in admin console for logo example theme 2015-07-27 13:30:55 +02:00
Stian Thorgersen 6a2b369014 KEYCLOAK-1707 Can't export SAML keys 2015-07-27 13:00:22 +02:00
Stian Thorgersen fda6a6657f KEYCLOAK-1708 Authentication flows uses h2 in table 2015-07-27 12:32:55 +02:00
Stian Thorgersen 04565dad00 KEYCLOAK-1706 Service Account tab for clients displays title twice 2015-07-27 12:30:06 +02:00
Stian Thorgersen ac0ae06463 Merge pull request #1508 from stianst/master
KEYCLOAK-1694 Null Client Exception on OAuth Grant Page
2015-07-27 11:43:13 +02:00
Stian Thorgersen a8775f757f KEYCLOAK-1694 Null Client Exception on OAuth Grant Page 2015-07-27 09:59:50 +02:00
Stian Thorgersen e4f4ed923d Merge pull request #1507 from stianst/master
KEYCLOAK-1699 There are 3 failed tests when running testsuite with -P…
2015-07-27 09:57:52 +02:00
Stian Thorgersen c7915fa95d KEYCLOAK-1699 There are 3 failed tests when running testsuite with -Pinfinispan 2015-07-27 08:52:00 +02:00
Bill Burke 652b118634 Merge pull request #1506 from patriot1burke/master
timeout message
2015-07-25 15:27:51 -04:00
Bill Burke f122ff1471 Merge pull request #1505 from patriot1burke/master
login timeouts, verify email
2015-07-25 12:43:53 -04:00
Bill Burke f76b90fab9 timeout message 2015-07-25 12:43:46 -04:00
Bill Burke ccd8beae92 Merge remote-tracking branch 'upstream/master' 2015-07-25 12:16:05 -04:00
Bill Burke 33f01009d2 login timeouts, verify email 2015-07-25 12:13:41 -04:00
mposolda a0e3a71109 Fix infinispan - not finished 2015-07-25 12:05:16 +02:00
mposolda f35ecba801 Sybase - another attempt 2015-07-25 11:47:56 +02:00
Marek Posolda 0d7f26bd14 Merge pull request #1504 from mposolda/master
Migration
2015-07-25 11:36:04 +02:00
mposolda 2f7bdd2640 Fix migration version comparing bug 2015-07-25 09:00:50 +02:00
mposolda 3125e4ddd2 KEYCLOAK-1549 Mongo migration 2015-07-25 08:58:05 +02:00
Marek Posolda c624cb27da Merge pull request #1503 from mposolda/master
KEYCLOAK-1549 Migration for attributes and LDAP mappers - JPA
2015-07-24 23:29:28 +02:00
mposolda 06adf9a094 Sybase fix 2015-07-24 23:28:52 +02:00
mposolda 94ed55ee35 KEYCLOAK-1549 Migration for attributes and LDAP mappers - JPA 2015-07-24 23:09:48 +02:00
Marek Posolda 95c8603b69 Merge pull request #1502 from cwalker67/master
Added null email check in duplicate email check code
2015-07-24 23:04:46 +02:00
Charles Walker 9ad2a8272e quick return check for null email address, in reference to duplicate email check issue #1510 2015-07-24 16:08:26 -04:00
Charles Walker 6dc17da00a Merge pull request #1 from keycloak/master
merge updates
2015-07-24 15:55:34 -04:00
Marek Posolda 97aa1c6b2c Merge pull request #1501 from mposolda/master
Temporarily comment the test failing on Oracle and MSSQL as the funct…
2015-07-24 21:50:35 +02:00
mposolda 084fed8377 Temporarily comment the test failing on Oracle and MSSQL as the functionality is not used right now 2015-07-24 21:49:51 +02:00
Marek Posolda 68d86e4fa1 Merge pull request #1500 from mposolda/master
Fix JPA UserSession provider and MySQL
2015-07-24 20:46:46 +02:00
mposolda 5203373047 Fix JPA UserSession provider and MySQL 2015-07-24 20:39:39 +02:00
Stian Thorgersen 86de481ba1 Merge pull request #1499 from stianst/master
KEYCLOAK-1542
2015-07-24 17:30:29 +02:00
Stian Thorgersen 5d075a97dd Fixes to server-info 2015-07-24 16:45:58 +02:00
Stian Thorgersen e89499f5db Fix xmlns for modules in feature packs 2015-07-24 16:45:27 +02:00
Stian Thorgersen a1f0208767 Merge branch 'velias-KEYCLOAK-1542' 2015-07-24 14:48:10 +02:00
Stian Thorgersen d1964c20ab Refactored server-info and updated admin console 2015-07-24 14:47:37 +02:00
Marek Posolda 1e035bf2e5 Merge pull request #1498 from mposolda/master
Skip testDotInUsername for the MSAD configuration with sAMAccountName…
2015-07-24 13:03:24 +02:00
mposolda f3b87f9cf9 Skip testDotInUsername for the MSAD configuration with sAMAccountName as username 2015-07-24 13:01:54 +02:00
Stian Thorgersen d2ea45e1eb Merge pull request #1496 from stianst/master
KEYCLOAK-1691 and KEYCLOAK-1695
2015-07-24 12:52:19 +02:00
Marek Posolda 58ad6b1a40 Merge pull request #1497 from mposolda/master
Mongo model fix
2015-07-24 12:47:47 +02:00
mposolda 772ef3cd10 Mongo model fix 2015-07-24 12:46:47 +02:00
Stian Thorgersen 204dfd52c8 Merge branch 'KEYCLOAK-1542' of https://github.com/velias/keycloak into velias-KEYCLOAK-1542 2015-07-24 12:17:33 +02:00
Vlastimil Elias 244d3452d0 KEYCLOAK-1542 - removed unused code from the page template 2015-07-24 11:07:01 +02:00
Stian Thorgersen e65f8a7150 KEYCLOAK-1695 Upgrade to WildFly 9.0.1.Final 2015-07-24 10:44:15 +02:00
Stian Thorgersen 90d6991b9d KEYCLOAK-1691 Enable adapter subsystem to use with WildFly Swarm 2015-07-24 10:16:25 +02:00
Stian Thorgersen 87ca3f203a Merge pull request #1488 from stianst/master
KEYCLOAK-1506 Warning of Keycloak 1.3.1 on MySQL 5.6
2015-07-24 09:58:02 +02:00
Marek Posolda 3f3a20e178 Merge pull request #1494 from mposolda/master
KEYCLOAK-1693 Added test and possibility to create users with dot in …
2015-07-24 09:57:55 +02:00
mposolda ce1a19fdbe KEYCLOAK-1693 Added test and possibility to create users with dot in username 2015-07-24 09:33:16 +02:00
Marek Posolda 26ac92a6b1 Merge pull request #1493 from dylanplecki/issue-1693
KEYCLOAK-1693 LDAP DN parse error on escaped characters
2015-07-24 09:07:06 +02:00
Marek Posolda 1c7dd0a533 Merge pull request #1492 from mposolda/master
Simplify embedded server bootstrap in LDAP and Kerberos examples
2015-07-23 22:13:22 +02:00
Dylan Plecki ceb29d76b2 Fix regression in RegEx statements 2015-07-23 14:49:03 -05:00
Dylan Plecki 6efb354cce Fix LDAP DN component matching with negative lookbehind RegEx 2015-07-23 14:48:56 -05:00
Dylan Plecki 8ae242a6ed Fix LDAP RDN resolution based on unescaped comma split 2015-07-23 14:48:48 -05:00
mposolda 5f0f92fd15 Fix test to pass with MSAD 2015-07-23 21:39:40 +02:00
mposolda e521fa3554 Simplify embedded server bootstrap in LDAP and Kerberos examples 2015-07-23 21:17:40 +02:00
Marek Posolda b8f73cf21f Merge pull request #1491 from mposolda/master
Fix MSAD and OpenLDAP
2015-07-23 18:32:32 +02:00
mposolda d068cddbaf Fix MSAD and OpenLDAP 2015-07-23 18:03:12 +02:00
Bill Burke 99422835ab Merge pull request #1489 from patriot1burke/master
fix typo
2015-07-23 11:09:31 -04:00
Bill Burke 68263360c7 fix typo 2015-07-23 11:09:07 -04:00
Vlastimil Elias 34f5ddab0f Merge branch 'KEYCLOAK-1542' of https://github.com/velias/keycloak.git into KEYCLOAK-1542 2015-07-23 16:49:11 +02:00
Stian Thorgersen 0cc4630fc6 KEYCLOAK-1506 Warning of Keycloak 1.3.1 on MySQL 5.6 2015-07-23 16:46:06 +02:00
Vlastimil Elias ee57c79784 KEYCLOAK-1542 - rewrote showing info from providers to be generic 2015-07-23 16:40:57 +02:00
Vlastimil Elias 7e41b8df27 KEYCLOAK-1542 - code formatting cleanup 2015-07-23 16:40:56 +02:00
Vlastimil Elias 79c1d7bafa KEYCLOAK-1542 - code cleanup ahead of PR 2015-07-23 16:40:55 +02:00
Vlastimil Elias 652b2fee86 KEYCLOAK-1542 - Server Info page extended by info about DB and MongoDB.
Functional test for /serverinfo REST endpoint added.
2015-07-23 16:40:54 +02:00
Vlastimil Elias dfb871c26a KEYCLOAK-1542 - added system and memory info into "System Info" page 2015-07-23 16:40:53 +02:00
Vlastimil Elias 99f74acb94 KEYCLOAK-1542 - rewrote showing info from providers to be generic 2015-07-23 16:39:27 +02:00
Stian Thorgersen 83f7682606 Merge pull request #1487 from stianst/master
KEYCLOAK-1463
2015-07-23 15:53:50 +02:00
Stian Thorgersen c4a07f3098 KEYCLOAK-1463
Need better UI for Terms and Conditions
2015-07-23 14:35:57 +02:00
Stian Thorgersen c9451f4f35 Merge pull request #1486 from stianst/master
KEYCLOAK-1593 Move impersonate button on user details page
2015-07-23 14:24:49 +02:00
Stian Thorgersen dff4922783 KEYCLOAK-1593 Move impersonate button on user details page 2015-07-23 14:24:19 +02:00
Stian Thorgersen c05b666f3c Merge pull request #1483 from stianst/master
KEYCLOAK-1591 Issues with token settings page
2015-07-23 13:26:38 +02:00
Marek Posolda 9905024f08 Merge pull request #1485 from mposolda/service-acc
KEYCLOAK-401 Service account docs
2015-07-23 12:19:06 +02:00
mposolda b0cb457287 KEYCLOAK-401 Service account docs 2015-07-23 12:18:09 +02:00
Marek Posolda d4946c1c08 Merge pull request #1484 from mposolda/service-acc
KEYCLOAK-401 Service account refactoring and fixes
2015-07-23 12:09:33 +02:00
Stian Thorgersen 1d745b5cbd KEYCLOAK-1443 Add delete action to tables 2015-07-23 12:07:31 +02:00
mposolda c99785f266 KEYCLOAK-401 Service account refactoring and fixes 2015-07-23 11:29:52 +02:00
Stian Thorgersen 9ecdec3f45 KEYCLOAK-1591 Issues with token settings page 2015-07-23 11:23:53 +02:00
Stian Thorgersen 866f45bd95 Merge pull request #1479 from stianst/master
KEYCLOAK-1588 Strange version of slf4j not available in maven central
2015-07-23 09:17:21 +02:00
Bill Burke 320a79dbff Merge pull request #1482 from patriot1burke/master
better description
2015-07-22 14:47:16 -04:00
Bill Burke 1e0b6f1aad better description 2015-07-22 14:46:58 -04:00
Bill Burke 251ad6727a Merge pull request #1481 from patriot1burke/master
brute force fixes and enhancements
2015-07-22 14:46:29 -04:00
Bill Burke 1b1f56d183 ugh 2015-07-22 14:22:41 -04:00
Bill Burke 7dc05a45ac conflict 2015-07-22 14:20:52 -04:00
Bill Burke 7257bab289 brute force user ui 2015-07-22 14:16:09 -04:00
Bill Burke 48a76c2d0d test brute force 2015-07-22 12:30:52 -04:00
Stian Thorgersen d78c83b236 KEYCLOAK-1588 Strange version of slf4j not available in maven central 2015-07-22 16:27:34 +02:00
Bill Burke d9b0415047 brute force fixes, code cleanup, tests 2015-07-22 09:40:11 -04:00
Stian Thorgersen af2e3de96d Merge pull request #1474 from stianst/master
KEYCLOAK-1427
2015-07-22 14:30:45 +02:00
Vlastimil Elias 1c142cb170 KEYCLOAK-1542 - code formatting cleanup 2015-07-22 14:28:08 +02:00
Stian Thorgersen d5dae7d444 KEYCLOAK-1428 Disable buttons on forms instead of hiding 2015-07-22 14:05:47 +02:00
Vlastimil Elias 85816be967 KEYCLOAK-1542 - code cleanup ahead of PR 2015-07-22 13:35:56 +02:00
Stian Thorgersen e66d658955 KEYCLOAK-1428 Disable buttons on forms instead of hiding 2015-07-22 11:50:24 +02:00
Stian Thorgersen 1916fded95 Fix location of buttons on password-policy form 2015-07-22 11:50:23 +02:00
Stian Thorgersen 8cc8f4c49c Fix tests 2015-07-22 11:50:23 +02:00
Stian Thorgersen 1a3bf16729 KEYCLOAK-1434 Change edit action to buttons to make sure styles are correct 2015-07-22 11:50:23 +02:00
Stian Thorgersen 5304b533fc KEYCLOAK-1434 Add edit action to tables 2015-07-22 11:50:23 +02:00
Stian Thorgersen 0156d47d97 KEYCLOAK-1535 Set tooltip-placement correctly 2015-07-22 11:50:23 +02:00
Stian Thorgersen b04ac6cdba KEYCLOAK-1427 Add remove user button to all user tabs 2015-07-22 11:50:23 +02:00
Stian Thorgersen f43e4200da Removed title on password policy page 2015-07-22 11:50:23 +02:00
Stian Thorgersen 2ba7aef2b1 KEYCLOAK-1427 Add remove user federation button to all user federation tabs 2015-07-22 11:50:23 +02:00
Stian Thorgersen 7a1932cab4 KEYCLOAK-1427 Add remove identity provider button to all identity provider tabs 2015-07-22 11:50:23 +02:00
Stian Thorgersen 59f189229c KEYCLOAK-1427 Add remove client button to all client tabs 2015-07-22 11:50:23 +02:00
Stian Thorgersen 29af7a1d29 KEYCLOAK-1427 Added delete realm button to all realm settings tabs 2015-07-22 11:49:39 +02:00
Marek Posolda 3d9ddc53e6 Merge pull request #1477 from mposolda/service-acc
KEYCLOAK-401 Service accounts initial impl. Client credentials grant support. Demo
2015-07-22 11:37:55 +02:00
mposolda 1a34feda65 KEYCLOAK-401 Added service account demo 2015-07-22 11:07:57 +02:00
mposolda d8c1081578 KEYCLOAK-401 KEYCLOAK-941 Service accounts initial impl. Client credentials grant support 2015-07-22 10:55:50 +02:00
Bill Burke 1085a1da62 Merge pull request #1476 from patriot1burke/master
non-browser flow
2015-07-21 23:15:51 -04:00
Bill Burke 576db8e0e1 Merge remote-tracking branch 'upstream/master' 2015-07-21 20:56:22 -04:00
Bill Burke fe9dc4a28d non-browser flow 2015-07-21 20:56:05 -04:00
Stian Thorgersen d2aaae2340 Merge pull request #1475 from mstruk/KEYCLOAK-1496
KEYCLOAK-1496 Effective roles select element is not updated when addi…
2015-07-21 19:03:44 +02:00
Vlastimil Elias 84e40cbc2c KEYCLOAK-1542 - Server Info page extended by info about DB and MongoDB.
Functional test for /serverinfo REST endpoint added.
2015-07-21 16:09:47 +02:00
Marko Strukelj 42672a9ae2 KEYCLOAK-1496 Effective roles select element is not updated when adding composite client role 2015-07-21 15:59:21 +02:00
Stian Thorgersen 2dd2173553 Merge pull request #1473 from mstruk/KEYCLOAK-1560
KEYCLOAK-1560 IDENTITY_PROVIDER_LOGIN event is send twice
2015-07-21 10:28:32 +02:00
Marko Strukelj fcd5400cda KEYCLOAK-1560 IDENTITY_PROVIDER_LOGIN event is send twice 2015-07-21 09:49:37 +02:00
Marek Posolda 23b69bb7a7 Merge pull request #1467 from mposolda/master
LDAP and case-sensitivity fixes
2015-07-21 08:58:07 +02:00
mposolda c31b0945d8 Kerberos example README 2015-07-21 08:26:16 +02:00
mposolda c71a4ac4e8 KEYCLOAK-1545 KEYCLOAK-1551 Ensure that username and email are always saved to DB lowercased 2015-07-21 08:26:16 +02:00
mposolda 38c7ca64cb KEYCLOAK-1571 Error when the value of UUID LDAP attribute is the same of the Username LDAP attribute 2015-07-21 08:26:16 +02:00
Bill Burke bc187fe7b3 Merge pull request #1472 from patriot1burke/master
clean up client sessions
2015-07-20 19:17:31 -04:00
Bill Burke 548c0db0ae Merge remote-tracking branch 'upstream/master' 2015-07-20 12:21:57 -04:00
Bill Burke 3ecd1307b0 clean up client sessions 2015-07-20 12:21:48 -04:00
Vlastimil Elias b51661b790 KEYCLOAK-1542 - added system and memory info into "System Info" page 2015-07-20 17:11:04 +02:00
Stian Thorgersen 02d6e41ce3 Merge pull request #1471 from stianst/master
KEYCLOAK-1576
2015-07-20 15:21:51 +02:00
Stian Thorgersen f884aed25e KEYCLOAK-1576 2015-07-20 13:35:56 +02:00
Stian Thorgersen f2dee1a470 Add support for multi-part to MailServer util 2015-07-20 13:35:33 +02:00
Stian Thorgersen d5d806760f Merge branch 'ssilvert-KEYCLOAK-1414-cli-script-adapters' 2015-07-20 13:11:10 +02:00
Stian Thorgersen efe2a8f789 Merge branch 'KEYCLOAK-1414-cli-script-adapters' of https://github.com/ssilvert/keycloak into ssilvert-KEYCLOAK-1414-cli-script-adapters
Conflicts:
	docbook/reference/en/en-US/modules/jboss-adapter.xml
2015-07-20 13:10:51 +02:00
Stian Thorgersen 69bbed999f Merge pull request #1466 from ssilvert/KEYCLOAK-1415-server-cli-script
KEYCLOAK-1415 server cli script
2015-07-20 13:08:13 +02:00
Stian Thorgersen 5b7d4184f0 Merge pull request #1470 from stianst/master
Enabled testsuite/integration-arquillian on Travis
2015-07-20 11:52:13 +02:00
Stian Thorgersen 422b7ed5ef Enabled testsuite/integration-arquillian on Travis 2015-07-20 10:39:08 +02:00
Stian Thorgersen 66a2b916f2 Fix CRLF with LF 2015-07-20 07:48:02 +02:00
Stian Thorgersen 27ac253098 Merge pull request #1469 from Smartling/KEYCLOAK-1494-Fix
Support loading keycloak.json from the classpath
2015-07-20 06:48:14 +02:00
Scott Rossillo 1839b24b90 Support for loading keycloak.json from the classpath
Spring Boot and non-web based applications don't have a WEB-INF
directory. Support loading Spring Security adapter's keycloak.json
from the class path.
2015-07-19 12:10:33 -04:00
Bill Burke a60ebb6210 Merge pull request #1468 from patriot1burke/master
required action import/export
2015-07-18 09:06:39 -04:00
Bill Burke 4dba4f3c02 fix 2015-07-17 23:07:36 -04:00
Bill Burke 6727af2f35 required action import/export 2015-07-17 22:48:07 -04:00
Stan Silvert 5bcf334bc5 Don't add security-domain to server. 2015-07-17 12:48:32 -04:00
Stan Silvert ef49bd685e KEYCLOAK-1415 Add CLI scripts to WildFly and EAP overlay bundles. 2015-07-17 12:34:20 -04:00
Stan Silvert 092562fb94 KEYCLOAK-1414 Add CLI script for installing JBoss/WildFly/EAP adapters. 2015-07-17 12:23:10 -04:00
Bill Burke 44e2983803 Merge pull request #1462 from patriot1burke/master
migrate RequiredCredentials
2015-07-17 10:28:21 -04:00
Bill Burke 2e848da1a8 resolve conflicts 2015-07-17 09:45:53 -04:00
Stian Thorgersen 22ae4ecb23 Merge pull request #1464 from stianst/master
KEYCLOAK-1385 Introduce end-of-line normalization
2015-07-17 14:04:59 +02:00
Stian Thorgersen 1642ac2394 KEYCLOAK-1385 Introduce end-of-line normalization 2015-07-17 13:46:51 +02:00
Stian Thorgersen be8aa93cca Merge pull request #1463 from mstruk/remove-war
KEYCLOAK-1345 Remove distribution/subsystem-war
2015-07-17 13:26:34 +02:00
Marko Strukelj fc7ba85639 KEYCLOAK-1345 Remove distribution/subsystem-war 2015-07-17 12:41:00 +02:00
Stian Thorgersen 11d1dd6419 KEYCLOAK-1470 2015-07-17 11:46:02 +02:00
Stian Thorgersen e8bd7270e9 KEYCLOAK-1483 2015-07-17 11:22:04 +02:00
Stian Thorgersen 99e2afa81b KEYCLOAK-1498 2015-07-17 10:54:43 +02:00
Stian Thorgersen 676792d07d KEYCLOAK-1475 2015-07-17 10:33:18 +02:00
Stian Thorgersen 0bec2bcd1e KEYCLOAK-1504 2015-07-17 10:21:15 +02:00
Stian Thorgersen 25328048aa KEYCLOAK-1566 2015-07-17 10:09:28 +02:00
Bill Burke e51d2137cf migrate RequiredCredentials 2015-07-16 22:03:12 -04:00
Bill Burke 5695677873 Merge pull request #1458 from patriot1burke/master
idp initiated relaystate query param
2015-07-16 10:34:12 -04:00
Stian Thorgersen 9d86f582ac Merge branch 'girirajsharma-master' 2015-07-16 16:32:25 +02:00
Stian Thorgersen 97b0558f71 Merge branch 'master' of https://github.com/girirajsharma/keycloak into girirajsharma-master
Conflicts:
	forms/common-themes/src/main/resources/theme/base/admin/resources/partials/client-detail.html
	forms/common-themes/src/main/resources/theme/base/admin/resources/partials/role-detail.html
	forms/common-themes/src/main/resources/theme/base/admin/resources/partials/user-detail.html
2015-07-16 16:31:16 +02:00
Bill Burke e825be1c79 nonce in tokens 2015-07-16 10:17:44 -04:00
Stian Thorgersen 88252c3dfc Merge pull request #1457 from mstruk/keycloak-prod
KEYCLOAK-1331 Add product.conf and product module
2015-07-16 16:11:44 +02:00
Stian Thorgersen 02997b593f Merge pull request #1459 from stianst/master
Some fixes to integration-arquillian
2015-07-16 16:10:37 +02:00
giriraj sharma 9de81a0b14 Updated patternfly delete glyphicon css. 2015-07-16 18:28:56 +05:30
giriraj sharma ab13182091 [Keycloak-1427] Updated Delete icons with 'pointer' as hovering cursor. 2015-07-16 18:26:58 +05:30
Stian Thorgersen e75e4580ae Some fixes to integration-arquillian
Conflicts:
	testsuite/integration-arquillian/pom.xml
2015-07-16 14:49:38 +02:00
Bill Burke b7f031d199 Merge remote-tracking branch 'upstream/master' 2015-07-16 08:49:23 -04:00
Bill Burke 808d27be2d idp initiated relaystate query param 2015-07-16 08:48:07 -04:00
Marko Strukelj dcf8751ff7 KEYCLOAK-1331 Add product.conf and product module 2015-07-16 14:16:10 +02:00
Bill Burke ec6e3d80ee Merge pull request #1456 from patriot1burke/master
SAML IDP Initiated Login
2015-07-15 20:35:01 -04:00
Bill Burke 5a9badf683 relay state 2015-07-15 20:22:30 -04:00
Bill Burke dd11dcef93 docs 2015-07-15 20:18:14 -04:00
Bill Burke e9851957f0 Merge remote-tracking branch 'upstream/master' 2015-07-15 20:09:13 -04:00
Bill Burke 57cfbb3770 SAML IDP Initiated login 2015-07-15 20:08:55 -04:00
Bill Burke da2590819d Merge pull request #1455 from patriot1burke/master
export/import flows
2015-07-15 15:08:09 -04:00
Bill Burke d74d93a522 fix problems 2015-07-15 14:54:14 -04:00
Bill Burke b3eadcc990 Merge remote-tracking branch 'upstream/master' 2015-07-15 14:17:54 -04:00
Bill Burke f4d4405c20 export/import flows 2015-07-15 14:17:23 -04:00
Stian Thorgersen 1ebec0e2e5 Merge pull request #1454 from brmeyer/KEYCLOAK-1563
KEYCLOAK-1563 update docs for server/adapter subsystem split & WF 9.0…
2015-07-15 09:37:00 +02:00
Brett Meyer 4433347ff3 KEYCLOAK-1563 update docs for server/adapter subsystem split & WF 9.0.0.Final 2015-07-14 15:55:14 -04:00
Stian Thorgersen 08c539ba51 Merge pull request #1452 from stianst/master
KEYCLOAK-1530 Ability to specify default database schema
2015-07-14 15:21:08 +02:00
Stian Thorgersen 4e538dd138 KEYCLOAK-1530 Ability to specify default database schema 2015-07-14 14:34:04 +02:00
Stian Thorgersen 66373ccab2 Merge pull request #1451 from stianst/master
KEYCLOAK-1426 and KEYCLOAK-1565
2015-07-14 12:12:06 +02:00
Stian Thorgersen 9c82c0700d Merge pull request #1425 from girirajsharma/master
[KEYCLOAK-1430] Buttons in form headers should not be primary buttons
2015-07-14 12:04:45 +02:00
Stian Thorgersen a480e50c16 KEYCLOAK-1426 Updated icons in menu 2015-07-14 11:53:02 +02:00
Stian Thorgersen 4391bf4f70 KEYCLOAK-1565 Updated to PatternFly 1.3.0 2015-07-14 11:52:58 +02:00
Stian Thorgersen 18f46cb527 Merge pull request #1450 from stianst/master
KEYCLOAK-1426
2015-07-14 11:32:19 +02:00
Stian Thorgersen 32b89adc04 Wire up new menu 2015-07-14 11:19:44 +02:00
Stian Thorgersen 5a213fcad9 Merge branch 'KEYCLOAK-1426' of https://github.com/andresgalante/keycloak 2015-07-14 10:09:34 +02:00
Stian Thorgersen d6f1d1bb3c Merge pull request #1449 from gtudan/KEYCLOAK-1564
KEYCLOAK-1564: Add CORS-Headers to token requests by password credentials
2015-07-14 09:10:22 +02:00
Gregor Tudan c8c0d0e804 KEYCLOAK-1564: Add CORS-Headers to token requests by password credentials 2015-07-14 08:22:08 +02:00
Stian Thorgersen aeddf2a860 Merge pull request #1448 from ssilvert/KEYCLOAK-1547-infinispan-session-timeout
Keycloak 1547 infinispan session timeout
2015-07-13 19:13:59 +02:00
giriraj sharma b876a5f7bd [KEYCLOAK-1430] Buttons in form headers should not be primary buttons 2015-07-13 22:41:54 +05:30
Stan Silvert af8949c291 Change to make removeUserSession() a protected method. 2015-07-13 11:21:35 -04:00
Stian Thorgersen e3da38df7c KEYCLOAK-1538 Deploy server feature pack to maven repo 2015-07-13 16:47:58 +02:00
Stian Thorgersen a16079e38d Remove unused feature-packs-builds 2015-07-13 14:08:25 +02:00
Stian Thorgersen e13b0fac63 Merge pull request #1447 from mstruk/KEYCLOAK-1370
KEYCLOAK-1370 Empty module de.idyl.winzipaes in keycloak-server-dist
2015-07-13 13:05:12 +02:00
Marko Strukelj 26190350c4 KEYCLOAK-1370 Empty module de.idyl.winzipaes in keycloak-server-dist 2015-07-13 12:42:06 +02:00
Bill Burke 7598cc62d3 Merge pull request #1446 from patriot1burke/master
test impersonation
2015-07-12 10:40:43 -04:00
Bill Burke b3211fa8c2 tooltip 2015-07-12 10:24:15 -04:00
Bill Burke 8dcc909b6e Merge remote-tracking branch 'upstream/master' 2015-07-12 10:12:31 -04:00
Bill Burke fafaf2c490 test impersonate 2015-07-12 10:12:19 -04:00
Marek Posolda 11e2f19503 Merge pull request #1444 from mposolda/master
Use kc-provider-config in LDAP mappers
2015-07-11 23:29:00 +02:00
mposolda d67bd0eff2 Use kc-provider-config in LDAP mappers 2015-07-11 23:11:01 +02:00
Marek Posolda 43bbea9a7c Merge pull request #1443 from mposolda/master
JSON import issue from older versions. Fix import at startup if master realm not present
2015-07-11 19:21:28 +02:00
mposolda dc366c53a7 KEYCLOAK-1175 Import at startup can fail if master realm not present 2015-07-11 18:56:52 +02:00
mposolda fe1ede26be KEYCLOAK-1558 Can't import the file exported in 1.2.0.Beta1 through admin console 2015-07-11 18:56:52 +02:00
Bill Burke aca799b28c Merge pull request #1442 from patriot1burke/master
impersonation in admin console
2015-07-11 11:36:01 -04:00
Bill Burke 1017a0af1d Merge remote-tracking branch 'upstream/master' 2015-07-11 11:09:48 -04:00
Bill Burke ff25484a34 viewUser fixes 2015-07-11 11:01:26 -04:00
Marek Posolda af922920ab Merge pull request #1441 from mposolda/master
KEYCLOAK-1233 Admin console support for add/remove federated identity
2015-07-11 16:48:29 +02:00
Bill Burke 919a3f1b91 fixes 2015-07-11 10:30:23 -04:00
Bill Burke 1ec8e63e9e impersonation redo in admin console 2015-07-11 10:12:55 -04:00
Bill Burke 96c76a059a Merge remote-tracking branch 'upstream/master' 2015-07-11 10:10:37 -04:00
Bill Burke 608701aea7 impersonation redo in admin console 2015-07-11 10:10:05 -04:00
mposolda 142d44a01f KEYCLOAK-1233 Admin console support for add/remove federated identity 2015-07-11 14:08:49 +02:00
mposolda 83c0f537ce Minor update in docs 2015-07-11 11:29:46 +02:00
Bill Burke aeab25b7fe Merge pull request #1440 from patriot1burke/master
user impersonation
2015-07-10 21:21:39 -04:00
Bill Burke ef255c6a5c fix build errors 2015-07-10 21:02:25 -04:00
Bill Burke 474ebed0ee Merge remote-tracking branch 'upstream/master' 2015-07-10 20:39:15 -04:00
Bill Burke 6e55604dc3 impersonation 2015-07-10 20:38:43 -04:00
Marek Posolda 2dfdfefb1a Merge pull request #1438 from mposolda/master
KEYCLOAK-1531 LDAP example and update Kerberos example to use example…
2015-07-09 22:45:56 +02:00
Stan Silvert 48f78cf80a KEYCLOAK-1547 Need to use overridable removeUserSession() method. 2015-07-09 14:46:54 -04:00
mposolda 69cc28dd4b KEYCLOAK-1531 LDAP example and update Kerberos example to use example embedded LDAP 2015-07-09 19:55:37 +02:00
Marek Posolda adb8bcf791 Merge pull request #1437 from mposolda/master
KEYCLOAK-1505 Fix JS error in admin console on old browsers
2015-07-09 10:33:27 +02:00
mposolda bd22d30674 KEYCLOAK-1505 Fix JS error in admin console on old browsers 2015-07-09 10:20:55 +02:00
mposolda afbf1cc33f Comment fix 2015-07-09 10:18:52 +02:00
Bill Burke 485df59c5b Merge pull request #1436 from patriot1burke/master
recaptcha docs
2015-07-08 19:47:45 -04:00
Bill Burke 43308b326d Merge pull request #1435 from patriot1burke/master
role selector
2015-07-08 19:47:22 -04:00
Bill Burke 6c9708c700 recaptcha docs 2015-07-08 19:47:15 -04:00
Bill Burke 4a962aa75a Merge remote-tracking branch 'upstream/master' 2015-07-08 19:18:23 -04:00
Bill Burke e786158071 role selector 2015-07-08 19:18:11 -04:00
Marek Posolda ea5a767948 Merge pull request #1434 from mposolda/master
KEYCLOAK-1533 KEYCLOAK-1534
2015-07-08 21:19:54 +02:00
mposolda bde65a6c57 KEYCLOAK-1533 Handle importing LDAP user with duplicate email during authentication 2015-07-08 20:41:32 +02:00
mposolda 94c0a436b5 KEYCLOAK-1534 handle account management update email or username to the already existing value 2015-07-08 15:27:05 +02:00
mposolda bddf1adeba Improve description for object classes 2015-07-08 12:27:15 +02:00
Bill Burke 9406a577c2 Merge pull request #1431 from mstruk/wf9-version
KEYCLOAK-1512 Upgrade to WildFly 9.0.0.Final
2015-07-07 11:34:34 -04:00
Bill Burke 40344726e1 Merge pull request #1432 from mstruk/ispn-activator
KEYCLOAK-1529 Drop InfinispanCacheActivator and make subsystem do it
2015-07-07 11:34:15 -04:00
Bill Burke 08ffea23b7 Merge pull request #1433 from patriot1burke/master
config directive
2015-07-07 11:32:45 -04:00
Bill Burke f1ddaa8051 config directive 2015-07-07 11:31:28 -04:00
Marko Strukelj 7ae62c1060 KEYCLOAK-1529 Drop InfinispanCacheActivator and make subsystem do it 2015-07-07 16:40:03 +02:00
Marko Strukelj 7c51046d8a KEYCLOAK-1512 Upgrade to WildFly 9.0.0.Final 2015-07-07 14:13:13 +02:00
Bill Burke df6d75e2c5 Merge pull request #1427 from grange74/KEYCLOAK-1486
KEYCLOAK-1486 fixed User link in Clients' Active Sessions page
2015-07-06 17:57:53 -04:00
Bill Burke 3c88d9666d Merge pull request #1430 from patriot1burke/master
auth config ui
2015-07-06 17:56:16 -04:00
Bill Burke ee74025f38 Merge pull request #1429 from mikeazo/patch-1
fixed typo in closing th tag
2015-07-06 17:55:51 -04:00
Bill Burke d49c7d47a2 Merge remote-tracking branch 'upstream/master' 2015-07-06 17:44:52 -04:00
Bill Burke 8f18e9bbbc auth config ui 2015-07-06 17:44:39 -04:00
mikeazo be96a3785b fixed typo in closing th tag 2015-07-06 13:41:10 -04:00
Marek Posolda f3aeb5ec9f Merge pull request #1428 from mposolda/master
Embedded LDAP for examples. LDAP sync bugfixing
2015-07-04 22:46:54 +02:00
mposolda 71ea61e7a6 KEYCLOAK-1532 LDAP sync fixes and other bugfixing 2015-07-04 22:25:47 +02:00
mposolda c6c73e5e59 KEYCLOAK-1531 Added embedded LDAP for examples. Added module keycloak-util-embedded-ldap with common code for testsuite and examples 2015-07-04 21:06:24 +02:00
nick.grange ae242f8480 KEYCLOAK-1486 fixed User link in Clients' Active Sessions page
Changed User link in Clients' Active Sessions page to use userId
instead of username to show User details instead of Resource not found.
Renamed UserSessionRepresentation’s user attribute to username as it
was ambiguous and only used in 1 place (i.e. client-sessions.html).
2015-07-04 22:38:34 +10:00
Stian Thorgersen 351a17f68d Merge pull request #1426 from stianst/master
KEYCLOAK-1530
2015-07-03 15:18:52 +02:00
Stian Thorgersen 1c4f7cb339 KEYCLOAK-1530
Ability to specify default database schema
2015-07-03 14:56:33 +02:00
Andres Galante 2713af189f fixes realm selector when there are too many realms on the list 2015-07-02 16:55:42 -03:00
Andres Galante be62d1a915 styles new menu 2015-07-02 16:45:48 -03:00
Bill Burke 68d71a6767 Merge pull request #1423 from patriot1burke/master
display flows
2015-07-02 11:44:51 -04:00
Bill Burke 46c88ad1bf Merge remote-tracking branch 'upstream/master' 2015-07-02 11:26:28 -04:00
Bill Burke 917151123f display flows 2015-07-02 11:25:51 -04:00
Stian Thorgersen b9e9d6a787 Merge branch 'velias-KEYCLOAK-1421' 2015-07-02 14:16:42 +02:00
Stian Thorgersen db20077c37 Merge branch 'KEYCLOAK-1421' of https://github.com/velias/keycloak into velias-KEYCLOAK-1421
Conflicts:
	testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
2015-07-02 14:15:54 +02:00
Stian Thorgersen ec3d027f90 Merge pull request #1421 from stianst/master
KEYCLOAK-1507
2015-07-02 14:10:57 +02:00
Stian Thorgersen 50678085c9 Merge pull request #1403 from mstruk/KEYCLOAK-1484
KEYCLOAK-1484 Keycloak from server-dist and demo-dist doesn't start
2015-07-02 14:10:19 +02:00
Stian Thorgersen 5af4785ba1 KEYCLOAK-1507
Tomcat Adapter throws NPE under certain conditions
2015-07-02 09:08:40 +02:00
Stian Thorgersen f59d42d5d3 Merge pull request #1420 from girirajsharma/master
[KEYCLOAK-1435] Base URL on client table should open in new tab
2015-07-02 09:00:24 +02:00
giriraj sharma fc7ae1ee96 [KEYCLOAK-1435] Base URL on client table should open in new tab 2015-07-02 06:40:22 +05:30
Bill Burke 2699bb9a44 Merge pull request #1368 from girirajsharma/master
[KEYCLOAK-1427] Move delete buttons
2015-07-01 15:32:11 -04:00
Bill Burke 212f5b4082 Merge pull request #1410 from dbarentine/master
Spec compliance, bug fixes
2015-07-01 15:27:47 -04:00
Bill Burke 9591f48077 Merge pull request #1419 from patriot1burke/master
recapthca
2015-07-01 15:26:20 -04:00
Bill Burke 0a8494a0f2 Merge remote-tracking branch 'upstream/master' 2015-07-01 15:10:14 -04:00
Bill Burke 39f2a4ab71 repatcha 2015-07-01 15:10:04 -04:00
Bill Burke 39aa09ca36 form action refactor 2015-07-01 14:07:02 -04:00
Bill Burke 45c5a2ae78 Merge pull request #1418 from patriot1burke/master
registration flow
2015-06-30 13:19:18 -04:00
Bill Burke a1c612f833 remove old code 2015-06-30 12:47:34 -04:00
Bill Burke bc39bb32d4 Merge remote-tracking branch 'upstream/master' 2015-06-30 12:46:29 -04:00
Bill Burke 884308ecb5 reg flow 2015-06-30 12:46:10 -04:00
Marek Posolda 2d7f232c3d Merge pull request #1417 from mposolda/master
KEYCLOAK-1487 multivalued attributes support
2015-06-30 14:56:45 +02:00
Bill Burke afa65d9ead registration flow 2015-06-29 22:12:06 -04:00
mposolda 605c88a029 KEYCLOAK-1487 Multivalued support for UserAttribute protocol mapper. End-to-end LDAP example test including application 2015-06-29 21:45:47 +02:00
mposolda 09994d1730 KEYCLOAK-1487 Support for multiple values of one UserModel attribute. LDAP multivalued attribute support 2015-06-29 14:56:40 +02:00
girirajSharma bb9c99ebf6 [KEYCLOAK-1427] Move delete buttons 2015-06-28 14:31:40 +05:30
Marek Posolda d4819886a6 Merge pull request #1416 from mposolda/master
LDAP mappers fixes
2015-06-26 14:43:10 +02:00
mposolda 23445123a2 KEYCLOAK-1490 Possibility to always read user attribute values from LDAP 2015-06-26 14:06:31 +02:00
mposolda 773bb43b41 KEYCLOAK-1487 Fix LDAP case-sensitivity. Show warning in case of duplicate username 2015-06-25 19:27:22 +02:00
mposolda 493dddde02 Mongo fix 2015-06-25 19:24:50 +02:00
Bill Burke 2e5704c6b4 Merge pull request #1413 from patriot1burke/master
refactor auth spi into additional form spi
2015-06-24 21:29:26 -04:00
Bill Burke be6c843bba Merge remote-tracking branch 'upstream/master' 2015-06-24 21:07:51 -04:00
Bill Burke 064d677fdc form auth 2015-06-24 21:07:38 -04:00
Marek Posolda 084ab782da Merge pull request #1412 from mposolda/master
KEYCLOAK-1501 Fix osgi packaging. Improve fuse demo example
2015-06-24 16:43:09 +02:00
mposolda 1a10a1ef75 KEYCLOAK-1501 Fix osgi packaging and fuse demo. Improve example 2015-06-24 16:26:05 +02:00
mposolda acc77e4e6c Remove ClientConnectionFilter filter mappings from web.xml in distribution 2015-06-24 11:10:22 +02:00
Stian Thorgersen 2c0ff9be60 Merge pull request #1407 from ssilvert/enforcer
Add enforcer plugin to enforce maven version.
2015-06-23 18:42:18 +02:00
Dane Barentine b9f5946cf0 [KEYCLOAK-1493] Added explicit dependency on keycloak-saml-core 2015-06-22 14:50:04 -07:00
Dane Barentine c403968fa8 [KEYCLOAK-1493] Added explicit dependency on keycloak-saml-core 2015-06-22 11:07:29 -07:00
Dane Barentine 14baef425e [KEYCLOAK-1493] Added a couple of WSTrust constants 2015-06-22 11:07:23 -07:00
Dane Barentine 8da532da93 [KEYCLOAK-1492] Fix mapClaim when nested attribute already exists 2015-06-22 11:00:40 -07:00
Dane Barentine facf701897 [KEYCLOAK-1491] SAML Spec compliance. NameIDFormat is optional, AttributeStatement must contain one or more attribute or encryptedattribute statements 2015-06-22 10:58:13 -07:00
Vlastimil Elias f9fe9ea5d6 rebased to latest keycloak/master 2015-06-22 10:48:54 +02:00
Vlastimil Elias f5a80c3007 KEYCLOAK-1421 patched source formatting 2015-06-22 10:37:27 +02:00
Vlastimil Elias 7cff37e707 KEYCLOAK-1421 Added timestamp of keycloak user creation into user models
and persistence
2015-06-22 10:37:26 +02:00
Vlastimil Elias 4e8c6b3fc4 KEYCLOAK-1421 patched source formatting 2015-06-22 10:33:57 +02:00
Vlastimil Elias 82282c1c75 KEYCLOAK-1421 - user created date added to the admin console 2015-06-22 10:32:39 +02:00
Vlastimil Elias d7379f29da KEYCLOAK-1421 Added timestamp of keycloak user creation into user models
and persistence
2015-06-22 10:32:37 +02:00
Bill Burke 000159226d refactor 2015-06-21 12:09:22 -04:00
Bill Burke 4ebdb8d24b refactor 2015-06-21 11:52:30 -04:00
Bill Burke fc2df08e15 ClientSessionModel.getNotes() 2015-06-20 09:07:54 -04:00
Bill Burke aaa83dc19a Merge pull request #1408 from patriot1burke/master
make authenticator config optional
2015-06-19 21:17:23 -04:00
Bill Burke adff0d5da0 make authenticator config optional 2015-06-19 21:16:45 -04:00
Stan Silvert 285d6931bc Add enforcer plugin to enforce maven version. 2015-06-19 18:14:25 -04:00
Bill Burke 114b687c5c Merge pull request #1406 from patriot1burke/master
refactor registration and console pages
2015-06-19 18:06:12 -04:00
Bill Burke a26ade3988 refactor registration and console pages 2015-06-19 17:51:59 -04:00
Bill Burke 94e2983310 Merge pull request #1405 from patriot1burke/master
cleanup client sessions
2015-06-19 16:23:31 -04:00
Bill Burke fb2f5f6756 Merge remote-tracking branch 'upstream/master' 2015-06-19 14:44:00 -04:00
Bill Burke d7b818cba2 cleanup client sessions 2015-06-19 14:43:40 -04:00
Bill Burke 8d885d14ed Merge pull request #1404 from patriot1burke/master
handle page refresh better
2015-06-18 20:16:29 -04:00
Bill Burke 39e0023a5f Merge remote-tracking branch 'upstream/master' 2015-06-18 20:01:34 -04:00
Bill Burke 84faac0cd6 handle page refresh better 2015-06-18 20:01:12 -04:00
Bill Burke 1bce639d35 refactor flow first phase 2015-06-18 16:48:28 -04:00
Marko Strukelj f2061610b9 KEYCLOAK-1484 Keycloak from server-dist and demo-dist doesn't start 2015-06-18 20:36:32 +02:00
Bill Burke 8716f9b41a Merge pull request #1401 from mstruk/KEYCLOAK-1476
KEYCLOAK-1476 NotSerializableException: org.keycloak.models.cache.entities.CachedClientRole
2015-06-17 17:36:02 -04:00
Bill Burke a24c817bb7 Merge pull request #1402 from patriot1burke/master
cleanup authenticators
2015-06-17 17:34:57 -04:00
Bill Burke 47997e0056 Merge remote-tracking branch 'upstream/master' 2015-06-17 17:15:16 -04:00
Bill Burke 70fd7bea99 cleanup authenticators 2015-06-17 17:15:01 -04:00
Marko Strukelj 52565375b3 KEYCLOAK-1476 NotSerializableException: org.keycloak.models.cache.entities.CachedClientRole
- Remove noop code (Enum serialization 101 - http://docs.oracle.com/javase/6/docs/platform/serialization/spec/serial-arch.html#6469)
2015-06-17 22:05:32 +02:00
Bill Burke 2c327d9eee Merge pull request #1389 from patriot1burke/master
access code checks
2015-06-17 15:59:23 -04:00
Stian Thorgersen caeb710444 KEYCLOAK-1476 2015-06-17 19:34:41 +02:00
Marko Strukelj 0b0b101184 KEYCLOAK-1476 NotSerializableException: org.keycloak.models.cache.entities.CachedClientRole
Conflicts:
	model/api/src/main/java/org/keycloak/models/AuthenticationExecutionModel.java
2015-06-17 19:34:38 +02:00
Bill Burke f5b4a0788e timeout message 2015-06-17 10:16:21 -04:00
Bill Burke 1aa338fe3e Merge remote-tracking branch 'upstream/master' 2015-06-17 09:43:14 -04:00
Bill Burke 5615d8d870 required actions edit 2015-06-17 09:42:58 -04:00
Stian Thorgersen 9711ccd914 Merge pull request #1397 from stianst/master
Fixes
2015-06-17 15:11:33 +02:00
Stian Thorgersen fbc2b845ad KEYCLOAK-1476 NotSerializableException: org.keycloak.models.cache.entities.CachedClientRole 2015-06-17 14:05:55 +02:00
Stian Thorgersen 39ecca0989 KEYCLOAK-1479 2015-06-17 13:53:11 +02:00
Stian Thorgersen f19b6afd85 Fix demo-dist build prob 2015-06-17 13:53:11 +02:00
Stian Thorgersen dca347398d Make it possible to specify ldif file for LDAPEmbeddedServer 2015-06-17 13:53:11 +02:00
Stian Thorgersen de6341bd87 Fix demo-dist build prob 2015-06-17 13:53:11 +02:00
mposolda 5cb9dbb87a Reduce liquibase logging during test to debug 2015-06-17 12:15:30 +02:00
Bill Burke dddc5181e7 required actions storage/display 2015-06-16 22:48:39 -04:00
Bill Burke 3b78fa2d5d required actions model 2015-06-16 18:17:38 -04:00
Bill Burke 2a64f5e3ce Merge remote-tracking branch 'upstream/master' 2015-06-16 09:30:07 -04:00
Bill Burke 8f5b53e3ce clientsession timeout checks 2015-06-16 09:29:36 -04:00
Stian Thorgersen 605f5decb3 Merge pull request #1392 from mstruk/KEYCLOAK-1448
KEYCLOAK-1448 Cannot configure an authenticator for method KEYCLOAK
2015-06-16 14:11:28 +01:00
Marko Strukelj d00e128920 KEYCLOAK-1448 Cannot configure an authenticator for method KEYCLOAK 2015-06-16 14:51:31 +02:00
Stian Thorgersen 226c1c53c0 Merge pull request #1390 from stianst/master
Add missing ExampleDS
2015-06-16 13:40:36 +01:00
Stian Thorgersen 001b874903 Add missing ExampleDS 2015-06-16 14:40:19 +02:00
Stian Thorgersen cc523ea356 Merge pull request #1388 from stianst/master
Fixes
2015-06-16 13:03:10 +01:00
Stian Thorgersen 5dc2b7b1d5 KEYCLOAK-1446
Field ... of subresource ... will not be injected according to spec
2015-06-16 14:02:21 +02:00
Bill Burke cd84e78b27 access code checks 2015-06-16 07:59:53 -04:00
Stian Thorgersen dedaa24972 Updated clustering docs 2015-06-16 13:31:58 +02:00
Stian Thorgersen 1b0c4e5d1f KEYCLOAK-1468
Infinispan cache not available in JNDI
2015-06-16 13:31:51 +02:00
Stian Thorgersen b7e3fc5f73 Recover server-overlay name 2015-06-16 08:11:15 +02:00
Stian Thorgersen 9b9ec09788 Merge pull request #1384 from stianst/master
Fix event-store example
2015-06-16 06:21:30 +01:00
Bill Burke bd7ceb0b73 Merge pull request #1383 from patriot1burke/master
verify clientsession actions
2015-06-15 18:28:17 -04:00
Bill Burke 9638c0dd83 verify clientsession actions 2015-06-15 18:04:55 -04:00
Stian Thorgersen 60f40544bb Fix event-store example 2015-06-15 20:24:32 +02:00
Stian Thorgersen 066fb7178d Merge pull request #1382 from stianst/master
Added wildfly extension to dist
2015-06-15 19:14:05 +01:00
Stian Thorgersen cd762e5e8c Added wildfly extension to dist 2015-06-15 20:13:20 +02:00
Stian Thorgersen f990d68cee Merge pull request #1380 from stianst/master
Fixes
2015-06-15 15:04:31 +01:00
Bill Burke 88f14b39a7 Merge pull request #1378 from patriot1burke/master
auth spi
2015-06-15 09:50:05 -04:00
Stian Thorgersen eda64584d7 Update keycloak-server.json 2015-06-15 15:49:55 +02:00
Bill Burke 2f2a2dced6 Merge remote-tracking branch 'upstream/master' 2015-06-15 09:28:25 -04:00
Bill Burke 38a2ea2fdf fix merge conflict mistakes 2015-06-15 09:28:11 -04:00
Bill Burke 43bad9a608 merge 2015-06-15 09:02:15 -04:00
Stian Thorgersen be5f3086ce KEYCLOAK-1449 Demo bundle doesn't include subsystem configuration 2015-06-15 15:01:22 +02:00
Stian Thorgersen 663f12d5e6 Merge pull request #1376 from stianst/master
Fixes
2015-06-15 14:00:09 +01:00
Stian Thorgersen 6e758d721d Fix CDI examples 2015-06-15 14:21:27 +02:00
Stian Thorgersen 4c98b04ab7 KEYCLOAK-1447 LinkageError deploying oauth-client-cdi to WildFly 8.2.0.Final 2015-06-15 13:22:36 +02:00
Stian Thorgersen f846645989 Update adapter installation docs 2015-06-15 09:03:50 +02:00
Stian Thorgersen 6bc79b590c Renamed eap6 server overlay poms 2015-06-15 09:03:50 +02:00
Stian Thorgersen 2ad7e870d8 Merge pull request #1374 from stianst/master
Fix testsuite/docker-cluster deps
2015-06-15 06:41:11 +01:00
Stian Thorgersen 87636669ae Fix testsuite/docker-cluster deps 2015-06-15 07:40:19 +02:00
Stian Thorgersen 8d627f1329 Merge pull request #1369 from stianst/master
KEYCLOAK-1411
2015-06-15 06:32:49 +01:00
Bill Burke c51cc4703b kerberos fixes 2015-06-14 20:58:02 -04:00
mposolda a1124c9e1f KEYCLOAK-1260 Upgrade h2 version to fix locking issues in SAMLKeyCloakServerBrokerWithSignatureTest 2015-06-12 19:58:27 +02:00
mposolda 20e245cb05 KEYCLOAK-1298 Fix constraint names to be uppercased 2015-06-12 19:17:12 +02:00
mposolda 5c8e165080 Enable liquibase trace logging with JPA profile 2015-06-12 17:20:57 +02:00
mposolda afe088a9e8 Fix Oracle together with Sybase 2015-06-12 17:20:38 +02:00
Stian Thorgersen 162f31baa2 Update server and adapter install docs 2015-06-12 16:14:03 +02:00
Stian Thorgersen 28a50df746 KEYCLOAK-1411
DefaultCacheUserProvider addUser returns UserModel instance which is not cached/managed by the cache
2015-06-12 15:33:22 +02:00
Stian Thorgersen 5a0d600322 Merge pull request #1367 from stianst/master
Bump version
2015-06-12 13:36:42 +01:00
Stian Thorgersen 38c1945ce4 Bump version 2015-06-12 14:35:34 +02:00
Stian Thorgersen 939527bd98 Bump version 2015-06-12 14:32:06 +02:00
Stian Thorgersen cc2de52a1a Revert to old RestEasy until we can drop support for EAP 6.4 2015-06-12 14:20:08 +02:00
Stian Thorgersen 4ccc37abbb Add EAP6 standalone.xml to source instead of dl eap6 from techpreview repo 2015-06-12 14:20:08 +02:00
Stian Thorgersen 47d1681e90 Merge pull request #1365 from stianst/master
Error page is displayed if user rejects sign in with social provider
2015-06-12 13:03:08 +01:00
Stian Thorgersen c89a412661 KEYCLOAK-1321
Error page is displayed if user rejects sign in with social provider
2015-06-12 13:32:30 +02:00
Stian Thorgersen 5bd53804f9 Fix admin-api to show that users are retrieved by ip, not username 2015-06-12 13:32:30 +02:00
Stian Thorgersen 0d957311b4 Merge pull request #1364 from mstruk/wf9cr2
KEYCLOAK-1441 Upgrade to WildFly 9 CR2
2015-06-12 11:30:42 +01:00
Marko Strukelj c2495acca9 KEYCLOAK-1441 Upgrade to WildFly 9 CR2 2015-06-12 11:49:36 +02:00
Marek Posolda c297b29a13 Merge pull request #1363 from mposolda/master
KEYCLOAK-1403 Update liquibase to newest version. Fix Sybase
2015-06-12 11:26:09 +02:00
mposolda 112ebf77d5 KEYCLOAK-1403 Update liquibase to newest version. Fix Sybase 2015-06-12 11:11:28 +02:00
Stian Thorgersen 5993d40fab Merge pull request #1353 from Smartling/KEYCLOAK-1438
Fix Spring Security adapter logout handling
2015-06-12 07:50:00 +01:00
Stian Thorgersen 2d82d15e5b Merge pull request #1361 from ssilvert/KEYCLOAK-1083-unlock-user-account
KEYCLOAK-1083: Provide a way for admin to unlock user account
2015-06-12 07:44:07 +01:00
Stian Thorgersen 656b157103 Merge pull request #1360 from mstruk/fix-poms
Fixed pom issues that were generating tons of Maven warnings
2015-06-12 07:43:38 +01:00
Bill Burke 392fa21f1e finish reg 2015-06-11 21:15:53 -04:00
Bill Burke fa99b5415d flow alias lookup 2015-06-11 18:02:49 -04:00
Marek Posolda 514417ac2d Merge pull request #1362 from mposolda/master
KEYCLOAK-1405 Fix MSSQL Server
2015-06-11 22:37:16 +02:00
mposolda 938cfe2555 KEYCLOAK-1405 Fix MSSQL Server 2015-06-11 22:23:45 +02:00
Stan Silvert d6e64a2c5e KEYCLOAK-1083: Provide a way for admin to unlock user account 2015-06-11 15:32:03 -04:00
Bill Burke c52d16da6d default required actions in model 2015-06-11 15:18:09 -04:00
Bill Burke 3f62cd9271 terms and conditions 2015-06-11 14:39:08 -04:00
Marek Posolda df7cb4a9d0 Merge pull request #1359 from mposolda/master
Database fixes
2015-06-11 17:14:19 +02:00
Marko Strukelj 9a37696d29 Fixed pom issues that were generating tons of Maven warnings 2015-06-11 16:57:33 +02:00
mposolda 20fe7ec7b8 Database fixes 2015-06-11 16:56:38 +02:00
Stian Thorgersen 37cef49565 Merge pull request #1357 from mstruk/eap6
KEYCLOAK-1412 Server-overlay for EAP 6.4
2015-06-11 15:00:20 +01:00
Stian Thorgersen b5ee395aac Merge pull request #1358 from tkyjovsk/master
fixed some UI tests broken by KEYCLOAK-1431
2015-06-11 13:56:23 +01:00
fkiss 7b89b80f71 added ignore on role mappings test 2015-06-11 14:37:12 +02:00
Tomas Kyjovsky 08f2b0dea9 fixed UI tests broken by KEYCLOAK-1431 2015-06-11 14:15:05 +02:00
Marko Strukelj 92e17f4b40 KEYCLOAK-1412 Server-overlay for EAP 6.4
- Added as7-server-subsystem
 - Added eap6-server-overlay
 - Moved modules to eap6-server-modules
 - Renamed wildfly-server-subsystem to wf9-server-subsystem for consistency
2015-06-11 09:40:47 +02:00
Stian Thorgersen b8aedd5a3a Merge pull request #1356 from matzew/ImportFix
Applying suggested import change from mstruk 💄
2015-06-11 08:06:27 +01:00
Matthias Wessendorf d3e178d459 Applying suggested import change from mstruk 💄 2015-06-11 08:52:53 +02:00
Stian Thorgersen 996d8e8cd3 Merge pull request #1355 from stianst/master
KEYCLOAK-1439 Admin Console is not loaded when Keycloak is installed …
2015-06-11 07:38:29 +01:00
Stian Thorgersen 0e1a059d8d KEYCLOAK-1439 Admin Console is not loaded when Keycloak is installed as root context 2015-06-11 08:15:42 +02:00
Tomas Kyjovsky 30359b51fa Merge upstream-master into tkyjovsk-master 2015-06-10 23:27:36 +02:00
Marek Posolda d8880e5ff3 Merge pull request #1354 from mposolda/master
KEYCLOAK-1260 Fix saml backchannel logout with JPA UserSession provid…
2015-06-10 21:37:05 +02:00
Stian Thorgersen 6819b8e3a5 Merge pull request #1352 from girirajsharma/master
[KEYCLOAK-1431] Update page titles
2015-06-10 18:28:25 +01:00
mposolda 03b521926a KEYCLOAK-1260 Fix saml backchannel logout with JPA UserSession provider on MySQL + PostgreSQL 2015-06-10 18:59:07 +02:00
Scott Rossillo abfec23404 Fix Spring Security adapter logout handling
Stops KeycloakLogoutHandler from throwing an exception if the
authentication is not of type KeycloakAuthenticationToken.

Fixes KEYCLOAK-1438.
2015-06-10 12:22:18 -04:00
Bill Burke 3dd282e11b pluggable required actions backend 2015-06-10 11:38:01 -04:00
girirajsharma 92efe8441e [KEYCLOAK-1431] Update page titles 2015-06-10 20:23:39 +05:30
Bill Burke 95349e6e2e clientsession.action to String 2015-06-10 09:21:23 -04:00
fkiss 15f8e83d4a added initial tests and page for assigning user role mappings 2015-06-10 15:02:25 +02:00
Bill Burke 0095968a73 Merge pull request #1344 from velias/KEYCLOAK-1373
KEYCLOAK-1373 - Allow to map other informations provided by Social Identity providers into Keycloak user profile attributes
2015-06-10 09:02:03 -04:00
Stian Thorgersen ad01d64803 Merge pull request #1351 from girirajsharma/master
[KEYCLOAK-1425] Remove address options on registration screen
2015-06-10 13:32:18 +01:00
girirajsharma 30405804bc [KEYCLOAK-1425] Remove address options on registration screen 2015-06-10 17:42:22 +05:30
Stian Thorgersen 6093d00fdd Merge pull request #1350 from girirajsharma/master
[KEYCLOAK-1424] Login button on login screen should be on the left
2015-06-10 12:14:06 +01:00
girirajsharma 1ba5ea411b [KEYCLOAK-1424] Login button on login screen should be on the left 2015-06-10 16:14:19 +05:30
Tomas Kyjovsky 9dd7a947e9 Merge upstream-master into tkyjovsk-master 2015-06-10 10:40:32 +02:00
Stian Thorgersen c51e6a916c Merge pull request #1346 from mstruk/srv-overlay
Re-enabled server-overlay, and demo-dist for Wildfly 9
2015-06-10 07:30:49 +01:00
Marek Posolda e9b9da6d20 Merge pull request #1349 from mposolda/master
KEYCLOAK-1416 federation provider/mapper model fixes
2015-06-09 23:39:49 +02:00
mposolda 557edbec6d KEYCLOAK-1416 federation provider/mapper model fixes 2015-06-09 23:15:43 +02:00
Marek Posolda 93650c442a Merge pull request #1348 from mposolda/master
KEYCLOAK-1088 Audit of user grants during login
2015-06-09 20:55:26 +02:00
mposolda d3e9b29d78 KEYCLOAK-1088 Audit of user grants during login 2015-06-09 20:37:12 +02:00
Marek Posolda 7cf1b002d2 Merge pull request #1347 from mposolda/master
Fix AdminRecoveryTest + minor fixes in messages
2015-06-09 18:06:59 +02:00
mposolda e96ba202e9 Fix AdminRecoveryTest to not break admin tests 2015-06-09 17:44:07 +02:00
mposolda 9a5ca4d367 Minor improve in error messages and tests 2015-06-09 17:43:20 +02:00
Marko Strukelj e6928c6456 KEYCLOAK-1417 Re-enable demo-dist 2015-06-09 16:35:46 +02:00
Marko Strukelj 245edcb5b9 KEYCLOAK-1418 Re-enable server-overlay
- it's based on server-dist for Wildfly 9 in order to reuse server-feature-pack - no dependency on distribution/modules
2015-06-09 16:35:46 +02:00
Marek Posolda e4cb97aa49 Merge pull request #1345 from mposolda/master
KEYCLOAK-1401 Fix oracle and sybase - step 1
2015-06-09 15:51:51 +02:00
mposolda bc93066fe3 KEYCLOAK-1401 Fix oracle and sybase - step 1 2015-06-09 15:35:03 +02:00
Lukas Kubik bf686bd791 Revert "Add new .gitattributes file"
This reverts commit 01e232158b.
2015-06-09 15:19:36 +02:00
Lukas Kubik 01e232158b Add new .gitattributes file 2015-06-09 15:16:34 +02:00
Vlastimil Elias c6e0195a3c KEYCLOAK-1373 - added attribute importer for other social providers,
documented
2015-06-09 13:49:58 +02:00
Stian Thorgersen 966d939c12 Merge pull request #1340 from mstruk/srv-subsystem
Cleanup, and simplify keycloak-server-subsystem
2015-06-09 07:05:07 +01:00
Stian Thorgersen c61c05be51 Merge pull request #1335 from ssilvert/keycloak-config
KEYCLOAK-1404: Need recovery mechanism for master admin user
2015-06-09 07:02:47 +01:00
Stian Thorgersen 7b099e3d6b Merge pull request #1341 from mstruk/KEYCLOAK-1370
KEYCLOAK-1370 Empty module de.idyl.winzipaes in keycloak-server-dist
2015-06-09 06:45:39 +01:00
Marek Posolda 6d257a0d4c Merge pull request #1343 from mposolda/master
KEYCLOAK-1358 docs for LDAP mappers
2015-06-08 21:11:27 +02:00
mposolda b80a4a0aa9 KEYCLOAK-1358 docs for LDAP mappers 2015-06-08 21:10:38 +02:00
Marek Posolda aabb3428a8 Merge pull request #1342 from mposolda/master
JSON migration, LDAP logging reduced to trace/debug
2015-06-08 20:24:45 +02:00
mposolda 80ff7b92db KEYCLOAK-886 Reduce some LDAP info logging to trace and debug 2015-06-08 19:23:32 +02:00
mposolda 7badd3d5e5 JSON migration 2015-06-08 19:23:32 +02:00
Stan Silvert e977a363ef Require user to specify a temporary admin password to do admin recovery. 2015-06-08 13:04:52 -04:00
Bill Burke 91283878ac html encoding fix 2015-06-08 12:38:16 -04:00
Vlastimil Elias 74ace4006c Added base abstract implementation of Attribute mapper for Social
providers, used for GitHub provider
2015-06-08 17:04:53 +02:00
Marko Strukelj 7be957f4f9 KEYCLOAK-1370 Empty module de.idyl.winzipaes in keycloak-server-dist 2015-06-08 15:59:51 +02:00
Marko Strukelj 3643e76a06 Cleanup, and simplify keycloak-server-subsystem
- KEYCLOAK-1346 Remove support for overlays in server subsystem
 - KEYCLOAK-1347 Remove support for multiple auth-servers
 - KEYCLOAK-1348 Simplify server subsystem definition
2015-06-08 15:33:34 +02:00
Marek Posolda 07bc756785 Merge pull request #1339 from mposolda/master
DB migration
2015-06-08 13:17:15 +02:00
mposolda 0af68d28f1 KEYCLOAK-1357 LDAP migration 2015-06-08 12:29:24 +02:00
mposolda 75e1f50faf KEYCLOAK-1390 mongo migration for identity providers 2015-06-08 12:29:18 +02:00
Bill Burke dcc40b0a63 error handling 2015-06-05 15:51:43 -04:00
Bill Burke dc0d9a8dce merge 2015-06-05 14:44:37 -04:00
Bill Burke 021b01f0bd passing tests 2015-06-05 13:49:24 -04:00
Marek Posolda b578122f19 Merge pull request #1337 from mposolda/ldap
KEYCLOAK-1067 Upgrade embedmongo plugin version. Speed-up mongo tests…
2015-06-05 18:53:36 +02:00
mposolda e014dcce76 KEYCLOAK-1067 Upgrade embedmongo plugin version. Speed-up mongo testsuite 2015-06-05 18:51:27 +02:00
Marek Posolda a1bdf2837e Merge pull request #1336 from mposolda/ldap
Mongo fixes & few other fixes
2015-06-05 18:29:45 +02:00
mposolda 0092d9f74d Mongo fixes & few other fixes 2015-06-05 17:52:56 +02:00
Stan Silvert e48aafd588 Fix spelling error. 2015-06-05 07:46:39 -04:00
Marek Posolda d958d85290 Merge pull request #1334 from mposolda/ldap
KEYCLOAK-1359 more Active Directory fixes
2015-06-05 11:59:08 +02:00
mposolda 5b40031251 KEYCLOAK-1359 more Active Directory fixes 2015-06-05 11:32:29 +02:00
Stian Thorgersen 399a4a0511 Merge pull request #1333 from stianst/master
KEYCLOAK-1407 Label for otp on login is 'Log in'
2015-06-05 08:52:48 +01:00
Stian Thorgersen bebe51c885 KEYCLOAK-1407 Label for otp on login is 'Log in' 2015-06-05 09:37:34 +02:00
Stan Silvert 6812514683 KEYCLOAK-1404: Need recovery mechanism for master admin user 2015-06-04 15:29:44 -04:00
Marek Posolda 62de481329 Merge pull request #1332 from mposolda/ldap
KEYCLOAK-1359 LDAP & Active directory fixes and improvements
2015-06-04 20:47:10 +02:00
mposolda c3eb6df220 KEYCLOAK-1359 LDAP & Active directory fixes and improvements 2015-06-04 20:15:44 +02:00
Stian Thorgersen d875b9885d Merge pull request #1331 from stianst/master
KEYCLOAK-1325 Public/private SPI
2015-06-04 15:26:46 +01:00
Bill Burke 9ab023cc6c more 2015-06-04 10:18:24 -04:00
Stian Thorgersen 3510e17dd3 Merge pull request #1330 from vramik/master
KEYCLOAK-1398 - Change type of 'REPRESENTATION' from BLOB to TEXT in …
2015-06-04 15:02:12 +01:00
Stian Thorgersen f50570e350 KEYCLOAK-1325
Public/private SPI
2015-06-04 15:59:47 +02:00
vramik a52cdae1f7 KEYCLOAK-1398 - Change type of 'REPRESENTATION' from BLOB to TEXT in jpa-changelog-1.3.0.Beta1.xml 2015-06-04 15:43:55 +02:00
Marek Posolda 826c60ae36 Merge pull request #1324 from velias/KEYCLOAK-1371
KEYCLOAK-1371 - Perform "Update Profile on First Login" only if some of mandatory user profile fields is missing from identity provider
2015-06-04 15:19:59 +02:00
Stian Thorgersen d2c9d1569c Merge pull request #1329 from mstruk/modules-cleanup
Clean up distribution/modules and adapter-feature-packs
2015-06-04 13:56:35 +01:00
Stian Thorgersen 15dca61c59 Merge pull request #1318 from cfsnyder/master
KEYCLOAK-681 multi-part emails
2015-06-04 13:55:52 +01:00
Stian Thorgersen 4224496611 Doc update 2015-06-04 14:41:24 +02:00
Stian Thorgersen 7467fbaa12 Merge pull request #1328 from girirajsharma/master
Minor fix: resolved a scope variable in services.js and a typo.
2015-06-04 11:52:17 +01:00
Marko Strukelj 580e4fb0b2 Clean up distribution/modules and adapter-feature-packs 2015-06-04 11:39:08 +02:00
girirajsharma 90b15a070c Minor fix: resolved a scope variable in services.js and a typo. 2015-06-04 14:35:48 +05:30
Bill Burke b54061fc3f more 2015-06-03 18:51:57 -04:00
Marek Posolda ce7de3b576 Merge pull request #1327 from mposolda/ldap
KEYCLOAK-1359 More LDAP fixes
2015-06-03 20:00:58 +02:00
mposolda 31d0365e85 KEYCLOAK-1359 More LDAP fixes 2015-06-03 19:57:11 +02:00
Stian Thorgersen 084da8a03d Merge pull request #1325 from stianst/master
KEYCLOAK-1386 Direct Grant API always on
2015-06-03 18:29:29 +01:00
Marek Posolda e395ecb749 Merge pull request #1326 from mposolda/ldap
KEYCLOAK-1359 Fix testsuite with OpenLDAP, Other LDAP fixes
2015-06-03 18:45:43 +02:00
mposolda a34cb92fc1 KEYCLOAK-1359 Fix testsuite with OpenLDAP, Other LDAP fixes 2015-06-03 18:44:23 +02:00
Bill Burke c12fe28b2d phased auth spi introduction 2015-06-03 10:55:03 -04:00
Cory Snyder 0ac000adca KEYCLOAK-681 multi-part emails 2015-06-03 10:33:18 -04:00
Stian Thorgersen 1dd0b563b6 KEYCLOAK-1386 Direct Grant API always on 2015-06-03 16:24:15 +02:00
Marek Posolda 26acf6fa83 Merge pull request #1323 from mposolda/ldap
Ldap: testsuite upgrade + per-request federation caching
2015-06-03 15:36:29 +02:00
Vlastimil Elias dcc19a39d7 KEYCLOAK-1371 - Perform "Update Profile on First Login" only if some of
mandatory user profile fields is missing from identity provider
2015-06-03 15:24:25 +02:00
mposolda 496062ef0c KEYCLOAK-1359 LDAP tests update 2015-06-03 14:54:14 +02:00
mposolda b27f18c380 KEYCLOAK-838 per-request cache in UserFederationManager 2015-06-03 12:48:19 +02:00
Marek Posolda 442d65bb5f Merge pull request #1322 from mposolda/master
KEYCLOAK-1368 allow forwarding to error page in bearer-only deploymen…
2015-06-03 12:47:04 +02:00
mposolda 35e4a5e56d KEYCLOAK-1368 allow forwarding to error page in bearer-only deployments. Adding DeploymentBuilder 2015-06-03 12:34:56 +02:00
Stian Thorgersen fb60ca115f Merge pull request #1321 from girirajsharma/master
[KEYCLOAK-1356] Order the roles in a alphabetical way
2015-06-03 11:00:57 +01:00
Stian Thorgersen 3d3871b0e6 Merge pull request #1291 from AOEpeople/KEYCLOAK-1305
KEYCLOAK-1305 Add possibility to change username
2015-06-03 10:51:34 +01:00
Stian Thorgersen 060a59f982 Merge pull request #1317 from velias/KEYCLOAK-1372
KEYCLOAK-1372 - do not perform email verification if email is provided by trusted Identity provider
2015-06-03 10:29:52 +01:00
Vlastimil Elias c6c0abbedf KEYCLOAK-1372 - typo patched 2015-06-03 11:00:02 +02:00
Vlastimil Elias df182c3301 KEYCLOAK-1372 - tests updated to test whole user flow including email
verification step
2015-06-03 10:54:33 +02:00
Marek Posolda 56c858d917 Merge pull request #1297 from AOEpeople/KEYCLOAK-1350
KEYCLOAK-1350 client_session_state should be updated when refreshing a token
2015-06-03 09:15:50 +02:00
Stian Thorgersen 00068c460a Merge pull request #1320 from bradthurber/missing-space-in-example-customer-app-string
minor text edit for an error message on customer example
2015-06-03 07:30:54 +01:00
girirajsharma 5d0b6400df [KEYCLOAK-1356] Order the roles in a alphabetical way 2015-06-03 02:02:20 +05:30
Brad Thurber 413295e15e minor text edit 2015-06-02 15:34:50 -04:00
Vlastimil Elias 1c3d165e5d KEYCLOAK-1372 - tests improved 2015-06-02 15:41:50 +02:00
Petr Mensik 5fe0406ec9 Fixed addDisabledUser test 2015-06-02 15:37:19 +02:00
Sebastian Rose 17affe576f KEYCLOAK-1350 client_session_state should be updated when refreshing a token 2015-06-02 15:01:47 +02:00
Vlastimil Elias b86d091ad1 KEYCLOAK-1372 - do not perform email verification if email is provided
by trusted Identity provider
2015-06-02 14:59:29 +02:00
Stian Thorgersen ea544c639e Merge pull request #1316 from girirajsharma/master
[KEYCLOAK-1367] - Enter doesn't work in user search box
2015-06-02 13:35:03 +01:00
Niko Köbler 492e6cd856 KEYCLOAK-1305 Add possibility to change username 2015-06-02 14:08:19 +02:00
Bill Burke 5680be743c Merge pull request #1298 from AOEpeople/KEYCLOAK-1103
KEYCLOAK-1103 proxy configuration for inject header if user is logged in, but do not enforce login
2015-06-02 08:04:05 -04:00
Bill Burke 1fd22ee672 Merge pull request #1288 from dbarentine/master
[KEYCLOAK-1354] Make destination optional
2015-06-02 07:59:50 -04:00
girirajsharma c3faea0428 [KEYCLOAK-1367] - Enter doesn't work in user search box 2015-06-02 17:25:05 +05:30
Stian Thorgersen 483ac69c47 Merge pull request #1315 from velias/KEYCLOAK-1362
KEYCLOAK-1362 - button CSS classes are defined by theme properties now to be customizable
2015-06-02 10:55:18 +01:00
Stian Thorgersen 805ad9f250 Merge pull request #1314 from mstruk/modules-cleanup
KEYCLOAK-1332 Remove adapter modules from server
2015-06-02 10:54:46 +01:00
Vlastimil Elias 43799fd315 KEYCLOAK-1362 - button CSS classes are defined by theme properties 2015-06-02 10:47:13 +02:00
Marko Strukelj 91ec4cb5c7 KEYCLOAK-1332 Remove adapter modules from server 2015-06-02 10:22:26 +02:00
Stian Thorgersen 634ce85f17 Merge pull request #1313 from stianst/master
Changes to Travis around caching
2015-06-02 09:15:44 +01:00
Stian Thorgersen b6c52e8859 Changes to Travis around caching 2015-06-02 09:59:06 +02:00
Stian Thorgersen d042f6e2c9 Merge pull request #1311 from tkyjovsk/master
Removed keycloak-wildfly-adapter-subsystem dependency from keycloak-jboss-modules.
2015-06-02 08:42:36 +01:00
Stian Thorgersen cfe8c2956f Merge pull request #1309 from velias/KEYCLOAK-1369
KEYCLOAK-1369 GUI order attribute of Social providers is reflected in Account management app
2015-06-02 08:41:58 +01:00
Stian Thorgersen 235a8eab02 Merge pull request #1308 from mstruk/srv-subsystem
KEYCLOAK-1304 WF9 server subsystem
2015-06-02 08:41:37 +01:00
Stian Thorgersen 6baefa7490 Merge pull request #1307 from velias/KEYCLOAK-1361
KEYCLOAK-1361 - ability to add custom fields (user.attributes) on login-update-profile.ftl page
2015-06-02 08:40:54 +01:00
Stian Thorgersen 319b29aa7d Merge pull request #1300 from girirajsharma/master
[KEYCLOAK-1200] From and To filter fields in Event viewer in admin app
2015-06-02 08:32:02 +01:00
Stian Thorgersen 02428e4f0f Merge pull request #1306 from vramik/master
KEYCLOAK-1366 - Change type of 'REPRESENTATION' from VARCHAR to BLOB …
2015-06-02 08:30:19 +01:00
Tomas Kyjovsky 3fe93eebb6 Removed keycloak-wildfly-adapter-subsystem dependency from keycloak-jboss-modules. 2015-06-01 19:18:56 +02:00
Marek Posolda f5c7c14ce0 Merge pull request #1310 from mposolda/ldap2
KEYCLOAK-886 LDAP: Fixes and improvements
2015-06-01 18:12:04 +02:00
mposolda f57ab78916 KEYCLOAK-886 LDAP: Fixes and improvements 2015-06-01 17:38:34 +02:00
Vlastimil Elias 087dab6f3d KEYCLOAK-1369 GUI order attribute of Social providers is reflected in
Account management app
2015-06-01 17:01:57 +02:00
Marko Strukelj 3df504b6b4 KEYCLOAK-1304 WF9 server subsystem
- remove unnecessary dependencies
2015-06-01 16:07:59 +02:00
Vlastimil Elias ea98b26766 KEYCLOAK-1361 - ability to add custom fields (user.attributes) on
login-update-profile.ftl page
2015-06-01 15:44:36 +02:00
Stian Thorgersen 6d6e598ce5 Merge pull request #1304 from lkubik/remove-multiple-mysql-versions
Remove duplicit mysql version declaration
2015-06-01 13:35:39 +01:00
Lukas Kubik 67ad7463f4 Remove duplicit mysql version declaration 2015-06-01 14:08:32 +02:00
vramik df6b481112 KEYCLOAK-1366 - Change type of 'REPRESENTATION' from VARCHAR to BLOB in jpa-changelog-1.3.0.Beta1.xml 2015-06-01 11:43:06 +02:00
Marek Posolda 5301b556f0 Merge pull request #1303 from mposolda/ldap2
Update links in kerberos docs and example README
2015-05-29 21:45:32 +02:00
mposolda 2ff7345b08 Update links in kerberos docs and example README 2015-05-29 21:44:28 +02:00
Stian Thorgersen bafcd3f036 Merge pull request #1302 from stianst/master
KEYCLOAK-1327 Updated for users
2015-05-29 15:59:07 +01:00
Stian Thorgersen 5f787028df KEYCLOAK-1327 Updated for users 2015-05-29 15:29:04 +01:00
Stian Thorgersen e1e65af8ea Merge pull request #1301 from mstruk/wf9
KEYCLOAK-1303 WF9 adapter subsystem
2015-05-29 15:23:28 +01:00
girirajsharma 5bb71d396a [KEYCLOAK-1200] From and To filter fields in Event viewer in admin app 2015-05-29 19:13:56 +05:30
Stian Thorgersen 058f44743c Merge pull request #1299 from stianst/master
Misc
2015-05-29 14:22:47 +01:00
Marko Strukelj 2077a2a3af KEYCLOAK-1303 WF9 adapter subsystem
- not dependent on distribution/modules any more
 - keycloak-adapter-subsystem moved to keycloak-wf9-subsystem
 - still installed as <extension module="org.keycloak.keycloak-adapter-subsystem"/>
2015-05-29 15:17:41 +02:00
Stian Thorgersen 5a3a0ae437 KEYCLOAK-1325 Log warning if internal SPI is used 2015-05-29 13:58:40 +01:00
Sebastian Rose b4204fc806 getOrDefault not in java 7 2015-05-29 14:33:52 +02:00
Sebastian Rose e8c90c1327 fixed typo in doc 2015-05-29 14:33:52 +02:00
Sebastian Rose 136f2c8bb7 documentation fixed 2015-05-29 14:33:52 +02:00
Sebastian Rose 2b5e0e238d constants 2015-05-29 14:33:52 +02:00
Sebastian Rose a6eface8bc configurable header names, documentation 2015-05-29 14:33:52 +02:00
Sebastian Rose 7659b1aa18 KEYCLOAK-1103 - First draft 2015-05-29 14:33:52 +02:00
Stian Thorgersen a953b52eac KEYCLOAK-1327 Updated for client stats 2015-05-29 13:15:35 +01:00
Stian Thorgersen 6f164f0ee9 KEYCLOAK-1327 Updated for clients 2015-05-29 13:15:34 +01:00
Stian Thorgersen f61a9d7a70 Merge pull request #1296 from mstruk/as7
KEYCLOAK-1301 AS7 / EAP6 adapter subsystem
2015-05-29 10:13:59 +01:00
Marko Strukelj 4f270bffd0 Refactor EAP 6 adapter distribution
- not dependent on distribution/modules any more
 - uses the same modules as AS7
 - again use <extension module="org.keycloak.keycloak-adapter-subsystem"/>
2015-05-28 23:56:11 +02:00
Marko Strukelj fa90602aa0 Refactor AS 7 adapter distribution
- not dependent on distribution/modules any more
 - again use <extension module="org.keycloak.keycloak-adapter-subsystem"/>
2015-05-28 23:56:11 +02:00
Marek Posolda eaf5034ec7 Merge pull request #1295 from mposolda/ldap2
Ldap fixes + added authType to UI to allow users specify LDAP auth type
2015-05-28 20:44:31 +02:00
mposolda e83de896c9 LDAP fixes + added authType to UI to allow users specify authType 2015-05-28 19:54:15 +02:00
mposolda bcd607a1ee KEYCLOAK-1360 ModelExceptionMapper logges the exception 2015-05-28 19:54:15 +02:00
Bill Burke e1adceeb85 Merge pull request #1294 from patriot1burke/master
javadoc
2015-05-28 09:31:38 -04:00
Bill Burke 106bdc3c52 javadoc 2015-05-28 09:30:57 -04:00
Stian Thorgersen 5229807020 Merge pull request #1293 from girirajsharma/master
[KEYCLOAK-1276] Update Zocial.css
2015-05-28 15:26:13 +02:00
girirajsharma 1e89467b31 [KEYCLOAK-1276] Update Zocial.css 2015-05-28 18:39:51 +05:30
Stian Thorgersen f65b502a96 Merge pull request #1283 from girirajsharma/master
[KEYCLOAK-1200]- From and To filter fields in Event viewer in admin app
2015-05-28 15:03:22 +02:00
girirajsharma efe8342965 [KEYCLOAK-1200]- From and To filter fields in Event viewer in admin app 2015-05-28 18:05:31 +05:30
Marek Posolda 90cb3acd2f Merge pull request #1292 from mposolda/ldap2
Ldap enhancements + Make admin requests to have RealmModel and ClientModel available
2015-05-28 12:40:11 +02:00
mposolda 98dd87efbc Added ProviderConfigProperty.CLIENT_LIST and refactor role federation mapper to use it 2015-05-28 12:28:26 +02:00
mposolda ce6576ce84 KEYCLOAK-1355 Make admin requests to have RealmModel and ClientModel available in KeycloakContext 2015-05-28 12:28:26 +02:00
mposolda 5d4869f915 KEYCLOAK-1300 Fullname test 2015-05-28 12:28:26 +02:00
Stian Thorgersen 92567a070c Merge pull request #1290 from mstruk/wf8
Reintroduce org.keycloak.keycloak-adapter-subsystem module to WF8
2015-05-28 10:08:30 +02:00
Marko Strukelj 30955c4e2c Reintroduce org.keycloak.keycloak-adapter-subsystem module to WF8
- again use <extension module="org.keycloak.keycloak-adapter-subsystem"/>
2015-05-28 09:49:34 +02:00
Stian Thorgersen f9d51db182 Merge pull request #1282 from behana/master
Add send-verify-email endpoint to admin-rest-api
2015-05-28 09:09:06 +02:00
Dane Barentine 852e799fea [KEYCLOAK-1354] Make destination optional and fix details for SAML login events 2015-05-27 15:36:10 -07:00
behana bbc3e99bb5 KEYCLOAK-1353 Option to pass client_id to resetPasswordMail 2015-05-28 00:10:36 +02:00
behana e8e22ee44c KEYCLOAK-1352 Add send-verify-email to admin-rest-api 2015-05-28 00:05:39 +02:00
Bill Burke 7a211beede Merge pull request #1287 from patriot1burke/master
unfinished working auth spi
2015-05-27 14:38:05 -04:00
Bill Burke 24279b138b Merge remote-tracking branch 'upstream/master' 2015-05-27 14:28:57 -04:00
Bill Burke a2718a889d unfinished working auth spi 2015-05-27 14:28:47 -04:00
Bill Burke 756de9f7f6 Merge pull request #1286 from patriot1burke/master
auth spi initialization
2015-05-27 11:27:10 -04:00
Bill Burke 143d176dcd Merge remote-tracking branch 'upstream/master' 2015-05-27 10:39:59 -04:00
Bill Burke a1f7cfaf3a auth spi initialization 2015-05-27 10:39:46 -04:00
Stian Thorgersen a549b3ac70 Merge pull request #1284 from pmensik/integration-arquillian
Prepare UI testing for PR
2015-05-27 10:25:01 +02:00
Marek Posolda 43c9179204 Merge pull request #1285 from mposolda/ldap
KEYCLOAK-886 User Federation Mappers - admin console
2015-05-26 18:28:43 +02:00
mposolda dfe232cf80 KEYCLOAK-886 User Federation Mappers - admin console 2015-05-26 17:48:52 +02:00
Petr Mensik ba88cdce70 Prepare UI testing for PR 2015-05-26 15:57:01 +02:00
Stian Thorgersen 269f9fe860 Merge pull request #1274 from mstruk/wf8
Wildfly 8.2.0.Final compatibility
2015-05-26 09:24:56 +02:00
Stian Thorgersen 4a670ab236 Merge pull request #1276 from mstruk/fix-demos
Fix HttpClient issues in example demos on AS7 / Wildfly
2015-05-26 09:02:06 +02:00
Stian Thorgersen ab934f3d35 Merge pull request #1273 from girirajsharma/master
[KEYCLOAK-1334] Forgot password page does not return validation error
2015-05-26 08:56:04 +02:00
Stian Thorgersen 24eca809f1 Merge pull request #1275 from mstruk/pom-repo-fix
Fix build issue with missing org.jboss.as version 7.5.0.Final-redhat-15
2015-05-26 08:55:34 +02:00
Bill Burke 57780b6520 Merge pull request #1279 from patriot1burke/master
auth spi data model
2015-05-22 17:03:45 -04:00
Bill Burke f5e301fe0d merge 2015-05-22 16:15:55 -04:00
Bill Burke 68976f5b0c auth spi datamodel 2015-05-22 16:03:26 -04:00
girirajsharma 8e7e208265 [KEYCLOAK-1334] Forgot password page does not return validation error
message when input field is empty
2015-05-23 01:18:23 +05:30
mposolda 0951c11aa6 Revert mistakenly edited file 2015-05-22 21:31:03 +02:00
Marek Posolda 3d4ca01242 Merge pull request #1277 from mposolda/ldap
Ldap enhancements - step 1
2015-05-22 21:28:07 +02:00
mposolda 319f86e91a KEYCLOAK-886 Admin console - step 1 2015-05-22 21:09:55 +02:00
mposolda 490b3e3603 KEYCLOAK-886 Added builtin federation mappers when creating new LDAP Federation model. Testsuite passing 2015-05-22 21:09:55 +02:00
mposolda 7476ee51e4 KEYCLOAK-886 Model and representations for UserFederationMappers 2015-05-22 21:09:50 +02:00
mposolda a9f1fda68a KEYCLOAK-630 Added Role Federation mapper. Fixes and refactoring 2015-05-22 21:08:33 +02:00
mposolda 975337f225 KEYCLOAK-1300 Added FullNameLDAPFederationMapper 2015-05-22 21:08:21 +02:00
mposolda 1490f106f2 KEYCLOAK-599 Added UserFederationMappers. Added UserAttributeLDAPFederationMapper 2015-05-22 21:07:32 +02:00
mposolda 61c35265a6 KEYCLOAK-826 Show count of created/updated users during federation sync 2015-05-22 21:06:38 +02:00
mposolda 0f4497e53e Remove user from KC after removing from federation 2015-05-22 21:06:38 +02:00
Marko Strukelj ca60c283fc Fix HttpClient issues in example demos on AS7 / Wildfly
- don't use org.keycloak.adapter.HttpClientBuilder - it's Keycloak internals
 - don't use HttpClient 4.2 or 4.3 APIs (not default in AS7, and Wildfly 8)
    so way we can use the same jboss-deployment-structure.xml
2015-05-22 19:16:34 +02:00
Marko Strukelj 37298bdbd6 Fix build issue with missing org.jboss.as version 7.5.0.Final-redhat-15
- activeByDefault profile is turned off when -P is used
2015-05-22 18:10:40 +02:00
Marko Strukelj d70fd86a82 Wildfly 8.2.0.Final compatibility
- added integration/keycloak/wf8-subsystem
 - added distribution/adapters/wf8-adapter containing wf8-modules, and wf8-adapter-zip
 - there's no dependency on distribution/modules
 - subsystem is installed by unzipping keycloak-wf8-adapter-dist.zip to Wildfly 8.2.0.Final, and adding <extension-module>org.keycloak.keycloak-wf8-subsystem</extension-module> to standalone.xml
2015-05-22 17:38:02 +02:00
Stian Thorgersen ad606cbce6 Merge pull request #1272 from stianst/master
Version bump
2015-05-22 09:05:30 +02:00
Stian Thorgersen 4e0a32a37a Version bump 2015-05-22 09:04:30 +02:00
Stian Thorgersen 7290040008 Merge pull request #1270 from mstruk/as7
AS 7.1.1.Final / EAP 6 compatibility
2015-05-22 09:04:06 +02:00
Marko Strukelj 91bf50eb6c AS 7.1.1.Final / EAP 6.4 compatibility 2015-05-21 11:30:26 +02:00
Stian Thorgersen 748ed30b47 Merge pull request #1268 from stianst/master
Fixes
2015-05-20 07:56:54 +02:00
Stian Thorgersen b88d2f792d NotSerializableException: org.keycloak.models.sessions.infinispan.entities.LoginFailureKey 2015-05-20 07:11:17 +02:00
Stian Thorgersen c8b19fa1ae Updated release instructions 2015-05-20 07:10:53 +02:00
Stian Thorgersen c0795ce2c7 Merge pull request #1267 from stianst/master
Updated admin events
2015-05-19 11:40:42 +02:00
Stian Thorgersen 12c3aa83dd Updated admin events 2015-05-19 11:40:17 +02:00
Stian Thorgersen c193ba0c81 Merge pull request #1261 from panga/master
KEYCLOAK-1306 - Better Admin API error handling (new)
2015-05-19 08:56:19 +02:00
Stian Thorgersen d8226c457f Merge pull request #1266 from stianst/master
Dist fixes
2015-05-19 08:30:44 +02:00
Stian Thorgersen a507771f7c Fix demo dist 2015-05-19 08:15:39 +02:00
Stian Thorgersen 2f8d577e95 Fix server-overlay 2015-05-19 08:15:39 +02:00
Stian Thorgersen 362babe5e2 Fixed server-dist 2015-05-19 08:15:39 +02:00
Bill Burke d9297cee16 Merge pull request #1265 from patriot1burke/master
phase 1 auth/required actions SPI
2015-05-18 16:57:15 -04:00
Bill Burke 3851a2fe72 merge 2015-05-18 16:41:51 -04:00
Bill Burke 338300df32 1st phase auth/required action spi 2015-05-18 16:32:38 -04:00
Stian Thorgersen 0c7f63b2f3 Merge branch 'master' of https://github.com/girirajsharma/keycloak into girirajsharma-master
Conflicts:
	services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
2015-05-18 06:56:12 +02:00
Stian Thorgersen 9a87b7f196 Merge pull request #1263 from panga/fix_response
Fix wrong response code
2015-05-15 09:13:50 +02:00
Leonardo Loch Zanivan abcd830af1 Fix response code 2015-05-13 15:39:51 -03:00
Leonardo Loch Zanivan f807c999b6 Initial messages SPI implementation for Admin REST Services. 2015-05-13 11:13:49 -03:00
girirajsharma ccd5deb85f [KEYCLOAK 392] Audit admin events 2015-05-13 16:47:30 +05:30
Stian Thorgersen dbf9525860 KEYCLOAK-1312 Add clearToken to keycloak.js 2015-05-13 13:13:36 +02:00
Stian Thorgersen 502efe42c9 KEYCLOAK-1288 2015-05-13 11:50:36 +02:00
Stian Thorgersen f0787d98d1 Merge pull request #1259 from stianst/master
Fix welcome-theme in test server
2015-05-13 11:31:19 +02:00
Stian Thorgersen d2ed8302a7 Fix welcome-theme in test server 2015-05-13 11:25:43 +02:00
Stian Thorgersen 15310d1e97 Merge pull request #1257 from stianst/master
KEYCLOAK-1310 Don't log migration model for fresh instal
2015-05-13 11:17:55 +02:00
Stian Thorgersen 38af401a16 KEYCLOAK-1310 Don't log migration model for fresh instal 2015-05-13 11:16:50 +02:00
Stian Thorgersen ab1d39dfb3 Merge pull request #1256 from stianst/master
KEYCLOAK-1277 Fix upgrading from 1.0.x to 1.2.0.Beta1
2015-05-13 10:55:26 +02:00
Stian Thorgersen d35786fe49 KEYCLOAK-1277 Fix upgrading from 1.0.x to 1.2.0.Beta1
Conflicts:
	connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml
2015-05-13 10:54:48 +02:00
Stian Thorgersen b9db84edf3 Merge pull request #1254 from stianst/master
KEYCLOAK-1307 Fix docs for databaseSchema
2015-05-13 08:11:59 +02:00
Stian Thorgersen c3176cac6a KEYCLOAK-1307 Fix docs for databaseSchema 2015-05-13 08:09:29 +02:00
Stian Thorgersen 6c98d64874 Merge pull request #1238 from raehalme/KEYCLOAK-1294
Added support for GrantedAuthoritiesMapper in KeycloakAuthenticationProvider
2015-05-13 06:57:29 +02:00
Stian Thorgersen 269dc26029 Merge pull request #1250 from ssilvert/patch-1
Fix parent pom.
2015-05-12 14:55:20 +02:00
Stian Thorgersen 48d26fc0e9 Merge pull request #1249 from ssilvert/patch-2
Fix parent pom.
2015-05-12 14:55:11 +02:00
Stan Silvert 797bf49ea6 Update pom.xml 2015-05-12 08:39:57 -04:00
Stan Silvert fd96bacf70 Update pom.xml 2015-05-12 08:38:08 -04:00
Stian Thorgersen 7f9739cd4f Merge pull request #1248 from stianst/master
Added isPrivate to Spi
2015-05-12 08:25:56 +02:00
Stian Thorgersen 698660c92a Added isPrivate to Spi 2015-05-12 08:25:24 +02:00
Stian Thorgersen 5aa90243a0 Merge pull request #1247 from Smartling/KEYCLOAK-1299
Add Servlet 2.x support to the Spring Security adapter
2015-05-12 07:26:50 +02:00
Scott Rossillo 4d32ac8765 Add Servlet 2.x support to the Spring Security adapter
Cookie.setHttpOnly() was added in Servlet 3.0. Make setting a
cookie as HttpOnly dependent on servlet version.
2015-05-11 19:48:16 -04:00
Stian Thorgersen 224f85b981 Merge pull request #1246 from stianst/master
Moved adapter feature pack
2015-05-11 16:27:38 +02:00
Stian Thorgersen 29c72c0744 Moved adapter feature pack 2015-05-11 16:27:16 +02:00
Stian Thorgersen 36c162126b Merge pull request #1245 from stianst/master
Removed unused xslt from server-dist
2015-05-11 16:14:01 +02:00
Stian Thorgersen 252dfe006b Removed unused xslt from server-dist 2015-05-11 16:13:44 +02:00
Stian Thorgersen d1743f0608 Merge pull request #1244 from stianst/master
Build server dist with feature pack
2015-05-11 16:09:42 +02:00
Stian Thorgersen 9168cf811c Build server dist with feature pack 2015-05-11 16:09:16 +02:00
Stian Thorgersen 9e50ae6a01 Merge pull request #1243 from girirajsharma/patch-1
Minor issue: Fixed non-resolvable pom error while updating db schema.
2015-05-11 15:10:38 +02:00
Giriraj Sharma 371c798116 Minor issue: Fixed non-resolvabe pom error while updating schema via hibernate. 2015-05-11 18:38:02 +05:30
Stian Thorgersen d00e0021b6 Merge branch 'master' of https://github.com/girirajsharma/keycloak into girirajsharma-master
Conflicts:
	connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-master.xml
	services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java
2015-05-11 13:36:30 +02:00
Stian Thorgersen bce3e61b7d Merge pull request #1242 from stianst/master
KEYCLOAK-1289 Support environment variables in keycloak.json
2015-05-11 11:03:50 +02:00
Stian Thorgersen ccbd4bace1 KEYCLOAK-1289 Support environment variables in keycloak.json 2015-05-11 10:17:25 +02:00
Thomas Raehalme 78999537f0 Added support for GrantedAuthoritiesMapper in KeycloakAuthenticationProvider. 2015-05-09 13:42:09 +03:00
Bill Burke e3b0cc7093 Merge pull request #1236 from Smartling/KEYCLOAK-1291
Improve Spring Security adapter default configuration
2015-05-08 20:53:36 -04:00
Bill Burke 50014f4398 Merge pull request #1235 from Smartling/KEYCLOAK-1290
Use backchannel logout for Spring Security SSO
2015-05-08 20:53:26 -04:00
Bill Burke 833c276424 Merge pull request #1234 from mstruk/wfly-subs-split-master
Wildfly 9 - subsystem split + feature packs
2015-05-08 20:53:17 -04:00
Bill Burke 770525a385 Merge pull request #1237 from patriot1burke/master
username mapper
2015-05-08 20:53:05 -04:00
Bill Burke e4204a56f5 username mapper 2015-05-08 20:41:31 -04:00
Scott Rossillo d37a9eada3 Improve Spring Security adapter default configuration 2015-05-08 18:24:49 -04:00
Scott Rossillo a7bfae2f56 Use backchannel logout for Spring Security SSO
Use backchannel logout for Keycloak's Spring Security adapter
single sign-out to allow Spring Security's logout complete handler
to fire.
2015-05-08 18:20:17 -04:00
Stian Thorgersen aaebcd074e Merge pull request #1233 from Smartling/KEYCLOAK-1274
Add Spring Security adapter documentation
2015-05-08 07:10:03 +02:00
Stian Thorgersen 58fc4520c9 Merge pull request #1232 from Smartling/KEYCLOAK-1287
Enable Spring Security adapter to register nodes
2015-05-08 07:09:42 +02:00
Stian Thorgersen 53716697ca Merge pull request #1222 from Smartling/KEYCLOAK-1273
Improve Spring Security adapter client to client authorization
2015-05-08 07:01:14 +02:00
Stian Thorgersen 96668daefa Merge pull request #1231 from Smartling/KEYCLOAK-1286
Permit Spring Security adapter to process admin tasks with CSRF enabled
2015-05-08 07:00:15 +02:00
Scott Rossillo 4b033d3d93 Add Spring Security adapter documentation 2015-05-08 00:23:25 -04:00
Scott Rossillo 8ca9a6a64a Enable Spring Security adapter to register nodes
Enable dynamic application node registration and unregistration
from Spring Security protected applications.
2015-05-07 20:09:16 -04:00
Scott Rossillo 2ce3925ba9 Permit Spring Security adapter to process admin tasks with CSRF enabled
Spring Security's CSRF protection blocks Keycloak administrative
actions when configured with the default request matcher.

This provides a CSRF request matcher that permits Keycloak
administrative actions without the CSRF token.
2015-05-07 19:58:27 -04:00
Marek Posolda 3d9adbe991 Merge pull request #1230 from mposolda/master
KEYCLOAK-1284 Allow users to easily inject or configure MongoClient
2015-05-07 20:56:48 +02:00
mposolda f16828e129 KEYCLOAK-1284 Allow users to easily inject or configure MongoClient for MongoConnectionProvider 2015-05-07 20:40:17 +02:00
mposolda 91eb80beb0 Minor improvements 2015-05-07 20:07:30 +02:00
Marko Strukelj 30682968ff Fix invalid module references that should point to keycloak-wildfly-adapter 2015-05-07 17:21:23 +02:00
Bill Burke 620e3b67e9 Merge pull request #1229 from patriot1burke/master
fix nameid policy
2015-05-07 10:53:34 -04:00
Bill Burke afe1ddd719 Merge remote-tracking branch 'upstream/master' 2015-05-07 10:52:55 -04:00
Bill Burke 0aefacc88e fix name id policy 2015-05-07 10:52:12 -04:00
Stian Thorgersen 366c707afa Merge pull request #1227 from stianst/master
KEYCLOAK-1282
2015-05-07 09:39:54 +02:00
Stian Thorgersen 707e29adef KEYCLOAK-1282 2015-05-07 09:39:28 +02:00
Stian Thorgersen 66f2735224 Merge pull request #1225 from stianst/master
KEYCLOAK-1279
2015-05-07 06:46:25 +02:00
Stian Thorgersen 86e19c274f KEYCLOAK-1279 2015-05-07 06:46:12 +02:00
Stian Thorgersen 46bb59e348 Merge pull request #1224 from stianst/master
Fix doc for installing onto EAP
2015-05-07 06:29:53 +02:00
Stian Thorgersen 37cbba57e6 Fix doc for installing onto EAP 2015-05-07 06:27:32 +02:00
Scott Rossillo b05da425b9 Improve Spring Security adapter client to client authorization 2015-05-06 16:54:55 -04:00
Marko Strukelj c28f5cef7a Fix WildFly org.apache.httpcomponents issue 2015-05-06 18:57:40 +02:00
Marko Strukelj f65e804836 WildFly testsuite work 2015-05-06 16:51:49 +02:00
Marko Strukelj 01e9b3bcff Upgrade version on overlooked poms to 1.3.0.Beta1-SNAPSHOT 2015-05-05 21:30:42 +02:00
Marko Strukelj 4e58bed39e Move keycloak modules under integration/keycloak 2015-05-05 20:48:13 +02:00
Marko Strukelj 7d2942e1be KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Rename keycloak-server-subsystem dir to wildfly-server-subsystem
 - Rename keycloak-agent-subsystem dir to keycloak-wildfly-agent-subsystem
 - Rename artifacts accordingly (keycloak- prefix)
 Only maven artifacts are renamed, jboss-modules modules are still called keycloak-server-subsystem, and keycloak-agent-subsystem
2015-05-05 20:43:23 +02:00
Marko Strukelj 943404689e KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Use WildFly 9.0.0.CR1
2015-05-05 20:40:05 +02:00
Marko Strukelj 89875aea02 KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Fix deprecated uses, and more code cleanup
2015-05-05 20:40:05 +02:00
Marko Strukelj 70ce96caa0 KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Fix overlooked file renames causing subsystem tests to fail
2015-05-05 20:40:05 +02:00
Marko Strukelj 625fb02dfe Fix typo preventing adapter-only-dist feature pack to build 2015-05-05 20:40:04 +02:00
Stan Silvert 18966334ab Update README.md 2015-05-05 20:40:04 +02:00
Stan Silvert a8f3756bbc Rename feature pack artifacts. Fix empty content directory. 2015-05-05 20:40:04 +02:00
Stan Silvert f0dab97b80 Add README file. 2015-05-05 20:40:04 +02:00
Stan Silvert 3a7bba041f Create builds based on WildFly 9 feature packs. 2015-05-05 20:40:04 +02:00
Marko Strukelj a50c0e61e4 Fix missing wildfly-undertow version 2015-05-05 20:40:04 +02:00
Marko Strukelj 87cb28eaab KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Fix server-subsystem tests
2015-05-05 20:40:04 +02:00
Marko Strukelj 03fa58a271 KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- POM dependencies cleanup
2015-05-05 20:40:03 +02:00
Marko Strukelj 666e610334 Upgrade WildFly to 9.0.0.RC1-SNAPSHOT 2015-05-05 20:40:03 +02:00
Marko Strukelj 3c76a85674 KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- More code and pom cleanup
2015-05-05 20:40:03 +02:00
Marko Strukelj c571ad9902 KEYCLOAK-1183 Split subsystem into separate server and adapter subsystems
- Renamed keycloak-subsystem into keycloak-server-subsystem
 - Added keycloak-adapter-subsystem without auth-server support
 - Removed adapter config from keycloak-server subsystem
 - Added proper .xsd for server subsystem
2015-05-05 20:40:03 +02:00
Tomaz Cerar 355c440c3d Update subsystem code to reflect latest standards 2015-05-05 20:38:52 +02:00
Tomaz Cerar 9a17658f84 remove eap6 dup 2015-05-05 20:38:52 +02:00
Bill Burke 69347aa7f6 Merge pull request #1220 from panga/master
KEYCLOAK-1269 and KEYCLOAK-1270
2015-05-05 14:31:48 -04:00
Bill Burke bf259f4c98 Merge pull request #1221 from patriot1burke/master
no backchannel if state
2015-05-05 14:18:52 -04:00
Bill Burke 082ebe8043 no backchannel if state 2015-05-05 13:58:07 -04:00
Leonardo Zanivan a13a02c995 KEYCLOAK-1270 fix 2015-05-05 11:17:27 -03:00
Leonardo Zanivan 3a9ac80786 Merge branch 'master' of github.com:panga/keycloak 2015-05-05 10:30:32 -03:00
Leonardo Zanivan d3cf177ebc Fix user.emailVerified on realm import 2015-05-05 10:29:44 -03:00
Leonardo Zanivan 7b49dbb74e Merge pull request #1 from keycloak/master
Merge
2015-05-05 10:27:59 -03:00
Stian Thorgersen 4cc249bcd4 Merge pull request #1219 from stianst/master
Fixes
2015-05-05 11:56:19 +02:00
Stian Thorgersen 035529d7a2 Version bump 2015-05-05 11:45:21 +02:00
Stian Thorgersen fa91c0ed03 Added missing dependencies to testsuite/docker-cluster£ 2015-05-05 10:40:47 +02:00
Stian Thorgersen adbde56c1a Removed tar.gz dist of docs 2015-05-05 10:28:04 +02:00
girirajsharma 70f53c6c06 [KEYCLOAK-392] - Admin audit events 2015-05-03 01:46:52 +05:30
3367 changed files with 265441 additions and 167194 deletions

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
* text=auto
*.html text eol=lf
*.java text eol=lf
*.js text eol=lf
*.json text eol=lf
*.jsp text eol=lf
*.md text eol=lf
*.properties text eol=lf
*.svg text auto
*.xml text eol=lf
*.xsl text eol=lf
*.png binary
*.jpg binary
*.gif binary
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
+13 -2
View File
@@ -1,8 +1,19 @@
language: java
jdk:
- oraclejdk8
cache:
directories:
- $HOME/.m2
sudo: false
after_script: 'misc/.travis/after.sh'
before_cache:
- rm -rf $HOME/.m2/repository/org/keycloak
install: mvn install -Pdistribution -DskipTests=true -B -V
script:
- mvn test -B
- mvn -file testsuite/integration-arquillian test -B
sudo: false
+50 -50
View File
@@ -1,50 +1,50 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-core</artifactId>
<name>Keycloak Broker Core</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
<?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.6.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-core</artifactId>
<name>Keycloak Broker Core</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
@@ -58,6 +58,11 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
return null;
}
@Override
public Response performLogin(AuthenticationRequest request) {
return null;
}
@Override
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
return null;
@@ -73,6 +78,11 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, BrokeredIdentityContext context) {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
@@ -18,8 +18,10 @@
package org.keycloak.broker.provider;
import org.keycloak.Config;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import java.io.InputStream;
import java.util.HashMap;
@@ -1,31 +1,38 @@
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.IdentityProviderMapper;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
@Override
public void close() {
}
@Override
public IdentityProviderMapper create(KeycloakSession session) {
return null;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
}
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.IdentityProviderMapper;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
@Override
public void close() {
}
@Override
public IdentityProviderMapper create(KeycloakSession session) {
return null;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
}
@@ -17,6 +17,7 @@
*/
package org.keycloak.broker.provider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.IdentityProviderModel;
import java.util.HashMap;
@@ -32,6 +33,7 @@ public class BrokeredIdentityContext {
private String id;
private String username;
private String modelUsername;
private String email;
private String firstName;
private String lastName;
@@ -42,6 +44,7 @@ public class BrokeredIdentityContext {
private IdentityProviderModel idpConfig;
private IdentityProvider idp;
private Map<String, Object> contextData = new HashMap<>();
private ClientSessionModel clientSession;
public BrokeredIdentityContext(String id) {
if (id == null) {
@@ -59,6 +62,11 @@ public class BrokeredIdentityContext {
this.id = id;
}
/**
* Username in remote idp
*
* @return
*/
public String getUsername() {
return username;
}
@@ -67,6 +75,19 @@ public class BrokeredIdentityContext {
this.username = username;
}
/**
* username to store in UserModel
*
* @return
*/
public String getModelUsername() {
return modelUsername;
}
public void setModelUsername(String modelUsername) {
this.modelUsername = modelUsername;
}
public String getEmail() {
return email;
}
@@ -147,6 +168,14 @@ public class BrokeredIdentityContext {
this.lastName = lastName;
}
public ClientSessionModel getClientSession() {
return clientSession;
}
public void setClientSession(ClientSessionModel clientSession) {
this.clientSession = clientSession;
}
public void setName(String name) {
if (name != null) {
int i = name.lastIndexOf(' ');
@@ -0,0 +1,89 @@
package org.keycloak.broker.provider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedAttributeMapper extends AbstractIdentityProviderMapper {
public static final String ATTRIBUTE = "attribute";
public static final String ATTRIBUTE_VALUE = "attribute.value";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE);
property.setLabel("User Attribute");
property.setHelpText("Name of user attribute you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("User Attribute Value");
property.setHelpText("Value you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Attribute";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "hardcoded-attribute-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
user.setSingleAttribute(attribute, attributeValue);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
user.setSingleAttribute(attribute, attributeValue);
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a value to a specific user attribute.";
}
}
@@ -1,110 +1,110 @@
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
public static final String ROLE = "role";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static String[] parseRole(String role) {
int scopeIndex = role.indexOf('.');
if (scopeIndex > -1) {
String appName = role.substring(0, scopeIndex);
role = role.substring(scopeIndex + 1);
String[] rtn = {appName, role};
return rtn;
} else {
String[] rtn = {null, role};
return rtn;
}
}
public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
String[] parsedRole = parseRole(roleName);
RoleModel role = null;
if (parsedRole[0] == null) {
role = realm.getRole(parsedRole[1]);
} else {
ClientModel client = realm.getClientByClientId(parsedRole[0]);
role = client.getRole(parsedRole[1]);
}
return role;
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Role";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(ROLE);
RoleModel role = getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a role mapping for it.";
}
}
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
public static final String ROLE = "role";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static String[] parseRole(String role) {
int scopeIndex = role.lastIndexOf('.');
if (scopeIndex > -1) {
String appName = role.substring(0, scopeIndex);
role = role.substring(scopeIndex + 1);
String[] rtn = {appName, role};
return rtn;
} else {
String[] rtn = {null, role};
return rtn;
}
}
public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
String[] parsedRole = parseRole(roleName);
RoleModel role = null;
if (parsedRole[0] == null) {
role = realm.getRole(parsedRole[1]);
} else {
ClientModel client = realm.getClientByClientId(parsedRole[0]);
role = client.getRole(parsedRole[1]);
}
return role;
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Role";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(ROLE);
RoleModel role = getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a role mapping for it.";
}
}
@@ -0,0 +1,87 @@
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProviderMapper {
public static final String ATTRIBUTE = "attribute";
public static final String ATTRIBUTE_VALUE = "attribute.value";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE);
property.setLabel("User Session Attribute");
property.setHelpText("Name of user session attribute you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("User Session Attribute Value");
property.setHelpText("Value you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded User Session Attribute";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "hardcoded-user-session-attribute-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
context.getClientSession().setUserSessionNote(attribute, attributeValue);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
context.getClientSession().setUserSessionNote(attribute, attributeValue);
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a value to a specific user session attribute.";
}
}
@@ -20,6 +20,7 @@ package org.keycloak.broker.provider;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -35,7 +36,7 @@ import javax.ws.rs.core.UriInfo;
*/
public interface IdentityProvider<C extends IdentityProviderModel> extends Provider {
public interface AuthenticationCallback {
interface AuthenticationCallback {
/**
* This method should be called by provider after the JAXRS callback endpoint has finished authentication
* with the remote IDP
@@ -43,9 +44,15 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
* @param context
* @return
*/
public Response authenticated(BrokeredIdentityContext context);
Response authenticated(BrokeredIdentityContext context);
Response cancelled(String code);
Response error(String code, String message);
}
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, BrokeredIdentityContext context);
void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context);
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
@@ -18,6 +18,8 @@
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.ProviderFactory;
import java.io.InputStream;
@@ -1,26 +1,56 @@
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
public static final String ANY_PROVIDER = "*";
String[] getCompatibleProviders();
String getDisplayCategory();
String getDisplayType();
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
}
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
public static final String ANY_PROVIDER = "*";
String[] getCompatibleProviders();
String getDisplayCategory();
String getDisplayType();
/**
* Called to determine what keycloak username and email to use to process the login request from the external IDP
* Usually used to map BrokeredIdentityContet.username or email.
*
* @param session
* @param realm
* @param mapperModel
* @param context
*/
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called after UserModel is created for first time for this user.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called when this user has logged in before and has already been imported.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
}
@@ -9,6 +9,11 @@ import org.keycloak.provider.Spi;
*/
public class IdentityProviderMapperSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "identity-provider-mapper";
@@ -28,6 +28,11 @@ public class IdentityProviderSpi implements Spi {
public static final String IDENTITY_PROVIDER_SPI_NAME = "identity_provider";
@Override
public boolean isInternal() {
return false;
}
@Override
public String getName() {
return IDENTITY_PROVIDER_SPI_NAME;
@@ -1 +1,3 @@
org.keycloak.broker.provider.HardcodedRoleMapper
org.keycloak.broker.provider.HardcodedRoleMapper
org.keycloak.broker.provider.HardcodedAttributeMapper
org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper
@@ -1,2 +1,2 @@
org.keycloak.broker.provider.IdentityProviderSpi
org.keycloak.broker.provider.IdentityProviderSpi
org.keycloak.broker.provider.IdentityProviderMapperSpi
+58 -58
View File
@@ -1,58 +1,58 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-oidc</artifactId>
<name>Keycloak Broker - OpenID Connect Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?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.6.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-oidc</artifactId>
<name>Keycloak Broker - OpenID Connect Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -20,7 +20,7 @@ package org.keycloak.broker.oidc;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.ClientConnection;
import org.keycloak.common.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.AbstractIdentityProvider;
@@ -58,6 +58,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
public static final String FEDERATED_ACCESS_TOKEN = "FEDERATED_ACCESS_TOKEN";
public static final String FEDERATED_REFRESH_TOKEN = "FEDERATED_REFRESH_TOKEN";
public static final String FEDERATED_TOKEN_EXPIRATION = "FEDERATED_TOKEN_EXPIRATION";
public static final String ACCESS_DENIED = "access_denied";
protected static ObjectMapper mapper = new ObjectMapper();
public static final String OAUTH2_PARAMETER_ACCESS_TOKEN = "access_token";
@@ -213,9 +214,11 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
@QueryParam(OAuth2Constants.ERROR) String error) {
if (error != null) {
//logger.error("Failed " + getConfig().getAlias() + " broker login: " + error);
event.event(EventType.LOGIN);
event.error(error);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
if (error.equals(ACCESS_DENIED)) {
return callback.cancelled(state);
} else {
return callback.error(state, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
}
try {
@@ -1,114 +1,114 @@
package org.keycloak.broker.oidc;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.adapters.action.AdminAction;
import org.keycloak.representations.adapters.action.LogoutAction;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.security.PublicKey;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
super(config);
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
return new KeycloakEndpoint(callback, realm, event);
}
@Override
protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
JsonWebToken access = validateToken(idpKey, response.getToken());
context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
}
protected class KeycloakEndpoint extends OIDCEndpoint {
public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
super(callback, realm, event);
}
@POST
@Path(AdapterConstants.K_LOGOUT)
public Response backchannelLogout(String input) {
JWSInput token = new JWSInput(input);
PublicKey key = getExternalIdpKey();
if (key != null) {
if (!verify(token, key)) {
logger.warn("Failed to verify logout request");
return Response.status(400).build();
}
}
LogoutAction action = null;
try {
action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!validateAction(action)) return Response.status(400).build();
if (action.getKeycloakSessionIds() != null) {
for (String sessionId : action.getKeycloakSessionIds()) {
String brokerSessionId = getConfig().getAlias() + "." + sessionId;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null
&& userSession.getState() != UserSessionModel.State.LOGGING_OUT
&& userSession.getState() != UserSessionModel.State.LOGGED_OUT
) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
}
}
}
return Response.ok().build();
}
protected boolean validateAction(AdminAction action) {
if (!action.validate()) {
logger.warn("admin request failed, not validated" + action.getAction());
return false;
}
if (action.isExpired()) {
logger.warn("admin request failed, expired token");
return false;
}
if (!getConfig().getClientId().equals(action.getResource())) {
logger.warn("Resource name does not match");
return false;
}
return true;
}
@Override
public SimpleHttp generateTokenRequest(String authorizationCode) {
return super.generateTokenRequest(authorizationCode)
.param(AdapterConstants.CLIENT_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
}
}
}
package org.keycloak.broker.oidc;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.adapters.action.AdminAction;
import org.keycloak.representations.adapters.action.LogoutAction;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.security.PublicKey;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
super(config);
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
return new KeycloakEndpoint(callback, realm, event);
}
@Override
protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
JsonWebToken access = validateToken(idpKey, response.getToken());
context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
}
protected class KeycloakEndpoint extends OIDCEndpoint {
public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
super(callback, realm, event);
}
@POST
@Path(AdapterConstants.K_LOGOUT)
public Response backchannelLogout(String input) {
JWSInput token = new JWSInput(input);
PublicKey key = getExternalIdpKey();
if (key != null) {
if (!verify(token, key)) {
logger.warn("Failed to verify logout request");
return Response.status(400).build();
}
}
LogoutAction action = null;
try {
action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!validateAction(action)) return Response.status(400).build();
if (action.getKeycloakSessionIds() != null) {
for (String sessionId : action.getKeycloakSessionIds()) {
String brokerSessionId = getConfig().getAlias() + "." + sessionId;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null
&& userSession.getState() != UserSessionModel.State.LOGGING_OUT
&& userSession.getState() != UserSessionModel.State.LOGGED_OUT
) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
}
}
}
return Response.ok().build();
}
protected boolean validateAction(AdminAction action) {
if (!action.validate()) {
logger.warn("admin request failed, not validated" + action.getAction());
return false;
}
if (action.isExpired()) {
logger.warn("admin request failed, expired token");
return false;
}
if (!getConfig().getClientId().equals(action.getResource())) {
logger.warn("Resource name does not match");
return false;
}
return true;
}
@Override
public SimpleHttp generateTokenRequest(String authorizationCode) {
return super.generateTokenRequest(authorizationCode)
.param(AdapterConstants.CLIENT_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
}
}
}
@@ -17,10 +17,15 @@
*/
package org.keycloak.broker.oidc;
import org.keycloak.broker.oidc.mappers.UsernameTemplateMapper;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
@@ -50,4 +55,5 @@ public class KeycloakOIDCIdentityProviderFactory extends AbstractIdentityProvide
return OIDCIdentityProviderFactory.parseOIDCConfig(inputStream);
}
}
}
@@ -19,6 +19,7 @@ package org.keycloak.broker.oidc;
import org.codehaus.jackson.JsonNode;
import org.jboss.logging.Logger;
import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
import org.keycloak.broker.oidc.util.JsonSimpleHttp;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.AuthenticationRequest;
@@ -41,7 +42,7 @@ import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.PemUtils;
import org.keycloak.common.util.PemUtils;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@@ -50,6 +51,7 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.security.PublicKey;
@@ -224,7 +226,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
name = getJsonProperty(userInfo, "name");
preferredUsername = getJsonProperty(userInfo, "preferred_username");
email = getJsonProperty(userInfo, "email");
identity.getContextData().put(USER_INFO, userInfo);
AbstractJsonUserAttributeMapper.storeUserProfileForMapper(identity, userInfo, getConfig().getAlias());
}
identity.getContextData().put(FEDERATED_ACCESS_TOKEN_RESPONSE, tokenResponse);
identity.getContextData().put(VALIDATED_ID_TOKEN, idToken);
@@ -287,10 +289,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
}
JsonWebToken token = jws.readJsonContent(JsonWebToken.class);
String aud = token.getAudience();
String iss = token.getIssuer();
if (aud != null && !aud.equals(getConfig().getClientId())) {
if (!token.hasAudience(getConfig().getClientId())) {
throw new IdentityBrokerException("Wrong audience from token.");
}
@@ -17,11 +17,15 @@
*/
package org.keycloak.broker.oidc;
import org.keycloak.broker.oidc.mappers.UsernameTemplateMapper;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKParser;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
@@ -30,6 +34,7 @@ import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.io.InputStream;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
/**
@@ -89,7 +94,7 @@ public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory
}
} catch (IOException e) {
throw new RuntimeException("F ailed to query JWKSet from: " + uri, e);
throw new RuntimeException("Failed to query JWKSet from: " + uri, e);
}
}
@@ -99,4 +104,5 @@ public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory
protected static boolean keyTypeSupported(String type) {
return type != null && type.equals("RSA");
}
}
@@ -1,93 +1,97 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
public static final String CLAIM = "claim";
public static final String CLAIM_VALUE = "claim.value";
public static Object getClaimValue(JsonWebToken token, String claim) {
String[] split = claim.split("\\.");
Map<String, Object> jsonObject = token.getOtherClaims();
for (int i = 0; i < split.length; i++) {
if (i == split.length - 1) {
return jsonObject.get(split[i]);
} else {
Object val = jsonObject.get(split[i]);
if (!(val instanceof Map)) return null;
jsonObject = (Map<String, Object>)val;
}
}
return null;
}
protected Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String claim = mapperModel.getConfig().get(CLAIM);
{ // search access token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
{ // search ID Token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
return null;
}
protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
Object value = getClaimValue(mapperModel, context);
String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
return valueEquals(desiredValue, value);
}
public boolean valueEquals(String desiredValue, Object value) {
if (value instanceof String) {
if (desiredValue.equals(value)) return true;
} else if (value instanceof Double) {
try {
if (Double.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Integer) {
try {
if (Integer.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Boolean) {
try {
if (Boolean.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof List) {
List list = (List)value;
for (Object val : list) {
return valueEquals(desiredValue, val);
}
}
return false;
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
public static final String CLAIM = "claim";
public static final String CLAIM_VALUE = "claim.value";
public static Object getClaimValue(JsonWebToken token, String claim) {
String[] split = claim.split("\\.");
Map<String, Object> jsonObject = token.getOtherClaims();
for (int i = 0; i < split.length; i++) {
if (i == split.length - 1) {
return jsonObject.get(split[i]);
} else {
Object val = jsonObject.get(split[i]);
if (!(val instanceof Map)) return null;
jsonObject = (Map<String, Object>)val;
}
}
return null;
}
public static Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String claim = mapperModel.getConfig().get(CLAIM);
return getClaimValue(context, claim);
}
public static Object getClaimValue(BrokeredIdentityContext context, String claim) {
{ // search access token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
{ // search ID Token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
return null;
}
protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
Object value = getClaimValue(mapperModel, context);
String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
return valueEquals(desiredValue, value);
}
public boolean valueEquals(String desiredValue, Object value) {
if (value instanceof String) {
if (desiredValue.equals(value)) return true;
} else if (value instanceof Double) {
try {
if (Double.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Integer) {
try {
if (Integer.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Boolean) {
try {
if (Boolean.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof List) {
List list = (List)value;
for (Object val : list) {
return valueEquals(desiredValue, val);
}
}
return false;
}
}
@@ -0,0 +1,206 @@
package org.keycloak.broker.oidc.mappers;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.JsonNode;
import org.jboss.logging.Logger;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
/**
* Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user
* attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who
* uses {@link JsonNode} user profile.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper {
protected static final Logger logger = Logger.getLogger(AbstractJsonUserAttributeMapper.class);
protected static final Logger LOGGER_DUMP_USER_PROFILE = Logger.getLogger("org.keycloak.social.user_profile_dump");
private static final String JSON_PATH_DELIMITER = ".";
/**
* Config param where name of mapping source JSON User Profile field is stored.
*/
public static final String CONF_JSON_FIELD = "jsonField";
/**
* Config param where name of mapping target USer attribute is stored.
*/
public static final String CONF_USER_ATTRIBUTE = "userAttribute";
/**
* Key in {@link BrokeredIdentityContext#getContextData()} where {@link JsonNode} with user profile is stored.
*/
public static final String CONTEXT_JSON_NODE = OIDCIdentityProvider.USER_INFO;
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CONF_JSON_FIELD);
property1.setLabel("Social Profile JSON Field Path");
property1.setHelpText("Path of field in Social provider User Profile JSON data to get value from. You can use dot notation for nesting and square brackets for array index. Eg. 'contact.address[0].country'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(CONF_USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store information into.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
/**
* Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure.
*
* @param user context to store profile data into
* @param profile to store into context
* @param provider identification of social provider to be used in log dump
*
* @see #importNewUser(KeycloakSession, RealmModel, UserModel, IdentityProviderMapperModel, BrokeredIdentityContext)
* @see BrokeredIdentityContext#getContextData()
*/
public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
user.getContextData().put(AbstractJsonUserAttributeMapper.CONTEXT_JSON_NODE, profile);
if (LOGGER_DUMP_USER_PROFILE.isDebugEnabled())
LOGGER_DUMP_USER_PROFILE.debug("User Profile JSON Data for provider "+provider+": " + profile);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public String getHelpText() {
return "Import user profile information if it exists in Social provider JSON data into the specified user attribute.";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
if (attribute == null || attribute.trim().isEmpty()) {
logger.debug("Attribute is not configured");
return;
}
attribute = attribute.trim();
String value = getJsonValue(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
// we do not update user profile from social provider
}
protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
if (jsonField == null || jsonField.trim().isEmpty()) {
logger.debug("JSON field path is not configured");
return null;
}
jsonField = jsonField.trim();
if (jsonField.startsWith(JSON_PATH_DELIMITER) || jsonField.endsWith(JSON_PATH_DELIMITER) || jsonField.startsWith("[")) {
logger.debug("JSON field path is invalid " + jsonField);
return null;
}
JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE);
String value = getJsonValue(profileJsonNode, jsonField);
if (value == null) {
logger.debug("User profile JSON value '" + jsonField + "' is not available.");
}
return value;
}
protected static String getJsonValue(JsonNode baseNode, String fieldPath) {
logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
if (baseNode != null) {
int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
String currentFieldName = fieldPath;
if (idx > 0) {
currentFieldName = fieldPath.substring(0, idx).trim();
if (currentFieldName.isEmpty()) {
logger.debug("JSON path is invalid " + fieldPath);
return null;
}
}
String currentNodeName = currentFieldName;
int arrayIndex = -1;
if (currentFieldName.endsWith("]")) {
int bi = currentFieldName.indexOf("[");
if (bi == -1) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
try {
String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
arrayIndex = Integer.parseInt(is);
} catch (Exception e) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
currentNodeName = currentFieldName.substring(0,bi).trim();
}
JsonNode currentNode = baseNode.get(currentNodeName);
if (arrayIndex > -1 && currentNode.isArray()) {
logger.debug("Going to take array node at index " + arrayIndex);
currentNode = currentNode.get(arrayIndex);
}
if (currentNode == null) {
logger.debug("JsonNode not found for name " + currentFieldName);
return null;
}
if (idx < 0) {
if (!currentNode.isValueNode()) {
logger.debug("JsonNode is not value node for name " + currentFieldName);
return null;
}
String ret = currentNode.asText();
if (ret != null && !ret.trim().isEmpty())
return ret.trim();
} else {
return getJsonValue(currentNode, fieldPath.substring(idx + 1));
}
}
return null;
}
}
@@ -1,105 +1,105 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClaimToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(CLAIM_VALUE);
property1.setLabel("Claim Value");
property1.setHelpText("Value the claim must have. If the claim is an array, then the value must be contained in the array.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if claim is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Claim to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClaimToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(CLAIM_VALUE);
property1.setLabel("Claim Value");
property1.setHelpText("Value the claim must have. If the claim is an array, then the value must be contained in the array.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if claim is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Claim to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
@@ -1,118 +1,118 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
private static final String EXTERNAL_ROLE = "external.role";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(EXTERNAL_ROLE);
property1.setLabel("External role");
property1.setHelpText("External role to check for. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if external role is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "External Role to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role != null) {
user.grantRole(role);
}
}
private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
//if (token == null) return;
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
String externalRoleName = parseRole[1];
String claimName = null;
if (parseRole[0] == null) {
claimName = "realm_access.roles";
} else {
claimName = "resource_access." + parseRole[0] + ".roles";
}
Object claim = getClaimValue(token, claimName);
if (valueEquals(externalRoleName, claim)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
return role;
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role == null) {
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "Looks for an external role in a keycloak access token. If external role exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
private static final String EXTERNAL_ROLE = "external.role";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(EXTERNAL_ROLE);
property1.setLabel("External role");
property1.setHelpText("External role to check for. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if external role is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "External Role to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role != null) {
user.grantRole(role);
}
}
private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
//if (token == null) return;
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
String externalRoleName = parseRole[1];
String claimName = null;
if (parseRole[0] == null) {
claimName = "realm_access.roles";
} else {
claimName = "resource_access." + parseRole[0] + ".roles";
}
Object claim = getClaimValue(token, claimName);
if (valueEquals(externalRoleName, claim)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
return role;
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role == null) {
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "Looks for an external role in a keycloak access token. If external role exists, grant the user the specified realm or application role.";
}
}
@@ -1,100 +1,98 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
if (value != null) {
user.setAttribute(attribute, value.toString());
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
String current = user.getAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared claim if it exists in ID or access token into the specified user attribute.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value.toString());
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
String current = user.getFirstAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setSingleAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared claim if it exists in ID or access token into the specified user attribute.";
}
}
@@ -0,0 +1,109 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${CLAIM.sub}'. ALIAS is the provider alias. CLAIM.<NAME> references an ID or Access token claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${CLAIM.preferred_username}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.startsWith("CLAIM.")) {
String name = variable.substring("CLAIM.".length());
Object value = AbstractClaimMapper.getClaimValue(context, name);
if (value == null) value = "";
m.appendReplacement(sb, value.toString());
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
String username = sb.toString();
context.setModelUsername(username);
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
@@ -1,32 +1,32 @@
package org.keycloak.broker.oidc.util;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.keycloak.broker.provider.util.SimpleHttp;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JsonSimpleHttp extends SimpleHttp {
public JsonSimpleHttp(String url, String method) {
super(url, method);
}
public static JsonSimpleHttp doGet(String url) {
return new JsonSimpleHttp(url, "GET");
}
public static JsonSimpleHttp doPost(String url) {
return new JsonSimpleHttp(url, "POST");
}
private static ObjectMapper mapper = new ObjectMapper();
public static JsonNode asJson(SimpleHttp request) throws IOException {
return mapper.readTree(request.asString());
}
}
package org.keycloak.broker.oidc.util;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.keycloak.broker.provider.util.SimpleHttp;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JsonSimpleHttp extends SimpleHttp {
public JsonSimpleHttp(String url, String method) {
super(url, method);
}
public static JsonSimpleHttp doGet(String url) {
return new JsonSimpleHttp(url, "GET");
}
public static JsonSimpleHttp doPost(String url) {
return new JsonSimpleHttp(url, "POST");
}
private static ObjectMapper mapper = new ObjectMapper();
public static JsonNode asJson(SimpleHttp request) throws IOException {
return mapper.readTree(request.asString());
}
}
@@ -1,2 +1,2 @@
org.keycloak.broker.oidc.OIDCIdentityProviderFactory
org.keycloak.broker.oidc.OIDCIdentityProviderFactory
org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory
@@ -1,3 +1,4 @@
org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
org.keycloak.broker.oidc.mappers.UserAttributeMapper
org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
org.keycloak.broker.oidc.mappers.UserAttributeMapper
org.keycloak.broker.oidc.mappers.UsernameTemplateMapper
@@ -0,0 +1,120 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
*/
package org.keycloak.broker.oidc.mappers;
import java.io.IOException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Assert;
import org.junit.Test;
/**
* Unit test for {@link AbstractJsonUserAttributeMapper}
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public class AbstractJsonUserAttributeMapperTest {
private static ObjectMapper mapper = new ObjectMapper();
private static JsonNode baseNode;
private JsonNode getJsonNode() throws JsonProcessingException, IOException {
if (baseNode == null)
baseNode = mapper.readTree("{ \"value1\" : \"v1 \",\"value_empty\" : \"\", \"value_b\" : true, \"value_i\" : 454, " + " \"value_array\":[\"a1\",\"a2\"], " +" \"nest1\": {\"value1\": \" fgh \",\"value_empty\" : \"\", \"nest2\":{\"value_b\" : false, \"value_i\" : 43}}, "+ " \"nesta\": { \"a\":[{\"av1\": \"vala1\"},{\"av1\": \"vala2\"}]}"+" }");
return baseNode;
}
@Test
public void getJsonValue_invalidPath() throws JsonProcessingException, IOException {
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "."));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), ".."));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "...value1"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), ".value1"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value1."));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "[]"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "[value1"));
}
@Test
public void getJsonValue_simpleValues() throws JsonProcessingException, IOException {
//unknown field returns null
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_unknown"));
// we check value is trimmed also!
Assert.assertEquals("v1", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_empty"));
Assert.assertEquals("true", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_b"));
Assert.assertEquals("454", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_i"));
}
@Test
public void getJsonValue_nestedSimpleValues() throws JsonProcessingException, IOException {
// null if path points to JSON object
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.nest2"));
//unknown field returns null
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.value_unknown"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.nest2.value_unknown"));
// we check value is trimmed also!
Assert.assertEquals("fgh", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.value1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.value_empty"));
Assert.assertEquals("false", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.nest2.value_b"));
Assert.assertEquals("43", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.nest2.value_i"));
// null if invalid nested path
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1."));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nest1.nest2."));
}
@Test
public void getJsonValue_simpleArray() throws JsonProcessingException, IOException {
// array field itself returns null if no index is provided
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array"));
// outside index returns null
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[2]"));
//corect index
Assert.assertEquals("a1", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[0]"));
Assert.assertEquals("a2", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[1]"));
//incorrect array constructs
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[]"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array]"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array["));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[a]"));
Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[-2]"));
}
@Test
public void getJsonValue_nestedArrayWithObjects() throws JsonProcessingException, IOException {
Assert.assertEquals("vala1", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[0].av1"));
Assert.assertEquals("vala2", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[1].av1"));
//different path erros or nonexisting indexes or fields return null
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[2].av1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[0]"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[0].av_unknown"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[].av1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a.av1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a].av1"));
Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[.av1"));
}
}
+23 -23
View File
@@ -1,23 +1,23 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-parent</artifactId>
<name>Keycloak Broker Parent</name>
<description/>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>oidc</module>
<module>saml</module>
</modules>
</project>
<?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.6.1.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-parent</artifactId>
<name>Keycloak Broker Parent</name>
<description/>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>oidc</module>
<module>saml</module>
</modules>
</project>
+50 -50
View File
@@ -1,50 +1,50 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-saml</artifactId>
<name>Keycloak Broker - SAML Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-protocol</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?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.6.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-saml</artifactId>
<name>Keycloak Broker - SAML Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-protocol</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -1,485 +1,438 @@
package org.keycloak.broker.saml;
import org.jboss.logging.Logger;
import org.keycloak.ClientConnection;
import org.keycloak.VerificationException;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
import org.keycloak.protocol.saml.SAMLRequestParser;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlProtocolUtils;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
import org.keycloak.saml.processing.web.util.PostBindingUtil;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SAMLEndpoint {
protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
public static final String SAML_ASSERTION = "SAML_ASSERTION";
public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
protected RealmModel realm;
protected EventBuilder event;
protected SAMLIdentityProviderConfig config;
protected IdentityProvider.AuthenticationCallback callback;
protected SAMLIdentityProvider provider;
@Context
private UriInfo uriInfo;
@Context
private KeycloakSession session;
@Context
private ClientConnection clientConnection;
@Context
private HttpHeaders headers;
public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
this.realm = realm;
this.config = config;
this.callback = callback;
this.provider = provider;
}
@GET
public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
}
/**
*/
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@FormParam(GeneralConstants.RELAY_STATE) String relayState) {
return new PostBinding().execute(samlRequest, samlResponse, relayState);
}
protected abstract class Binding {
private boolean checkSsl() {
if (uriInfo.getBaseUri().getScheme().equals("https")) {
return true;
} else {
return !realm.getSslRequired().isRequired(clientConnection);
}
}
protected Response basicChecks(String samlRequest, String samlResponse) {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
}
protected abstract String getBindingType();
protected abstract void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException;
protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
protected PublicKey getIDPKey() {
X509Certificate certificate = null;
try {
certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return certificate.getPublicKey();
}
public Response execute(String samlRequest, String samlResponse, String relayState) {
event = new EventBuilder(realm, session, clientConnection);
Response response = basicChecks(samlRequest, samlResponse);
if (response != null) return response;
if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
else return handleSamlResponse(samlResponse, relayState);
}
protected Response handleSamlRequest(String samlRequest, String relayState) {
SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
// validate destination
if (!uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SAML_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
if (config.isValidateSignature()) {
try {
verifySignature(holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
}
if (requestAbstractType instanceof LogoutRequestType) {
logger.debug("** logout request");
event.event(EventType.LOGOUT);
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
return logoutRequest(logout, relayState);
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
protected Response logoutRequest(LogoutRequestType request, String relayState) {
String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
for (UserSessionModel userSession : userSessions) {
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
} else {
for (String sessionIndex : request.getSessionIndex()) {
String brokerSessionId = brokerUserId + "." + sessionIndex;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null) {
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
}
}
String issuerURL = getEntityId(uriInfo, realm);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(request.getID());
builder.destination(config.getSingleLogoutServiceUrl());
builder.issuer(issuerURL);
builder.relayState(relayState);
if (config.isWantAuthnRequestsSigned()) {
builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signDocument();
}
try {
if (config.isPostBindingResponse()) {
return builder.postBinding().response();
} else {
return builder.redirectBinding().response();
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
} catch (ProcessingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getEntityId(UriInfo uriInfo, RealmModel realm) {
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
}
protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
try {
AssertionType assertion = getAssertion(responseType);
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
//Map<String, String> notes = new HashMap<>();
BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
identity.setCode(relayState);
identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
identity.getContextData().put(SAML_ASSERTION, assertion);
identity.setUsername(subjectNameID.getValue());
if (subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
identity.setEmail(subjectNameID.getValue());
}
if (config.isStoreToken()) {
identity.setToken(samlResponse);
}
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType)statement;
identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
break;
}
}
if (assertion.getAttributeStatements() != null ) {
for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
AttributeType attribute = choice.getAttribute();
if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
|| X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
}
}
}
}
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
identity.setBrokerUserId(brokerUserId);
identity.setIdpConfig(config);
identity.setIdp(provider);
if (authn != null && authn.getSessionIndex() != null) {
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
}
return callback.authenticated(identity);
} catch (Exception e) {
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
}
}
private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
if (assertions.isEmpty()) {
throw new IdentityBrokerException("No assertion from response.");
}
ResponseType.RTChoiceType rtChoiceType = assertions.get(0);
EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
if (encryptedAssertion != null) {
decryptAssertion(responseType, realm.getPrivateKey());
}
return responseType.getAssertions().get(0).getAssertion();
}
public Response handleSamlResponse(String samlResponse, String relayState) {
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
// validate destination
if (!uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SAML_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
if (config.isValidateSignature()) {
try {
verifySignature(holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
}
if (statusResponse instanceof ResponseType) {
return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
} else {
// todo need to check that it is actually a LogoutResponse
return handleLogoutResponse(holder, statusResponse, relayState);
}
//throw new RuntimeException("Unknown response type");
}
protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
if (relayState == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}
protected ResponseType decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ProcessingException {
SAML2Response saml2Response = new SAML2Response();
try {
Document doc = saml2Response.convert(responseType);
Element enc = DocumentUtil.getElement(doc, new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
if (enc == null) {
throw new IdentityBrokerException("No encrypted assertion found.");
}
String oldID = enc.getAttribute(JBossSAMLConstants.ID.get());
Document newDoc = DocumentUtil.createDocument();
Node importedNode = newDoc.importNode(enc, true);
newDoc.appendChild(importedNode);
Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
SAMLParser parser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
.getNodeAsStream(decryptedDocumentElement)));
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
return responseType;
} catch (Exception e) {
throw new IdentityBrokerException("Could not decrypt assertion.", e);
}
}
}
protected class PostBinding extends Binding {
@Override
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestPostBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
byte[] samlBytes = PostBindingUtil.base64Decode(response);
String xml = new String(samlBytes);
return SAMLRequestParser.parseResponseDocument(samlBytes);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_POST_BINDING;
}
}
protected class RedirectBinding extends Binding {
@Override
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
PublicKey publicKey = getIDPKey();
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
return SAMLRequestParser.parseRequestRedirectBinding(response);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_REDIRECT_BINDING;
}
}
}
package org.keycloak.broker.saml;
import org.jboss.logging.Logger;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.VerificationException;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
import org.keycloak.saml.SAML2LogoutResponseBuilder;
import org.keycloak.saml.SAMLRequestParser;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlProtocolUtils;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
import org.keycloak.saml.processing.web.util.PostBindingUtil;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SAMLEndpoint {
protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
public static final String SAML_ASSERTION = "SAML_ASSERTION";
public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
protected RealmModel realm;
protected EventBuilder event;
protected SAMLIdentityProviderConfig config;
protected IdentityProvider.AuthenticationCallback callback;
protected SAMLIdentityProvider provider;
@Context
private UriInfo uriInfo;
@Context
private KeycloakSession session;
@Context
private ClientConnection clientConnection;
@Context
private HttpHeaders headers;
public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
this.realm = realm;
this.config = config;
this.callback = callback;
this.provider = provider;
}
@GET
public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
}
/**
*/
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@FormParam(GeneralConstants.RELAY_STATE) String relayState) {
return new PostBinding().execute(samlRequest, samlResponse, relayState);
}
protected abstract class Binding {
private boolean checkSsl() {
if (uriInfo.getBaseUri().getScheme().equals("https")) {
return true;
} else {
return !realm.getSslRequired().isRequired(clientConnection);
}
}
protected Response basicChecks(String samlRequest, String samlResponse) {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
}
protected abstract String getBindingType();
protected abstract void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException;
protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
protected PublicKey getIDPKey() {
X509Certificate certificate = null;
try {
certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return certificate.getPublicKey();
}
public Response execute(String samlRequest, String samlResponse, String relayState) {
event = new EventBuilder(realm, session, clientConnection);
Response response = basicChecks(samlRequest, samlResponse);
if (response != null) return response;
if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
else return handleSamlResponse(samlResponse, relayState);
}
protected Response handleSamlRequest(String samlRequest, String relayState) {
SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
// validate destination
if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
if (config.isValidateSignature()) {
try {
verifySignature(GeneralConstants.SAML_REQUEST_KEY, holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
}
if (requestAbstractType instanceof LogoutRequestType) {
logger.debug("** logout request");
event.event(EventType.LOGOUT);
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
return logoutRequest(logout, relayState);
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
protected Response logoutRequest(LogoutRequestType request, String relayState) {
String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
for (UserSessionModel userSession : userSessions) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
} else {
for (String sessionIndex : request.getSessionIndex()) {
String brokerSessionId = brokerUserId + "." + sessionIndex;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
}
}
String issuerURL = getEntityId(uriInfo, realm);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(request.getID());
builder.destination(config.getSingleLogoutServiceUrl());
builder.issuer(issuerURL);
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(relayState);
if (config.isWantAuthnRequestsSigned()) {
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signatureAlgorithm(provider.getSignatureAlgorithm())
.signDocument();
}
try {
if (config.isPostBindingResponse()) {
return binding.postBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
} else {
return binding.redirectBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
} catch (ProcessingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getEntityId(UriInfo uriInfo, RealmModel realm) {
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
}
protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
try {
AssertionType assertion = AssertionUtil.getAssertion(responseType, realm.getPrivateKey());
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
//Map<String, String> notes = new HashMap<>();
BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
identity.setCode(relayState);
identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
identity.getContextData().put(SAML_ASSERTION, assertion);
identity.setUsername(subjectNameID.getValue());
//SAML Spec 2.2.2 Format is optional
if (subjectNameID.getFormat() != null && subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
identity.setEmail(subjectNameID.getValue());
}
if (config.isStoreToken()) {
identity.setToken(samlResponse);
}
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType)statement;
identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
break;
}
}
if (assertion.getAttributeStatements() != null ) {
for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
AttributeType attribute = choice.getAttribute();
if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
|| X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
}
}
}
}
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
identity.setBrokerUserId(brokerUserId);
identity.setIdpConfig(config);
identity.setIdp(provider);
if (authn != null && authn.getSessionIndex() != null) {
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
}
return callback.authenticated(identity);
} catch (Exception e) {
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
}
}
public Response handleSamlResponse(String samlResponse, String relayState) {
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
// validate destination
if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
if (config.isValidateSignature()) {
try {
verifySignature(GeneralConstants.SAML_RESPONSE_KEY, holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
}
if (statusResponse instanceof ResponseType) {
return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
} else {
// todo need to check that it is actually a LogoutResponse
return handleLogoutResponse(holder, statusResponse, relayState);
}
//throw new RuntimeException("Unknown response type");
}
protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
if (relayState == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}
}
protected class PostBinding extends Binding {
@Override
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestPostBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
byte[] samlBytes = PostBindingUtil.base64Decode(response);
String xml = new String(samlBytes);
return SAMLRequestParser.parseResponseDocument(samlBytes);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_POST_BINDING;
}
}
protected class RedirectBinding extends Binding {
@Override
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
PublicKey publicKey = getIDPKey();
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo, key);
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
return SAMLRequestParser.parseRequestRedirectBinding(response);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_REDIRECT_BINDING;
}
}
}
@@ -33,20 +33,18 @@ import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.SAML2AuthnRequestBuilder;
import org.keycloak.protocol.saml.SAML2LogoutRequestBuilder;
import org.keycloak.protocol.saml.SAML2NameIDPolicyBuilder;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
import org.keycloak.saml.SAML2AuthnRequestBuilder;
import org.keycloak.saml.SAML2LogoutRequestBuilder;
import org.keycloak.saml.SAML2NameIDPolicyBuilder;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -92,7 +90,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
.issuer(issuerURL)
.forceAuthn(getConfig().isForceAuthn())
.protocolBinding(protocolBinding)
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat))
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat));
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(request.getState());
if (getConfig().isWantAuthnRequestsSigned()) {
@@ -109,14 +108,15 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
KeyPair keypair = new KeyPair(publicKey, privateKey);
authnRequestBuilder.signWith(keypair);
authnRequestBuilder.signDocument();
binding.signWith(keypair);
binding.signatureAlgorithm(getSignatureAlgorithm());
binding.signDocument();
}
if (getConfig().isPostBindingAuthnRequest()) {
return authnRequestBuilder.postBinding().request();
return binding.postBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
} else {
return authnRequestBuilder.redirectBinding().request();
return binding.redirectBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
}
} catch (Exception e) {
throw new IdentityBrokerException("Could not create authentication request.", e);
@@ -153,9 +153,10 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl();
if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("") || !getConfig().isBackchannelSupported()) return;
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
try {
int status = SimpleHttp.doPost(singleLogoutServiceUrl)
.param(GeneralConstants.SAML_REQUEST_KEY, logoutBuilder.postBinding().encoded())
.param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(logoutBuilder.buildDocument()).encoded())
.param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus();
boolean success = status >=200 && status < 400;
if (!success) {
@@ -178,7 +179,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
} else {
try {
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
return logoutBuilder.postBinding().request();
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
return binding.postBinding(logoutBuilder.buildDocument()).request(singleLogoutServiceUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -192,13 +194,19 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
.issuer(getEntityId(uriInfo, realm))
.sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX))
.userPrincipal(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT), userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEFORMAT))
.destination(singleLogoutServiceUrl)
.destination(singleLogoutServiceUrl);
return logoutBuilder;
}
private JaxrsSAML2BindingBuilder buildLogoutBinding(UserSessionModel userSession, RealmModel realm) {
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(userSession.getId());
if (getConfig().isWantAuthnRequestsSigned()) {
logoutBuilder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signatureAlgorithm(getSignatureAlgorithm())
.signDocument();
}
return logoutBuilder;
return binding;
}
@Override
@@ -220,7 +228,7 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
String descriptor =
"<EntityDescriptor entityID=\"" + getEntityId(uriInfo, realm) + "\">\n" +
"<EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + getEntityId(uriInfo, realm) + "\">\n" +
" <SPSSODescriptor AuthnRequestsSigned=\"" + getConfig().isWantAuthnRequestsSigned() + "\"\n" +
" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n" +
" <NameIDFormat>" + getConfig().getNameIDPolicyFormat() + "\n" +
@@ -245,4 +253,14 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
"</EntityDescriptor>\n";
return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
}
public SignatureAlgorithm getSignatureAlgorithm() {
String alg = getConfig().getSignatureAlgorithm();
if (alg != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
if (algorithm != null) return algorithm;
}
return SignatureAlgorithm.RSA_SHA256;
}
}
@@ -87,6 +87,14 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
getConfig().put("wantAuthnRequestsSigned", String.valueOf(wantAuthnRequestsSigned));
}
public String getSignatureAlgorithm() {
return getConfig().get("signatureAlgorithm");
}
public void setSignatureAlgorithm(String signatureAlgorithm) {
getConfig().put("signatureAlgorithm", signatureAlgorithm);
}
public String getEncryptionPublicKey() {
return getConfig().get("encryptionPublicKey");
}
@@ -18,13 +18,17 @@
package org.keycloak.broker.saml;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.broker.saml.mappers.UsernameTemplateMapper;
import org.keycloak.dom.saml.v2.metadata.EndpointType;
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.util.DocumentUtil;
@@ -69,75 +73,79 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
List<EntityDescriptorType.EDTChoiceType> choiceType = entityType.getChoiceType();
if (!choiceType.isEmpty()) {
EntityDescriptorType.EDTChoiceType edtChoiceType = choiceType.get(0);
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
IDPSSODescriptorType idpDescriptor = null;
if (!descriptors.isEmpty()) {
EntityDescriptorType.EDTDescriptorChoiceType edtDescriptorChoiceType = descriptors.get(0);
IDPSSODescriptorType idpDescriptor = edtDescriptorChoiceType.getIdpDescriptor();
//Metadata documents can contain multiple Descriptors (See ADFS metadata documents) such as RoleDescriptor, SPSSODescriptor, IDPSSODescriptor.
//So we need to loop through to find the IDPSSODescriptor.
for(EntityDescriptorType.EDTChoiceType edtChoiceType : entityType.getChoiceType()) {
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
if (idpDescriptor != null) {
SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
String singleSignOnServiceUrl = null;
boolean postBinding = false;
for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleSignOnServiceUrl = endpoint.getLocation().toString();
postBinding = true;
break;
} else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleSignOnServiceUrl = endpoint.getLocation().toString();
}
}
String singleLogoutServiceUrl = null;
for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
} else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
}
}
samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setPostBindingResponse(postBinding);
samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
String defaultCertificate = null;
if (keyDescriptor != null) {
for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
Element keyInfo = keyDescriptorType.getKeyInfo();
Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
} else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
} else if (keyDescriptorType.getUse() == null) {
defaultCertificate = x509KeyInfo.getTextContent();
}
}
}
if (defaultCertificate != null) {
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
}
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
}
}
return samlIdentityProviderConfig.getConfig();
if(!descriptors.isEmpty() && descriptors.get(0).getIdpDescriptor() != null) {
idpDescriptor = descriptors.get(0).getIdpDescriptor();
}
}
if (idpDescriptor != null) {
SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
String singleSignOnServiceUrl = null;
boolean postBinding = false;
for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleSignOnServiceUrl = endpoint.getLocation().toString();
postBinding = true;
break;
} else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleSignOnServiceUrl = endpoint.getLocation().toString();
}
}
String singleLogoutServiceUrl = null;
for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
} else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
}
}
samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setPostBindingResponse(postBinding);
samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
String defaultCertificate = null;
if (keyDescriptor != null) {
for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
Element keyInfo = keyDescriptorType.getKeyInfo();
Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
} else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
} else if (keyDescriptorType.getUse() == null) {
defaultCertificate = x509KeyInfo.getTextContent();
}
}
}
if (defaultCertificate != null) {
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
}
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
}
}
return samlIdentityProviderConfig.getConfig();
}
}
} catch (ParsingException pe) {
throw new RuntimeException("Could not parse IdP SAML Metadata", pe);
@@ -150,4 +158,5 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
public String getId() {
return PROVIDER_ID;
}
}
@@ -1,140 +1,140 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String ATTRIBUTE_VALUE = "attribute.value";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("Attribute Value");
property.setHelpText("Value the attribute must have. If the attribute is a list, then the value must be contained in the list.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Mapper";
}
@Override
public String getDisplayType() {
return "SAML Attribute to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
for (Object val : attr.getAttributeValue()) {
if (val.equals(desiredValue)) return true;
}
}
}
return false;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String ATTRIBUTE_VALUE = "attribute.value";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("Attribute Value");
property.setHelpText("Value the attribute must have. If the attribute is a list, then the value must be contained in the list.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Mapper";
}
@Override
public String getDisplayType() {
return "SAML Attribute to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
for (Object val : attr.getAttributeValue()) {
if (val.equals(desiredValue)) return true;
}
}
}
return false;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
@@ -1,132 +1,129 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store saml attribute.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
if (value != null) {
user.setAttribute(attribute, value.toString());
}
}
protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue == null || attributeValue.isEmpty()) return null;
return attributeValue.get(0).toString();
}
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
String current = user.getAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
}
}
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store saml attribute.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value.toString());
}
}
protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !friendly.equals(attr.getFriendlyName())) continue;
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue == null || attributeValue.isEmpty()) return null;
return attributeValue.get(0).toString();
}
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
String current = user.getFirstAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setSingleAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
}
}
@@ -0,0 +1,133 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${NAMEID}'. ALIAS is the provider alias. NAMEID is that SAML name id assertion. ATTRIBUTE.<NAME> references a SAML attribute where name is the attribute name or friendly name.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${NAMEID}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.equals("NAMEID")) {
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
m.appendReplacement(sb, subjectNameID.getValue());
} else if (variable.startsWith("ATTRIBUTE.")) {
String name = variable.substring("ATTRIBUTE.".length());
String value = "";
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name.equals(attr.getName()) || name.equals(attr.getFriendlyName())) {
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue != null && !attributeValue.isEmpty()) {
value = attributeValue.get(0).toString();
}
break;
}
}
}
m.appendReplacement(sb, value);
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
context.setModelUsername(sb.toString());
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
@@ -1,2 +1,3 @@
org.keycloak.broker.saml.mappers.AttributeToRoleMapper
org.keycloak.broker.saml.mappers.UserAttributeMapper
org.keycloak.broker.saml.mappers.AttributeToRoleMapper
org.keycloak.broker.saml.mappers.UserAttributeMapper
org.keycloak.broker.saml.mappers.UsernameTemplateMapper
@@ -1,29 +1,31 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-model-sessions-mem</artifactId>
<name>Keycloak Model Sessions Mem</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?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.6.1.Final</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-api</artifactId>
<name>Keycloak Client API</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,275 @@
package org.keycloak.client.registration;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.common.util.Base64;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistration {
private String clientRegistrationUrl;
private HttpClient httpClient;
private Auth auth;
public static ClientRegistrationBuilder create() {
return new ClientRegistrationBuilder();
}
private ClientRegistration() {
}
public ClientRepresentation create(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = doPost(content);
return deserialize(resultStream, ClientRepresentation.class);
}
public ClientRepresentation get() throws ClientRegistrationException {
if (auth instanceof ClientIdSecretAuth) {
String clientId = ((ClientIdSecretAuth) auth).clientId;
return get(clientId);
} else {
throw new ClientRegistrationException("Requires client authentication");
}
}
public ClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = doGet(clientId);
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}
public void update(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
doPut(content, client.getClientId());
}
public void delete() throws ClientRegistrationException {
if (auth instanceof ClientIdSecretAuth) {
String clientId = ((ClientIdSecretAuth) auth).clientId;
delete(clientId);
} else {
throw new ClientRegistrationException("Requires client authentication");
}
}
public void delete(String clientId) throws ClientRegistrationException {
doDelete(clientId);
}
public void close() throws ClientRegistrationException {
if (httpClient instanceof CloseableHttpClient) {
try {
((CloseableHttpClient) httpClient).close();
} catch (IOException e) {
throw new ClientRegistrationException("Failed to close http client", e);
}
}
}
private InputStream doPost(String content) throws ClientRegistrationException {
try {
HttpPost request = new HttpPost(clientRegistrationUrl);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setEntity(new StringEntity(content));
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
InputStream responseStream = null;
if (response.getEntity() != null) {
responseStream = response.getEntity().getContent();
}
if (response.getStatusLine().getStatusCode() == 201) {
return responseStream;
} else {
responseStream.close();
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private InputStream doGet(String endpoint) throws ClientRegistrationException {
try {
HttpGet request = new HttpGet(clientRegistrationUrl + "/" + endpoint);
request.setHeader(HttpHeaders.ACCEPT, "application/json");
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
InputStream responseStream = null;
if (response.getEntity() != null) {
responseStream = response.getEntity().getContent();
}
if (response.getStatusLine().getStatusCode() == 200) {
return responseStream;
} else if (response.getStatusLine().getStatusCode() == 404) {
responseStream.close();
return null;
} else {
responseStream.close();
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private void doPut(String content, String endpoint) throws ClientRegistrationException {
try {
HttpPut request = new HttpPut(clientRegistrationUrl + "/" + endpoint);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setHeader(HttpHeaders.ACCEPT, "application/json");
request.setEntity(new StringEntity(content));
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent().close();
}
if (response.getStatusLine().getStatusCode() != 200) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private void doDelete(String endpoint) throws ClientRegistrationException {
try {
HttpDelete request = new HttpDelete(clientRegistrationUrl + "/" + endpoint);
auth.addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent().close();
}
if (response.getStatusLine().getStatusCode() != 200) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
private String serialize(ClientRepresentation client) throws ClientRegistrationException {
try {
return JsonSerialization.writeValueAsString(client);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to write json object", e);
}
}
private <T> T deserialize(InputStream inputStream, Class<T> clazz) throws ClientRegistrationException {
try {
return JsonSerialization.readValue(inputStream, clazz);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to read json object", e);
}
}
public static class ClientRegistrationBuilder {
private String realm;
private String authServerUrl;
private Auth auth;
private HttpClient httpClient;
public ClientRegistrationBuilder realm(String realm) {
this.realm = realm;
return this;
}
public ClientRegistrationBuilder authServerUrl(String authServerUrl) {
this.authServerUrl = authServerUrl;
return this;
}
public ClientRegistrationBuilder auth(String token) {
this.auth = new TokenAuth(token);
return this;
}
public ClientRegistrationBuilder auth(String clientId, String clientSecret) {
this.auth = new ClientIdSecretAuth(clientId, clientSecret);
return this;
}
public ClientRegistrationBuilder httpClient(HttpClient httpClient) {
this.httpClient = httpClient;
return this;
}
public ClientRegistration build() {
ClientRegistration clientRegistration = new ClientRegistration();
clientRegistration.clientRegistrationUrl = authServerUrl + "/realms/" + realm + "/client-registration/default";
clientRegistration.httpClient = httpClient != null ? httpClient : HttpClients.createDefault();
clientRegistration.auth = auth;
return clientRegistration;
}
}
public interface Auth {
void addAuth(HttpRequest httpRequest);
}
public static class AuthorizationHeaderAuth implements Auth {
private String credentials;
public AuthorizationHeaderAuth(String credentials) {
this.credentials = credentials;
}
public void addAuth(HttpRequest httpRequest) {
httpRequest.setHeader(HttpHeaders.AUTHORIZATION, credentials);
}
}
public static class TokenAuth extends AuthorizationHeaderAuth {
public TokenAuth(String token) {
super("Bearer " + token);
}
}
public static class ClientIdSecretAuth extends AuthorizationHeaderAuth {
private String clientId;
public ClientIdSecretAuth(String clientId, String clientSecret) {
super("Basic " + Base64.encodeBytes((clientId + ":" + clientSecret).getBytes()));
this.clientId = clientId;
}
}
}
@@ -0,0 +1,16 @@
package org.keycloak.client.registration;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationException extends Exception {
public ClientRegistrationException(String s, Throwable throwable) {
super(s, throwable);
}
public ClientRegistrationException(String s) {
super(s);
}
}
@@ -0,0 +1,22 @@
package org.keycloak.client.registration;
import org.apache.http.StatusLine;
import java.io.IOException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class HttpErrorException extends IOException {
private StatusLine statusLine;
public HttpErrorException(StatusLine statusLine) {
this.statusLine = statusLine;
}
public StatusLine getStatusLine() {
return statusLine;
}
}
Executable
+94
View File
@@ -0,0 +1,94 @@
<?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.6.1.Final</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-common</artifactId>
<name>Keycloak Common</name>
<packaging>jar</packaging>
<description>Common library and dependencies shared with server and all adapters</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.common.*
</keycloak.osgi.export>
<keycloak.osgi.import>
*;resolution:=optional
</keycloak.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<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>
</project>
@@ -1,13 +1,13 @@
package org.keycloak;
/**
* Information about the client connection
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientConnection {
String getRemoteAddr();
String getRemoteHost();
int getReportPort();
}
package org.keycloak.common;
/**
* Information about the client connection
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientConnection {
String getRemoteAddr();
String getRemoteHost();
int getReportPort();
}
@@ -1,4 +1,4 @@
package org.keycloak;
package org.keycloak.common;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+37
View File
@@ -0,0 +1,37 @@
package org.keycloak.common;
import org.keycloak.common.util.Time;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Version {
public static final String UNKNOWN = "UNKNOWN";
public static String VERSION;
public static String RESOURCES_VERSION;
public static String BUILD_TIME;
static {
Properties props = new Properties();
InputStream is = Version.class.getResourceAsStream("/keycloak-version.properties");
try {
props.load(is);
Version.VERSION = props.getProperty("version");
Version.BUILD_TIME = props.getProperty("build-time");
Version.RESOURCES_VERSION = Version.VERSION.toLowerCase();
if (Version.RESOURCES_VERSION.endsWith("-snapshot")) {
Version.RESOURCES_VERSION = Version.RESOURCES_VERSION.replace("-snapshot", "-" + Time.currentTime());
}
} catch (IOException e) {
Version.VERSION= Version.UNKNOWN;
Version.BUILD_TIME= Version.UNKNOWN;
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.constants;
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,4 +1,4 @@
package org.keycloak.constants;
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -0,0 +1,19 @@
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ServiceAccountConstants {
String CLIENT_AUTH = "client_auth";
String SERVICE_ACCOUNT_USER_PREFIX = "service-account-";
String CLIENT_ID_PROTOCOL_MAPPER = "Client ID";
String CLIENT_HOST_PROTOCOL_MAPPER = "Client Host";
String CLIENT_ADDRESS_PROTOCOL_MAPPER = "Client IP Address";
String CLIENT_ID = "clientId";
String CLIENT_HOST = "clientHost";
String CLIENT_ADDRESS = "clientAddress";
}
@@ -1,4 +1,4 @@
package org.keycloak.enums;
package org.keycloak.common.enums;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,6 +1,6 @@
package org.keycloak.enums;
package org.keycloak.common.enums;
import org.keycloak.ClientConnection;
import org.keycloak.common.ClientConnection;
import java.net.InetAddress;
import java.net.UnknownHostException;
File diff suppressed because it is too large. Load diff
@@ -1,44 +1,42 @@
package org.keycloak.util;
import net.iharder.Base64;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Base64Url {
public static String encode(byte[] bytes) {
String s = Base64.encodeBytes(bytes);
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
public static byte[] decode(String s) {
s = s.replace('-', '+'); // 62nd char of encoding
s = s.replace('_', '/'); // 63rd char of encoding
switch (s.length() % 4) // Pad with trailing '='s
{
case 0:
break; // No pad chars in this case
case 2:
s += "==";
break; // Two pad chars
case 3:
s += "=";
break; // One pad char
default:
throw new RuntimeException(
"Illegal base64url string!");
}
try {
return Base64.decode(s);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package org.keycloak.common.util;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Base64Url {
public static String encode(byte[] bytes) {
String s = Base64.encodeBytes(bytes);
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
public static byte[] decode(String s) {
s = s.replace('-', '+'); // 62nd char of encoding
s = s.replace('_', '/'); // 63rd char of encoding
switch (s.length() % 4) // Pad with trailing '='s
{
case 0:
break; // No pad chars in this case
case 2:
s += "==";
break; // Two pad chars
case 3:
s += "=";
break; // One pad char
default:
throw new RuntimeException(
"Illegal base64url string!");
}
try {
return Base64.decode(s);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -1,166 +1,165 @@
package org.keycloak.util;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
* @version $Revision: 2 $
*/
public class CertificateUtils {
static {
BouncyIntegration.init();
}
/**
* Generates version 3 {@link java.security.cert.X509Certificate}.
*
* @param keyPair the key pair
* @param caPrivateKey the CA private key
* @param caCert the CA certificate
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
// Serial Number
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
// Validity
Date notBefore = new Date(System.currentTimeMillis());
Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
// SubjectPublicKeyInfo
SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
.getEncoded()));
X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
DigestCalculator digCalc = new BcDigestCalculatorProvider()
.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
// Subject Key Identifier
certGen.addExtension(Extension.subjectKeyIdentifier, false,
x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
// Authority Key Identifier
certGen.addExtension(Extension.authorityKeyIdentifier, false,
x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
// Key Usage
certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
| KeyUsage.cRLSign));
// Extended Key Usage
KeyPurposeId[] EKU = new KeyPurposeId[2];
EKU[0] = KeyPurposeId.id_kp_emailProtection;
EKU[1] = KeyPurposeId.id_kp_serverAuth;
certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
// Basic Constraints
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
// Content Signer
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
// Certificate
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
} catch (Exception e) {
throw new RuntimeException("Error creating X509v3Certificate.", e);
}
}
/**
* Generate version 1 self signed {@link java.security.cert.X509Certificate}..
*
* @param caKeyPair the CA key pair
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
Date validityEndDate = new Date(calendar.getTime().getTime());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
validityEndDate, subjectDN, subPubKeyInfo);
X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
return new JcaX509CertificateConverter().getCertificate(holder);
} catch (Exception e) {
throw new RuntimeException("Error creating X509v1Certificate.", e);
}
}
/**
* Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
*
* @param privateKey the private key
*
* @return the content signer
*/
public static ContentSigner createSigner(PrivateKey privateKey) {
try {
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
} catch (Exception e) {
throw new RuntimeException("Could not create content signer.", e);
}
}
}
package org.keycloak.common.util;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
* @version $Revision: 2 $
*/
public class CertificateUtils {
static {
BouncyIntegration.init();
}
/**
* Generates version 3 {@link java.security.cert.X509Certificate}.
*
* @param keyPair the key pair
* @param caPrivateKey the CA private key
* @param caCert the CA certificate
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
// Serial Number
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
// Validity
Date notBefore = new Date(System.currentTimeMillis());
Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
// SubjectPublicKeyInfo
SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
.getEncoded()));
X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
DigestCalculator digCalc = new BcDigestCalculatorProvider()
.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
// Subject Key Identifier
certGen.addExtension(Extension.subjectKeyIdentifier, false,
x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
// Authority Key Identifier
certGen.addExtension(Extension.authorityKeyIdentifier, false,
x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
// Key Usage
certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
| KeyUsage.cRLSign));
// Extended Key Usage
KeyPurposeId[] EKU = new KeyPurposeId[2];
EKU[0] = KeyPurposeId.id_kp_emailProtection;
EKU[1] = KeyPurposeId.id_kp_serverAuth;
certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
// Basic Constraints
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
// Content Signer
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
// Certificate
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
} catch (Exception e) {
throw new RuntimeException("Error creating X509v3Certificate.", e);
}
}
/**
* Generate version 1 self signed {@link java.security.cert.X509Certificate}..
*
* @param caKeyPair the CA key pair
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
Date validityEndDate = new Date(calendar.getTime().getTime());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
validityEndDate, subjectDN, subPubKeyInfo);
X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
return new JcaX509CertificateConverter().getCertificate(holder);
} catch (Exception e) {
throw new RuntimeException("Error creating X509v1Certificate.", e);
}
}
/**
* Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
*
* @param privateKey the private key
*
* @return the content signer
*/
public static ContentSigner createSigner(PrivateKey privateKey) {
try {
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
} catch (Exception e) {
throw new RuntimeException("Could not create content signer.", e);
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.Collection;
import java.util.Iterator;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.DataInputStream;
import java.io.InputStream;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@@ -1,37 +1,37 @@
package org.keycloak.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class EnvUtil {
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
private EnvUtil() {
}
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val) {
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
}
package org.keycloak.common.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class EnvUtil {
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
private EnvUtil() {
}
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val) {
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
}
@@ -1,37 +1,37 @@
package org.keycloak.util;
import org.keycloak.constants.GenericConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FindFile {
public static InputStream findFile(String keycloakConfigFile) {
if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
// Try current class classloader first
InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
}
if (is != null) {
return is;
} else {
throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
}
} else {
// Fallback to file
try {
return new FileInputStream(keycloakConfigFile);
} catch (FileNotFoundException fnfe) {
throw new RuntimeException(fnfe);
}
}
}
}
package org.keycloak.common.util;
import org.keycloak.common.constants.GenericConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FindFile {
public static InputStream findFile(String keycloakConfigFile) {
if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
// Try current class classloader first
InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
}
if (is != null) {
return is;
} else {
throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
}
} else {
// Fallback to file
try {
return new FileInputStream(keycloakConfigFile);
} catch (FileNotFoundException fnfe) {
throw new RuntimeException(fnfe);
}
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.util;
package org.keycloak.common.util;
/**
* @author pedroigor
@@ -34,7 +34,17 @@ public class HtmlUtils {
for (int i = 0; i < value.length(); i++) {
char chr = value.charAt(i);
if (chr != '\'' && chr != '"' && chr != '<' && chr != '>' && chr != '/') {
if (chr == '<') {
escaped.append("&lt;");
} else if (chr == '>') {
escaped.append("&gt;");
} else if (chr == '"') {
escaped.append("&quot;");
} else if (chr == '\'') {
escaped.append("&apos;");
} else if (chr == '&') {
escaped.append("&amp;");
} else {
escaped.append(chr);
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -12,13 +12,12 @@ import java.lang.reflect.Method;
import javax.security.auth.kerberos.KerberosTicket;
import net.iharder.Base64;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.Oid;
import org.keycloak.constants.KerberosConstants;
import org.keycloak.util.reflections.Reflections;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.reflections.Reflections;
import sun.security.jgss.GSSCredentialImpl;
import sun.security.jgss.GSSManagerImpl;
import sun.security.jgss.krb5.Krb5InitCredential;
@@ -0,0 +1,56 @@
package org.keycloak.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import org.keycloak.common.constants.GenericConstants;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeystoreUtil {
static {
BouncyIntegration.init();
}
public enum KeystoreFormat {
JKS,
PKCS12
}
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
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;
}
public static PrivateKey loadPrivateKeyFromKeystore(String keystoreFile, String storePassword, String keyPassword, String keyAlias, KeystoreFormat format) {
InputStream stream = FindFile.findFile(keystoreFile);
try {
KeyStore keyStore = null;
if (format == KeystoreFormat.JKS) {
keyStore = KeyStore.getInstance(format.toString());
} else {
keyStore = KeyStore.getInstance(format.toString(), "BC");
}
keyStore.load(stream, storePassword.toCharArray());
PrivateKey key = (PrivateKey) keyStore.getKey(keyAlias, keyPassword.toCharArray());
if (key == null) {
throw new RuntimeException("Couldn't load key with alias '" + keyAlias + "' from keystore");
}
return key;
} catch (Exception e) {
throw new RuntimeException("Failed to load private key: " + e.getMessage(), e);
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.ArrayList;
import java.util.Collection;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
/*
* JBoss, Home of Professional Open Source.
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,7 +1,7 @@
/**
*
*/
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.regex.Pattern;
@@ -1,110 +1,108 @@
package org.keycloak.util;
import net.iharder.Base64;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
/**
* Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class PemUtils {
static {
BouncyIntegration.init();
}
private PemUtils() {
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(String cert) throws Exception {
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException {
String pem = pemFromStream(is);
return pemToDer(pem);
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException {
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
public static String removeBeginEnd(String pem) {
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String pemFromStream(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
}
package org.keycloak.common.util;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
/**
* Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class PemUtils {
static {
BouncyIntegration.init();
}
private PemUtils() {
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(String cert) throws Exception {
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException {
String pem = pemFromStream(is);
return pemToDer(pem);
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException {
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
public static String removeBeginEnd(String pem) {
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String pemFromStream(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.Serializable;
import java.text.DateFormat;
@@ -1,35 +1,35 @@
package org.keycloak.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class StreamUtil {
private StreamUtil() {
}
public static String readString(InputStream in) throws IOException
{
char[] buffer = new char[1024];
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int wasRead;
do
{
wasRead = reader.read(buffer, 0, 1024);
if (wasRead > 0)
{
builder.append(buffer, 0, wasRead);
}
}
while (wasRead > -1);
return builder.toString();
}
}
package org.keycloak.common.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class StreamUtil {
private StreamUtil() {
}
public static String readString(InputStream in) throws IOException
{
char[] buffer = new char[1024];
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int wasRead;
do
{
wasRead = reader.read(buffer, 0, 1024);
if (wasRead > 0)
{
builder.append(buffer, 0, wasRead);
}
}
while (wasRead > -1);
return builder.toString();
}
}
@@ -19,7 +19,7 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.File;
import java.util.Properties;
@@ -0,0 +1,25 @@
package org.keycloak.common.util;
import java.util.Properties;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class SystemEnvProperties extends Properties {
@Override
public String getProperty(String key) {
if (key.startsWith("env.")) {
return System.getenv().get(key.substring(4));
} else {
return System.getProperty(key);
}
}
@Override
public String getProperty(String key, String defaultValue) {
String value = getProperty(key);
return value != null ? value : defaultValue;
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.Date;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.UnsupportedEncodingException;
import java.net.URI;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.beans.Introspector;
import java.io.Serializable;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.lang.reflect.AccessibleObject;
import java.security.PrivilegedAction;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.lang.reflect.Type;
+2
View File
@@ -0,0 +1,2 @@
version=${product.version}
build-time=${product.build-time}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.2.0.RC1-SNAPSHOT</version>
<version>1.6.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -90,18 +90,7 @@ public class DefaultFileConnectionProviderFactory implements FileConnectionProvi
ImportUtils.importFromStream(session, JsonSerialization.mapper, fis, Strategy.IGNORE_EXISTING);
session.realms().getMigrationModel().setStoredVersion(model.getModelVersion());
List<RealmRepresentation> realmReps = new ArrayList<RealmRepresentation>();
for (RealmRepresentation realmRep : model.getRealms()) {
if (Config.getAdminRealm().equals(realmRep.getRealm())) {
realmReps.add(0, realmRep);
} else {
realmReps.add(realmRep);
}
}
for (RealmRepresentation realmRep : realmReps) {
ImportUtils.importRealm(session, realmRep, Strategy.IGNORE_EXISTING);
}
ImportUtils.importRealms(session, model.getRealms(), Strategy.IGNORE_EXISTING);
} catch (IOException ioe) {
logger.error("Unable to read model file " + kcdata.getAbsolutePath(), ioe);
} finally {
@@ -9,6 +9,11 @@ import org.keycloak.provider.Spi;
*/
public class FileConnectionSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "connectionsFile";
@@ -1,30 +1,30 @@
package org.keycloak.connections.file;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Model {
private String modelVersion;
private List<RealmRepresentation> realms;
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public List<RealmRepresentation> getRealms() {
return realms;
}
public void setRealms(List<RealmRepresentation> realms) {
this.realms = realms;
}
}
package org.keycloak.connections.file;
import org.keycloak.representations.idm.RealmRepresentation;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Model {
private String modelVersion;
private List<RealmRepresentation> realms;
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public List<RealmRepresentation> getRealms() {
return realms;
}
public void setRealms(List<RealmRepresentation> realms) {
this.realms = realms;
}
}
+36 -36
View File
@@ -1,36 +1,36 @@
<?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.2.0.RC1-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-http-client</artifactId>
<name>Keycloak Connections Apache HttpClient</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?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.6.1.Final</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-http-client</artifactId>
<name>Keycloak Connections Apache HttpClient</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -12,8 +12,8 @@ import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.util.EnvUtil;
import org.keycloak.util.KeystoreUtil;
import org.keycloak.common.util.EnvUtil;
import org.keycloak.common.util.KeystoreUtil;
import java.io.IOException;
import java.io.InputStream;
@@ -1,281 +1,281 @@
package org.keycloak.connections.httpclient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
/**
* Abstraction for creating HttpClients. Allows SSL configuration.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HttpClientBuilder {
public static enum HostnameVerificationPolicy {
/**
* Hostname verification is not done on the server's certificate
*/
ANY,
/**
* Allows wildcards in subdomain names i.e. *.foo.com
*/
WILDCARD,
/**
* CN must match hostname connecting to
*/
STRICT
}
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
private static class PassthroughTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
protected KeyStore truststore;
protected KeyStore clientKeyStore;
protected String clientPrivateKeyPassword;
protected boolean disableTrustManager;
protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
protected SSLContext sslContext;
protected int connectionPoolSize = 100;
protected int maxPooledPerRoute = 0;
protected long connectionTTL = -1;
protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
protected HostnameVerifier verifier = null;
protected long socketTimeout = -1;
protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
protected long establishConnectionTimeout = -1;
protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
protected boolean disableCookies = false;
/**
* Socket inactivity timeout
*
* @param timeout
* @param unit
* @return
*/
public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
{
this.socketTimeout = timeout;
this.socketTimeoutUnits = unit;
return this;
}
/**
* When trying to make an initial socket connection, what is the timeout?
*
* @param timeout
* @param unit
* @return
*/
public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
{
this.establishConnectionTimeout = timeout;
this.establishConnectionTimeoutUnits = unit;
return this;
}
public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
this.connectionTTL = ttl;
this.connectionTTLUnit = unit;
return this;
}
public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
this.maxPooledPerRoute = maxPooledPerRoute;
return this;
}
public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
return this;
}
/**
* Disable trust management and hostname verification. <i>NOTE</i> this is a security
* hole, so only set this option if you cannot or do not want to verify the identity of the
* host you are communicating with.
*/
public HttpClientBuilder disableTrustManager() {
this.disableTrustManager = true;
return this;
}
/**
* Disable cookie management.
*/
public HttpClientBuilder disableCookies(boolean disable) {
this.disableTrustManager = disable;
return this;
}
/**
* SSL policy used to verify hostnames
*
* @param policy
* @return
*/
public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
this.policy = policy;
return this;
}
public HttpClientBuilder sslContext(SSLContext sslContext) {
this.sslContext = sslContext;
return this;
}
public HttpClientBuilder trustStore(KeyStore truststore) {
this.truststore = truststore;
return this;
}
public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
this.clientKeyStore = keyStore;
this.clientPrivateKeyPassword = password;
return this;
}
public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
this.clientKeyStore = keyStore;
this.clientPrivateKeyPassword = new String(password);
return this;
}
static class VerifierWrapper implements X509HostnameVerifier {
protected HostnameVerifier verifier;
VerifierWrapper(HostnameVerifier verifier) {
this.verifier = verifier;
}
@Override
public void verify(String host, SSLSocket ssl) throws IOException {
if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
}
@Override
public void verify(String host, X509Certificate cert) throws SSLException {
throw new SSLException("This verification path not implemented");
}
@Override
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
throw new SSLException("This verification path not implemented");
}
@Override
public boolean verify(String s, SSLSession sslSession) {
return verifier.verify(s, sslSession);
}
}
public CloseableHttpClient build() {
X509HostnameVerifier verifier = null;
if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
else {
switch (policy) {
case ANY:
verifier = new AllowAllHostnameVerifier();
break;
case WILDCARD:
verifier = new BrowserCompatHostnameVerifier();
break;
case STRICT:
verifier = new StrictHostnameVerifier();
break;
}
}
try {
SSLConnectionSocketFactory sslsf = null;
SSLContext theContext = sslContext;
if (disableTrustManager) {
theContext = SSLContext.getInstance("TLS");
theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
new SecureRandom());
verifier = new AllowAllHostnameVerifier();
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else if (theContext != null) {
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else if (clientKeyStore != null || truststore != null) {
theContext = createSslContext("TLS", clientKeyStore, clientPrivateKeyPassword, truststore, null);
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else {
final SSLContext tlsContext = SSLContext.getInstance("TLS");
tlsContext.init(null, null, null);
sslsf = new SSLConnectionSocketFactory(tlsContext, verifier);
}
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout((int) establishConnectionTimeout)
.setSocketTimeout((int) socketTimeout).build();
org.apache.http.impl.client.HttpClientBuilder builder = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(sslsf)
.setMaxConnTotal(connectionPoolSize)
.setMaxConnPerRoute(maxPooledPerRoute);
if (disableCookies) builder.disableCookieManagement();
return builder.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private SSLContext createSslContext(
final String algorithm,
final KeyStore keystore,
final String keyPassword,
final KeyStore truststore,
final SecureRandom random)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
return SSLContexts.custom()
.useProtocol(algorithm)
.setSecureRandom(random)
.loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
.loadTrustMaterial(truststore)
.build();
}
package org.keycloak.connections.httpclient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;
/**
* Abstraction for creating HttpClients. Allows SSL configuration.
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HttpClientBuilder {
public static enum HostnameVerificationPolicy {
/**
* Hostname verification is not done on the server's certificate
*/
ANY,
/**
* Allows wildcards in subdomain names i.e. *.foo.com
*/
WILDCARD,
/**
* CN must match hostname connecting to
*/
STRICT
}
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
private static class PassthroughTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
protected KeyStore truststore;
protected KeyStore clientKeyStore;
protected String clientPrivateKeyPassword;
protected boolean disableTrustManager;
protected HostnameVerificationPolicy policy = HostnameVerificationPolicy.WILDCARD;
protected SSLContext sslContext;
protected int connectionPoolSize = 100;
protected int maxPooledPerRoute = 0;
protected long connectionTTL = -1;
protected TimeUnit connectionTTLUnit = TimeUnit.MILLISECONDS;
protected HostnameVerifier verifier = null;
protected long socketTimeout = -1;
protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
protected long establishConnectionTimeout = -1;
protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
protected boolean disableCookies = false;
/**
* Socket inactivity timeout
*
* @param timeout
* @param unit
* @return
*/
public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
{
this.socketTimeout = timeout;
this.socketTimeoutUnits = unit;
return this;
}
/**
* When trying to make an initial socket connection, what is the timeout?
*
* @param timeout
* @param unit
* @return
*/
public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
{
this.establishConnectionTimeout = timeout;
this.establishConnectionTimeoutUnits = unit;
return this;
}
public HttpClientBuilder connectionTTL(long ttl, TimeUnit unit) {
this.connectionTTL = ttl;
this.connectionTTLUnit = unit;
return this;
}
public HttpClientBuilder maxPooledPerRoute(int maxPooledPerRoute) {
this.maxPooledPerRoute = maxPooledPerRoute;
return this;
}
public HttpClientBuilder connectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
return this;
}
/**
* Disable trust management and hostname verification. <i>NOTE</i> this is a security
* hole, so only set this option if you cannot or do not want to verify the identity of the
* host you are communicating with.
*/
public HttpClientBuilder disableTrustManager() {
this.disableTrustManager = true;
return this;
}
/**
* Disable cookie management.
*/
public HttpClientBuilder disableCookies(boolean disable) {
this.disableTrustManager = disable;
return this;
}
/**
* SSL policy used to verify hostnames
*
* @param policy
* @return
*/
public HttpClientBuilder hostnameVerification(HostnameVerificationPolicy policy) {
this.policy = policy;
return this;
}
public HttpClientBuilder sslContext(SSLContext sslContext) {
this.sslContext = sslContext;
return this;
}
public HttpClientBuilder trustStore(KeyStore truststore) {
this.truststore = truststore;
return this;
}
public HttpClientBuilder keyStore(KeyStore keyStore, String password) {
this.clientKeyStore = keyStore;
this.clientPrivateKeyPassword = password;
return this;
}
public HttpClientBuilder keyStore(KeyStore keyStore, char[] password) {
this.clientKeyStore = keyStore;
this.clientPrivateKeyPassword = new String(password);
return this;
}
static class VerifierWrapper implements X509HostnameVerifier {
protected HostnameVerifier verifier;
VerifierWrapper(HostnameVerifier verifier) {
this.verifier = verifier;
}
@Override
public void verify(String host, SSLSocket ssl) throws IOException {
if (!verifier.verify(host, ssl.getSession())) throw new SSLException("Hostname verification failure");
}
@Override
public void verify(String host, X509Certificate cert) throws SSLException {
throw new SSLException("This verification path not implemented");
}
@Override
public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
throw new SSLException("This verification path not implemented");
}
@Override
public boolean verify(String s, SSLSession sslSession) {
return verifier.verify(s, sslSession);
}
}
public CloseableHttpClient build() {
X509HostnameVerifier verifier = null;
if (this.verifier != null) verifier = new VerifierWrapper(this.verifier);
else {
switch (policy) {
case ANY:
verifier = new AllowAllHostnameVerifier();
break;
case WILDCARD:
verifier = new BrowserCompatHostnameVerifier();
break;
case STRICT:
verifier = new StrictHostnameVerifier();
break;
}
}
try {
SSLConnectionSocketFactory sslsf = null;
SSLContext theContext = sslContext;
if (disableTrustManager) {
theContext = SSLContext.getInstance("TLS");
theContext.init(null, new TrustManager[]{new PassthroughTrustManager()},
new SecureRandom());
verifier = new AllowAllHostnameVerifier();
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else if (theContext != null) {
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else if (clientKeyStore != null || truststore != null) {
theContext = createSslContext("TLS", clientKeyStore, clientPrivateKeyPassword, truststore, null);
sslsf = new SSLConnectionSocketFactory(theContext, verifier);
} else {
final SSLContext tlsContext = SSLContext.getInstance("TLS");
tlsContext.init(null, null, null);
sslsf = new SSLConnectionSocketFactory(tlsContext, verifier);
}
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout((int) establishConnectionTimeout)
.setSocketTimeout((int) socketTimeout).build();
org.apache.http.impl.client.HttpClientBuilder builder = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(sslsf)
.setMaxConnTotal(connectionPoolSize)
.setMaxConnPerRoute(maxPooledPerRoute);
if (disableCookies) builder.disableCookieManagement();
return builder.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private SSLContext createSslContext(
final String algorithm,
final KeyStore keystore,
final String keyPassword,
final KeyStore truststore,
final SecureRandom random)
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
return SSLContexts.custom()
.useProtocol(algorithm)
.setSecureRandom(random)
.loadKeyMaterial(keystore, keyPassword != null ? keyPassword.toCharArray() : null)
.loadTrustMaterial(truststore)
.build();
}
}
@@ -9,6 +9,11 @@ import org.keycloak.provider.Spi;
*/
public class HttpClientSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "connectionsHttpClient";
+32 -31
View File
@@ -1,31 +1,32 @@
<?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.2.0.RC1-SNAPSHOT</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>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?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.6.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>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -66,6 +66,19 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
} else {
initEmbedded();
}
// Backwards compatibility
if (cacheManager.getCacheConfiguration(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME) == null) {
logger.warnf("No configuration provided for '%s' cache. Using '%s' configuration as template",
InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, InfinispanConnectionProvider.SESSION_CACHE_NAME);
Configuration sessionCacheConfig = cacheManager.getCacheConfiguration(InfinispanConnectionProvider.SESSION_CACHE_NAME);
if (sessionCacheConfig != null) {
ConfigurationBuilder confBuilder = new ConfigurationBuilder().read(sessionCacheConfig);
Configuration offlineSessionConfig = confBuilder.build();
cacheManager.defineConfiguration(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME, offlineSessionConfig);
}
}
}
}
}
@@ -11,6 +11,7 @@ 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 OFFLINE_SESSION_CACHE_NAME = "offlineSessions";
static final String LOGIN_FAILURE_CACHE_NAME = "loginFailures";
<K, V> Cache<K, V> getCache(String name);
@@ -9,6 +9,11 @@ import org.keycloak.provider.Spi;
*/
public class InfinispanConnectionSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}
@Override
public String getName() {
return "connectionsInfinispan";
+76 -76
View File
@@ -1,76 +1,76 @@
<?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.2.0.RC1-SNAPSHOT</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>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</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>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</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>
</plugin>
</plugins>
</build>
<properties>
<username>sa</username>
<password></password>
<driver>org.h2.Driver</driver>
</properties>
</project>
<?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.6.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>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</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>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</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>${project.url}</url>
<driver>${driver}</driver>
<username>${username}</username>
<password>${password}</password>
<referenceUrl>${referenceUrl}</referenceUrl>
<referenceDriver>${driver}</referenceDriver>
<referenceUsername>${username}</referenceUsername>
<referencePassword>${password}</referencePassword>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<username>sa</username>
<password></password>
<driver>org.h2.Driver</driver>
</properties>
</project>
@@ -46,26 +46,26 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
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";
public String getCurrentVersionSql(String defaultSchema) {
return "SELECT ID from " + getTable("DATABASECHANGELOG", defaultSchema) + " ORDER BY DATEEXECUTED DESC LIMIT 1";
}
@Override
public void update(KeycloakSession session, Connection connection) {
public void update(KeycloakSession session, Connection connection, String defaultSchema) {
logger.debug("Starting database update");
// Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
ThreadLocalSessionContext.setCurrentSession(session);
try {
Liquibase liquibase = getLiquibase(connection);
Liquibase liquibase = getLiquibase(connection, defaultSchema);
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");
statement.executeQuery("SELECT id FROM " + getTable("REALM", defaultSchema));
logger.infov("Updating database from {0} to {1}", FIRST_VERSION, changeSets.get(changeSets.size() - 1).getId());
liquibase.markNextChangeSetRan(null);
@@ -93,9 +93,9 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
}
@Override
public void validate(Connection connection) {
public void validate(Connection connection, String defaultSchema) {
try {
Liquibase liquibase = getLiquibase(connection);
Liquibase liquibase = getLiquibase(connection, defaultSchema);
liquibase.validate();
} catch (Exception e) {
@@ -103,7 +103,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
}
}
private Liquibase getLiquibase(Connection connection) throws Exception {
private Liquibase getLiquibase(Connection connection, String defaultSchema) throws Exception {
ServiceLocator sl = ServiceLocator.getInstance();
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
@@ -125,6 +125,9 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
LogFactory.setInstance(new LogWrapper());
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
if (defaultSchema != null) {
database.setDefaultSchemaName(defaultSchema);
}
return new Liquibase(CHANGELOG, new ClassLoaderResourceAccessor(getClass().getClassLoader()), database);
}
@@ -228,4 +231,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
}
public static String getTable(String table, String defaultSchema) {
return defaultSchema != null ? defaultSchema + "." + table : table;
}
}
Loaded 100 of 3367 files, more files were not shown because too many files have changed in this diff. Show more