Compare commits

...
444 Commits
Author SHA1 Message Date
keycloak-bot 732ccb8920 Set version to 1.8.0.Alpha1 2015-12-13 20:54:39 +00:00
Marko Strukelj 32af1bd3a5 KEYCLOAK-2223 Upgrade to WildFly 10.0.0.CR4 2015-12-13 21:26:07 +01:00
Bill Burke 38b9d05cd7 Merge pull request #1941 from patriot1burke/master
client templates
2015-12-11 21:02:40 -05:00
Bill Burke e26e31d8b4 client template ui 2015-12-11 17:56:45 -05:00
Bill Burke 2328e0a6f9 Merge remote-tracking branch 'upstream/master' 2015-12-11 10:31:55 -05:00
Bill Burke 96e1813b34 client templates backend 2015-12-11 10:31:42 -05:00
Pavel Drozd b466cec4e5 Merge pull request #1940 from vramik/master
arquillian-testsuite: updated screenshooter version
2015-12-11 15:32:51 +01:00
Pavel Drozd 9228c6a16b Merge pull request #1938 from mhajas/fixDataTable
Fix adapter tests errors caused by changed DataTable fragment
2015-12-11 15:29:28 +01:00
Pavel Drozd 35f8e3c19f Merge pull request #1937 from pdrozd/ssl-required
Support for testing ssl-required.
2015-12-11 15:28:38 +01:00
vramik 9956f425eb arquillian-testsuite: updated screenshooter version 2015-12-11 12:15:27 +01:00
mhajas dcaf7ea9d5 Fix test errors caused by changed DataTable fragment 2015-12-10 11:46:40 +01:00
Pavel Drozd 3f51f620b7 Support for testing ssl-required. 2015-12-10 07:21:23 +01:00
Marek Posolda 06e44b185e Merge pull request #1936 from mposolda/master
KEYCLOAK-2124 Post-Broker login flow support
2015-12-09 17:35:00 +01:00
mposolda 17a2bd266b KEYCLOAK-2124 post-broker login flow docs 2015-12-09 17:34:44 +01:00
mposolda 081db0d353 KEYCLOAK-2124 Post-Broker login flow support 2015-12-09 16:36:26 +01:00
Marek Posolda df26caed07 Merge pull request #1933 from vramik/clients
KEYCLOAK-2203, KEYCLOAK-2205
2015-12-09 10:28:56 +01:00
Marek Posolda 9f9067663f Merge pull request #1932 from mhajas/fixDataTable
Fix xpath for rows in DataTable fragment
2015-12-09 10:28:48 +01:00
Marek Posolda 0f3d8b8513 Merge pull request #1935 from thomasdarimont/patch-1
Fixed missing ':' in the JSON example.
2015-12-09 08:52:32 +01:00
mhajas 4ca3bf530f Merge remote-tracking branch 'upstream/master' into fixDataTable 2015-12-09 07:41:45 +01:00
Thomas Darimont c8c0a45ce4 Fixed missing ':' in the JSON example. 2015-12-08 18:45:25 +01:00
Stian Thorgersen 7313b843b9 Merge pull request #1934 from stianst/KEYCLOAK-1900-PASS-HASH
KEYCLOAK-1900 Password Hash SPI
2015-12-08 16:17:32 +01:00
Stian Thorgersen 321cac2ab8 KEYCLOAK-1900 Refactoring 2015-12-08 14:06:40 +01:00
tsudot 162dd4051d KEYCLOAK-1900 Add password hash SPI and provider
- Default encoder set to Pbkdf2PasswordEncoder
2015-12-08 13:25:59 +01:00
vramik cd19c1acdf fix tests witch fails with phantomjs 2015-12-08 08:40:40 +01:00
vramik 44ed912154 Merge branch 'master' of https://github.com/keycloak/keycloak into clients
Conflicts:
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientForm.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/FlashMessage.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java
	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/clients/ClientRolesTest.java
2015-12-07 15:45:02 +01:00
vramik 39856c32d1 Merge branch 'master' of https://github.com/keycloak/keycloak into clients
Conflicts:
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/clients/CreateClientForm.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/FlashMessage.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/fragment/OnOffSwitch.java
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractAuthTest.java
	testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/console/clients/ClientRolesTest.java
2015-12-07 15:44:34 +01:00
vramik d3a893b171 KEYCLOAK-2203 - Add new cluster node form doesn't validate host input 2015-12-07 15:28:39 +01:00
vramik ba861f227e added UI tests for client's tabs: clustering, installation 2015-12-07 15:09:24 +01:00
Tomas Kyjovsky 4a57bcc0b4 Merge pull request #1903 from tkyjovsk/master
Increased pageload timeout. Increased other timeouts for travis. Better handling of closeable alert messages.
2015-12-07 11:09:37 +01:00
Tomas Kyjovsky 87a8e017fa Disabled crudRole test, unstable. Role tests need rewrite. 2015-12-07 09:10:32 +01:00
Tomas Kyjovsky b8fe608aaf Merge upstream-master 2015-12-07 05:59:51 +01:00
mhajas d3e6b38a8e Fix xpath for DataTable row and tests 2015-12-04 14:26:24 +01:00
Marek Posolda 8589327cdd Merge pull request #1931 from mposolda/master
KEYCLOAK-2197 Fix broker tests to work with sybase. Added LoggingRule
2015-12-04 12:24:33 +01:00
vramik 1b936a1230 added UI tests for client scope 2015-12-04 12:04:39 +01:00
mposolda 45c490b640 KEYCLOAK-2197 Fix broker tests to work with sybase. Added LoggingRule 2015-12-04 11:44:30 +01:00
vramik 1dd3fc537b added UI tests for client mappers saml 2015-12-03 14:47:13 +01:00
Stian Thorgersen 73cf2404ff Merge pull request #1928 from stianst/master
KEYCLOAK-2176 Add default roles and actions to users created with add…
2015-12-03 13:30:29 +01:00
vramik c16b6e6a43 update ClientSettingsTest due to KEYCLOAK-1129 2015-12-03 12:49:29 +01:00
Stian Thorgersen 8d23422605 KEYCLOAK-2176 Add default roles and actions to users created with add-user script 2015-12-03 11:45:56 +01:00
Stian Thorgersen 9cd8d1612e Merge pull request #1926 from ssilvert/mappers-tooltip
Fix typo for mappers.tooltip
2015-12-03 11:44:39 +01:00
Stian Thorgersen 277faea1d0 Merge pull request #1924 from ppalaga/151202-rename-w9-subsystem-dir
Rename keycloak-wf9-subsystem directory to keycloak-wildfly-subsystem to match t
2015-12-03 10:53:36 +01:00
Stian Thorgersen 58c7b6090b Merge pull request #1919 from stianst/master
Cache fixes
2015-12-03 10:53:18 +01:00
Stian Thorgersen f45bb62fcc KEYCLOAK-2192
Class serialization issues when Realm and User caches are in ASYNC mode
2015-12-03 08:24:30 +01:00
Stian Thorgersen 34c3ffaae1 Ported AdminApiTest to use admin client 2015-12-03 08:24:23 +01:00
Stian Thorgersen a218cc3034 KEYCLOAK-2179 Cache fixes 2015-12-03 08:24:16 +01:00
Stan Silvert c62b3822f4 Fix typo for mappers.tooltip 2015-12-02 11:54:02 -05:00
Tomas Kyjovsky b0e9720f88 Increased arquillian timeouts. 2015-12-02 16:46:15 +01:00
Tomas Kyjovsky 6507f58b49 Merge upstream-master 2015-12-02 16:11:45 +01:00
Tomas Kyjovsky 46e2440d30 Refactoring of arquillian waiting methods. 2015-12-02 15:58:23 +01:00
vramik 9b51b6e43b Merge upstream/master into clients 2015-12-02 15:18:15 +01:00
Peter Palaga 4772b8401a KEYCLOAK-2099 fixup: Rename keycloak-wf9-subsystem directory to
keycloak-wildfly-subsystem to match the WF module it contains
2015-12-02 14:51:48 +01:00
vramik 2b25c120d4 added UI tests for client mappers oidc 2015-12-02 13:12:05 +01:00
Marek Posolda c19e65f93c Merge pull request #1922 from mposolda/master
Minor fixes in kerberos example
2015-12-02 12:15:18 +01:00
mposolda 87994e032d Minor fixes in kerberos example 2015-12-02 11:31:12 +01:00
Stian Thorgersen ee6753d31b KEYCLOAK-1813 KEYCLOAK-2182 Fixes enable/disable cache 2015-12-02 11:24:04 +01:00
Stian Thorgersen 09c18306c2 KEYCLOAK-2179
Realm and user cache is invalidated when added to other nodes
2015-12-02 11:23:54 +01:00
Marek Posolda 6124fd64f3 Merge pull request #1918 from mposolda/master
Fix typos
2015-12-02 10:25:15 +01:00
mposolda 2a03d23098 Fix typos 2015-12-02 08:51:20 +01:00
Stian Thorgersen ff806eae08 Version bump 2015-12-01 19:54:28 +01:00
Tomas Kyjovsky e44d6f9888 Merge upstream-master 2015-12-01 17:30:02 +01:00
Tomas Kyjovsky 4e79dde17f Removed travis profile from arq. testsuite. 2015-12-01 17:29:28 +01:00
Tomas Kyjovsky 29e05ecf0d Fixed arquillian wait intervals config. 2015-12-01 17:28:28 +01:00
Marek Posolda a388782f9b Merge pull request #1916 from mposolda/master
KEYCLOAK-2172 Added migration docs
2015-12-01 17:03:15 +01:00
mposolda 352ea30d20 KEYCLOAK-2172 Added migration docs 2015-12-01 17:02:31 +01:00
Marek Posolda 6e0444e17b Merge pull request #1915 from mposolda/master
KEYCLOAK-2172 Make Identity broker User Attribute mappers compatible …
2015-12-01 16:45:47 +01:00
Stian Thorgersen b3f0dc7399 Merge pull request #1914 from stianst/KEYCLOAK-2176
KEYCLOAK-2176
2015-12-01 16:37:56 +01:00
mposolda ad34d63cb3 KEYCLOAK-2172 Make Identity broker User Attribute mappers compatible with First Broker Login flow 2015-12-01 15:48:25 +01:00
Stian Thorgersen 703720fa43 Merge pull request #1912 from stianst/KEYCLOAK-2173
KEYCLOAK-2173 No such method on Infinispan on EAP6
2015-12-01 15:19:16 +01:00
Stian Thorgersen e01c789a93 KEYCLOAK-2176
User added by add-user script doesn't have access to account management
2015-12-01 15:14:40 +01:00
Stian Thorgersen 8064c88e3c Merge pull request #1913 from stianst/KEYCLOAK-2175
KEYCLOAK-2175
2015-12-01 14:41:55 +01:00
Stian Thorgersen b06e747d28 Merge pull request #1911 from stianst/KEYCLOAK-2174
KEYCLOAK-2174 javax/mail not found for DefaultEmailSenderProviderFactory
2015-12-01 14:33:28 +01:00
Stian Thorgersen f9b89df326 KEYCLOAK-2175
WildFly server overlay includes aesh/main as well as aesh/0.65
2015-12-01 14:32:05 +01:00
Stian Thorgersen 778a96c9e4 KEYCLOAK-2173 No such method on Infinispan on EAP6 2015-12-01 13:54:17 +01:00
Stian Thorgersen f6f6b6a258 KEYCLOAK-2174 javax/mail not found for DefaultEmailSenderProviderFactory 2015-12-01 13:49:22 +01:00
vramik c4f3bd3dda Merge upstream/master 2015-12-01 12:51:57 +01:00
Marek Posolda 9d5356a001 Merge pull request #1910 from mposolda/master
KEYCLOAK-2149 Fix possible NPE during migration
2015-12-01 12:35:27 +01:00
mposolda 32fb604c88 KEYCLOAK-2149 Fix possible NPE during migration 2015-12-01 11:41:32 +01:00
Marek Posolda b3ea8f3add Merge pull request #1909 from mposolda/master
KEYCLOAK-2171 Fix broker test with MySQL and Sybase
2015-12-01 10:04:57 +01:00
mposolda 382161c425 KEYCLOAK-2171 Fix broker test with MySQL and Sybase 2015-12-01 09:20:18 +01:00
Marek Posolda ec527da868 Merge pull request #1908 from mposolda/master
KEYCLOAK-1129 Implicit flow docs
2015-12-01 00:00:40 +01:00
mposolda 0038c1ce9a KEYCLOAK-1129 Implicit flow docs 2015-11-30 23:59:09 +01:00
Marek Posolda d8fb0f1540 Merge pull request #1906 from mposolda/master
KEYCLOAK-2167 EmailAsUsername not reflected during registration throu…
2015-11-30 23:45:41 +01:00
Bill Burke 866c11b25b Merge pull request #1907 from patriot1burke/master
KEYCLOAK-2059
2015-11-30 17:42:35 -05:00
Bill Burke 64f5d032ed KEYCLOAK-2059 2015-11-30 17:40:35 -05:00
mposolda 635310123e KEYCLOAK-2167 EmailAsUsername not reflected during registration through broker 2015-11-30 22:46:34 +01:00
Marek Posolda 0bf53ad0ab Merge pull request #1905 from mposolda/master
Minor fixes
2015-11-30 20:58:26 +01:00
mposolda bf7863b300 Minor fixes 2015-11-30 20:18:36 +01:00
Marek Posolda 07e12f3b5f Merge pull request #1904 from mposolda/master
Fixes
2015-11-30 20:05:46 +01:00
mposolda 0f3d2bbfb4 KEYCLOAK-2149 DB fixes. firstBrokerLogin migration 2015-11-30 18:57:31 +01:00
Tomas Kyjovsky ed30c4454a Increased arquillian timeouts for travis. 2015-11-30 17:09:57 +01:00
Tomas Kyjovsky 0d4771a763 Merge upstream-master 2015-11-30 16:48:25 +01:00
Tomas Kyjovsky a8317e0cc2 1) Pageload timeout set to 60s. Other timeouts set by arq props in arquillian.xml 2) Refactoring: FlashMessage --> AdminConsoleAlert and AccountManagementAlert 2015-11-30 16:43:18 +01:00
mposolda 5b61a10b55 KEYCLOAK-2061 Direct Access Grants disabled by default 2015-11-30 15:56:21 +01:00
mposolda ec327c99f4 KEYCLOAK-2152 KEYCLOAK-2061 Client switches changes. Support for response_types and grant_types in OIDC Client registration 2015-11-30 15:31:38 +01:00
Stian Thorgersen 0492d84b59 Merge pull request #1902 from stianst/master
KEYCLOAK-2158
2015-11-30 15:22:33 +01:00
vramik 6a7a823fb4 merge upstream/master 2015-11-30 14:59:44 +01:00
Bill Burke f394e2552a Merge pull request #1798 from girirajsharma/Keycloak-2044
[KEYCLOAK-2044] Cannot map multiple external roles into Keycloak roles through custom OIDC Identity Provider
2015-11-30 08:42:03 -05:00
Stian Thorgersen 5a686c4260 KEYCLOAK-2158
Add add-user-keycloak.sh to server overlays
2015-11-30 14:03:54 +01:00
Stian Thorgersen 642e93be93 Merge pull request #1901 from mstruk/adapter-install-cli
KEYCLOAK-2166 Name clash of bin/adapter-install.cli in adapter-dist and saml-adapter-dist
2015-11-30 13:52:41 +01:00
Stian Thorgersen 2a6851b01f Merge pull request #1900 from stianst/KEYCLOAK-2063
KEYCLOAK-2063 Fix verify email link from admin endpoint
2015-11-30 13:17:17 +01:00
Marko Strukelj 2726db0be9 KEYCLOAK-2166 Name clash of bin/adapter-install.cli in adapter-dist and saml-adapter-dist 2015-11-30 12:53:51 +01:00
Stian Thorgersen 61c2ec04a4 Merge pull request #1898 from velias/KEYCLOAK-2164
KEYCLOAK-2164 - removed Cancel button from 'Change password' screen in Account app
2015-11-30 12:45:39 +01:00
Stian Thorgersen 8d6a1d5a1d Merge pull request #1899 from stianst/master
Exclude admin console tests from Travis due to stability issues
2015-11-30 12:44:29 +01:00
Stian Thorgersen 233b1e2553 KEYCLOAK-2063 Fix verify email link from admin endpoint 2015-11-30 12:10:45 +01:00
Stian Thorgersen 956ea431c8 Merge pull request #1897 from mstruk/npe
KEYCLOAK-2039 NPE on startup if keycloak-server.json can't be found
2015-11-30 11:44:56 +01:00
Stian Thorgersen 265b6d5e2a Exclude admin console tests from Travis due to stability issues 2015-11-30 11:29:59 +01:00
Vlastimil Elias b22c28b20e KEYCLOAK-2164 - removed Cancel button from 'Change password' screen in
Account app
2015-11-30 11:05:22 +01:00
Stian Thorgersen 243acdd04e Merge pull request #1889 from stianst/KEYCLOAK-2131-VAL-MAP-NAME
KEYCLOAK-2131 Create mapper form doesn't validate name input
2015-11-30 10:55:33 +01:00
Stian Thorgersen c49394c308 Merge pull request #1888 from stianst/KEYCLOAK-2132-ROLE-SELECTOR
KEYCLOAK-2132
2015-11-30 10:51:44 +01:00
Marko Strukelj fd5cb84dd1 KEYCLOAK-2039 NPE on startup if keycloak-server.json can't be found
- fix NPE and throw RuntimeException if config file not found
2015-11-30 10:26:39 +01:00
Stian Thorgersen 54b5a6c41e Merge pull request #1896 from vramik/authFlows
arquillian-testsuite: auth flows tests
2015-11-30 09:52:12 +01:00
Stian Thorgersen 83fa03e8cc Merge pull request #1894 from mstruk/saml-subsystem
KEYCLOAK-1924 SAML adapter full subsystem EAP/Wildfly
2015-11-30 09:51:33 +01:00
Stian Thorgersen 6863b711e3 Merge pull request #1892 from gtudan/KEYCLOAK-2163
KEYCLOAK-2163: require user-admin role for clearing brute force detection status
2015-11-30 09:50:59 +01:00
Stian Thorgersen 2c5510284d Merge pull request #1891 from mstruk/wildfly-modules-rename
KEYCLOAK-2099 WildFly 10 adapter subsystem
2015-11-30 09:48:15 +01:00
Stian Thorgersen 96cfb895db Merge pull request #1890 from stianst/KEYCLOAK-2137-ROLE-NAME-MAP-DUP
Keycloak 2137 role name map dup
2015-11-30 09:47:23 +01:00
Gregor Tudan 46f947113c KEYCLOAK-2163: require user admin role for clearing bruteforce detection status 2015-11-30 08:56:26 +01:00
Marek Posolda fa4e32ddcb Merge pull request #1895 from mposolda/master
Implicit flow and hybrid flow. Client switches.
2015-11-28 09:02:52 +01:00
mposolda 57b60797ce KEYCLOAK-1129 Implicit flow: more work 2015-11-28 00:15:41 +01:00
Marko Strukelj 38d160fab2 KEYCLOAK-1924 SAML adapter full subsystem EAP/Wildfly 2015-11-27 22:49:35 +01:00
mposolda ef80b64d1c KEYCLOAK-1129 Implicit flow and Hybrid flow support 2015-11-27 22:28:38 +01:00
mposolda 8d2e4c0316 KEYCLOAK-2061 Add switches to enable/disable grant types for clients 2015-11-27 22:28:38 +01:00
Bill Burke ae83ad258b Merge pull request #1893 from patriot1burke/master
KEYCLOAK-2058
2015-11-27 15:27:08 -05:00
Bill Burke 5fa59262ce fix saml admin console 2015-11-27 15:24:56 -05:00
Marko Strukelj 373fc23fc0 KEYCLOAK-2099 WildFly 10 adapter subsystem 2015-11-27 20:46:20 +01:00
Stian Thorgersen 58dc8776d6 KEYCLOAK-2137 Select mapperTypeCreate contains Role Name Mapper twice 2015-11-27 16:13:50 +01:00
Stian Thorgersen 20212d8d70 KEYCLOAK-2131 Create mapper form doesn't validate name input 2015-11-27 16:01:22 +01:00
Stian Thorgersen cb20d360c4 KEYCLOAK-2132
Error message is not displyed when trying to select empty role.
2015-11-27 15:53:33 +01:00
Stian Thorgersen 8e127bf699 Merge pull request #1887 from stianst/KEYCLOAK-2111
KEYCLOAK-2111 Cannot select language on Login dialog on small resolution
2015-11-27 15:39:13 +01:00
Stian Thorgersen 4d24a874f9 KEYCLOAK-2111 Cannot select language on Login dialog on small resolution 2015-11-27 14:42:37 +01:00
Stian Thorgersen 7200996ae0 Merge pull request #1886 from stianst/master
KEYCLOAK-2156
2015-11-27 12:32:07 +01:00
Stian Thorgersen 34cc750b13 KEYCLOAK-2156
Unrecognized field identityFederationEnabled importing old realm json
2015-11-27 12:31:00 +01:00
Stian Thorgersen 0ad6d708da Merge pull request #1884 from stianst/KEYCLOAK-2106-JWT-FIX
KEYCLOAK-2106 HTTP 500 for unparsable refresh tokens
2015-11-27 10:54:08 +01:00
Stian Thorgersen c83e3bd2d1 KEYCLOAK-2106 HTTP 500 for unparsable refresh tokens 2015-11-27 08:59:23 +01:00
Stian Thorgersen 5ea880cfff Merge pull request #1880 from stianst/KEYCLOAK-2129-USRCACHE
KEYCLOAK-2139
2015-11-26 21:14:08 +01:00
Stian Thorgersen 4276328794 Merge pull request #1883 from stianst/KEYCLOAK-2147-FF
KEYCLOAK-2147
2015-11-26 21:07:46 +01:00
Stian Thorgersen 7c4c77d70e KEYCLOAK-2147 2015-11-26 20:24:33 +01:00
Stian Thorgersen 632216d53f KEYCLOAK-2144 Set locale cookie to http-only 2015-11-26 20:06:05 +01:00
Stian Thorgersen d5105164e9 Merge pull request #1882 from abstractj/KEYCLOAK-2048
KEYCLOAK-2148: Update HmacOTP to make use of SecureRandom
2015-11-26 19:40:52 +01:00
Stian Thorgersen 7a9e2db18f Merge pull request #1879 from abstractj/KEYCLOAK-2136
KEYCLOAK-2136: Unexpected error when trying to create mapper with aleady existing name
2015-11-26 19:40:04 +01:00
Bruno Oliveira 0d582a1326 KEYCLOAK-2148: Update HmacOTP to make use of SecureRandom 2015-11-26 15:53:56 -02:00
Bruno Oliveira a99df49bc9 KEYCLOAK-2136: Unexpected error when trying to create mapper with already existing name 2015-11-26 13:55:10 -02:00
Stian Thorgersen b996e88dbd KEYCLOAK-2139
UserCache invalidation does not work proper
2015-11-26 16:39:06 +01:00
Stian Thorgersen 426a2b46fc Merge pull request #1877 from stianst/KEYCLOAK-2129
KEYCLOAK-2129
2015-11-26 15:33:39 +01:00
Stian Thorgersen 4a020d545b Merge pull request #1876 from stianst/KEYCLOAK-2082
KEYCLOAK-2082
2015-11-26 12:43:05 +01:00
Stian Thorgersen ee363a4c56 KEYCLOAK-2129 2015-11-26 12:41:55 +01:00
Stian Thorgersen bf4d5f4df9 KEYCLOAK-2082
Cross site scripting issues
2015-11-26 10:12:43 +01:00
Stian Thorgersen 30ec60b4e2 Merge pull request #1849 from girirajsharma/KEYCLOAK-2117
[KEYCLOAK-2117] It is possible to add a user or group attribute with an empty key
2015-11-26 09:25:49 +01:00
Stian Thorgersen a744ecba9e Merge pull request #1875 from abstractj/KEYCLOAK-2057
KEYCLOAK-2057: DB error with JPA EventStore and long value of not-existing client
2015-11-26 09:25:08 +01:00
Stian Thorgersen e764461b1a Merge pull request #1874 from stianst/KEYCLOAK-2134-IFRAME
KEYCLOAK-2134 login-status-iframe.html without any parameter throws 5…
2015-11-26 08:19:28 +01:00
Bruno Oliveira f376facb48 KEYCLOAK-2057: DB error with JPA EventStore and long value of not-existing client 2015-11-26 01:32:05 -02:00
girirajsharma 31614df7c4 [KEYCLOAK-2117] It is possible to add a user or group attribute with an empty key 2015-11-26 00:41:19 +05:30
Stian Thorgersen 335f852600 Merge pull request #1869 from stianst/EMAIL
Email fixes
2015-11-25 20:05:45 +01:00
Stian Thorgersen c26aeb654b KEYCLOAK-2134 login-status-iframe.html without any parameter throws 500 with NullpointerException 2015-11-25 19:58:46 +01:00
Stian Thorgersen 969cc6eb9e Merge pull request #1873 from stianst/master
Ignore LdapUserFederationTest#invalidSettingsTest
2015-11-25 19:58:17 +01:00
Stian Thorgersen f5326e1f42 Ignore LdapUserFederationTest#invalidSettingsTest 2015-11-25 19:57:31 +01:00
Stian Thorgersen e664a4a6b2 Merge pull request #1868 from stianst/KEYCLOAK-2043
KEYCLOAK-2043 Set cache-control header in well-known endpoints
2015-11-25 19:55:45 +01:00
Stian Thorgersen c15571f65c Merge pull request #1866 from mhajas/master
Added ConfigTest to integration arquillian testsuite
2015-11-25 19:06:54 +01:00
Stian Thorgersen 1eacdc6904 KEYCLOAK-2043 Set cache-control header in well-known endpoints 2015-11-25 18:58:44 +01:00
Stian Thorgersen be040eaa18 KEYCLOAK-2133 KEYCLOAK-1782 2015-11-25 18:58:05 +01:00
Bill Burke 889679c715 Merge pull request #1872 from patriot1burke/master
KEYCLOAK-1970
2015-11-25 12:01:51 -05:00
Bill Burke 8ae3551c4d KEYCLOAK-1970 2015-11-25 12:01:28 -05:00
Bill Burke cfd4de033b Merge pull request #1871 from patriot1burke/master
2115 and 2114
2015-11-25 12:00:34 -05:00
Bill Burke d6e2bccb16 Merge pull request #1840 from velias/KEYCLOAK-2075
KEYCLOAK-2075 KEYCLOAK-2107 - support for SAML IsPassive mode
2015-11-25 10:35:00 -05:00
Bill Burke eeec89583e Merge remote-tracking branch 'upstream/master' 2015-11-25 10:18:37 -05:00
Bill Burke d2bdb74fef Merge pull request #1870 from patriot1burke/master
KEYCLOAK-2095
2015-11-25 10:18:15 -05:00
Bill Burke b04b124351 KEYCLOAK-2114 2015-11-25 10:13:44 -05:00
Bill Burke 067cb120f8 KEYCLOAK-2115 2015-11-25 09:58:57 -05:00
Bill Burke 0bab4e63fa KEYCLOAK-2095 2015-11-25 09:52:11 -05:00
Bill Burke b48f32380c Merge pull request #1867 from ramirost/feature/locale_ca
Added Catalan translations
2015-11-25 08:58:27 -05:00
Bill Burke 0c8f3f734d Merge pull request #1855 from Smartling/KEYCLOAK-1391
KEYCLOAK-1391: Return an HTTP 401 for API requests
2015-11-25 08:57:05 -05:00
Bill Burke 4f401c7547 Merge pull request #1848 from girirajsharma/KEYCLOAK-2121
[KEYCLOAK-2121] Adding user or group attributes using ENTER key deletes first attribute
2015-11-25 08:53:42 -05:00
Bill Burke df74338cbc Merge pull request #1850 from girirajsharma/KEYCLOAK-2113
[KEYCLOAK-2113] Cannot delete group
2015-11-25 08:52:26 -05:00
Vlastimil Elias e3060e5e58 rebased to latest master 2015-11-25 13:46:29 +01:00
Ramiro Sánchez 15309a94cc Added Catalan translations 2015-11-25 09:48:53 +01:00
vramik 2e39221b98 added UI tests for clients 2015-11-25 09:27:23 +01:00
Stian Thorgersen c05e21c049 Merge pull request #1863 from stianst/KEYCLOAK-2050
KEYCLOAK-2050 KEYCLOAK-2051 Fix notifications
2015-11-25 09:08:00 +01:00
mhajas 62d519ed37 fix phantomjs problem with ConfigTest 2015-11-25 08:42:41 +01:00
Vlastimil Elias 18fa03bf97 KEYCLOAK-2107 - support IsPassive mode in SAML SP adapter library
KEYCLOAK-2075 - added integration tests for both server and adapter side
2015-11-25 08:39:55 +01:00
Vlastimil Elias 0bdb05e152 KEYCLOAK-2075 - support for IsPassive mode in SAML IdP endpoint 2015-11-25 08:29:46 +01:00
mhajas 09af45201b Merge remote-tracking branch 'upstream/master' 2015-11-25 07:36:32 +01:00
Stian Thorgersen dd85c125cb KEYCLOAK-2050 KEYCLOAK-2051 Fix notifications 2015-11-25 07:28:27 +01:00
Stian Thorgersen 274838aa64 Merge pull request #1860 from stianst/KEYCLOAK-2118
KEYCLOAK-2118 OTP Policy form doesn't remember Number of Digits
2015-11-25 06:59:17 +01:00
Stian Thorgersen ecb39cda0c Merge pull request #1865 from ramirost/feature/locale_es
Feature/locale es
2015-11-25 06:58:36 +01:00
Stian Thorgersen 3685a185d4 Merge pull request #1859 from stianst/reset-pass
KEYCLOAK-1758 add-user script
2015-11-25 06:56:35 +01:00
Bill Burke 030a35476a Merge pull request #1864 from patriot1burke/master
sendError() handling
2015-11-24 18:46:59 -05:00
Ramiro Sánchez 4ffe86583b fixed Spanish translations 2015-11-25 00:17:09 +01:00
Ramiro Sánchez 24f765ceef Merge branch 'upstream/master' into fork/master
* upstream_master: (115 commits)
  KEYCLOAK-1964 Database field for passwordPolicy is too small
  KEYCLOAK-1971 REST end point does't validate password policies properly
  KEYCLOAK-2104 Add caching of message bundles and properties to ExtendingThemeManager
  KEYCLOAK-2116 - Fix Label of Regenerate Secret button.
  Tweak Travis again
  KEYCLOAK-1937 OpenID Connect Dynamic Client Registration
  fix null pointer
  remove empty password check in direct grant flow
  Updated Travis configuration
  Exclude .lastUpdated files from Travis cache
  KEYCLOAK-2119 OTP Policy form validates both TOTP and HOTP at the same time
  [KEYCLOAK-2119] OTP Policy form validates both TOTP and HOTP at the same time
  KEYCLOAK-2010
  remove empty password check
  default groups ui
  KEYCLOAK-1749 Add documentation and fixed clean-up of expired initial access tokens
  Remove unused import
  Fix missing group in angular $scope in GroupMembersCtrl.
  arquillian-testsuite: Customizable waiting timeouts in class WaitUtils. Changed time unit to MILLISECONDS.
  default groups
  ...
2015-11-24 23:52:24 +01:00
Bill Burke c729835c3e fix2 2015-11-24 17:25:05 -05:00
Bill Burke 507fa4c250 fix 2015-11-24 17:21:30 -05:00
Bill Burke bba781beee messed up 2015-11-24 17:19:55 -05:00
Bill Burke 980a1eca5e Merge remote-tracking branch 'upstream/master' 2015-11-24 16:48:40 -05:00
Bill Burke ff63c5552a sendError() handling' 2015-11-24 16:48:24 -05:00
Stian Thorgersen 985661c1b9 Merge pull request #1862 from stianst/KEYCLOAK-1964
KEYCLOAK-1964 Database field for passwordPolicy is too small
2015-11-24 22:04:52 +01:00
Stian Thorgersen b168656eab KEYCLOAK-2118 OTP Policy form doesn't remember Number of Digits 2015-11-24 22:04:37 +01:00
Stian Thorgersen 94ba87ac05 Merge pull request #1861 from stianst/KEYCLOAK-1971
KEYCLOAK-1971 REST end point does't validate password policies properly
2015-11-24 21:55:16 +01:00
Stian Thorgersen cfc28b861b KEYCLOAK-1758 add-user script 2015-11-24 21:54:58 +01:00
Stian Thorgersen 38408658f9 Merge pull request #1857 from thomasdarimont/issue/KEYCLOAK-2116
KEYCLOAK-2116 - Fix Label of Regenerate Secret button.
2015-11-24 21:23:44 +01:00
Stian Thorgersen 998bb9986f Merge pull request #1853 from stianst/KEYCLOAK-2104
KEYCLOAK-2104 Add caching of message bundles and properties to Extend…
2015-11-24 21:22:02 +01:00
Stian Thorgersen 8d2a95d66b KEYCLOAK-1964 Database field for passwordPolicy is too small 2015-11-24 20:57:41 +01:00
Stian Thorgersen 500bced6ee KEYCLOAK-1971 REST end point does't validate password policies properly 2015-11-24 20:50:41 +01:00
Stian Thorgersen 81960a6996 KEYCLOAK-2104 Add caching of message bundles and properties to ExtendingThemeManager 2015-11-24 20:23:20 +01:00
Stian Thorgersen ccd456dba6 Merge pull request #1858 from stianst/master
Tweak Travis again
2015-11-24 20:23:14 +01:00
Thomas Darimont bac39bc71e KEYCLOAK-2116 - Fix Label of Regenerate Secret button. 2015-11-24 20:11:55 +01:00
Stian Thorgersen a8c2e79565 Tweak Travis again 2015-11-24 20:08:41 +01:00
Marek Posolda d6089597ff Merge pull request #1847 from gerbermichi/password
remove empty password check
2015-11-24 17:23:51 +01:00
Stian Thorgersen c901fc7480 Merge pull request #1845 from stianst/client-reg
Client reg
2015-11-24 16:33:55 +01:00
Stian Thorgersen 4f2b97de7f KEYCLOAK-1937
OpenID Connect Dynamic Client Registration

KEYCLOAK-1938
Register clients from SAML Entity Descriptors
2015-11-24 15:39:36 +01:00
Michael Gerber 9a3e023c43 fix null pointer 2015-11-24 13:54:33 +00:00
Michael Gerber 142ef50728 remove empty password check in direct grant flow 2015-11-24 11:11:16 +00:00
Stian Thorgersen d2ba4669ab Merge pull request #1856 from stianst/master
Updated Travis configuration
2015-11-24 10:57:08 +01:00
Stian Thorgersen ba0b59bfd0 Updated Travis configuration 2015-11-24 10:00:58 +01:00
Scott Rossillo f1c3295cec KEYCLOAK-1391: Return an HTTP 401 for API requests
Non browser HTTP requests shouldn't redirect to the Keycloak login
page. Instead, return an HTTP 401 with a proper WWW-Authenticate
header.
2015-11-23 10:46:14 -05:00
Stian Thorgersen 04ddf7ba4d Merge pull request #1854 from stianst/master
Exclude .lastUpdated files from Travis cache
2015-11-23 14:01:46 +01:00
mhajas 8f346a5f59 Merge remote-tracking branch 'origin/master' 2015-11-23 13:12:23 +01:00
mhajas 22e3abdaa8 added ConfigTest for events 2015-11-23 13:11:55 +01:00
Stian Thorgersen f1af3e9fb7 Exclude .lastUpdated files from Travis cache 2015-11-23 13:08:13 +01:00
Stian Thorgersen 5e479ba4df Merge pull request #1852 from stianst/master
KEYCLOAK-2119
2015-11-23 12:48:16 +01:00
Stian Thorgersen f6743eff69 KEYCLOAK-2119
OTP Policy form validates both TOTP and HOTP at the same time
2015-11-23 12:02:39 +01:00
Stian Thorgersen 5a761f2f3a Merge pull request #1851 from girirajsharma/KEYCLOAK-2119
[KEYCLOAK-2119] OTP Policy form validates both TOTP and HOTP at the same time
2015-11-23 11:59:00 +01:00
Stian Thorgersen 261d32f8e7 Merge pull request #1841 from vramik/master
arquillian-testsuite: Customizable waiting timeouts in class WaitUtil…
2015-11-23 11:26:22 +01:00
Stian Thorgersen 282e702ef6 Merge pull request #1836 from tkyjovsk/master
KEYCLOAK-1646 Added adapter test module for EAP6
2015-11-23 11:23:29 +01:00
Stian Thorgersen cc014fe0e5 Merge pull request #1844 from lkubik/unusedImport
Remove unused import
2015-11-23 11:21:13 +01:00
girirajsharma 95f62901c2 [KEYCLOAK-2119] OTP Policy form validates both TOTP and HOTP at the same time 2015-11-22 23:04:45 +05:30
girirajsharma cf8b0abaad [KEYCLOAK-2113] Cannot delete group 2015-11-22 20:52:31 +05:30
girirajsharma e761fb24e6 [KEYCLOAK-2121] Adding user or group attributes using ENTER key deletes first attribute 2015-11-22 16:14:34 +05:30
Bill Burke b1deed67df Merge remote-tracking branch 'upstream/master' 2015-11-21 08:58:15 -05:00
Bill Burke d3cadc9a47 saml error handling 2015-11-21 08:58:02 -05:00
Bill Burke 32e069eadc Merge pull request #1846 from patriot1burke/master
default groups UI
2015-11-20 19:18:21 -05:00
Bill Burke 17c97c2f68 KEYCLOAK-2010 2015-11-20 16:18:42 -05:00
Bill Burke 48bb4d86e0 Merge pull request #1842 from thomasdarimont/issue/missing-groupid-membersctrl
Fix missing group in angular $scope in GroupMembersCtrl.
2015-11-20 16:07:37 -05:00
Michael Gerber eda018ba0a remove empty password check 2015-11-20 18:42:56 +01:00
Bill Burke ac1baa059f Merge pull request #1797 from raehalme/KEYCLOAK-2041
KEYCLOAK-2041 Use sendError instead of setStatus to report errors
2015-11-20 11:50:37 -05:00
Bill Burke 670b620da7 Merge remote-tracking branch 'upstream/master' 2015-11-20 10:41:19 -05:00
Bill Burke 1545593cde default groups ui 2015-11-20 10:41:08 -05:00
Stian Thorgersen aedd23a43d Merge pull request #1843 from stianst/client-reg
KEYCLOAK-1749 Add documentation and fixed clean-up of expired initial…
2015-11-19 19:58:42 +01:00
Stian Thorgersen 7e8c80c0df KEYCLOAK-1749 Add documentation and fixed clean-up of expired initial access tokens 2015-11-19 16:11:41 +01:00
Lukas Kubik 9f6813fcad Remove unused import 2015-11-19 15:15:55 +01:00
Thomas Darimont 14292843ff Fix missing group in angular $scope in GroupMembersCtrl.
Previously navigating to the group members tab of a group breaks other groups links (RoleMappings, Attributes etc.) because the groupId part of the url is missing.
 One sees:
 /auth/admin/master/console/#/realms/master/groups//role-mappings
 Instead of:
 /auth/admin/master/console/#/realms/master/groups/0f77aeed-7d16-4938-9fcc-c74b1125e5e0/role-mappings
2015-11-19 13:54:18 +01:00
vramik 71e25bcd65 arquillian-testsuite: Customizable waiting timeouts in class WaitUtils. Changed time unit to MILLISECONDS. 2015-11-19 13:14:30 +01:00
Bill Burke 9f1fa5ebb9 Merge pull request #1839 from patriot1burke/master
default groups back end
2015-11-18 20:59:46 -05:00
Bill Burke 98958a2bc4 default groups 2015-11-18 19:40:30 -05:00
Bill Burke 7da9f8085d Merge pull request #1838 from patriot1burke/master
groups: resolve roles, and mongo fixes
2015-11-18 16:19:17 -05:00
Bill Burke 6989589e72 Merge remote-tracking branch 'upstream/master' 2015-11-18 15:24:45 -05:00
Bill Burke 4f00f6cceb group mongo 2015-11-18 15:24:27 -05:00
Stian Thorgersen 95e729b0b7 Merge pull request #1832 from stianst/client-reg
KEYCLOAK-2085
2015-11-18 19:34:47 +01:00
Tomas Kyjovsky 38c460de82 KEYCLOAK-1646 Added module for adapter tests on EAP6. Using 'wildfly-arquillian-container-managed' instead of 'jboss-as-arquillian-container-managed' for both EAP6 and AS7 adapter tests. 2015-11-18 18:21:46 +01:00
Bill Burke 41331111da resolve conflicts 2015-11-18 09:39:19 -05:00
Bill Burke bff334d365 group token/assertion and tests 2015-11-18 09:36:47 -05:00
Stian Thorgersen 41c9289f14 KEYCLOAK-1749 Moved clien registration api 2015-11-18 15:09:32 +01:00
Marek Posolda 1d06d9dd64 Merge pull request #1834 from mposolda/master
KEYCLOAK-2102 added AbstractKerberosTest.caseInsensitiveTest
2015-11-18 14:05:46 +01:00
Stian Thorgersen ec9b2933cc Merge pull request #1833 from thomasdarimont/issue/KEYCLOAK-2101
KEYCLOAK-2101 - Ensure consistent property order in json configuration export.
2015-11-18 13:30:15 +01:00
Stian Thorgersen 1ff5d6eb06 KEYCLOAK-2085 Internationalization in client initial access controller 2015-11-18 13:25:08 +01:00
mposolda bc22abf8cb KEYCLOAK-2102 added AbstractKerberosTest.caseInsensitiveTest 2015-11-18 12:35:17 +01:00
Marek Posolda 81eb1e1e30 Merge pull request #1830 from bagges/master
[KEYCLOAK-2102] treat principal name case insensitive
2015-11-18 12:35:06 +01:00
Stian Thorgersen e8cb3a416d KEYCLOAK-2085 Added initial access token support to admin console 2015-11-18 10:33:27 +01:00
Stian Thorgersen 764c20d748 KEYCLOAK-2085 Initial access tokens for client registration 2015-11-18 10:33:24 +01:00
Thomas Darimont c81d0c0898 KEYCLOAK-2101 - Ensure consistent order for properties in json configuration export.
We now explicitly order the AuthenticatorFlows, AuthenticatorConfig, as well
as RequiredActions to ensure a consistent order for the configuration export to make
it easier to diff / version keycloak configuration files.
Previously the order of the json properties of an configuration export were
non deterministic. The configuration file could look partially different after a
 export, import, export sequence even if no changes were made.
2015-11-17 22:34:21 +01:00
Stian Thorgersen 67fca8f1f3 Merge pull request #1831 from abstractj/KEYCLOAK-2100
KEYCLOAK-2100: 500 Internal Server Error with Update the events provider via Admin REST API
2015-11-17 20:35:48 +01:00
Bruno Oliveira 22c5c803ca KEYCLOAK-2100: 500 Internal Server Error with Update the events provider via Admin REST API 2015-11-17 14:04:24 -02:00
Stian Thorgersen f6d716a386 Merge pull request #1829 from stianst/client-reg
KEYCLOAK-1749 Rotate registration access token, add registration acce…
2015-11-17 13:29:53 +01:00
Stian Thorgersen 62c5bc0e91 KEYCLOAK-1749 Rotate registration access token, add registration access token to admin console 2015-11-17 09:44:50 +01:00
Markus Backes 5e329d7b29 Merge branch 'master' of https://github.com/keycloak/keycloak 2015-11-17 09:32:41 +01:00
Markus Backes 1bd9b18803 treat principal name case insensitive
* Kerberos login with active directory failed with invalid username or password because AD treats principal names in a case insensitive way (https://ssimo.org/blog/id_016.html)
2015-11-17 09:32:14 +01:00
Stian Thorgersen 96fe4269ec Merge pull request #1828 from abstractj/KEYCLOAK-2065
KEYCLOAK-2065: Update the client via Admin REST API causes 500 Internal Server Error
2015-11-17 08:31:54 +01:00
Stian Thorgersen 83ff02ea53 Merge pull request #1825 from stianst/client-reg
KEYCLOAK-1749 Client registration service
2015-11-16 20:23:55 +01:00
Stian Thorgersen 1df741a307 Merge pull request #1826 from lkubik/changeAllJettyToProvided
KEYCLOAK-2081
2015-11-16 20:23:31 +01:00
Bruno Oliveira 409356f734 KEYCLOAK-2065: Update the client via Admin REST API causes 500 Internal Server Error 2015-11-16 16:32:52 -02:00
Stian Thorgersen bad0a95123 KEYCLOAK-1749 Client registration service
Changed endpoints of client registration to just clients

Started installation

Added adapter config retrival to client reg
2015-11-16 13:24:56 +01:00
Stian Thorgersen 1bc08fff16 Merge pull request #1823 from abstractj/KEYCLOAK-2056
KEYCLOAK-2056: Removal of file model provider
2015-11-16 08:33:56 +01:00
Marek Posolda ab436705c8 Merge pull request #1827 from mposolda/broker-reauthentication
KEYCLOAK-1750 First broker login - migration, documentation. Other minor fixes
2015-11-13 20:10:28 +01:00
mposolda ea7709a104 KEYCLOAK-2026 Fix realm.getMasterAdminClient() in JPA and Mongo models 2015-11-13 18:51:09 +01:00
mposolda 1d5a01577e KEYCLOAK-1750 First broker login - migration 2015-11-13 18:51:09 +01:00
mposolda 4288260aa6 KEYCLOAK-1822 Don't redirect to login theme when error during link identity in account mgmt. 2015-11-13 18:51:09 +01:00
mposolda 600d1f8a56 KEYCLOAK-1750 First broker login - docs 2015-11-13 18:51:09 +01:00
Bruno Oliveira f7b1af7e11 Removal of module keycloak-connections-file 2015-11-13 13:44:15 -02:00
Bruno Oliveira 4b0e33e388 KEYCLOAK-2056: Removal of file model provider 2015-11-13 13:44:15 -02:00
Stian Thorgersen 8caaabb2e5 Merge pull request #1820 from thomasdarimont/issue/KEYCLOAK-2068-NPE-in-KeycloakOidcFilter
KEYCLOAK-2068 - Fix Potential NPE when using Servlet-Filter Adapter.
2015-11-13 16:00:34 +01:00
Stian Thorgersen 1bd0e23f31 Merge pull request #1824 from bystrikhorvath/master
KEYCLOAK-2077: correcting paths in custom-attributes.xml
2015-11-13 15:53:31 +01:00
Lukas Kubik 13a52c1bb2 KEYCLOAK-2081
Change scope of jetty dependencies to provided
2015-11-13 15:43:11 +01:00
Bill Burke fa7a7d35a9 Merge remote-tracking branch 'upstream/master' 2015-11-13 09:30:37 -05:00
Bill Burke fe5809db4d token group roles 2015-11-13 09:30:25 -05:00
Bill Burke 1510d9672a Merge pull request #1803 from gerbermichi/user
KEYCLOAK-2024 - username guessing
2015-11-13 08:53:05 -05:00
Bill Burke 9b93468131 Merge pull request #1818 from patriot1burke/master
group membership ui
2015-11-13 08:49:23 -05:00
bystrikhorvath 2e16a55815 KEYCLOAK-2077: correcting paths in custom-attributes.xml 2015-11-13 14:00:20 +01:00
Marek Posolda f65665b5eb Merge pull request #1822 from mposolda/broker-reauthentication
KEYCLOAK-1750 first broker login - events and tests
2015-11-13 10:27:38 +01:00
mposolda ce4a865579 KEYCLOAK-1750 First broker login - tests 2015-11-13 09:32:46 +01:00
mposolda f2e4e67ba0 KEYCLOAK-1750 First broker login - events 2015-11-13 09:32:46 +01:00
Stian Thorgersen 37f1eaae0e Merge pull request #1821 from stianst/master
KEYCLOAK-2037 Update documentation
2015-11-13 09:04:17 +01:00
Stian Thorgersen 6c3a3517b8 KEYCLOAK-2037 Update documentation 2015-11-13 09:03:58 +01:00
Thomas Darimont c4416a25e0 KEYCLOAK-2068 - Fix Potential NPE when using Servlet-Filter Adapter.
When using the `org.keycloak.adapters.servlet.KeycloakOIDCFilter` a `NullPointerException`
can be thrown in the `org.keycloak.adapters.servlet.FilterSessionStore` within the `getParam`
method of the generated wrapper in `buildWrapper` when the `content-type` is not set.
Since the `content-type` is only used to parse the body. We just check whether the `body`
is `null` and if so avoid touching the `content-type` which prevents the NPE.

If the `body` is null we return an empty `MultivaluedHashMap` for the parameters.
2015-11-13 00:14:34 +01:00
Bill Burke 550f773293 Merge remote-tracking branch 'upstream/master' 2015-11-12 13:16:50 -05:00
Bill Burke d7ea66ad44 group membership ui 2015-11-12 13:16:30 -05:00
Bill Burke 2022a8d36b Merge pull request #1817 from patriot1burke/master
user group membership ui
2015-11-12 13:09:37 -05:00
Bill Burke 0d20e3c7ff Merge remote-tracking branch 'upstream/master' 2015-11-12 11:31:55 -05:00
Bill Burke 21119604c6 user group membership 2015-11-12 11:31:44 -05:00
Stian Thorgersen 973609d39b Merge pull request #1816 from stianst/master
KEYCLOAK-2066
2015-11-12 14:44:03 +01:00
Stian Thorgersen 77bccda7a4 KEYCLOAK-2066
View details on import client not working
2015-11-12 14:03:09 +01:00
Stian Thorgersen 0c9f0ea3e6 Merge pull request #1813 from vmuzikar/missing-ids
Add missing IDs to some UI elements; add POs to Client Mappers
2015-11-12 13:36:19 +01:00
Stian Thorgersen 73197332c4 Merge pull request #1814 from pdrozd/federation-tests
Add Federation tests for admin console.
2015-11-12 13:36:03 +01:00
Stian Thorgersen ee0dd7e200 Merge pull request #1815 from abstractj/KEYCLOAK-2064
KEYCLOAK-2064: Update pax-web to make use of SecureRandom
2015-11-12 13:35:33 +01:00
Bruno Oliveira 9203971809 KEYCLOAK-2064: Update pax-web to make use of SecureRandom 2015-11-12 09:46:45 -02:00
Pavel Drozd 4e7fe1de8d Add Federation tests for admin console. 2015-11-12 12:23:37 +01:00
Stian Thorgersen 4646a4aceb Merge pull request #1811 from stianst/master
KEYCLOAK-2060
2015-11-12 11:59:00 +01:00
Stian Thorgersen 64baa28301 Merge pull request #1810 from lkubik/updateJettyScope
Change scope of jetty dependencies in jetty-adapter-spi
2015-11-12 09:23:44 +01:00
Stian Thorgersen db84571546 Merge pull request #1807 from vramik/KEYCLOAK-2031
KEYCLOAK-2031: Input validation in OTP Policy page fix, test
2015-11-12 09:23:13 +01:00
Stian Thorgersen 99cddcef6c Merge pull request #1805 from velias/KEYCLOAK-2033
KEYCLOAK-2033 - Allow custom SPI Providers to show additional info on
2015-11-12 09:21:38 +01:00
Stian Thorgersen 1891019067 Merge pull request #1802 from equinux/pr/fix-js-parameter-encoding
Fix parameter encoding in JS adapter
2015-11-12 09:19:21 +01:00
Stian Thorgersen b0b4d26fa3 KEYCLOAK-2060
Upgrade to WildFly 9.0.2.Final
2015-11-12 09:17:47 +01:00
Bill Burke 6cc76b2e3d Merge pull request #1788 from patriot1burke/master
groups data model
2015-11-11 19:38:01 -05:00
Bill Burke 33ac048c8c resolve conflicts 2015-11-11 18:06:39 -05:00
Bill Burke e25157655b group ui 2015-11-11 18:03:53 -05:00
Stian Thorgersen 213abb87ba Merge pull request #1808 from stianst/master
KEYCLOAK-2055
2015-11-11 20:24:08 +01:00
Lukas Kubik 825a68c6c9 Change scope of jetty dependencies in jetty-adapter-spi. 2015-11-11 17:01:46 +01:00
Stian Thorgersen 816ed9419b Merge pull request #1809 from lkubik/unifyJettyVersionWithOthers
Unify jetty version in keycloak-jetty-adapter-spi with other jetty versions
2015-11-11 16:10:17 +01:00
Stian Thorgersen 15f1a38b51 KEYCLOAK-2055
Invalid links in docs index.html
2015-11-11 14:32:43 +01:00
Lukas Kubik 1f75f85a20 Unify jetty version in keycloak-jetty-adapter-spi with other versions 2015-11-11 13:58:22 +01:00
Vaclav Muzikar dfb39d13a2 Removed IDs from Password Policy
(cherry picked from commit 35376b7)
2015-11-11 12:00:44 +01:00
Bill Burke b8391e0935 Merge pull request #1778 from girirajsharma/keycloak-1994
[KEYCLOAK-1994] It's not possible to create flow with same name as deleted nested flow
2015-11-10 10:58:57 -05:00
vramik ab56460325 KEYCLOAK-2031: Input validation in OTP Policy page fix, test 2015-11-10 16:57:29 +01:00
Vaclav Muzikar 059ebacffc Removed IDs from redirect URIs and Web Origins in Client
(cherry picked from commit 5c68854)
2015-11-10 15:46:55 +01:00
Stian Thorgersen e1a07bd5a8 Merge pull request #1806 from tkyjovsk/karaf-fuse-update
Karaf fuse update
2015-11-10 15:28:36 +01:00
Tomas Kyjovsky 37d7182fc9 Merge upstream-master into karaf-fuse-update
Conflicts:
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/arquillian/KeycloakArquillianExtension.java
2015-11-10 13:44:23 +01:00
Tomas Kyjovsky e1ba26bcae KEYCLOAK-1661 Added support for testing adapters/examples on fuse 6.2. Moved CustomKarafContainer from the base module to the adapters/karaf module. 2015-11-10 13:39:59 +01:00
Vlastimil Elias b39146f6f5 KEYCLOAK-2033 - Allow custom SPI Providers to show additional info on
Server Info page
2015-11-10 12:55:36 +01:00
Marek Posolda caea1a3458 Merge pull request #1804 from mposolda/broker-reauthentication
KEYCLOAK-1750 First broker login changes
2015-11-10 11:52:47 +01:00
Dominique d'Argent 7ef747e7c4 Fix parameter encoding in JS adapter
- fixes https://issues.jboss.org/browse/KEYCLOAK-2047
- relates to keycloak/keycloak-js-bower#7
2015-11-10 11:20:06 +01:00
mposolda 4ca442d1b2 KEYCLOAK-1750 Option updateProfileOnFirstLogin moved from IdentityProvider to IdpReviewProfile authenticator 2015-11-10 11:06:23 +01:00
mposolda 99e75c69a0 KEYCLOAK-1750 First broker login - support for change password after first social login 2015-11-10 10:25:31 +01:00
Michael Gerber 1437f7da35 KEYCLOAK-2024 - username guessing 2015-11-10 09:04:10 +01:00
Stian Thorgersen fa9abbf016 Merge pull request #1801 from vramik/KEYCLOAK-2046
KEYCLOAK-2046 Remove JIRA checker extension
2015-11-10 07:50:24 +01:00
vramik 6bce32ba62 arquillian-testsuite: auth flows test 2015-11-09 15:59:34 +01:00
vramik ee801c2c32 arquillian-testsuite: KEYCLOAK-2046 2015-11-09 15:03:17 +01:00
Marek Posolda 2b23497f92 Merge pull request #1799 from mposolda/broker-reauthentication
KEYCLOAK-1750 Improve first time login with social. Added 'first brok…
2015-11-09 13:15:33 +01:00
Stian Thorgersen 04ba5c235e Merge pull request #1800 from stianst/master
Disable JIRA checker extension - this should be removed completely
2015-11-09 13:05:04 +01:00
Stian Thorgersen 1521f56225 Disable JIRA checker extension - this should be removed completely 2015-11-09 12:11:20 +01:00
Stian Thorgersen 251adbba0b Fix OTPPolicyTest 2015-11-09 12:10:19 +01:00
mposolda adbf2b22ad KEYCLOAK-1750 Improve first time login with social. Added 'first broker login' flow 2015-11-09 10:34:55 +01:00
Stian Thorgersen 2b29c3acf4 Merge pull request #1795 from abstractj/KEYCLOAK-2031
Input validation in OTP Policy page
2015-11-09 10:08:38 +01:00
Stian Thorgersen 076690e21e Merge pull request #1794 from tkyjovsk/karaf-fuse-update
Adapter tests for Karaf: Fuse Example installation now done via JMX i…
2015-11-09 10:08:27 +01:00
Stian Thorgersen b586f93182 Merge pull request #1793 from stianst/KEYCLOAK-2037
KEYCLOAK-2037 Fix domain mode for server-dist
2015-11-09 10:08:03 +01:00
Stian Thorgersen 5a318df041 Merge pull request #1791 from vramik/uitests
arquillian-testsuite add UI tests, page objects refactoring
2015-11-09 10:02:23 +01:00
Stian Thorgersen cd01ea49b4 Merge pull request #1777 from girirajsharma/keycloak-1993
[KEYCLOAK-1993] It's possible to create new authentication flow with empty name within another flow
2015-11-09 09:54:07 +01:00
girirajsharma dd2824ab20 [KEYCLOAK-2044] Cannot map multiple external roles into Keycloak roles through custom OIDC Identity Provider 2015-11-08 20:10:14 +05:30
Bruno Oliveira 8db6972441 Input validation in OTP Policy page 2015-11-06 11:52:21 -02:00
Tomas Kyjovsky 027311c0c0 Adapter tests for Karaf: Fuse Example installation now done via JMX instead of maven-karaf plugin. Needed for testing on Fuse. 2015-11-06 13:03:42 +01:00
Thomas Raehalme 68edf9ce48 Errors are now reported using sendError instead of setStatus.
This change was made to enable the use of error pages defined in web.xml.
2015-11-06 10:53:18 +02:00
Thomas Raehalme 7b7fbd3257 Added sendError(int) to HttpFacade.Response. 2015-11-06 10:47:08 +02:00
Stian Thorgersen d0c50fe56d KEYCLOAK-2037 Fix domain mode for server-dist 2015-11-06 08:44:50 +01:00
girirajsharma 4075d65241 [KEYCLOAK-1993] It's possible to create new authentication flow with empty name within another flow 2015-11-05 21:59:04 +05:30
vramik 267be83863 arquillian-testsuite: add UI test for OTP Policy
Conflicts:
	testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/console/page/authentication/flows/CreateFlow.java
2015-11-05 13:37:59 +01:00
Stian Thorgersen 15828e899b Merge pull request #1790 from dvantooster/master
KEYCLOAK-2032 Changed some column names from lower- to uppercase
2015-11-05 13:03:20 +01:00
Stian Thorgersen ce089019e6 Merge pull request #1786 from mhajas/master
Add consent tests to integration-arquillian testsuite
2015-11-05 13:02:44 +01:00
Stian Thorgersen c9c49a9c64 Merge branch 'ramirost-feature/i18n_es' 2015-11-05 12:59:29 +01:00
Stian Thorgersen 623f39862d Merge branch 'feature/i18n_es' of https://github.com/ramirost/keycloak into ramirost-feature/i18n_es 2015-11-05 12:59:06 +01:00
Stian Thorgersen 818c3ab1c5 Merge pull request #1785 from ccheneau/master
Fix french translation for account and login resource bundles
2015-11-05 12:54:17 +01:00
Stian Thorgersen 1ce028ead7 Merge pull request #1789 from abstractj/pbeutils-removal
Removal of PBEUtils
2015-11-05 12:49:22 +01:00
Stian Thorgersen d844e6b4af Merge pull request #1776 from girirajsharma/keycloak-1995
[KEYCLOAK-1995] Replace provider select options with Labels displayed in flows table
2015-11-05 12:08:23 +01:00
vramik 7b4dcb6965 arquillian-testsuite: add UI test for Bindings flows 2015-11-04 18:14:41 +01:00
Daniël van 't Ooster 7bd0b7ddfc KEYCLOAK-2032 Changed some column names from lower- to uppercase, so it is in sync with liquibase scripts 2015-11-04 11:43:09 +01:00
Bruno Oliveira d2912673b0 Removal of PBEUtils 2015-11-04 02:06:21 -02:00
Stian Thorgersen 28ee95138a Merge pull request #1773 from iperdomo/master
KEYCLOAK-2016
2015-11-03 15:55:21 +01:00
Bill Burke d46b4eb5fe Merge pull request #1780 from agolPL/master
extract hardcoded keycloak configuration file name
2015-11-02 11:51:04 -05:00
Bill Burke 151c56a304 conflicts 2015-11-02 11:21:10 -05:00
Bill Burke c2ad918975 group model 2015-11-02 11:19:19 -05:00
Tomas Kyjovsky 634eadb634 Merge pull request #1787 from vramik/migration
arquillian-testsuite: Migration test
2015-11-02 15:36:18 +01:00
vramik d26cfcda42 arquillian testsuite, migration test: update execution of dependency plugin for migration scenario 2015-11-02 11:56:26 +01:00
vramik 4a9a39c08d arquillian testsuite, migration test: fix 2015-10-30 14:01:48 +01:00
vramik 9796b7f06e arquillian testsuite, migration test: initial version of migration test 2015-10-30 13:27:38 +01:00
vramik c2e14cb924 arquillian testsuite, migration test: fixed typo in arquillian.xml, add migration test for 1.5.1.Final 2015-10-30 11:32:01 +01:00
Bill Burke d896800ec6 groups initial 2015-10-29 16:33:02 -04:00
mhajas b74e0dad10 remove ConfigTest 2015-10-29 16:50:29 +01:00
mhajas 2c8b0fc3e1 Merge remote-tracking branch 'upstream/master' 2015-10-29 16:41:46 +01:00
vramik cd640339fc arquillian testsuite, migration test: fixed assembly.xml for 1.6.1.Final 2015-10-29 15:11:50 +01:00
vramik 52c02f03ae arquillian testsuite, migration test: fixed assembly.xml for 1.6.1.Final 2015-10-29 15:09:33 +01:00
vramik 84da341912 arquillian testsuite, migration test: add support for 1.5.1.Final 2015-10-29 14:48:05 +01:00
vramik 2c3958ce27 arquillian testsuite, migration test: update test realm to 1.6.1.Final 2015-10-29 14:43:23 +01:00
vramik 515f049ce6 arquillian testsuite, migration test: update version from 1.6.0.Final to 1.6.1.Final 2015-10-29 14:27:23 +01:00
vramik 03acad9b9d arquillian testsuite: increased startup timeout for containers 2015-10-29 13:41:38 +01:00
vramik 0392ebab32 arquillian testsuite: remove adding test realm in migration scenario 2015-10-29 12:22:33 +01:00
vramik 52804da497 arquillian testsuite: improve log messages for migration test 2015-10-29 11:36:29 +01:00
Cédric Chéneau 31df2046f0 Correction page login 2015-10-28 09:38:02 +01:00
Cédric Chéneau f14681f122 Correction page account 2015-10-28 09:35:17 +01:00
Cédric Chéneau d7d52b3295 Correction page account 2015-10-28 09:34:16 +01:00
ccheneau 8e71910e00 Fix french translation for account and login resource bundles 2015-10-27 20:14:41 +01:00
vramik e6620ca005 arquillian-testsuite added initial version of migration test 2015-10-27 14:31:15 +01:00
Ramiro Sánchez 490b8ce86f Added Spanish language support 2015-10-27 12:05:32 +01:00
vramik 480444ffc5 Merge upstream/master into migration 2015-10-27 11:50:30 +01:00
vramik 2fd7e5b355 arquillian-testsuite fixed whitespaces 2015-10-27 11:43:49 +01:00
vramik f45e0aa387 arquillian-testsuite migration servers: removed unused properties 2015-10-27 11:41:33 +01:00
vramik 6c77c295d5 arquillian-testsuite refactoring migration servers 2015-10-27 11:40:41 +01:00
vmuzikar ccfaf72b09 Init changes
(cherry picked from commit 31d8cab)
2015-10-26 15:47:05 +01:00
vmuzikar 700740a378 Added POs for client mappers
(cherry picked from commit f2cd982)
2015-10-26 15:45:55 +01:00
vmuzikar 8062f5f50e Added POs for client mappers
(cherry picked from commit f491c3c)
2015-10-26 15:43:00 +01:00
vmuzikar 5e0851c25f Rewritten some POs to use @id attributes
(cherry picked from commit 12b9c7e)
2015-10-26 14:17:07 +01:00
Marek Posolda 81650a89f9 Merge pull request #1782 from mposolda/master
KEYCLOAK-2005 Fixed migration to take less time. Added UserProvider.g…
2015-10-26 14:12:14 +01:00
vmuzikar 709449243c Added @id to some UI elements
(cherry picked from commit 4034258)
2015-10-26 14:02:30 +01:00
mhajas df24d8a01f Merge remote-tracking branch 'upstream/master' 2015-10-26 12:26:47 +01:00
mposolda f8f4de9389 KEYCLOAK-2005 Fixed migration to take less time. Added UserProvider.grantToAllUsers 2015-10-26 11:06:19 +01:00
agolPl 9755d79879 extract keycloak configuration file name 2015-10-25 00:26:18 +02:00
girirajsharma 70cbeaf336 [KEYCLOAK-1994] It's not possible to create flow with same name as deleted nested flow 2015-10-24 22:57:40 +05:30
girirajsharma b0a71fbeb0 Replace provider select options with Labels displayed in flows table 2015-10-24 13:28:43 +05:30
Marek Posolda 44f56e1d74 Merge pull request #1775 from mposolda/master
Migration and other fixes
2015-10-23 23:41:08 +02:00
mposolda 74924f2f8c KEYCLOAK-2011 2015-10-23 22:48:06 +02:00
mposolda c498b06f68 KEYCLOAK-2007 Migration upgrade for 1.6.1 2015-10-23 22:47:53 +02:00
Iván Perdomo 525bee66a4 KEYCLOAK-2016
Change label to Forgot password
2015-10-23 16:02:30 +02:00
Stian Thorgersen cd51a95764 Merge pull request #1771 from ramirost/release/locale
Added support to indicate desired locale on login options
2015-10-23 15:16:37 +02:00
Ramiro Sánchez 57c282eca8 Updated documentation with the new 'locale' parameter 2015-10-23 14:32:16 +02:00
Ramiro Sánchez ebd02a1a7f Changed query parameter from kc_locale to ui_locales as suggested by stianst 2015-10-23 14:21:59 +02:00
Stian Thorgersen cc4583bc0b Merge pull request #1772 from stianst/master
KEYCLOAK-2015
2015-10-23 13:41:27 +02:00
Stian Thorgersen 11ef67722b KEYCLOAK-2015
autofocus on input text field in login-totp.ftl
2015-10-23 13:40:57 +02:00
Stian Thorgersen 5316dd6d50 Merge pull request #1770 from gerbermichi/autofocus
autofocus on input text field in login-reset-password.ftl
2015-10-23 13:39:29 +02:00
Stian Thorgersen 3cee33847f Merge pull request #1769 from gerbermichi/client
expose client attributes in ClientBean
2015-10-23 13:38:25 +02:00
Stian Thorgersen a2b5b6dc71 Merge pull request #1768 from stianst/master
Fix saml examples not excluded from deploy
2015-10-23 13:37:48 +02:00
Ramiro Sánchez a5dc91f9a6 Added support to indicate desired locale on login 2015-10-23 12:23:24 +02:00
Michael Gerber 3b4b1b20d8 expose client attributes in ClientBean 2015-10-23 09:41:03 +02:00
Michael Gerber b32423d96b autofocus on input field 2015-10-23 09:38:40 +02:00
Stian Thorgersen 4f2fe0197d Fix saml examples not excluded from deploy 2015-10-23 08:48:43 +02:00
Stian Thorgersen aa25c899ee Merge pull request #1765 from vramik/migration-kc16
add support for migration tests - Keycloak 1.6.0.Final
2015-10-23 08:31:08 +02:00
Marek Posolda fa6b99eaab Merge pull request #1767 from mposolda/master
KEYCLOAK-1999 KC server doesn't start on EAP 6.4 in local mode on Pos…
2015-10-22 15:08:54 +02:00
mposolda e04dbffb88 KEYCLOAK-1999 KC server doesn't start on EAP 6.4 in local mode on PostgreSQL 2015-10-22 14:28:08 +02:00
vramik f823b17b90 add path for migration test realm 2015-10-22 14:04:50 +02:00
mhajas 7dfb7ddccd Merge remote-tracking branch 'upstream/master' 2015-10-21 15:41:34 +02:00
vramik 4b444d36b0 removed changes in admin-client 2015-10-21 10:35:19 +02:00
Stian Thorgersen 23546402fa Merge pull request #1749 from cfsnyder/master
KEYCLOAK-1863 added both issuer and account name to otp configuration
2015-10-21 09:24:58 +02:00
vramik edfc7ea103 add support for migration tests - KC1.6.0.Final 2015-10-20 17:00:57 +02:00
Stian Thorgersen 3a7c84c9e1 Merge pull request #1763 from mstruk/KEYCLOAK-1988
KEYCLOAK-1988 Loader constraint violation in multi-tenant example
2015-10-20 06:06:40 +02:00
Stian Thorgersen c860c671d1 Fix parent of docbook modules 2015-10-19 19:37:51 +02:00
Marek Posolda 072950e9f3 Merge pull request #1762 from mposolda/master
KEYCLOAK-1987 Minor fixes in fuse demo
2015-10-19 19:23:05 +02:00
mposolda 8226abef40 KEYCLOAK-1987 Minor fixes in fuse demo 2015-10-19 17:29:04 +02:00
Bill Burke 0d05d38eb6 Merge remote-tracking branch 'upstream/master' 2015-10-19 10:21:03 -04:00
Stian Thorgersen 4f4368b29f Merge pull request #1761 from stianst/master
Version bump
2015-10-19 16:16:27 +02:00
Stian Thorgersen 3f8312427a Version bump 2015-10-19 16:15:29 +02:00
Marek Posolda 73bb579dc5 Merge pull request #1758 from mposolda/master
KEYCLOAK-1981 Migration fix of create-client
2015-10-19 14:11:37 +02:00
Stian Thorgersen c75528f81e Merge pull request #1760 from stianst/master
KEYCLOAK-1985
2015-10-19 13:35:37 +02:00
Stian Thorgersen 28bfac7214 KEYCLOAK-1985 2015-10-19 13:35:04 +02:00
Stian Thorgersen 1c9a347391 Merge pull request #1759 from stianst/master
KEYCLOAK-1984
2015-10-19 13:25:17 +02:00
Stian Thorgersen df03f51563 KEYCLOAK-1984
Examples includes pom.xml.releaseBackup
2015-10-19 13:25:02 +02:00
mposolda 7d590761dd KEYCLOAK-1981 Migration fix of create-client 2015-10-19 12:46:47 +02:00
Marek Posolda 944c416b45 Merge pull request #1757 from mposolda/master
KEYCLOAK-1983 Fix Oracle and Sybase
2015-10-19 12:27:45 +02:00
mposolda 028cbe1ce2 KEYCLOAK-1983 Fix Oracle and Sybase 2015-10-19 11:45:49 +02:00
Bill Burke 186de7235c Merge remote-tracking branch 'upstream/master' 2015-10-16 11:03:42 -04:00
Bill Burke 9433ef284a set browser flow switch 2015-10-16 11:03:30 -04:00
mhajas 32647d8682 Add tests for access grant and revoking grant 2015-10-16 16:22:30 +02:00
Cory Snyder d8ebf1e3d6 KEYCLOAK-1863 added both issuer and account name to otp configuration 2015-10-16 09:46:56 -04:00
1362 changed files with 42231 additions and 13224 deletions

No files matched your search

+3 -9
View File
@@ -3,17 +3,11 @@ language: java
jdk:
- oraclejdk8
cache:
directories:
- $HOME/.m2
before_cache:
- rm -rf $HOME/.m2/repository/org/keycloak
install: mvn install -Pdistribution -DskipTests=true -B -V
install:
- travis_wait mvn install -Pdistribution -DskipTests=true -B -V -q
script:
- mvn test -B
- mvn -file testsuite/integration-arquillian test -B
- mvn -file testsuite/integration-arquillian test -B -Pno-console
sudo: false
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -92,4 +92,9 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
}
@Override
public IdentityProviderDataMarshaller getMarshaller() {
return new DefaultDataMarshaller();
}
}
@@ -1,10 +1,10 @@
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;
import org.keycloak.models.UserModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -35,4 +35,9 @@ public abstract class AbstractIdentityProviderMapper implements IdentityProvider
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
}
@@ -18,9 +18,13 @@
package org.keycloak.broker.provider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.Constants;
import org.keycloak.models.IdentityProviderModel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -152,6 +156,22 @@ public class BrokeredIdentityContext {
this.contextData = contextData;
}
// Set the attribute, which will be available on "Update profile" page and in authenticators
public void setUserAttribute(String attributeName, String attributeValue) {
List<String> list = new ArrayList<>();
list.add(attributeValue);
getContextData().put(Constants.USER_ATTRIBUTES_PREFIX + attributeName, list);
}
public String getUserAttribute(String attributeName) {
List<String> userAttribute = (List<String>) getContextData().get(Constants.USER_ATTRIBUTES_PREFIX + attributeName);
if (userAttribute == null || userAttribute.isEmpty()) {
return null;
} else {
return userAttribute.get(0);
}
}
public String getFirstName() {
return firstName;
}
@@ -0,0 +1,46 @@
package org.keycloak.broker.provider;
import java.io.IOException;
import java.util.List;
import org.keycloak.common.util.Base64Url;
import org.keycloak.util.JsonSerialization;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class DefaultDataMarshaller implements IdentityProviderDataMarshaller {
@Override
public String serialize(Object value) {
if (value instanceof String) {
return (String) value;
} else {
try {
byte[] bytes = JsonSerialization.writeValueAsBytes(value);
return Base64Url.encode(bytes);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
@Override
public <T> T deserialize(String serialized, Class<T> clazz) {
try {
if (clazz.equals(String.class)) {
return clazz.cast(serialized);
} else {
byte[] bytes = Base64Url.decode(serialized);
if (List.class.isAssignableFrom(clazz)) {
List list = JsonSerialization.readValue(bytes, List.class);
return clazz.cast(list);
} else {
return JsonSerialization.readValue(bytes, clazz);
}
}
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
}
@@ -69,10 +69,10 @@ public class HardcodedAttributeMapper extends AbstractIdentityProviderMapper {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
user.setSingleAttribute(attribute, attributeValue);
context.setUserAttribute(attribute, attributeValue);
}
@Override
@@ -67,7 +67,7 @@ public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProvide
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
context.getClientSession().setUserSessionNote(attribute, attributeValue);
@@ -103,4 +103,10 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
*/
Response export(UriInfo uriInfo, RealmModel realm, String format);
/**
* Implementation of marshaller to serialize/deserialize attached data to Strings, which can be saved in clientSession
* @return
*/
IdentityProviderDataMarshaller getMarshaller();
}
@@ -0,0 +1,12 @@
package org.keycloak.broker.provider;
/**
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface IdentityProviderDataMarshaller {
String serialize(Object obj);
<T> T deserialize(String serialized, Class<T> clazz);
}
@@ -20,8 +20,10 @@ public interface IdentityProviderMapper extends Provider, ProviderFactory<Identi
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.
* Called to determine what keycloak username and email to use to process the login request from the external IDP.
* It's called before "FirstBrokerLogin" flow, so can be used to map attributes to BrokeredIdentityContext ( BrokeredIdentityContext.setUserAttribute ),
* which will be available on "Review Profile" page and in authenticators during FirstBrokerLogin flow
*
*
* @param session
* @param realm
@@ -31,7 +33,7 @@ public interface IdentityProviderMapper extends Provider, ProviderFactory<Identi
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called after UserModel is created for first time for this user.
* Called after UserModel is created for first time for this user. Called after "FirstBrokerLogin" flow
*
* @param session
* @param realm
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -5,6 +5,7 @@ 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.jose.jws.JWSInputException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
@@ -51,7 +52,13 @@ public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
@POST
@Path(AdapterConstants.K_LOGOUT)
public Response backchannelLogout(String input) {
JWSInput token = new JWSInput(input);
JWSInput token = null;
try {
token = new JWSInput(input);
} catch (JWSInputException e) {
logger.warn("Failed to verify logout request");
return Response.status(400).build();
}
PublicKey key = getExternalIdpKey();
if (key != null) {
if (!verify(token, key)) {
@@ -29,6 +29,7 @@ import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.RealmModel;
@@ -282,40 +283,41 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
throw new IdentityBrokerException("No token from server.");
}
JsonWebToken token;
try {
JWSInput jws = new JWSInput(encodedToken);
if (!verify(jws, key)) {
throw new IdentityBrokerException("token signature validation failed");
}
JsonWebToken token = jws.readJsonContent(JsonWebToken.class);
String iss = token.getIssuer();
if (!token.hasAudience(getConfig().getClientId())) {
throw new IdentityBrokerException("Wrong audience from token.");
}
if (!token.isActive()) {
throw new IdentityBrokerException("Token is no longer valid");
}
String trustedIssuers = getConfig().getIssuer();
if (trustedIssuers != null) {
String[] issuers = trustedIssuers.split(",");
for (String trustedIssuer : issuers) {
if (iss != null && iss.equals(trustedIssuer.trim())) {
return token;
}
}
throw new IdentityBrokerException("Wrong issuer from token. Got: " + iss + " expected: " + getConfig().getIssuer());
}
return token;
} catch (IOException e) {
throw new IdentityBrokerException("Could not decode token.", e);
token = jws.readJsonContent(JsonWebToken.class);
} catch (JWSInputException e) {
throw new IdentityBrokerException("Invalid token", e);
}
String iss = token.getIssuer();
if (!token.hasAudience(getConfig().getClientId())) {
throw new IdentityBrokerException("Wrong audience from token.");
}
if (!token.isActive()) {
throw new IdentityBrokerException("Token is no longer valid");
}
String trustedIssuers = getConfig().getIssuer();
if (trustedIssuers != null) {
String[] issuers = trustedIssuers.split(",");
for (String trustedIssuer : issuers) {
if (iss != null && iss.equals(trustedIssuer.trim())) {
return token;
}
}
throw new IdentityBrokerException("Wrong issuer from token. Got: " + iss + " expected: " + getConfig().getIssuer());
}
return token;
}
@Override
@@ -89,7 +89,7 @@ public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper
} else if (value instanceof List) {
List list = (List)value;
for (Object val : list) {
return valueEquals(desiredValue, val);
if (valueEquals(desiredValue, val)) return true;
}
}
return false;
@@ -69,8 +69,8 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
* @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 #preprocessFederatedIdentity(KeycloakSession, RealmModel, IdentityProviderMapperModel, BrokeredIdentityContext)
* @see BrokeredIdentityContext#getContextData()
*/
public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
@@ -100,17 +100,17 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
if (attribute == null || attribute.trim().isEmpty()) {
logger.debug("Attribute is not configured");
logger.warnf("Attribute is not configured for mapper %s", mapperModel.getName());
return;
}
attribute = attribute.trim();
String value = getJsonValue(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value);
context.setUserAttribute(attribute, value);
}
}
@@ -123,13 +123,13 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
if (jsonField == null || jsonField.trim().isEmpty()) {
logger.debug("JSON field path is not configured");
logger.warnf("JSON field path is not configured for mapper %s", mapperModel.getName());
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);
logger.warnf("JSON field path is invalid %s", jsonField);
return null;
}
@@ -138,7 +138,7 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr
String value = getJsonValue(profileJsonNode, jsonField);
if (value == null) {
logger.debug("User profile JSON value '" + jsonField + "' is not available.");
logger.debugf("User profile JSON value '%s' is not available.", jsonField);
}
return value;
@@ -70,11 +70,11 @@ public class UserAttributeMapper extends AbstractClaimMapper {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value.toString());
context.setUserAttribute(attribute, value.toString());
}
}
@@ -65,10 +65,6 @@ public class UsernameTemplateMapper extends AbstractClaimMapper {
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) {
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+6 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -45,6 +45,11 @@
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,88 @@
package org.keycloak.broker.saml;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.xml.stream.XMLEventReader;
import org.keycloak.broker.provider.DefaultDataMarshaller;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.StaxUtil;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.processing.core.parsers.util.SAMLParserUtil;
import org.keycloak.saml.processing.core.saml.v2.writers.SAMLAssertionWriter;
import org.keycloak.saml.processing.core.saml.v2.writers.SAMLResponseWriter;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SAMLDataMarshaller extends DefaultDataMarshaller {
@Override
public String serialize(Object obj) {
// Lame impl, but hopefully sufficient for now. See if something better is needed...
if (obj.getClass().getName().startsWith("org.keycloak.dom.saml")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
if (obj instanceof ResponseType) {
ResponseType responseType = (ResponseType) obj;
SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(responseType);
} else if (obj instanceof AssertionType) {
AssertionType assertion = (AssertionType) obj;
SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(assertion);
} else if (obj instanceof AuthnStatementType) {
AuthnStatementType authnStatement = (AuthnStatementType) obj;
SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(authnStatement, true);
} else {
throw new IllegalArgumentException("Don't know how to serialize object of type " + obj.getClass().getName());
}
} catch (ProcessingException pe) {
throw new RuntimeException(pe);
}
return new String(bos.toByteArray());
} else {
return super.serialize(obj);
}
}
@Override
public <T> T deserialize(String serialized, Class<T> clazz) {
if (clazz.getName().startsWith("org.keycloak.dom.saml")) {
String xmlString = serialized;
try {
if (clazz.equals(ResponseType.class) || clazz.equals(AssertionType.class)) {
byte[] bytes = xmlString.getBytes();
InputStream is = new ByteArrayInputStream(bytes);
Object respType = new SAMLParser().parse(is);
return clazz.cast(respType);
} else if (clazz.equals(AuthnStatementType.class)) {
byte[] bytes = xmlString.getBytes();
InputStream is = new ByteArrayInputStream(bytes);
XMLEventReader xmlEventReader = new SAMLParser().createEventReader(is);
AuthnStatementType authnStatement = SAMLParserUtil.parseAuthnStatement(xmlEventReader);
return clazz.cast(authnStatement);
} else {
throw new IllegalArgumentException("Don't know how to deserialize object of type " + clazz.getName());
}
} catch (ParsingException pe) {
throw new RuntimeException(pe);
}
} else {
return super.deserialize(serialized, clazz);
}
}
}
@@ -22,6 +22,7 @@ import org.keycloak.broker.provider.AbstractIdentityProvider;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProviderDataMarshaller;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
@@ -263,4 +264,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
return SignatureAlgorithm.RSA_SHA256;
}
@Override
public IdentityProviderDataMarshaller getMarshaller() {
return new SAMLDataMarshaller();
}
}
@@ -80,11 +80,11 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
if (value != null) {
user.setSingleAttribute(attribute, value.toString());
context.setUserAttribute(attribute, value.toString());
}
}
@@ -71,11 +71,6 @@ public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
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) {
@@ -0,0 +1,64 @@
package org.keycloak.broker.saml;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class SAMLDataMarshallerTest {
private static final String TEST_RESPONSE = "<samlp:Response xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_4804cf50-cd96-4b92-823e-89adaa0c78ba\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.920Z\" Destination=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\" InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"></samlp:StatusCode></samlp:Status><saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>";
private static final String TEST_ASSERTION = "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9\" Version=\"2.0\" IssueInstant=\"2015-11-06T11:00:33.911Z\"><saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://localhost:8082/auth/realms/realm-with-saml-idp-basic</saml:Issuer><saml:Subject><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified\">test-user</saml:NameID><saml:SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><saml:SubjectConfirmationData InResponseTo=\"ID_c6b90123-f0bb-4c5c-bf9d-388d5bbe467a\" NotOnOrAfter=\"2015-11-06T11:05:31.911Z\" Recipient=\"http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint\"></saml:SubjectConfirmationData></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore=\"2015-11-06T11:00:31.911Z\" NotOnOrAfter=\"2015-11-06T11:01:31.911Z\"><saml:AudienceRestriction><saml:Audience>http://localhost:8081/auth/realms/realm-with-broker</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name=\"mobile\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">617-666-7777</saml:AttributeValue></saml:Attribute><saml:Attribute Name=\"urn:oid:1.2.840.113549.1.9.1\" FriendlyName=\"email\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">test-user@localhost</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><saml:AttributeStatement><saml:Attribute Name=\"Role\" NameFormat=\"urn:oasis:names:tc:SAML:2.0:attrname-format:basic\"><saml:AttributeValue xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xsi:type=\"xs:string\">manager</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>";
private static final String TEST_AUTHN_TYPE = "<saml:AuthnStatement xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" AuthnInstant=\"2015-11-06T11:00:33.923Z\" SessionIndex=\"fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5\"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement>";
@Test
public void testParseResponse() throws Exception {
SAMLDataMarshaller serializer = new SAMLDataMarshaller();
ResponseType responseType = serializer.deserialize(TEST_RESPONSE, ResponseType.class);
// test ResponseType
Assert.assertEquals(responseType.getID(), "ID_4804cf50-cd96-4b92-823e-89adaa0c78ba");
Assert.assertEquals(responseType.getDestination(), "http://localhost:8081/auth/realms/realm-with-broker/broker/kc-saml-idp-basic/endpoint");
Assert.assertEquals(responseType.getIssuer().getValue(), "http://localhost:8082/auth/realms/realm-with-saml-idp-basic");
Assert.assertEquals(responseType.getAssertions().get(0).getID(), "ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9");
// back to String
String serialized = serializer.serialize(responseType);
Assert.assertEquals(TEST_RESPONSE, serialized);
}
@Test
public void testParseAssertion() throws Exception {
SAMLDataMarshaller serializer = new SAMLDataMarshaller();
AssertionType assertion = serializer.deserialize(TEST_ASSERTION, AssertionType.class);
// test assertion
Assert.assertEquals(assertion.getID(), "ID_29b196c2-d641-45c8-a423-8ed8e54d4cf9");
Assert.assertEquals(((NameIDType) assertion.getSubject().getSubType().getBaseID()).getValue(), "test-user");
// back to String
String serialized = serializer.serialize(assertion);
Assert.assertEquals(TEST_ASSERTION, serialized);
}
@Test
public void testParseAuthnType() throws Exception {
SAMLDataMarshaller serializer = new SAMLDataMarshaller();
AuthnStatementType authnStatement = serializer.deserialize(TEST_AUTHN_TYPE, AuthnStatementType.class);
// test authnStatement
Assert.assertEquals(authnStatement.getSessionIndex(), "fa0f4fd3-8a11-44f4-9acb-ee30c5bb8fe5");
// back to String
String serialized = serializer.serialize(authnStatement);
Assert.assertEquals(TEST_AUTHN_TYPE, serialized);
}
}
@@ -1,275 +0,0 @@
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;
}
}
}
@@ -2,14 +2,14 @@
<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>
<artifactId>keycloak-client-registration-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-api</artifactId>
<name>Keycloak Client API</name>
<artifactId>keycloak-client-registration-api</artifactId>
<name>Keycloak Client Registration API</name>
<description/>
<dependencies>
@@ -21,11 +21,6 @@
<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,68 @@
package org.keycloak.client.registration;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpRequest;
import org.keycloak.common.util.Base64;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public abstract class Auth {
public abstract void addAuth(HttpRequest request);
public static Auth token(String token) {
return new BearerTokenAuth(token);
}
public static Auth token(ClientInitialAccessPresentation initialAccess) {
return new BearerTokenAuth(initialAccess.getToken());
}
public static Auth token(ClientRepresentation client) {
return new BearerTokenAuth(client.getRegistrationAccessToken());
}
public static Auth token(OIDCClientRepresentation client) {
return new BearerTokenAuth(client.getRegistrationAccessToken());
}
public static Auth client(String clientId, String clientSecret) {
return new BasicAuth(clientId, clientSecret);
}
private static class BearerTokenAuth extends Auth {
private String token;
public BearerTokenAuth(String token) {
this.token = token;
}
@Override
public void addAuth(HttpRequest request) {
request.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
}
}
private static class BasicAuth extends Auth {
private String username;
private String password;
public BasicAuth(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public void addAuth(HttpRequest request) {
String val = Base64.encodeBytes((username + ":" + password).getBytes());
request.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + val);
}
}
}
@@ -0,0 +1,186 @@
package org.keycloak.client.registration;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
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 {
public static final ObjectMapper outputMapper = new ObjectMapper();
static {
outputMapper.getSerializationConfig().addMixInAnnotations(ClientRepresentation.class, ClientRepresentationMixIn.class);
outputMapper.getSerializationConfig().addMixInAnnotations(OIDCClientRepresentation.class, OIDCClientRepresentationMixIn.class);
outputMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
}
private final String JSON = "application/json";
private final String XML = "application/xml";
private final String DEFAULT = "default";
private final String INSTALLATION = "install";
private final String OIDC = "openid-connect";
private final String SAML = "saml2-entity-descriptor";
private HttpUtil httpUtil;
public static ClientRegistrationBuilder create() {
return new ClientRegistrationBuilder();
}
ClientRegistration(HttpUtil httpUtil) {
this.httpUtil = httpUtil;
}
public void close() throws ClientRegistrationException {
if (httpUtil != null) {
httpUtil.close();
}
httpUtil = null;
}
public ClientRegistration auth(Auth auth) {
httpUtil.setAuth(auth);
return this;
}
public ClientRepresentation create(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPost(content, JSON, JSON, DEFAULT);
return deserialize(resultStream, ClientRepresentation.class);
}
public ClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(JSON, DEFAULT, clientId);
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}
public AdapterConfig getAdapterConfig(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(JSON, INSTALLATION, clientId);
return resultStream != null ? deserialize(resultStream, AdapterConfig.class) : null;
}
public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPut(content, JSON, JSON, DEFAULT, client.getClientId());
return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
}
public void delete(ClientRepresentation client) throws ClientRegistrationException {
delete(client.getClientId());
}
public void delete(String clientId) throws ClientRegistrationException {
httpUtil.doDelete(DEFAULT, clientId);
}
public OIDCClientRegistration oidc() {
return new OIDCClientRegistration();
}
public SAMLClientRegistration saml() {
return new SAMLClientRegistration();
}
public static String serialize(Object obj) throws ClientRegistrationException {
try {
return outputMapper.writeValueAsString(obj);
} catch (IOException e) {
throw new ClientRegistrationException("Failed to write json object", e);
}
}
private static <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 class OIDCClientRegistration {
public OIDCClientRepresentation create(OIDCClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPost(content, JSON, JSON, OIDC);
return deserialize(resultStream, OIDCClientRepresentation.class);
}
public OIDCClientRepresentation get(String clientId) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doGet(JSON, OIDC, clientId);
return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
}
public OIDCClientRepresentation update(OIDCClientRepresentation client) throws ClientRegistrationException {
String content = serialize(client);
InputStream resultStream = httpUtil.doPut(content, JSON, JSON, OIDC, client.getClientId());
return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
}
public void delete(OIDCClientRepresentation client) throws ClientRegistrationException {
delete(client.getClientId());
}
public void delete(String clientId) throws ClientRegistrationException {
httpUtil.doDelete(OIDC, clientId);
}
}
public class SAMLClientRegistration {
public ClientRepresentation create(String entityDescriptor) throws ClientRegistrationException {
InputStream resultStream = httpUtil.doPost(entityDescriptor, XML, JSON, SAML);
return deserialize(resultStream, ClientRepresentation.class);
}
}
public static class ClientRegistrationBuilder {
private String url;
private HttpClient httpClient;
ClientRegistrationBuilder() {
}
public ClientRegistrationBuilder url(String realmUrl) {
url = realmUrl;
return this;
}
public ClientRegistrationBuilder url(String authUrl, String realm) {
url = HttpUtil.getUrl(authUrl, "realms", realm, "clients");
return this;
}
public ClientRegistrationBuilder httpClient(HttpClient httpClient) {
this.httpClient = httpClient;
return this;
}
public ClientRegistration build() {
if (url == null) {
throw new IllegalStateException("url not configured");
}
if (httpClient == null) {
httpClient = HttpClients.createDefault();
}
return new ClientRegistration(new HttpUtil(httpClient, url));
}
}
}
@@ -0,0 +1,13 @@
package org.keycloak.client.registration;
import org.codehaus.jackson.annotate.JsonIgnore;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
abstract class ClientRepresentationMixIn {
@JsonIgnore
String registrationAccessToken;
}
@@ -0,0 +1,171 @@
package org.keycloak.client.registration;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.keycloak.client.registration.Auth;
import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.HttpErrorException;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
class HttpUtil {
private HttpClient httpClient;
private String baseUri;
private Auth auth;
HttpUtil(HttpClient httpClient, String baseUri) {
this.httpClient = httpClient;
this.baseUri = baseUri;
}
void setAuth(Auth auth) {
this.auth = auth;
}
InputStream doPost(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
try {
HttpPost request = new HttpPost(getUrl(baseUri, path));
request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
request.setHeader(HttpHeaders.ACCEPT, acceptType);
request.setEntity(new StringEntity(content));
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);
}
}
InputStream doGet(String acceptType, String... path) throws ClientRegistrationException {
try {
HttpGet request = new HttpGet(getUrl(baseUri, path));
request.setHeader(HttpHeaders.ACCEPT, acceptType);
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 {
if (responseStream != null) {
responseStream.close();
}
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
InputStream doPut(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
try {
HttpPut request = new HttpPut(getUrl(baseUri, path));
request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
request.setHeader(HttpHeaders.ACCEPT, acceptType);
request.setEntity(new StringEntity(content));
addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent();
}
InputStream responseStream = null;
if (response.getEntity() != null) {
responseStream = response.getEntity().getContent();
}
if (response.getStatusLine().getStatusCode() == 200) {
return responseStream;
} else {
if (responseStream != null) {
responseStream.close();
}
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
void doDelete(String... path) throws ClientRegistrationException {
try {
HttpDelete request = new HttpDelete(getUrl(baseUri, path));
addAuth(request);
HttpResponse response = httpClient.execute(request);
if (response.getEntity() != null) {
response.getEntity().getContent().close();
}
if (response.getStatusLine().getStatusCode() != 204) {
throw new HttpErrorException(response.getStatusLine());
}
} catch (IOException e) {
throw new ClientRegistrationException("Failed to send request", e);
}
}
void close() throws ClientRegistrationException {
if (httpClient instanceof CloseableHttpClient) {
try {
((CloseableHttpClient) httpClient).close();
} catch (IOException e) {
throw new ClientRegistrationException("Failed to close http client", e);
}
}
}
static String getUrl(String baseUri, String... path) {
StringBuilder s = new StringBuilder();
s.append(baseUri);
for (String p : path) {
s.append('/');
s.append(p);
}
return s.toString();
}
private void addAuth(HttpRequestBase request) {
if (auth != null) {
auth.addAuth(request);
}
}
}
@@ -0,0 +1,22 @@
package org.keycloak.client.registration;
import org.codehaus.jackson.annotate.JsonIgnore;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
abstract class OIDCClientRepresentationMixIn {
@JsonIgnore
private Integer client_id_issued_at;
@JsonIgnore
private Integer client_secret_expires_at;
@JsonIgnore
private String registration_client_uri;
@JsonIgnore
private String registration_access_token;
}
+34
View File
@@ -0,0 +1,34 @@
<?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-client-registration-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.7.0.Final-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-registration-cli</artifactId>
<name>Keycloak Client Registration CLI</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-client-registration-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.aesh</groupId>
<artifactId>aesh</artifactId>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,72 @@
package org.keycloak.client.registration.cli;
import org.jboss.aesh.cl.parser.CommandLineParserException;
import org.jboss.aesh.console.AeshConsole;
import org.jboss.aesh.console.AeshConsoleBuilder;
import org.jboss.aesh.console.Prompt;
import org.jboss.aesh.console.command.Command;
import org.jboss.aesh.console.command.CommandNotFoundException;
import org.jboss.aesh.console.command.registry.AeshCommandRegistryBuilder;
import org.jboss.aesh.console.settings.Settings;
import org.jboss.aesh.console.settings.SettingsBuilder;
import org.jboss.aesh.terminal.Color;
import org.jboss.aesh.terminal.TerminalColor;
import org.jboss.aesh.terminal.TerminalString;
import org.keycloak.client.registration.Auth;
import org.keycloak.client.registration.ClientRegistration;
import org.keycloak.client.registration.cli.commands.CreateCommand;
import org.keycloak.client.registration.cli.commands.ExitCommand;
import org.keycloak.client.registration.cli.commands.SetupCommand;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationCLI {
private static ClientRegistration reg;
public static void main(String[] args) throws CommandLineParserException, CommandNotFoundException {
reg = ClientRegistration.create().url("http://localhost:8080/auth/realms/master").build();
reg.auth(Auth.token("..."));
Context context = new Context();
List<Command> commands = new LinkedList<>();
commands.add(new SetupCommand(context));
commands.add(new CreateCommand(context));
commands.add(new ExitCommand(context));
SettingsBuilder builder = new SettingsBuilder().logging(true);
builder.enableMan(true).readInputrc(false);
Settings settings = builder.create();
AeshCommandRegistryBuilder commandRegistryBuilder = new AeshCommandRegistryBuilder();
for (Command c : commands) {
commandRegistryBuilder.command(c);
}
AeshConsole aeshConsole = new AeshConsoleBuilder()
.commandRegistry(commandRegistryBuilder.create())
.settings(settings)
.prompt(new Prompt(new TerminalString("[clientreg]$ ",
new TerminalColor(Color.GREEN, Color.DEFAULT, Color.Intensity.BRIGHT))))
.create();
aeshConsole.start();
/*
if (args.length > 0) {
CommandContainer command = registry.getCommand(args[0], null);
ParserGenerator.parseAndPopulate(command, args[0], Arrays.copyOfRange(args, 1, args.length));
}*/
//commandInvocation.getCommandRegistry().getAllCommandNames()
}
}
@@ -0,0 +1,37 @@
package org.keycloak.client.registration.cli;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.keycloak.client.registration.ClientRegistration;
import org.keycloak.util.SystemPropertiesJsonParserFactory;
import java.io.IOException;
import java.io.InputStream;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Context {
private static final ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
static {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
}
private ClientRegistration reg;
public ClientRegistration getReg() {
return reg;
}
public void setReg(ClientRegistration reg) {
this.reg = reg;
}
public static <T> T readJson(InputStream bytes, Class<T> type) throws IOException {
return mapper.readValue(bytes, type);
}
}
@@ -0,0 +1,64 @@
package org.keycloak.client.registration.cli.commands;
import org.jboss.aesh.cl.Arguments;
import org.jboss.aesh.cl.CommandDefinition;
import org.jboss.aesh.cl.Option;
import org.jboss.aesh.console.command.Command;
import org.jboss.aesh.console.command.CommandResult;
import org.jboss.aesh.console.command.invocation.CommandInvocation;
import org.jboss.aesh.io.Resource;
import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.cli.Context;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@CommandDefinition(name="create", description = "[OPTIONS] FILE")
public class CreateCommand implements Command {
@Option(shortName = 'h', hasValue = false, description = "display this help and exit")
private boolean help;
@Arguments(description = "files or directories thats listed")
private List<Resource> arguments;
private Context context;
public CreateCommand(Context context) {
this.context = context;
}
@Override
public CommandResult execute(CommandInvocation commandInvocation) throws IOException, InterruptedException {
System.out.println(help);
if(help) {
commandInvocation.getShell().out().println(commandInvocation.getHelpInfo("create"));
}
else {
if(arguments != null) {
for(Resource f : arguments) {
System.out.println(f.getAbsolutePath());
ClientRepresentation rep = JsonSerialization.readValue(f.read(), ClientRepresentation.class);
try {
context.getReg().create(rep);
} catch (ClientRegistrationException e) {
e.printStackTrace();
}
}
}
}
// reg.create();
return CommandResult.SUCCESS;
}
}
@@ -0,0 +1,29 @@
package org.keycloak.client.registration.cli.commands;
import org.jboss.aesh.cl.CommandDefinition;
import org.jboss.aesh.console.command.Command;
import org.jboss.aesh.console.command.CommandResult;
import org.jboss.aesh.console.command.invocation.CommandInvocation;
import org.keycloak.client.registration.cli.Context;
import java.io.IOException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@CommandDefinition(name="exit", description = "Exit the program")
public class ExitCommand implements Command {
private Context context;
public ExitCommand(Context context) {
this.context = context;
}
@Override
public CommandResult execute(CommandInvocation commandInvocation) throws IOException, InterruptedException {
commandInvocation.stop();
return CommandResult.SUCCESS;
}
}
@@ -0,0 +1,48 @@
package org.keycloak.client.registration.cli.commands;
import org.jboss.aesh.cl.CommandDefinition;
import org.jboss.aesh.cl.Option;
import org.jboss.aesh.console.command.Command;
import org.jboss.aesh.console.command.CommandResult;
import org.jboss.aesh.console.command.invocation.CommandInvocation;
import org.jboss.aesh.io.Resource;
import org.keycloak.client.registration.ClientRegistrationException;
import org.keycloak.client.registration.cli.Context;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@CommandDefinition(name="setup", description = "")
public class SetupCommand implements Command {
@Option(shortName = 'h', hasValue = false, description = "display this help and exit")
private boolean help;
private Context context;
public SetupCommand(Context context) {
this.context = context;
}
@Override
public CommandResult execute(CommandInvocation commandInvocation) throws IOException, InterruptedException {
System.out.println(help);
if(help) {
commandInvocation.getShell().out().println(commandInvocation.getHelpInfo("create"));
}
return CommandResult.SUCCESS;
}
private String promptForUsername(CommandInvocation invocation) throws InterruptedException {
invocation.print("username: ");
return invocation.getInputLine();
}
}
+19
View File
@@ -0,0 +1,19 @@
<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.8.0.Alpha1</version>
</parent>
<name>Keycloak Client Registration Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-registration-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>api</module>
<!--<module>cli</module>-->
</modules>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -23,4 +23,19 @@ public class CollectionUtil {
}
return sb.toString();
}
// Return true if all items from col1 are in col2 and viceversa. Order is not taken into account
public static <T> boolean collectionEquals(Collection<T> col1, Collection<T> col2) {
if (col1.size() != col2.size()) {
return false;
}
for (T item : col1) {
if (!col2.contains(item)) {
return false;
}
}
return true;
}
}
@@ -341,6 +341,17 @@ public class KeycloakUriBuilder {
return this;
}
/**
* Set fragment, but not encode it. It assumes that given fragment was already properly encoded
*
* @param fragment
* @return
*/
public KeycloakUriBuilder encodedFragment(String fragment) {
this.fragment = fragment;
return this;
}
/**
* Only replace path params in path of URI. This changes state of URIBuilder.
*
@@ -13,7 +13,7 @@ public class ObjectUtil {
* @param str2
* @return true if both strings are null or equal
*/
public static boolean isEqualOrNull(Object str1, Object str2) {
public static boolean isEqualOrBothNull(Object str1, Object str2) {
if (str1 == null && str2 == null) {
return true;
}
@@ -24,4 +24,8 @@ public class ObjectUtil {
return str1.equals(str2);
}
public static String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
-43
View File
@@ -1,43 +0,0 @@
<?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.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-connections-file</artifactId>
<name>Keycloak Connections File</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-api</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-export-import-single-file</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
</dependency>
</dependencies>
</project>
@@ -1,86 +0,0 @@
/*
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.keycloak.connections.file;
import org.keycloak.models.KeycloakSession;
/**
* Provides the InMemoryModel and notifies the factory to save it when
* the session is done.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
*/
public class DefaultFileConnectionProvider implements FileConnectionProvider {
private final DefaultFileConnectionProviderFactory factory;
private final KeycloakSession session;
private final InMemoryModel inMemoryModel;
private boolean isRollbackOnly = false;
public DefaultFileConnectionProvider(DefaultFileConnectionProviderFactory factory,
KeycloakSession session,
InMemoryModel inMemoryModel) {
this.factory = factory;
this.session = session;
this.inMemoryModel = inMemoryModel;
}
@Override
public InMemoryModel getModel() {
return inMemoryModel;
}
@Override
public void sessionClosed(KeycloakSession session) {
factory.sessionClosed(session);
}
@Override
public void close() {
}
@Override
public void begin() {
}
@Override
public void commit() {
factory.commit(session);
}
@Override
public void rollback() {
factory.rollback(session);
}
@Override
public void setRollbackOnly() {
isRollbackOnly = true;
}
@Override
public boolean getRollbackOnly() {
return isRollbackOnly;
}
@Override
public boolean isActive() {
return factory.isActive(session);
}
}
@@ -1,210 +0,0 @@
/*
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.keycloak.connections.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.JsonToken;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.exportimport.Strategy;
import org.keycloak.exportimport.util.ExportUtils;
import org.keycloak.exportimport.util.ImportUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* This class dispenses a FileConnectionProvider to Keycloak sessions. It
* makes sure that only one InMemoryModel is provided for each session and it
* handles thread contention for the file where the model is read or saved.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
*/
public class DefaultFileConnectionProviderFactory implements FileConnectionProviderFactory {
protected static final Logger logger = Logger.getLogger(DefaultFileConnectionProviderFactory.class);
private File kcdata;
private final Map<KeycloakSession, FileConnectionProvider> allProviders = new HashMap<KeycloakSession, FileConnectionProvider>();
@Override
public void init(Config.Scope config) {
String fileName = config.get("fileName");
if (fileName == null) {
fileName = "keycloak-model.json";
}
String directory = config.get("directory");
if (directory == null) {
directory = System.getProperty("jboss.server.data.dir");
}
if (directory == null) {
directory = ".";
}
kcdata = new File(directory, fileName);
}
public void sessionClosed(KeycloakSession session) {
synchronized(allProviders) {
allProviders.remove(session);
//logger.info("Removed session " + session.hashCode());
//logger.info("sessionClosed: Session count=" + allModels.size());
}
}
void readModelFile(KeycloakSession session) {
synchronized(allProviders) {
if (!kcdata.exists()) {
return;
}
FileInputStream fis = null;
try {
fis = new FileInputStream(kcdata);
Model model = JsonSerialization.readValue(fis, Model.class);
ImportUtils.importFromStream(session, JsonSerialization.mapper, fis, Strategy.IGNORE_EXISTING);
session.realms().getMigrationModel().setStoredVersion(model.getModelVersion());
ImportUtils.importRealms(session, model.getRealms(), Strategy.IGNORE_EXISTING);
} catch (IOException ioe) {
logger.error("Unable to read model file " + kcdata.getAbsolutePath(), ioe);
} finally {
//logger.info("Read model file for session=" + session.hashCode());
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
logger.error("Failed to close output stream.", e);
}
}
}
}
void writeModelFile(KeycloakSession session) {
synchronized(allProviders) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(kcdata);
exportModel(session, outStream);
} catch (IOException e) {
logger.error("Unable to write model file " + kcdata.getAbsolutePath(), e);
} finally {
//logger.info("Wrote model file for session=" + session.hashCode());
try {
if (outStream != null) {
outStream.close();
}
} catch (IOException e) {
logger.error("Failed to close output stream.", e);
}
}
}
}
private void exportModel(KeycloakSession session, FileOutputStream outStream) throws IOException {
List<RealmModel> realms = session.realms().getRealms();
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
for (RealmModel realm : realms) {
reps.add(ExportUtils.exportRealm(session, realm, true));
}
Model model = new Model();
model.setRealms(reps);
model.setModelVersion(session.realms().getMigrationModel().getStoredVersion());
JsonSerialization.prettyMapper.writeValue(outStream, model);
}
@Override
public FileConnectionProvider create(KeycloakSession session) {
synchronized (allProviders) {
FileConnectionProvider fcProvider = allProviders.get(session);
if (fcProvider == null) {
InMemoryModel model = new InMemoryModel();
fcProvider = new DefaultFileConnectionProvider(this, session, model);
allProviders.put(session, fcProvider);
session.getTransaction().enlist(fcProvider);
readModelFile(session);
//logger.info("Added session " + session.hashCode() + " total sessions=" + allModels.size());
}
return fcProvider;
}
}
// commitCount is used for debugging. This allows you to easily run a test
// to a particular point and then examine the JSON file.
//private static int commitCount = 0;
void commit(KeycloakSession session) {
//commitCount++;
synchronized (allProviders) {
// in case commit was somehow called twice on the same session
if (!allProviders.containsKey(session)) return;
try {
writeModelFile(session);
} finally {
allProviders.remove(session);
//logger.info("Removed session " + session.hashCode());
//logger.info("*** commitCount=" + commitCount);
//logger.info("commit(): Session count=" + allModels.size());
}
// if (commitCount == 16) {Thread.dumpStack();System.exit(0);}
}
}
void rollback(KeycloakSession session) {
synchronized (allProviders) {
allProviders.remove(session);
//logger.info("rollback(): Session count=" + allModels.size());
}
}
boolean isActive(KeycloakSession session) {
synchronized (allProviders) {
return allProviders.containsKey(session);
}
}
@Override
public void close() {
}
@Override
public String getId() {
return "default";
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
}
@@ -1,109 +0,0 @@
/*
* Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @author tags. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.keycloak.connections.file;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
/**
* This class provides an in-memory copy of the entire model for each
* Keycloak session. At the start of the session, the model is read
* from JSON. When the session's transaction ends, the model is written back
* out.
*
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
*/
public class InMemoryModel {
private final Map<String, RealmModel> allRealms = new HashMap<String, RealmModel>();
// realmId, userId, userModel
private final Map<String, Map<String,UserModel>> allUsers = new HashMap<String, Map<String,UserModel>>();
private String modelVersion;
public InMemoryModel() {
}
public void putRealm(String id, RealmModel realm) {
allRealms.put(id, realm);
allUsers.put(id, new HashMap<String, UserModel>());
}
public String getModelVersion() {
return modelVersion;
}
public void setModelVersion(String modelVersion) {
this.modelVersion = modelVersion;
}
public RealmModel getRealm(String id) {
return allRealms.get(id);
}
public Collection<RealmModel> getRealms() {
return allRealms.values();
}
public RealmModel getRealmByName(String name) {
for (RealmModel realm : getRealms()) {
if (realm.getName().equals(name)) return realm;
}
return null;
}
public boolean removeRealm(String id) {
allUsers.remove(id);
return (allRealms.remove(id) != null);
}
protected Map<String, UserModel> realmUsers(String realmId) {
Map<String, UserModel> realmUsers = allUsers.get(realmId);
if (realmUsers == null) throw new NullPointerException("Realm users not found for id=" + realmId);
return realmUsers;
}
public void putUser(String realmId, String userId, UserModel user) {
realmUsers(realmId).put(userId, user);
}
public UserModel getUser(String realmId, String userId) {
return realmUsers(realmId).get(userId);
}
public boolean hasUserWithUsername(String realmId, String username) {
for (UserModel user : getUsers(realmId)) {
if (user.getUsername().equals(username)) return true;
}
return false;
}
public Collection<UserModel> getUsers(String realmId) {
return realmUsers(realmId).values();
}
public boolean removeUser(String realmId, String userId) {
return (realmUsers(realmId).remove(userId) != null);
}
}
@@ -1,30 +0,0 @@
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;
}
}
@@ -1 +0,0 @@
org.keycloak.connections.file.DefaultFileConnectionProviderFactory
@@ -1 +0,0 @@
org.keycloak.connections.file.FileConnectionSpi
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -69,7 +69,7 @@ public class DefaultInfinispanConnectionProviderFactory implements InfinispanCon
// Backwards compatibility
if (cacheManager.getCacheConfiguration(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME) == null) {
logger.warnf("No configuration provided for '%s' cache. Using '%s' configuration as template",
logger.debugf("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);
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.6.1_from15">
<preConditions onFail="MARK_RAN" onFailMessage="Upgrading from 1.6.0 version. Skipped 1.6.1_from15 changeSet and marked as ran">
<not>
<changeSetExecuted id="1.6.0" author="mposolda@redhat.com" changeLogFile="META-INF/jpa-changelog-1.6.0.xml" />
</not>
</preConditions>
<addColumn tableName="REALM">
<column name="OFFLINE_SESSION_IDLE_TIMEOUT" type="INT" defaultValueNumeric="0"/>
<column name="REVOKE_REFRESH_TOKEN" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
<addColumn tableName="KEYCLOAK_ROLE">
<column name="SCOPE_PARAM_REQUIRED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
<addColumn tableName="CLIENT">
<column name="ROOT_URL" type="VARCHAR(255)"/>
<column name="DESCRIPTION" type="VARCHAR(255)"/>
</addColumn>
<createTable tableName="OFFLINE_USER_SESSION">
<column name="USER_SESSION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="LAST_SESSION_REFRESH" type="INT"/>
<column name="OFFLINE_FLAG" type="VARCHAR(4)">
<constraints nullable="false"/>
</column>
<column name="DATA" type="CLOB"/>
</createTable>
<createTable tableName="OFFLINE_CLIENT_SESSION">
<column name="CLIENT_SESSION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="USER_SESSION_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="OFFLINE_FLAG" type="VARCHAR(4)">
<constraints nullable="false"/>
</column>
<column name="TIMESTAMP" type="INT"/>
<column name="DATA" type="CLOB"/>
</createTable>
<addPrimaryKey columnNames="USER_SESSION_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_US_SES_PK2" tableName="OFFLINE_USER_SESSION"/>
<addPrimaryKey columnNames="CLIENT_SESSION_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_CL_SES_PK2" tableName="OFFLINE_CLIENT_SESSION"/>
</changeSet>
<!-- Just for the update from 1.6.0 -->
<changeSet author="mposolda@redhat.com" id="1.6.1_from16">
<preConditions onFail="MARK_RAN" onFailMessage="Upgrading from 1.5.0 or older version. Skipped 1.6.1_from16 changeSet and marked as ran">
<changeSetExecuted id="1.6.0" author="mposolda@redhat.com" changeLogFile="META-INF/jpa-changelog-1.6.0.xml" />
</preConditions>
<dropPrimaryKey constraintName="CONSTRAINT_OFFLINE_US_SES_PK" tableName="OFFLINE_USER_SESSION" />
<dropPrimaryKey constraintName="CONSTRAINT_OFFLINE_CL_SES_PK" tableName="OFFLINE_CLIENT_SESSION" />
<addColumn tableName="OFFLINE_USER_SESSION">
<column name="OFFLINE_FLAG" type="VARCHAR(4)">
<constraints nullable="false"/>
</column>
</addColumn>
<update tableName="OFFLINE_USER_SESSION">
<column name="OFFLINE_FLAG" value="1"/>
</update>
<dropColumn tableName="OFFLINE_USER_SESSION" columnName="OFFLINE" />
<addColumn tableName="OFFLINE_CLIENT_SESSION">
<column name="OFFLINE_FLAG" type="VARCHAR(4)">
<constraints nullable="false"/>
</column>
</addColumn>
<update tableName="OFFLINE_CLIENT_SESSION">
<column name="OFFLINE_FLAG" value="1"/>
</update>
<dropColumn tableName="OFFLINE_CLIENT_SESSION" columnName="OFFLINE" />
<addPrimaryKey columnNames="USER_SESSION_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_US_SES_PK2" tableName="OFFLINE_USER_SESSION"/>
<addPrimaryKey columnNames="CLIENT_SESSION_ID, OFFLINE_FLAG" constraintName="CONSTRAINT_OFFL_CL_SES_PK2" tableName="OFFLINE_CLIENT_SESSION"/>
</changeSet>
<changeSet author="mposolda@redhat.com" id="1.6.1">
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.7.0">
<createTable tableName="KEYCLOAK_GROUP">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="NAME" type="VARCHAR(255)"/>
<column name="PARENT_GROUP" type="VARCHAR(36)"/>
<column name="REALM_ID" type="VARCHAR(36)"/>
</createTable>
<createTable tableName="GROUP_ROLE_MAPPING">
<column name="ROLE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="GROUP_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="GROUP_ATTRIBUTE">
<column name="ID" type="VARCHAR(36)" defaultValue="sybase-needs-something-here">
<constraints nullable="false"/>
</column>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="VALUE" type="VARCHAR(255)"/>
<column name="GROUP_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="USER_GROUP_MEMBERSHIP">
<column name="GROUP_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="USER_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<createTable tableName="REALM_DEFAULT_GROUPS">
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="GROUP_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<addColumn tableName="IDENTITY_PROVIDER">
<column name="FIRST_BROKER_LOGIN_FLOW_ID" type="VARCHAR(36)">
<constraints nullable="true"/>
</column>
</addColumn>
<addColumn tableName="REALM">
<column name="ACCESS_TOKEN_LIFE_IMPLICIT" type="INT" defaultValueNumeric="0"/>
</addColumn>
<dropDefaultValue tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LGN_MD" />
<dropColumn tableName="IDENTITY_PROVIDER" columnName="UPDATE_PROFILE_FIRST_LGN_MD"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GROUP" tableName="KEYCLOAK_GROUP"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="KEYCLOAK_GROUP" constraintName="FK_GROUP_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addPrimaryKey columnNames="ID" constraintName="CONSTRAINT_GROUP_ATTRIBUTE_PK" tableName="GROUP_ATTRIBUTE"/>
<addForeignKeyConstraint baseColumnNames="GROUP_ID" baseTableName="GROUP_ATTRIBUTE" constraintName="FK_GROUP_ATTRIBUTE_GROUP" referencedColumnNames="ID" referencedTableName="KEYCLOAK_GROUP"/>
<addPrimaryKey columnNames="GROUP_ID, USER_ID" constraintName="CONSTRAINT_USER_GROUP" tableName="USER_GROUP_MEMBERSHIP"/>
<addForeignKeyConstraint baseColumnNames="USER_ID" baseTableName="USER_GROUP_MEMBERSHIP" constraintName="FK_USER_GROUP_USER" referencedColumnNames="ID" referencedTableName="USER_ENTITY"/>
<addPrimaryKey columnNames="ROLE_ID, GROUP_ID" constraintName="CONSTRAINT_GROUP_ROLE" tableName="GROUP_ROLE_MAPPING"/>
<addForeignKeyConstraint baseColumnNames="GROUP_ID" baseTableName="GROUP_ROLE_MAPPING" constraintName="FK_GROUP_ROLE_GROUP" referencedColumnNames="ID" referencedTableName="KEYCLOAK_GROUP"/>
<addForeignKeyConstraint baseColumnNames="ROLE_ID" baseTableName="GROUP_ROLE_MAPPING" constraintName="FK_GROUP_ROLE_ROLE" referencedColumnNames="ID" referencedTableName="KEYCLOAK_ROLE"/>
<addUniqueConstraint columnNames="GROUP_ID" constraintName="CON_GROUP_ID_DEF_GROUPS" tableName="REALM_DEFAULT_GROUPS"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_DEFAULT_GROUPS" constraintName="FK_DEF_GROUPS_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="GROUP_ID" baseTableName="REALM_DEFAULT_GROUPS" constraintName="FK_DEF_GROUPS_GROUP" referencedColumnNames="ID" referencedTableName="KEYCLOAK_GROUP"/>
<addColumn tableName="CLIENT">
<column name="REGISTRATION_TOKEN" type="VARCHAR(255)"/>
<column name="STANDARD_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="true">
<constraints nullable="false"/>
</column>
<column name="IMPLICIT_FLOW_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
<column name="DIRECT_ACCESS_GRANTS_ENABLED" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
</column>
</addColumn>
<update tableName="CLIENT">
<column name="STANDARD_FLOW_ENABLED" valueBoolean="false"/>
<column name="DIRECT_ACCESS_GRANTS_ENABLED" valueBoolean="true"/>
<where>DIRECT_GRANTS_ONLY = :value</where>
<whereParams>
<param valueBoolean="true" />
</whereParams>
</update>
<dropDefaultValue tableName="CLIENT" columnName="DIRECT_GRANTS_ONLY" />
<dropColumn tableName="CLIENT" columnName="DIRECT_GRANTS_ONLY"/>
<modifyDataType tableName="REALM" columnName="PASSWORD_POLICY" newDataType="VARCHAR(2550)"/>
<!-- Sybase specific hacks -->
<modifySql dbms="sybase">
<regExpReplace replace=".*(SET DEFAULT NULL)" with="SELECT 1" />
</modifySql>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.8.0">
<addColumn tableName="IDENTITY_PROVIDER">
<column name="POST_BROKER_LOGIN_FLOW_ID" type="VARCHAR(36)">
<constraints nullable="true"/>
</column>
</addColumn>
<createTable tableName="CLIENT_TEMPLATE">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="NAME" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(36)"/>
<column name="DESCRIPTION" type="VARCHAR(255)"/>
<column name="PROTOCOL" type="VARCHAR(255)"/>
</createTable>
<dropNotNullConstraint tableName="PROTOCOL_MAPPER" columnName="CLIENT_ID" columnDataType="VARCHAR(36)"/>
<addColumn tableName="CLIENT">
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
<constraints nullable="true"/>
</column>
</addColumn>
<addColumn tableName="PROTOCOL_MAPPER">
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
<constraints nullable="true"/>
</column>
</addColumn>
<createTable tableName="REALM_CLIENT_TEMPLATE">
<column name="CLIENT_TEMPLATE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
<column name="REALM_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="ID" constraintName="PK_CLI_TEMPLATE" tableName="CLIENT_TEMPLATE"/>
<addUniqueConstraint columnNames="REALM_ID,NAME" constraintName="UK_CLI_TEMPLATE" tableName="CLIENT_TEMPLATE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="CLIENT_TEMPLATE" constraintName="FK_REALM_CLI_TMPLT" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="PROTOCOL_MAPPER" constraintName="FK_CLI_TMPLT_MAPPER" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="CLIENT" constraintName="FK_CLI_TMPLT_CLIENT" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
<addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="REALM_CLIENT_TEMPLATE" constraintName="FK_RLM_CLI_TMPLT_RLM" referencedColumnNames="ID" referencedTableName="REALM"/>
<addForeignKeyConstraint baseColumnNames="CLIENT_TEMPLATE_ID" baseTableName="REALM_CLIENT_TEMPLATE" constraintName="FK_RLM_CLI_TMPLT_CLI" referencedColumnNames="ID" referencedTableName="CLIENT_TEMPLATE"/>
</changeSet>
</databaseChangeLog>
@@ -9,5 +9,7 @@
<include file="META-INF/jpa-changelog-1.3.0.xml"/>
<include file="META-INF/jpa-changelog-1.4.0.xml"/>
<include file="META-INF/jpa-changelog-1.5.0.xml"/>
<include file="META-INF/jpa-changelog-1.6.0.xml"/>
<include file="META-INF/jpa-changelog-1.6.1.xml"/>
<include file="META-INF/jpa-changelog-1.7.0.xml"/>
<include file="META-INF/jpa-changelog-1.8.0.xml"/>
</databaseChangeLog>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,18 +1,5 @@
package org.keycloak.connections.jpa;
import org.hibernate.ejb.AvailableSettings;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
@@ -22,10 +9,25 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.sql.DataSource;
import org.hibernate.ejb.AvailableSettings;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import org.keycloak.connections.jpa.util.JpaUtils;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory, ServerInfoAwareProviderFactory {
private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
@@ -1,10 +1,10 @@
package org.keycloak.connections.jpa;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
}
@@ -12,7 +12,7 @@ public interface JpaUpdaterProvider extends Provider {
public String FIRST_VERSION = "1.0.0.Final";
public String LAST_VERSION = "1.6.0";
public String LAST_VERSION = "1.7.0";
public String getCurrentVersionSql(String defaultSchema);
@@ -31,6 +31,11 @@
<class>org.keycloak.models.jpa.entities.RequiredActionProviderEntity</class>
<class>org.keycloak.models.jpa.session.PersistentUserSessionEntity</class>
<class>org.keycloak.models.jpa.session.PersistentClientSessionEntity</class>
<class>org.keycloak.models.jpa.entities.GroupEntity</class>
<class>org.keycloak.models.jpa.entities.GroupAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.GroupRoleMappingEntity</class>
<class>org.keycloak.models.jpa.entities.UserGroupMembershipEntity</class>
<class>org.keycloak.models.jpa.entities.ClientTemplateEntity</class>
<!-- JpaAuditProviders -->
<class>org.keycloak.events.jpa.EventEntity</class>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -28,7 +28,8 @@ public class DefaultMongoUpdaterProvider implements MongoUpdaterProvider {
Update1_2_0_Beta1.class,
Update1_2_0_CR1.class,
Update1_3_0.class,
Update1_4_0.class
Update1_4_0.class,
Update1_7_0.class
};
@Override
@@ -0,0 +1,39 @@
package org.keycloak.connections.mongo.updater.impl.updates;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import org.keycloak.models.KeycloakSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class Update1_7_0 extends Update {
@Override
public String getId() {
return "1.7.0";
}
@Override
public void update(KeycloakSession session) throws ClassNotFoundException {
DBCollection clients = db.getCollection("clients");
DBCursor clientsCursor = clients.find();
try {
while (clientsCursor.hasNext()) {
BasicDBObject client = (BasicDBObject) clientsCursor.next();
boolean directGrantsOnly = client.getBoolean("directGrantsOnly", false);
client.append("standardFlowEnabled", !directGrantsOnly);
client.append("implicitFlowEnabled", false);
client.append("directAccessGrantsEnabled", directGrantsOnly);
client.removeField("directGrantsOnly");
clients.save(client);
}
} finally {
clientsCursor.close();
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,11 +1,12 @@
package org.keycloak.connections.mongo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import java.lang.reflect.Method;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.net.ssl.SSLSocketFactory;
import org.jboss.logging.Logger;
import org.keycloak.Config;
@@ -15,24 +16,26 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati
import org.keycloak.connections.mongo.updater.MongoUpdaterProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
import javax.net.ssl.SSLSocketFactory;
import java.lang.reflect.Method;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoClientURI;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory {
// TODO Make it dynamic
private String[] entities = new String[]{
"org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoUserEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoGroupEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoClientEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity",
"org.keycloak.models.mongo.keycloak.entities.MongoMigrationModelEntity",
@@ -1,9 +1,9 @@
package org.keycloak.connections.mongo;
import org.keycloak.provider.ServerInfoAwareProviderFactory;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
}
+1 -2
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
</parent>
<name>Connections Parent</name>
<description/>
@@ -17,7 +17,6 @@
<module>jpa-liquibase</module>
<module>infinispan</module>
<module>mongo</module>
<module>file</module>
<module>mongo-update</module>
<module>http-client</module>
</modules>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -27,6 +27,8 @@ public interface OAuth2Constants {
String AUTHORIZATION_CODE = "authorization_code";
String IMPLICIT = "implicit";
String PASSWORD = "password";
String CLIENT_CREDENTIALS = "client_credentials";
@@ -2,6 +2,7 @@ package org.keycloak;
import org.keycloak.common.VerificationException;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.representations.AccessToken;
import org.keycloak.util.TokenUtil;
@@ -22,7 +23,7 @@ public class RSATokenVerifier {
JWSInput input = null;
try {
input = new JWSInput(tokenString);
} catch (Exception e) {
} catch (JWSInputException e) {
throw new VerificationException("Couldn't parse token", e);
}
if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
@@ -30,7 +31,7 @@ public class RSATokenVerifier {
AccessToken token;
try {
token = input.readJsonContent(AccessToken.class);
} catch (IOException e) {
} catch (JWSInputException e) {
throw new VerificationException("Couldn't parse token signature", e);
}
String user = token.getSubject();
@@ -21,14 +21,14 @@ public class JWSInput {
byte[] signature;
public JWSInput(String wire) {
this.wireString = wire;
String[] parts = wire.split("\\.");
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
encodedHeader = parts[0];
encodedContent = parts[1];
encodedSignatureInput = encodedHeader + '.' + encodedContent;
public JWSInput(String wire) throws JWSInputException {
try {
this.wireString = wire;
String[] parts = wire.split("\\.");
if (parts.length < 2 || parts.length > 3) throw new IllegalArgumentException("Parsing error");
encodedHeader = parts[0];
encodedContent = parts[1];
encodedSignatureInput = encodedHeader + '.' + encodedContent;
content = Base64Url.decode(encodedContent);
if (parts.length > 2) {
encodedSignature = parts[2];
@@ -37,8 +37,8 @@ public class JWSInput {
}
byte[] headerBytes = Base64Url.decode(encodedHeader);
header = JsonSerialization.readValue(headerBytes, JWSHeader.class);
} catch (Exception e) {
throw new RuntimeException(e);
} catch (Throwable t) {
throw new JWSInputException(t);
}
}
@@ -80,8 +80,12 @@ public class JWSInput {
return header.getAlgorithm().getProvider().verify(this, key);
}
public <T> T readJsonContent(Class<T> type) throws IOException {
return JsonSerialization.readValue(content, type);
public <T> T readJsonContent(Class<T> type) throws JWSInputException {
try {
return JsonSerialization.readValue(content, type);
} catch (IOException e) {
throw new JWSInputException(e);
}
}
public String readContentAsString() {
@@ -0,0 +1,18 @@
package org.keycloak.jose.jws;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JWSInputException extends Exception {
public JWSInputException(String s) {
super(s);
}
public JWSInputException() {
}
public JWSInputException(Throwable throwable) {
super(throwable);
}
}
@@ -64,7 +64,7 @@ public class RSAProvider implements SignatureProvider {
verifier.update(input.getEncodedSignatureInput().getBytes("UTF-8"));
return verifier.verify(input.getSignature());
} catch (Exception e) {
throw new RuntimeException(e);
return false;
}
}
@@ -28,6 +28,7 @@ public class RefreshToken extends AccessToken {
this.subject = token.subject;
this.issuedFor = token.issuedFor;
this.sessionState = token.sessionState;
this.nonce = token.nonce;
if (token.realmAccess != null) {
realmAccess = token.realmAccess.clone();
}
@@ -0,0 +1,36 @@
package org.keycloak.representations.idm;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientInitialAccessCreatePresentation {
private Integer expiration;
private Integer count;
public ClientInitialAccessCreatePresentation() {
}
public ClientInitialAccessCreatePresentation(Integer expiration, Integer count) {
this.expiration = expiration;
this.count = count;
}
public Integer getExpiration() {
return expiration;
}
public void setExpiration(Integer expiration) {
this.expiration = expiration;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
@@ -0,0 +1,67 @@
package org.keycloak.representations.idm;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientInitialAccessPresentation {
private String id;
private String token;
private Integer timestamp;
private Integer expiration;
private Integer count;
private Integer remainingCount;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Integer getTimestamp() {
return timestamp;
}
public void setTimestamp(Integer timestamp) {
this.timestamp = timestamp;
}
public Integer getExpiration() {
return expiration;
}
public void setExpiration(Integer expiration) {
this.expiration = expiration;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public Integer getRemainingCount() {
return remainingCount;
}
public void setRemainingCount(Integer remainingCount) {
this.remainingCount = remainingCount;
}
}
@@ -19,13 +19,18 @@ public class ClientRepresentation {
protected Boolean enabled;
protected String clientAuthenticatorType;
protected String secret;
protected String registrationAccessToken;
protected String[] defaultRoles;
protected List<String> redirectUris;
protected List<String> webOrigins;
protected Integer notBefore;
protected Boolean bearerOnly;
protected Boolean consentRequired;
protected Boolean standardFlowEnabled;
protected Boolean implicitFlowEnabled;
protected Boolean directAccessGrantsEnabled;
protected Boolean serviceAccountsEnabled;
@Deprecated
protected Boolean directGrantsOnly;
protected Boolean publicClient;
protected Boolean frontchannelLogout;
@@ -35,6 +40,7 @@ public class ClientRepresentation {
protected Integer nodeReRegistrationTimeout;
protected Map<String, Integer> registeredNodes;
protected List<ProtocolMapperRepresentation> protocolMappers;
protected String clientTemplate;
public String getId() {
return id;
@@ -124,6 +130,14 @@ public class ClientRepresentation {
this.secret = secret;
}
public String getRegistrationAccessToken() {
return registrationAccessToken;
}
public void setRegistrationAccessToken(String registrationAccessToken) {
this.registrationAccessToken = registrationAccessToken;
}
public List<String> getRedirectUris() {
return redirectUris;
}
@@ -172,6 +186,30 @@ public class ClientRepresentation {
this.consentRequired = consentRequired;
}
public Boolean isStandardFlowEnabled() {
return standardFlowEnabled;
}
public void setStandardFlowEnabled(Boolean standardFlowEnabled) {
this.standardFlowEnabled = standardFlowEnabled;
}
public Boolean isImplicitFlowEnabled() {
return implicitFlowEnabled;
}
public void setImplicitFlowEnabled(Boolean implicitFlowEnabled) {
this.implicitFlowEnabled = implicitFlowEnabled;
}
public Boolean isDirectAccessGrantsEnabled() {
return directAccessGrantsEnabled;
}
public void setDirectAccessGrantsEnabled(Boolean directAccessGrantsEnabled) {
this.directAccessGrantsEnabled = directAccessGrantsEnabled;
}
public Boolean isServiceAccountsEnabled() {
return serviceAccountsEnabled;
}
@@ -180,6 +218,7 @@ public class ClientRepresentation {
this.serviceAccountsEnabled = serviceAccountsEnabled;
}
@Deprecated
public Boolean isDirectGrantsOnly() {
return directGrantsOnly;
}
@@ -251,4 +290,12 @@ public class ClientRepresentation {
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public String getClientTemplate() {
return clientTemplate;
}
public void setClientTemplate(String clientTemplate) {
this.clientTemplate = clientTemplate;
}
}
@@ -0,0 +1,61 @@
package org.keycloak.representations.idm;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClientTemplateRepresentation {
/**
* Use this value in ClientRepresentation.setClientTemplate when you want to clear this value
*/
public static final String NONE = "NONE";
protected String id;
protected String name;
protected String description;
protected String protocol;
protected List<ProtocolMapperRepresentation> protocolMappers;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<ProtocolMapperRepresentation> getProtocolMappers() {
return protocolMappers;
}
public void setProtocolMappers(List<ProtocolMapperRepresentation> protocolMappers) {
this.protocolMappers = protocolMappers;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
}
@@ -29,7 +29,7 @@ public class CredentialRepresentation {
private Integer period;
// only used when updating a credential. Might set required action
protected boolean temporary;
protected Boolean temporary;
public String getType() {
return type;
@@ -79,11 +79,11 @@ public class CredentialRepresentation {
this.hashIterations = hashIterations;
}
public boolean isTemporary() {
public Boolean isTemporary() {
return temporary;
}
public void setTemporary(boolean temporary) {
public void setTemporary(Boolean temporary) {
this.temporary = temporary;
}
@@ -0,0 +1,85 @@
package org.keycloak.representations.idm;
import org.codehaus.jackson.annotate.JsonIgnore;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class GroupRepresentation {
protected String id;
protected String name;
protected String path;
protected Map<String, List<String>> attributes;
protected List<String> realmRoles;
protected Map<String, List<String>> clientRoles;
protected List<GroupRepresentation> subGroups;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public List<String> getRealmRoles() {
return realmRoles;
}
public void setRealmRoles(List<String> realmRoles) {
this.realmRoles = realmRoles;
}
public Map<String, List<String>> getClientRoles() {
return clientRoles;
}
public void setClientRoles(Map<String, List<String>> clientRoles) {
this.clientRoles = clientRoles;
}
public Map<String, List<String>> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, List<String>> attributes) {
this.attributes = attributes;
}
public GroupRepresentation singleAttribute(String name, String value) {
if (this.attributes == null) attributes = new HashMap<>();
attributes.put(name, Arrays.asList(value));
return this;
}
public List<GroupRepresentation> getSubGroups() {
return subGroups;
}
public void setSubGroups(List<GroupRepresentation> subGroups) {
this.subGroups = subGroups;
}
}
@@ -46,12 +46,15 @@ public class IdentityProviderRepresentation {
* @see #UPFLM_MISSING
* @see #UPFLM_OFF
*/
@Deprecated
protected String updateProfileFirstLoginMode = UPFLM_ON;
protected boolean trustEmail;
protected boolean storeToken;
protected boolean addReadTokenRoleOnCreate;
protected boolean authenticateByDefault;
protected String firstBrokerLoginFlowAlias;
protected String postBrokerLoginFlowAlias;
protected Map<String, String> config = new HashMap<String, String>();
public String getInternalId() {
@@ -106,15 +109,17 @@ public class IdentityProviderRepresentation {
}
/**
* @return see {@link #updateProfileFirstLoginMode}
* @deprecated deprecated and replaced by configuration on IdpReviewProfileAuthenticator
*/
@Deprecated
public String getUpdateProfileFirstLoginMode() {
return updateProfileFirstLoginMode;
}
/**
* @param updateProfileFirstLoginMode see {@link #updateProfileFirstLoginMode}
* @deprecated deprecated and replaced by configuration on IdpReviewProfileAuthenticator
*/
@Deprecated
public void setUpdateProfileFirstLoginMode(String updateProfileFirstLoginMode) {
this.updateProfileFirstLoginMode = updateProfileFirstLoginMode;
}
@@ -127,6 +132,22 @@ public class IdentityProviderRepresentation {
this.authenticateByDefault = authenticateByDefault;
}
public String getFirstBrokerLoginFlowAlias() {
return firstBrokerLoginFlowAlias;
}
public void setFirstBrokerLoginFlowAlias(String firstBrokerLoginFlowAlias) {
this.firstBrokerLoginFlowAlias = firstBrokerLoginFlowAlias;
}
public String getPostBrokerLoginFlowAlias() {
return postBrokerLoginFlowAlias;
}
public void setPostBrokerLoginFlowAlias(String postBrokerLoginFlowAlias) {
this.postBrokerLoginFlowAlias = postBrokerLoginFlowAlias;
}
public boolean isStoreToken() {
return this.storeToken;
}
@@ -12,6 +12,7 @@ public class RealmRepresentation {
protected Integer notBefore;
protected Boolean revokeRefreshToken;
protected Integer accessTokenLifespan;
protected Integer accessTokenLifespanForImplicitFlow;
protected Integer ssoSessionIdleTimeout;
protected Integer ssoSessionMaxLifespan;
protected Integer offlineSessionIdleTimeout;
@@ -47,7 +48,9 @@ public class RealmRepresentation {
protected String certificate;
protected String codeSecret;
protected RolesRepresentation roles;
protected List<GroupRepresentation> groups;
protected List<String> defaultRoles;
protected List<String> defaultGroups;
@Deprecated
protected Set<String> requiredCredentials;
protected String passwordPolicy;
@@ -62,6 +65,7 @@ public class RealmRepresentation {
protected List<ScopeMappingRepresentation> scopeMappings;
protected Map<String, List<ScopeMappingRepresentation>> clientScopeMappings;
protected List<ClientRepresentation> clients;
protected List<ClientTemplateRepresentation> clientTemplates;
protected Map<String, String> browserSecurityHeaders;
protected Map<String, String> smtpServer;
protected List<UserFederationProviderRepresentation> userFederationProviders;
@@ -82,6 +86,7 @@ public class RealmRepresentation {
private List<IdentityProviderRepresentation> identityProviders;
private List<IdentityProviderMapperRepresentation> identityProviderMappers;
private List<ProtocolMapperRepresentation> protocolMappers;
@Deprecated
private Boolean identityFederationEnabled;
protected Boolean internationalizationEnabled;
protected Set<String> supportedLocales;
@@ -184,6 +189,14 @@ public class RealmRepresentation {
this.accessTokenLifespan = accessTokenLifespan;
}
public Integer getAccessTokenLifespanForImplicitFlow() {
return accessTokenLifespanForImplicitFlow;
}
public void setAccessTokenLifespanForImplicitFlow(Integer accessTokenLifespanForImplicitFlow) {
this.accessTokenLifespanForImplicitFlow = accessTokenLifespanForImplicitFlow;
}
public Integer getSsoSessionIdleTimeout() {
return ssoSessionIdleTimeout;
}
@@ -268,6 +281,14 @@ public class RealmRepresentation {
this.defaultRoles = defaultRoles;
}
public List<String> getDefaultGroups() {
return defaultGroups;
}
public void setDefaultGroups(List<String> defaultGroups) {
this.defaultGroups = defaultGroups;
}
public String getPrivateKey() {
return privateKey;
}
@@ -603,6 +624,7 @@ public class RealmRepresentation {
identityProviders.add(identityProviderRepresentation);
}
@Deprecated
public boolean isIdentityFederationEnabled() {
return identityProviders != null && !identityProviders.isEmpty();
}
@@ -775,4 +797,20 @@ public class RealmRepresentation {
public void setClientAuthenticationFlow(String clientAuthenticationFlow) {
this.clientAuthenticationFlow = clientAuthenticationFlow;
}
public List<GroupRepresentation> getGroups() {
return groups;
}
public void setGroups(List<GroupRepresentation> groups) {
this.groups = groups;
}
public List<ClientTemplateRepresentation> getClientTemplates() {
return clientTemplates;
}
public void setClientTemplates(List<ClientTemplateRepresentation> clientTemplates) {
this.clientTemplates = clientTemplates;
}
}
@@ -17,9 +17,9 @@ public class UserRepresentation {
protected String id;
protected Long createdTimestamp;
protected String username;
protected boolean enabled;
protected boolean totp;
protected boolean emailVerified;
protected Boolean enabled;
protected Boolean totp;
protected Boolean emailVerified;
protected String firstName;
protected String lastName;
protected String email;
@@ -40,6 +40,8 @@ public class UserRepresentation {
@Deprecated
protected List<SocialLinkRepresentation> socialLinks;
protected List<String> groups;
public String getSelf() {
return self;
}
@@ -96,27 +98,27 @@ public class UserRepresentation {
this.username = username;
}
public boolean isEnabled() {
public Boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public boolean isTotp() {
public Boolean isTotp() {
return totp;
}
public void setTotp(boolean totp) {
public void setTotp(Boolean totp) {
this.totp = totp;
}
public boolean isEmailVerified() {
public Boolean isEmailVerified() {
return emailVerified;
}
public void setEmailVerified(boolean emailVerified) {
public void setEmailVerified(Boolean emailVerified) {
this.emailVerified = emailVerified;
}
@@ -216,4 +218,12 @@ public class UserRepresentation {
public void setServiceAccountClientId(String serviceAccountClientId) {
this.serviceAccountClientId = serviceAccountClientId;
}
public List<String> getGroups() {
return groups;
}
public void setGroups(List<String> groups) {
this.groups = groups;
}
}
@@ -1,45 +0,0 @@
package org.keycloak.representations.idm;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserRoleMappingRepresentation {
protected String self; // link
protected String username;
protected Set<String> roles;
public String getSelf() {
return self;
}
public void setSelf(String self) {
this.self = self;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public UserRoleMappingRepresentation role(String role) {
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
}
@@ -1,15 +1,25 @@
package org.keycloak.services.resources.admin.info;
package org.keycloak.representations.info;
public class MemoryInfoRepresentation {
protected long total;
protected String totalFormated;
protected long used;
protected String usedFormated;
protected long free;
protected long freePercentage;
protected String freeFormated;
public static MemoryInfoRepresentation create() {
MemoryInfoRepresentation rep = new MemoryInfoRepresentation();
Runtime runtime = Runtime.getRuntime();
rep.total = runtime.maxMemory();
rep.totalFormated = formatMemory(rep.total);
rep.used = runtime.totalMemory() - runtime.freeMemory();
rep.usedFormated = formatMemory(rep.used);
rep.free = rep.total - rep.used;
rep.freeFormated = formatMemory(rep.free);
rep.freePercentage = rep.free * 100 / rep.total;
return rep;
}
@@ -18,15 +28,15 @@ public class MemoryInfoRepresentation {
}
public String getTotalFormated() {
return formatMemory(getTotal());
return totalFormated;
}
public long getFree() {
return getTotal() - getUsed();
return free;
}
public String getFreeFormated() {
return formatMemory(getFree());
return freeFormated;
}
public long getUsed() {
@@ -34,14 +44,14 @@ public class MemoryInfoRepresentation {
}
public String getUsedFormated() {
return formatMemory(getUsed());
return usedFormated;
}
public long getFreePercentage() {
return getFree() * 100 / getTotal();
return freePercentage;
}
private String formatMemory(long bytes) {
private static String formatMemory(long bytes) {
if (bytes > 1024L * 1024L) {
return bytes / (1024L * 1024L) + " MB";
} else if (bytes > 1024L) {
@@ -1,4 +1,4 @@
package org.keycloak.services.resources.admin.info;
package org.keycloak.representations.info;
import java.util.Map;
@@ -1,4 +1,4 @@
package org.keycloak.services.resources.admin.info;
package org.keycloak.representations.info;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
@@ -1,4 +1,4 @@
package org.keycloak.services.resources.admin.info;
package org.keycloak.representations.info;
import java.util.Map;
@@ -8,7 +8,6 @@ import java.util.Map;
public class SpiInfoRepresentation {
private boolean internal;
private boolean systemInfo;
private Map<String, ProviderRepresentation> providers;
@@ -20,14 +19,6 @@ public class SpiInfoRepresentation {
this.internal = internal;
}
public boolean isSystemInfo() {
return systemInfo;
}
public void setSystemInfo(boolean systemInfo) {
this.systemInfo = systemInfo;
}
public Map<String, ProviderRepresentation> getProviders() {
return providers;
}
@@ -1,7 +1,6 @@
package org.keycloak.services.resources.admin.info;
package org.keycloak.representations.info;
import org.keycloak.common.Version;
import org.keycloak.models.KeycloakSession;
import java.util.Date;
import java.util.Locale;
@@ -27,11 +26,11 @@ public class SystemInfoRepresentation {
private String userTimezone;
private String userLocale;
public static SystemInfoRepresentation create(KeycloakSession session) {
public static SystemInfoRepresentation create(long serverStartupTime) {
SystemInfoRepresentation rep = new SystemInfoRepresentation();
rep.version = Version.VERSION;
rep.serverTime = new Date().toString();
rep.uptimeMillis = System.currentTimeMillis() - session.getKeycloakSessionFactory().getServerStartupTimestamp();
rep.uptimeMillis = System.currentTimeMillis() - serverStartupTime;
rep.uptime = formatUptime(rep.uptimeMillis);
rep.javaVersion = System.getProperty("java.version");
rep.javaVendor = System.getProperty("java.vendor");
@@ -0,0 +1,223 @@
package org.keycloak.representations.oidc;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
public class OIDCClientRepresentation {
private List<String> redirect_uris;
private String token_endpoint_auth_method;
private List<String> grant_types;
private List<String> response_types;
private String client_id;
private String client_secret;
private String client_name;
private String client_uri;
private String logo_uri;
private String scope;
private String contacts;
private String tos_uri;
private String policy_uri;
private String jwks_uri;
private String jwks;
private String software_id;
private String software_version;
private Integer client_id_issued_at;
private Integer client_secret_expires_at;
private String registration_client_uri;
private String registration_access_token;
public List<String> getRedirectUris() {
return redirect_uris;
}
public void setRedirectUris(List<String> redirectUris) {
this.redirect_uris = redirectUris;
}
public String getTokenEndpointAuthMethod() {
return token_endpoint_auth_method;
}
public void setTokenEndpointAuthMethod(String token_endpoint_auth_method) {
this.token_endpoint_auth_method = token_endpoint_auth_method;
}
public List<String> getGrantTypes() {
return grant_types;
}
public void setGrantTypes(List<String> grantTypes) {
this.grant_types = grantTypes;
}
public List<String> getResponseTypes() {
return response_types;
}
public void setResponseTypes(List<String> responseTypes) {
this.response_types = responseTypes;
}
public String getClientId() {
return client_id;
}
public void setClientId(String clientId) {
this.client_id = clientId;
}
public String getClientSecret() {
return client_secret;
}
public void setClientSecret(String clientSecret) {
this.client_secret = clientSecret;
}
public String getClientName() {
return client_name;
}
public void setClientName(String client_name) {
this.client_name = client_name;
}
public String getClientUri() {
return client_uri;
}
public void setClientUri(String client_uri) {
this.client_uri = client_uri;
}
public String getLogoUri() {
return logo_uri;
}
public void setLogoUri(String logo_uri) {
this.logo_uri = logo_uri;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getContacts() {
return contacts;
}
public void setContacts(String contacts) {
this.contacts = contacts;
}
public String getTosUri() {
return tos_uri;
}
public void setTosUri(String tos_uri) {
this.tos_uri = tos_uri;
}
public String getPolicyUri() {
return policy_uri;
}
public void setPolicyUri(String policy_uri) {
this.policy_uri = policy_uri;
}
public String getJwksUri() {
return jwks_uri;
}
public void setJwksUri(String jwks_uri) {
this.jwks_uri = jwks_uri;
}
public String getJwks() {
return jwks;
}
public void setJwks(String jwks) {
this.jwks = jwks;
}
public String getSoftwareId() {
return software_id;
}
public void setSoftwareId(String softwareId) {
this.software_id = softwareId;
}
public String getSoftwareVersion() {
return software_version;
}
public void setSoftwareVersion(String softwareVersion) {
this.software_version = softwareVersion;
}
public Integer getClientIdIssuedAt() {
return client_id_issued_at;
}
public void setClientIdIssuedAt(Integer clientIdIssuedAt) {
this.client_id_issued_at = clientIdIssuedAt;
}
public Integer getClientSecretExpiresAt() {
return client_secret_expires_at;
}
public void setClientSecretExpiresAt(Integer client_secret_expires_at) {
this.client_secret_expires_at = client_secret_expires_at;
}
public String getRegistrationClientUri() {
return registration_client_uri;
}
public void setRegistrationClientUri(String registrationClientUri) {
this.registration_client_uri = registrationClientUri;
}
public String getRegistrationAccessToken() {
return registration_access_token;
}
public void setRegistrationAccessToken(String registrationAccessToken) {
this.registration_access_token = registrationAccessToken;
}
}
@@ -3,6 +3,7 @@ package org.keycloak.util;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.type.TypeReference;
import java.io.IOException;
import java.io.InputStream;
@@ -27,7 +28,10 @@ public class JsonSerialization {
public static void writeValueToStream(OutputStream os, Object obj) throws IOException {
mapper.writeValue(os, obj);
}
public static void writeValuePrettyToStream(OutputStream os, Object obj) throws IOException {
prettyMapper.writeValue(os, obj);
}
public static String writeValueAsPrettyString(Object obj) throws IOException {
@@ -53,6 +57,10 @@ public class JsonSerialization {
return readValue(bytes, type, false);
}
public static <T> T readValue(InputStream bytes, TypeReference<T> type) throws IOException {
return mapper.readValue(bytes, type);
}
public static <T> T readValue(InputStream bytes, Class<T> type, boolean replaceSystemProperties) throws IOException {
if (replaceSystemProperties) {
return sysPropertiesAwareMapper.readValue(bytes, type);
@@ -4,6 +4,7 @@ import java.io.IOException;
import org.keycloak.OAuth2Constants;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.representations.RefreshToken;
/**
@@ -19,6 +20,7 @@ public class TokenUtil {
public static final String TOKEN_TYPE_OFFLINE = "Offline";
public static boolean isOfflineTokenRequested(String scopeParam) {
if (scopeParam == null) {
return false;
@@ -40,11 +42,15 @@ public class TokenUtil {
* @param decodedToken
* @return
*/
public static RefreshToken getRefreshToken(byte[] decodedToken) throws IOException {
return JsonSerialization.readValue(decodedToken, RefreshToken.class);
public static RefreshToken getRefreshToken(byte[] decodedToken) throws JWSInputException {
try {
return JsonSerialization.readValue(decodedToken, RefreshToken.class);
} catch (IOException e) {
throw new JWSInputException(e);
}
}
public static RefreshToken getRefreshToken(String refreshToken) throws IOException {
public static RefreshToken getRefreshToken(String refreshToken) throws JWSInputException {
byte[] encodedContent = new JWSInput(refreshToken).getContent();
return getRefreshToken(encodedContent);
}
@@ -55,13 +61,9 @@ public class TokenUtil {
* @param refreshToken
* @return
*/
public static boolean isOfflineToken(String refreshToken) {
try {
RefreshToken token = getRefreshToken(refreshToken);
return token.getType().equals(TOKEN_TYPE_OFFLINE);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
public static boolean isOfflineToken(String refreshToken) throws JWSInputException {
RefreshToken token = getRefreshToken(refreshToken);
return token.getType().equals(TOKEN_TYPE_OFFLINE);
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -36,10 +36,6 @@
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-file</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-sessions-infinispan</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.6.0.Final-SNAPSHOT</version>
<version>1.8.0.Alpha1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
Loaded 100 of 1362 files, more files were not shown because too many files have changed in this diff. Show more