Compare commits

..
Author SHA1 Message Date
Lukas Kubik fb1b7dce00 Add excluded marshalling 2016-01-15 22:42:55 +01:00
Lukas Kubik 88aef967fe Downgrade infinspan version 2016-01-15 16:45:16 +01:00
Lukas Kubik 9f5f3a924c Disable testsuite module 2016-01-15 15:21:31 +01:00
Lukas Kubik 94be25a203 Bump the eap6-server-dist version 2016-01-15 15:11:07 +01:00
Lukas Kubik 4291a2c9f0 Temporarily add back the keycloak theme. 2016-01-15 15:08:35 +01:00
Lukas Kubik e9beb83955 Apply branding 2016-01-15 14:50:33 +01:00
Lukas Kubik 971fc8798a Add EAP 6 server dist module
Add IAM module to eap6-server-dist

KPR-144
Localhost:8080 should show IAM/Keycloak product console, not EAP console
2016-01-15 14:50:32 +01:00
Lukas Kubik f39e6b45cc Remove unsported ldap servers 2016-01-15 14:50:32 +01:00
Lukas Kubik 4af907295a Remove mongo modules and related dependencies 2016-01-15 14:50:32 +01:00
Lukas Kubik 7190030e16 Exclude stax-api and replace relaxngDataType with redhat version 2016-01-15 14:50:32 +01:00
Lukas Kubik 8e6f7b558d Replace JSR250 with jboss-annotations-api_1.1_spec 2016-01-15 14:50:32 +01:00
Lukas Kubik fad8b2ab75 Prod changes
KPR-145
Remove keycloak-as7-adapter-dist zip from the distribution zip files

KPR-146
Remove keycloak-jetty81-adapter-dist zip from the distribution zip files
2016-01-15 14:50:32 +01:00
keycloak-bot 2c65361943 Set version to 1.8.0.CR1 2016-01-13 08:22:50 +00:00
Stian Thorgersen 75d715d8a7 Merge pull request #2015 from stianst/master
Remove reference to built-in admin account from docs
2016-01-13 09:03:15 +01:00
Stian Thorgersen 62b90ee4e3 Remove reference to built-in admin account from docs 2016-01-13 09:02:52 +01:00
Stian Thorgersen 2f88868e20 Merge pull request #2014 from ssilvert/KEYCLOAK-2294-pi-testrealm
KEYCLOAK-2294 Partial import can fail with 'Removing a detached insta…
2016-01-13 08:37:49 +01:00
Stan Silvert b0de77013c KEYCLOAK-2294 Partial import can fail with 'Removing a detached instance' 2016-01-12 15:46:48 -05:00
Stian Thorgersen 25cd3e3ba8 Merge pull request #2013 from stianst/master
KEYCLOAK-2298
2016-01-12 20:31:37 +01:00
Stian Thorgersen 1b0bf966b6 KEYCLOAK-2298
Demo doesn't have add-user-keycloak.bat
2016-01-12 19:46:34 +01:00
Marek Posolda d8e28ad96b Merge pull request #2012 from mposolda/master
KEYCLOAK-2290 Migration fixes. Bulk update of algorithm field during migration
2016-01-12 18:49:34 +01:00
mposolda 3336d4d7ac KEYCLOAK-2290 bulk update of algorithm field during migration from 1.7 2016-01-12 18:04:50 +01:00
Stian Thorgersen ee3a880a55 Merge pull request #1999 from pedroigor/KEYCLOAK-2266
[KEYCLOAK-2266] - OAuth2 Token Introspection.
2016-01-12 15:37:41 +01:00
Pedro Igor c9f9ee9799 [KEYCLOAK-2266] - OAuth2 Token Introspection. 2016-01-12 11:16:42 -02:00
Marek Posolda 0536f2c247 Merge pull request #2010 from mposolda/master
KEYCLOAK-2229 Fix NoClassDefFoundError when IdpEmailVerificationAuthe…
2016-01-12 11:31:16 +01:00
mposolda 6f262423f1 KEYCLOAK-2229 Fix NoClassDefFoundError when IdpEmailVerificationAuthenticator is used for link accounts during first broker login 2016-01-12 10:37:44 +01:00
Stian Thorgersen 3c5e7872a7 Merge pull request #2009 from stianst/master
KEYCLOAK-2290
2016-01-12 10:32:22 +01:00
Stian Thorgersen 421dc6043d KEYCLOAK-2290
Migration: empty algorithm field on user credentials of type 'password'
2016-01-12 09:46:35 +01:00
Stian Thorgersen 9402f89d8e Merge pull request #2008 from stianst/master
KEYCLOAK-2229
2016-01-12 09:18:57 +01:00
Stian Thorgersen 81a0135fa6 KEYCLOAK-2229
First broker login throws NoClassDefFoundError: org/keycloak/broker/provider/BrokeredIdentityContext
2016-01-12 09:18:03 +01:00
Bill Burke 43dc250bf2 Merge pull request #2006 from thomasdarimont/issue/KEYCLOAK-2040-Conditional-OTP-Authentication
KEYCLOAK-2040 - Add support for Conditional OTP auth.
2016-01-11 14:56:48 -05:00
Marek Posolda bc3222ab67 Merge pull request #2007 from mposolda/master
Fix DB tests. Cleanup after AddUserTest
2016-01-11 18:56:56 +01:00
mposolda e761d6ce10 Fix DB tests. Cleanup after AddUserTest 2016-01-11 18:00:56 +01:00
Thomas Darimont 46991764d4 KEYCLOAK-2040 - Add support for Conditional OTP auth.
Previously it was not possible to conditionally show a OTP authentication
form. This PR adds support to conditionally require OTP authentication
based on a custom user attribute, a role, a request header pattern
(with black- and whitelisting) as well as a configurable default in
case no condition matches.
2016-01-11 17:39:42 +01:00
Stian Thorgersen 747c0f9869 Merge pull request #2004 from stianst/master
KEYCLOAK-2288
2016-01-11 17:32:38 +01:00
Marek Posolda 5424cd80a8 Merge pull request #2005 from mposolda/master
Fix MySQL - fixing transactions during bootstrap
2016-01-11 17:02:08 +01:00
Stian Thorgersen 8d2becf681 Fix import of com.mongodb.util.MyAsserts.assertFalse 2016-01-11 15:47:09 +01:00
mposolda c3f69fdc54 Fix MySQL - fixing transactions during bootstrap 2016-01-11 15:31:45 +01:00
Stian Thorgersen 45215f361f KEYCLOAK-2288
Upgrade Mongo driver version to 3.2.0
2016-01-11 15:10:00 +01:00
Stian Thorgersen 802488cea0 Merge pull request #2003 from mposolda/master
Fix mongo model
2016-01-11 13:58:06 +01:00
Stian Thorgersen 3ac3d79e30 Merge pull request #2002 from stianst/master
KEYCLOAK-2284
2016-01-11 13:22:44 +01:00
mposolda fe8755d4a4 Fix mongo model 2016-01-11 13:00:56 +01:00
Stian Thorgersen e2b889d727 KEYCLOAK-2284
Setup of background tasks doesn't close KeycloakSession
2016-01-11 11:41:36 +01:00
Stian Thorgersen 2ec4cb82cc Merge pull request #2001 from stianst/master
KEYCLOAK-2278
2016-01-11 11:41:15 +01:00
Stian Thorgersen bc14cade62 KEYCLOAK-2278
NoSuchMethodError org.infinispan.Cache.entrySet() in EAP6 server overlay
2016-01-11 10:07:04 +01:00
Stian Thorgersen a6c852603e Merge pull request #2000 from mstruk/truststore
KEYCLOAK-1717 Truststore SPI and file provider
2016-01-11 09:24:53 +01:00
Stian Thorgersen f1602b3b8d Merge pull request #1998 from ssilvert/partial-import
KEYCLOAK-1979: Partial import
2016-01-11 09:22:09 +01:00
Stian Thorgersen 7c8bc5814e Merge pull request #1990 from raehalme/KEYCLOAK-2257
KEYCLOAK-2257: Store user attribute when accepting terms and conditions
2016-01-11 09:03:58 +01:00
Stian Thorgersen 33f83689d5 Merge pull request #1995 from stianst/master
Add test to create user, set password and login using admin endpoints
2016-01-11 09:01:44 +01:00
Marko Strukelj 80e2b8eb39 KEYCLOAK-1717 Truststore SPI and file provider 2016-01-10 12:39:30 +01:00
Stan Silvert fbff61bfba For overwrite, do all deletes, then all adds.
Minor UI enhancements.
Fix 2 JPA bugs.
General cleanup.
Documentation.
2016-01-08 13:45:22 -05:00
Bill Burke ba1a17e668 Merge pull request #1997 from patriot1burke/master
KEYCLOAK-2189
2016-01-08 12:05:50 -05:00
Bill Burke 7bc7510d1b KEYCLOAK-2189 2016-01-08 12:05:43 -05:00
Bill Burke dc337d684a improve client creation when template 2016-01-08 11:40:46 -05:00
Bill Burke 0f9d50924c Merge pull request #1996 from patriot1burke/master
improve client creation when template
2016-01-08 11:40:45 -05:00
Stian Thorgersen cf0eb1184a Add test to create user, set password and login using admin endpoints 2016-01-08 16:37:01 +01:00
Stian Thorgersen ecd31010fe Merge pull request #1994 from stianst/KEYCLOAK-2259
KEYCLOAK-2259
2016-01-08 16:36:12 +01:00
Stian Thorgersen 0985d3c88a Merge pull request #1993 from stianst/master
KEYCLOAK-2276
2016-01-08 16:35:56 +01:00
Stian Thorgersen ddd99c2411 KEYCLOAK-2259
Redirect URIs and token domains are matched case-sensitively
2016-01-08 15:38:00 +01:00
Stian Thorgersen 7834637749 KEYCLOAK-2276
Login page doesn't render properly when window height is less than 550px
2016-01-08 15:19:59 +01:00
Stian Thorgersen a90d7e54d4 Merge pull request #1992 from stianst/master
KEYCLOAK-2275
2016-01-08 15:19:38 +01:00
Stian Thorgersen bae2b62200 KEYCLOAK-2275
No Content-Security-Policy meta tag found on Cordova 5.x
2016-01-08 14:34:52 +01:00
Stian Thorgersen 71bcf697cc Merge pull request #1991 from stianst/master
KEYCLOAK-2272
2016-01-08 14:34:31 +01:00
Stian Thorgersen 9acb4b86aa Add note that JDK8 is required to build and to run the server 2016-01-08 13:56:07 +01:00
Stian Thorgersen dee0be4237 KEYCLOAK-2272
Update keycloak-datasources.xml and keycloak-infinispan.xml
2016-01-08 13:39:49 +01:00
Thomas Raehalme c4544e8caf Like other timestamps attribute value is now seconds since 1970. 2016-01-08 14:21:43 +02:00
Thomas Raehalme bca3893070 Required action TermsAndConditions now stores user attribute indicating acceptance of terms and conditions. 2016-01-08 13:14:04 +02:00
Bill Burke 280725a2ae Merge pull request #1985 from patriot1burke/master
KEYCLOAK-1990 KEYCLOAK-1991
2016-01-07 18:24:31 -05:00
Bill Burke 2892b093ab Merge remote-tracking branch 'upstream/master' 2016-01-07 17:25:58 -05:00
Bill Burke 78fe064cf0 2213 2016-01-07 17:25:47 -05:00
Stian Thorgersen 30aaea73e4 Merge pull request #1989 from stianst/master
KEYCLOAK-2127 Re-enable set admin user with welcome page
2016-01-07 16:20:28 +01:00
Stian Thorgersen 4b1b697aa3 KEYCLOAK-2127 Re-enable set admin user with welcome page 2016-01-07 16:19:59 +01:00
Stian Thorgersen 112a44676d Merge pull request #1988 from stianst/KEYCLOAK-2269
KEYCLOAK-2269
2016-01-07 14:08:01 +01:00
Stian Thorgersen f7282d71e5 Merge pull request #1987 from stianst/master
KEYCLOAK-2252
2016-01-07 14:07:49 +01:00
Stian Thorgersen 9840c47970 Merge pull request #1986 from mhajas/master
KEYCLOAK-2127 Use add-user script for admin user creating
2016-01-07 13:17:47 +01:00
Stian Thorgersen 8695e16971 KEYCLOAK-2269
add-user script adds identityFederationEnabled field to keycloak-add-user.json
2016-01-07 13:17:10 +01:00
Stian Thorgersen 65f5ce9f13 KEYCLOAK-2252
Cannot delete client mapper with delete icon
2016-01-07 13:10:01 +01:00
Stian Thorgersen 77962ec896 Merge pull request #1984 from mstruk/providers-init
Prevent ProviderFactories being loaded twice
2016-01-07 11:57:12 +01:00
mhajas 54712e29aa Use user script for admin user creating 2016-01-07 11:24:51 +01:00
Bill Burke 71b6ed80ae Merge remote-tracking branch 'upstream/master' 2016-01-06 16:51:24 -05:00
Bill Burke 4a4bbf26f4 installation provider 2016-01-06 16:51:02 -05:00
Bill Burke 64de96d34b installation provider 2016-01-06 16:49:58 -05:00
Stian Thorgersen 084873f7fb Merge pull request #1981 from stianst/master
KEYCLOAK-2247 Upgrade to WildFly 10.0.0.CR5
2016-01-06 19:19:35 +01:00
Stian Thorgersen c684dac625 Tweak mem for Travis 2016-01-06 16:15:00 +01:00
Stian Thorgersen a5c159eeff KEYCLOAK-2247
Upgrade to WildFly 10.0.0.CR5
2016-01-06 16:15:00 +01:00
Bill Burke 1cbe5c4c80 Merge remote-tracking branch 'upstream/master' 2016-01-06 10:03:27 -05:00
Bill Burke 4a472b8272 KEYCLOAK-1990 KEYCLOAK-1991 2016-01-06 10:02:56 -05:00
Stian Thorgersen ddf74c0d9c Merge pull request #1983 from mstruk/ispn-conf
Fix missing offlineSessions local-cache config for demo-dist
2016-01-06 14:49:04 +01:00
Stian Thorgersen b2a3918fc3 Merge pull request #1982 from abstractj/KEYCLOAK-1919
Make use of display name by default for TOTP
2016-01-06 14:26:05 +01:00
Marko Strukelj aca00dd42c Prevent ProviderFactories being loaded twice 2016-01-05 23:07:13 +01:00
Marko Strukelj 2a8e868bc1 Fix missing offlineSession local-cache config for demo-dist 2016-01-05 22:56:44 +01:00
Stan Silvert 979205c827 Cleanup 2016-01-05 15:33:45 -05:00
Stan Silvert 55e36acfc0 For overwrite, delete then create.
Do all prepares to check for errors, then call doImport on each type.
Combine Realm Role and Client Role processing (RolesPartialImport).
2016-01-05 15:33:45 -05:00
Stan Silvert 4b6825806a Bare bones pagination for partial import results. 2016-01-05 15:33:44 -05:00
Stan Silvert 2d878805c1 Fix resource path for partial import events. 2016-01-05 15:33:43 -05:00
Stan Silvert dd038ddbd5 Add id to partial import results. 2016-01-05 15:33:43 -05:00
Stan Silvert f6a02bd408 Clean commit for partial import with single page for all imports. 2016-01-05 15:33:42 -05:00
Bruno Oliveira 7ec0dad88f Make use of display name by default for TOTP
- use realm name just in case of display name is not available
2016-01-05 18:31:13 -02:00
Marek Posolda 1e3ec1983d Merge pull request #1980 from mposolda/master
LDAP testing: added activation
2016-01-05 20:54:56 +01:00
mposolda 7ec02761ef LDAP testing: added activation 2016-01-05 20:53:25 +01:00
Bill Burke 7b30a6c9c4 Merge pull request #1979 from mposolda/master
Docs for LDAP mappers. Fix testsuite to pass with MSAD
2016-01-05 14:19:50 -05:00
Bill Burke 0d56713871 Merge pull request #1978 from patriot1burke/master
KEYCLOAK-2221
2016-01-05 14:19:33 -05:00
mposolda 658f204d92 Documentation for new LDAP mappers 2016-01-05 18:50:54 +01:00
mposolda 04401af470 Fix testsuite to pass with MSAD 2016-01-05 17:25:42 +01:00
Bill Burke 39d5a07218 KEYCLOAK-2221 2016-01-05 10:59:13 -05:00
Bill Burke a65f619c9a Merge pull request #1977 from mposolda/master
KEYCLOAK-2258 Removing leftovers of file model from docs and testsuite
2016-01-05 10:06:07 -05:00
Bill Burke 01c408ba68 Merge pull request #1975 from thomasdarimont/issue/KEYCLOAK-2256
KEYCLOAK-2256 - Guarantee deterministic ordering for custom user attributes in admin console.
2016-01-05 10:05:36 -05:00
Bill Burke 63975886cb Merge pull request #1974 from patriot1burke/master
set frameork for template config
2016-01-05 10:03:48 -05:00
Bill Burke c3f2ae1cd1 Merge pull request #1973 from thomasdarimont/issue/KEYCLOAK-2253
KEYCLOAK-2253 - Add support for ConfiguredProvider based UserFederationProviderFactory.
2016-01-05 10:03:40 -05:00
mposolda 133e4c59e5 KEYCLOAK-2258 Removing leftovers of file model from docs and testsuite 2016-01-05 15:25:22 +01:00
Marek Posolda d3247bc66a Merge pull request #1976 from mposolda/master
KEYCLOAK-2178 KEYCLOAK-1744 Added MSADUserAccountControlMapper. Remov…
2016-01-05 13:16:32 +01:00
mposolda b6718b44a1 KEYCLOAK-2178 KEYCLOAK-1744 Added MSADUserAccountControlMapper. Removing enableUserAccountControlAfterPasswordUpdate option 2016-01-05 12:11:48 +01:00
Thomas Darimont 15506e3db3 KEYCLOAK-2256 - Guarantee deterministic ordering for custom user attributes in admin console.
We now iterate over custom-user attributes in a deterministic way such that new attributes don't lead
to a complete reordering of the properties in the custom user attributes listings.
Previously the order of custom attributes in the user attributes listings was not deterministic which lead
to cases where keys that shared a common prefix where not placed at arbitrary positions.
Introduced a custom angularjs flter "toOrderedMapSortedByKey" that helps to deterministically iterate
over object properites.
2016-01-05 00:04:40 +01:00
Bill Burke 977f4051b3 Merge remote-tracking branch 'upstream/master' 2016-01-04 17:23:15 -05:00
Bill Burke 49c15f200e Merge pull request #1972 from dbarentine/master
KEYCLOAK-2255 Location header should return IdP alias instead of prov…
2016-01-04 17:18:42 -05:00
Bill Burke 3e5874b2a1 Merge pull request #1971 from abstractj/tooltip-initial-access-token
Tooltips for initial access token fields
2016-01-04 17:15:45 -05:00
Bill Burke f7ac5fae2a Merge pull request #1945 from raehalme/KEYCLOAK-1579
KEYCLOAK-1579: Replaced AdapterDeploymentContextBean with AdapterDeploymentContextFactoryBean
2016-01-04 17:15:25 -05:00
Bill Burke 22ba4847f4 Merge pull request #1965 from jean-merelis/translate
translation of messages to pt_BR
2016-01-04 17:14:55 -05:00
Bill Burke 90822e5b34 Merge pull request #1970 from abstractj/minor-update
Minor change for client registration documentation
2016-01-04 17:14:43 -05:00
Bill Burke 3f62cee836 Merge remote-tracking branch 'upstream/master' 2016-01-04 17:14:19 -05:00
Bill Burke 3bacbdf6ff set framework for template config 2016-01-04 17:13:15 -05:00
Thomas Darimont edcc39d906 KEYCLOAK-2253 - Use string representation for boolean properties in GenericUserFederationCtrl.
Adapted due to code review.
2016-01-04 23:07:08 +01:00
Thomas Darimont 3ec516d14c KEYCLOAK-2253 - Add support for ConfiguredProvider based UserFederationProviderFactory.
UserFederationProvidersResource is now aware of ConfiguredProvider and allows sophisticated
configuration of configuration properties via ProviderConfigProperty definitions.
See DummyUserFederationProviderFactory. getConfigProperties() for example.

Previously  UserFederationProvidersResource did only support simple key-value pairs for expressing
configurable options.

Tested this by launching a standalone KeycloakServer and creating a new Dummy UserFederationProvider.
The default values, labels and help messages are correctly displayed and the values are stored correctly.
2016-01-04 22:23:14 +01:00
Dane Barentine d8d0298498 KEYCLOAK-2255 Location header should return IdP alias instead of provider ID. 2016-01-04 11:30:57 -08:00
Thomas Raehalme 8356409b44 Fixed some typos in the docs and added paragraph regarding GrantedAuthoritiesMapper. 2016-01-04 21:16:37 +02:00
Thomas Raehalme 57971ce0b2 Changed docs to match the new code. 2016-01-04 21:09:36 +02:00
Stian Thorgersen b708cd671e Merge pull request #1969 from vmuzikar/ui-stability
[KEYCLOAK-1865] Enable LdapUserFederationTest#invalidSettingsTest - already fixed
2016-01-04 20:07:52 +01:00
Bruno Oliveira 1b857387f2 Minor change for client registration documentation 2016-01-04 16:31:39 -02:00
Bruno Oliveira cea70337ef Tooltips for initial access token fields 2016-01-04 15:49:57 -02:00
Bill Burke 6d5de7b44e Merge remote-tracking branch 'upstream/master' 2016-01-04 11:26:15 -05:00
Bill Burke 10eba78036 Merge remote-tracking branch 'upstream/master'
Conflicts:
	saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/profile/ecp/SamlEcpProfileProtocolFactory.java
2016-01-04 11:25:14 -05:00
Stian Thorgersen dd6b05224d Merge pull request #1968 from stianst/master
KEYCLOAK-2250
2016-01-04 14:33:39 +01:00
Stian Thorgersen e7009cac47 KEYCLOAK-2204 Add test to make sure disabled client can't refresh token 2016-01-04 13:15:58 +01:00
Stian Thorgersen eece3689f2 KEYCLOAK-2228
Deleting of realm when using JPA requires server restart
2016-01-04 13:04:33 +01:00
Vaclav Muzikar f48753f6e1 Enable LdapUserFederationTest#invalidSettingsTest - already fixed 2016-01-04 12:36:38 +01:00
Stian Thorgersen 392ce0b323 KEYCLOAK-2250
Infinispan offline sessions cache is missing from configuration files
2016-01-04 11:53:25 +01:00
Jean Merelis 2fce7f8498 fix doLogIn key (pt_BR) 2016-01-03 21:02:32 -02:00
Jean Merelis c5f19ff2b3 fix some missing translation (pt_BR) 2016-01-02 23:23:04 -02:00
Jean Merelis b24dfa0009 translation of messages to pt_BR 2016-01-02 00:37:47 -02:00
Stian Thorgersen a9b5d07263 Merge pull request #1964 from stianst/master
KEYCLOAK-2242
2015-12-23 14:39:41 +01:00
Stian Thorgersen eddf3eef17 KEYCLOAK-2242
Remove built-in admin account
2015-12-23 13:46:11 +01:00
Bill Burke dbac147419 client config refactor 2015-12-22 17:50:03 -05:00
Marek Posolda 6752a4f9b0 Merge pull request #1963 from mposolda/master
KEYCLOAK-1899 Added HardcodedLDAPRoleMapper
2015-12-22 20:43:09 +01:00
Pedro Igor 35804aa0df Merge pull request #1961 from pedroigor/KEYCLOAK-2202
[KEYCLOAK-2202] - Removing LoginProtocol in order to reuse SAML settings.
2015-12-22 13:48:54 -02:00
mposolda 41d22986d5 KEYCLOAK-1899 Added HardcodedLDAPRoleMapper 2015-12-22 16:22:02 +01:00
Pedro Igor 9172b5472e [KEYCLOAK-2202] - Removing LoginProtocol in order to reuse SAML settings. 2015-12-22 12:53:39 -02:00
Marek Posolda b27b0411a6 Merge pull request #1960 from mposolda/master
KEYCLOAK-2154 Group mapper fixes
2015-12-22 13:19:40 +01:00
mposolda 0c293089c3 KEYCLOAK-2154 Group mapper fixes 2015-12-22 12:32:37 +01:00
Marek Posolda 5403296ac6 Merge pull request #1959 from mposolda/master
KEYCLOAK-2154 Added Group mapper for LDAP. LDAP mappers improvements and fixes
2015-12-22 10:15:26 +01:00
mposolda 20548b402d Separate package for LDAP tests 2015-12-22 09:35:53 +01:00
mposolda 1747e0981f KEYCLOAK-2154 Added Group mapper for LDAP. LDAP mappers improvements and fixes 2015-12-22 08:54:09 +01:00
Bill Burke ea6374163d Merge pull request #1957 from stianst/master
KEYCLOAK-2043
2015-12-21 16:56:01 -05:00
Bill Burke 4782780857 Merge pull request #1958 from patriot1burke/master
refactor client create
2015-12-21 16:55:52 -05:00
Bill Burke b90409c5e4 refactor client create 2015-12-21 16:36:13 -05:00
Stian Thorgersen 9a921f66ff KEYCLOAK-2043
.well-known/openid-configuration doesn't set cache-control header
2015-12-21 15:35:23 +01:00
Stian Thorgersen 4a492ce13c Merge pull request #1956 from stianst/master
KEYCLOAK-2240
2015-12-21 14:29:17 +00:00
Stian Thorgersen 39904548eb KEYCLOAK-2240
Internationalize admin console title
2015-12-21 13:16:54 +01:00
Stian Thorgersen 18268f686c Merge pull request #1955 from stianst/master
Support for branding
2015-12-21 12:00:56 +00:00
Stian Thorgersen 1594e07628 KEYCLOAK-2239
Add link to keycloak.org to Keycloak logo
2015-12-21 12:15:36 +01:00
Stian Thorgersen 606e6fa479 KEYCLOAK-1934
Add display-name and display-name-html to realm
2015-12-21 12:15:13 +01:00
Stian Thorgersen 1afd3d422c Merge pull request #1952 from vmuzikar/ui-stability
KEYCLOAK-1865 Fix stability of some UI arquillian tests
2015-12-21 07:50:11 +00:00
Bill Burke 80fae7116b Merge pull request #1953 from patriot1burke/master
client template scope
2015-12-18 18:32:00 -05:00
Bill Burke 86a0995f29 fix test 2015-12-18 17:31:53 -05:00
Bill Burke a7c684b909 oops 2015-12-18 17:19:31 -05:00
Bill Burke 5caf3e0a2d Merge remote-tracking branch 'upstream/master' 2015-12-18 17:15:40 -05:00
Bill Burke d939b6a431 template scope 2015-12-18 17:15:27 -05:00
Vaclav Muzikar 42d17577d0 Upstream sync 2015-12-18 17:28:57 +01:00
Vaclav Muzikar eaf326dd37 Fix Client Mappers tests
(cherry picked from commit b9f9db0)
2015-12-18 17:18:59 +01:00
Vaclav Muzikar 53a542d1e2 Enable TokensTest (already fixed by previous commit bf70927)
(cherry picked from commit 6783bcb)
2015-12-18 17:15:20 +01:00
Vaclav Muzikar c51d5e9820 Fix PasswordPolicyTest
(cherry picked from commit 87b125e)
2015-12-18 17:15:18 +01:00
Vaclav Muzikar 817127a751 Fix + refactor SecurityDefensesTest
(cherry picked from commit a652173)
2015-12-18 17:15:16 +01:00
Vaclav Muzikar 0e6e3d10d8 Fix LoginSettingsTest
(cherry picked from commit bf70927)
2015-12-18 17:15:09 +01:00
Bill Burke 0197c69ac3 Merge pull request #1951 from pedroigor/KEYCLOAK-2202
[KEYCLOAK-2202] - Initial support for SAML ECP Profile.
2015-12-17 19:04:17 -05:00
Stian Thorgersen 83eea5036f Merge pull request #1948 from pdrozd/wf10
Arquillian xsl templates - changed namespaces to WF10.
2015-12-17 09:01:14 +00:00
Pedro Igor 1b614a379b [KEYCLOAK-2202] - Initial support for SAML ECP Profile. 2015-12-16 18:46:52 -02:00
Bill Burke 0527d441e3 better logging 2015-12-16 12:23:41 -05:00
Marek Posolda 6569b22c79 Merge pull request #1950 from mposolda/master
Mongo fix
2015-12-16 14:36:27 +01:00
mposolda d0ec1c3b02 Mongo fix 2015-12-16 14:35:59 +01:00
Marek Posolda 2fe7e2a952 Merge pull request #1949 from mposolda/master
LDAP mappers enhancements
2015-12-16 14:33:54 +01:00
mposolda 0d52e4e6c5 Added sync support to UserFederationMapper 2015-12-16 13:52:11 +01:00
mposolda 358c273d39 KEYCLOAK-2227 Added UserRolesRetrieveStrategy. Possibility to read user role mappings through 'memberOf' attribute 2015-12-16 13:52:11 +01:00
mposolda 215d59b1e5 KEYCLOAK-2053 Memberships based on memberUid like attribute 2015-12-16 13:52:11 +01:00
mposolda 2b409b3462 Minor test fix 2015-12-16 13:52:11 +01:00
Pavel Drozd b4e53b1677 Arquillian xsl templates - changed namespaces to WF10. 2015-12-16 10:26:10 +01:00
Marek Posolda 051f175f68 Merge pull request #1946 from dbarentine/master
KEYCLOAK-2229 Added depending on keycloak-broker-core module to resol…
2015-12-16 07:58:05 +01:00
Bill Burke fd447702e7 Merge pull request #1947 from patriot1burke/master
remove default client mappers when templated
2015-12-15 19:36:37 -05:00
Bill Burke ee79f5e69d remove default client mappers when templated 2015-12-15 17:37:53 -05:00
Dane Barentine de5baa9df7 KEYCLOAK-2229 Added depending on keycloak-broker-core module to resolve NoClassDefFoundError for BrokeredIdentityContext class 2015-12-15 11:15:55 -08:00
Thomas Raehalme 566a58b5d8 Replaced AdapterDeploymentContextBean with AdapterDeploymentContextFactoryBean and added support for KeycloakConfigResolver. 2015-12-15 11:53:10 +02:00
Marek Posolda f837cbfaa9 Merge pull request #1944 from mposolda/master
KEYCLOAK-1906 Customized LDAP filter. LDAP conditions improvements
2015-12-14 14:50:38 +01:00
mposolda 06a55419f1 KEYCLOAK-1906 Customized LDAP filter. LDAP conditions improvements 2015-12-14 13:55:11 +01:00
Marek Posolda 82a573a536 Merge pull request #1939 from mhajas/master
KEYCLOAK-1667 Added adapter tests of SAML to integration arquillian
2015-12-14 09:26:32 +01:00
Stian Thorgersen d46bad56ae Merge pull request #1942 from keycloak/wildfly-10
KEYCLOAK-2223 Upgrade to WildFly 10.0.0.CR4
2015-12-13 21:04:38 +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
mhajas 97357d020b Merge remote-tracking branch 'upstream/master' 2015-12-11 15:43:03 +01: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 5464e600ea Set SAMLServlet test abstract 2015-12-10 17:23:33 +01:00
mhajas cbdba622a5 Merge remote-tracking branch 'upstream/master' 2015-12-10 15:27:55 +01:00
mhajas 49e9965125 Fix timeouts after logout from servlet 2015-12-10 15:26:33 +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
mhajas b82346761c Merge remote-tracking branch 'upstream/master' 2015-12-09 10:53:50 +01:00
mhajas 595e7a92e2 Added SAML servlets adapter tests to integration-arquillian 2015-12-09 10:50:25 +01:00
mhajas fee1dea3e6 Added SAML example adapter tests to integration-arqullian 2015-12-09 10:48:53 +01:00
mhajas 9a58e1276a Added integration-arqullian servlet used in SAML tests 2015-12-09 10:45:56 +01:00
mhajas 1d401767d6 Added integration-arqullian SAML example page objects 2015-12-09 10:42:02 +01:00
mhajas 68e3b6c504 Added integration-arqullian SAML servlets page objects 2015-12-09 10:41:17 +01:00
mhajas 813ddf365e Added integration-arqullian keycloak-saml resources 2015-12-09 10:39:34 +01:00
mhajas edf3499662 Added integration-arqullian configuration for SAML adapter tests 2015-12-09 10:36:42 +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
Marko Strukelj 6b1287a553 KEYCLOAK-1988 Loader constraint violation in multi-tenant example 2015-10-19 22:11:31 +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
Stian Thorgersen 256ca2b665 Merge pull request #1756 from stianst/master
KEYCLOAK-1977
2015-10-19 08:47:21 +02:00
Stian Thorgersen e4412523d4 Merge pull request #1754 from vramik/migration-kc15
arquillian-testsuite add migration-kc15
2015-10-19 08:44:51 +02:00
Stian Thorgersen 073d82b367 KEYCLOAK-1977 2015-10-19 08:43:34 +02:00
Stian Thorgersen 484c5ebb15 Merge pull request #1755 from stianst/master
Tweak authentication flow page a bit
2015-10-19 08:42:22 +02:00
vramik 4c33704c56 add support for migration kc1.5.1 2015-10-18 16:01:26 +02:00
Marek Posolda 511763d4bc Merge pull request #1753 from mposolda/master
KEYCLOAK-1952 Migration fix. Change some INFO messages to DEBUG/TRACE
2015-10-17 10:02:55 +02:00
mposolda 605c80a68d KEYCLOAK-1952 Migration fix. Change some INFO messages to DEBUG/TRACE 2015-10-16 20:51:40 +02:00
Marek Posolda 2325143803 Merge pull request #1751 from mposolda/master
KEYCLOAK-1972 docs and export/import fixes for offline tokens. DB fixes
2015-10-16 19:58:41 +02:00
mposolda 9cc5ca3ce4 KEYCLOAK-1972 docs and export/import fixes for offline tokens. DB fixes 2015-10-16 19:09:52 +02:00
Marek Posolda d13c120b6c Merge pull request #1750 from mposolda/master
KEYCLOAK-1929 Change package names. Fix Fuse demo
2015-10-16 17:35:14 +02:00
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
mposolda 9942c7b519 Fix integration-arquillian 2015-10-16 16:57:28 +02:00
mposolda 4587fd23b6 KEYCLOAK-1929 Change package names. Fix Fuse demo 2015-10-16 16:30:42 +02:00
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
Stian Thorgersen c21b56d596 Merge pull request #1748 from stianst/tweak-auth-page
Tweak authentication flow page a bit
2015-10-16 14:54:51 +02:00
Stian Thorgersen 4ee5c32b1e Merge pull request #1745 from stianst/kc-1969
KEYCLOAK-1969
2015-10-16 14:54:09 +02:00
Stian Thorgersen 6386d95904 Tweak authentication flow page a bit 2015-10-16 14:04:57 +02:00
Stian Thorgersen f99395aebe Merge pull request #1746 from mhajas/master
KEYCLOAK-1865 - Stabilize some integration-arquillian tests
2015-10-16 14:04:04 +02:00
Stian Thorgersen 82a7173dba Merge pull request #1747 from stianst/kc-1975
KEYCLOAK-1975
2015-10-16 14:03:47 +02:00
Stian Thorgersen 2bf6f4b0fd Tweak authentication flow page a bit 2015-10-16 14:03:30 +02:00
Stian Thorgersen d8e90028af Merge pull request #1744 from stianst/kc-1973
KEYCLOAK-1973 Clear user from authentication context is password is n…
2015-10-16 12:52:46 +02:00
Stian Thorgersen d2afb4892a KEYCLOAK-1975
Increase/decrease flow priority doesn't work
2015-10-16 12:52:07 +02:00
Stian Thorgersen eb9f69eee0 KEYCLOAK-1969
Admin console displays Clients flow page when execution or execution flow is created.
2015-10-16 12:23:41 +02:00
mhajas 39f985e04a Clean code 2015-10-16 12:09:35 +02:00
mhajas 41a51d924b Merge remote-tracking branch 'upstream/master' 2015-10-16 12:03:03 +02:00
mhajas ce996f6a41 Fix PasswordPolicyTest stability 2015-10-16 11:33:11 +02:00
mhajas 244848afc4 Fix events tests stability 2015-10-16 11:31:45 +02:00
Stian Thorgersen 2910db5595 KEYCLOAK-1973 Clear user from authentication context is password is not valid 2015-10-16 11:24:45 +02:00
Stian Thorgersen a6556a49c2 Merge pull request #1738 from gerbermichi/locale
KEYCLOAK-1962 update realm overwrites supported locales with empty list
2015-10-16 10:21:20 +02:00
Bill Burke e4961056db Merge pull request #1743 from patriot1burke/master
KEYCLOAK-1941
2015-10-15 20:41:35 -04:00
Bill Burke c8eee38471 Merge pull request #1742 from patriot1burke/master
KEYCLOAK-1954
2015-10-15 20:41:12 -04:00
Bill Burke 1e4b3fc3b6 KEYCLOAK-1941 2015-10-15 20:26:20 -04:00
Bill Burke 14426f26f2 KEYCLOAK-1954 2015-10-15 20:05:44 -04:00
Bill Burke 19ad846306 Merge pull request #1741 from patriot1burke/master
KEYCLOAK-1960
2015-10-15 19:33:55 -04:00
Bill Burke 235ffb2ff6 KEYCLOAK-1960 2015-10-15 18:56:56 -04:00
Bill Burke 181fdeb0d0 KEYCLOAK-1960 2015-10-15 18:54:57 -04:00
Bill Burke 8674578d0d Merge pull request #1730 from patriot1burke/master
KEYCLOAK-1908
2015-10-15 18:32:57 -04:00
Bill Burke 9cf4186eb2 fix arquillian test 2015-10-15 17:56:51 -04:00
Marek Posolda 92ed01a61b Merge pull request #1740 from mposolda/master
Offline tokens fixes & improvements
2015-10-15 23:15:50 +02:00
Bill Burke 99028e9cab Merge remote-tracking branch 'upstream/master' 2015-10-15 16:30:35 -04:00
Bill Burke 20f18eec15 support browser refresh 2015-10-15 16:30:21 -04:00
mposolda 67435791ed KEYCLOAK-1961 revokeRefreshToken support for offline tokens and other fixes 2015-10-15 22:30:17 +02:00
mposolda b4520baee5 KEYCLOAK-1959 Role offline_access was effective only when explicitly added to user 2015-10-15 22:30:17 +02:00
mposolda 802a39b1ce KEYCLOAK-904 Offline session idle timeout + admin console 2015-10-15 22:30:17 +02:00
Stian Thorgersen 229b964867 Merge pull request #1739 from mstruk/cli
KEYCLOAK-1849 Overlay installation scripts not working
2015-10-15 16:26:44 +02:00
mhajas b413bcb41d Unignored test 2015-10-15 14:57:58 +02:00
Marko Strukelj 0c39e30241 KEYCLOAK-1849 Overlay installation scripts not working
- fix unsupported dependency 'org.infinispan:main' warning
2015-10-15 13:46:38 +02:00
Marko Strukelj 11a8d3842e KEYCLOAK-1849 Overlay installation scripts not working 2015-10-15 13:46:38 +02:00
mhajas 2c460c3adc Test password policies using REST 2015-10-15 12:44:27 +02:00
Vlasta Ramik aaddaa6c25 Merge remote-tracking branch 'upstream/master' 2015-10-15 12:30:17 +02:00
Stian Thorgersen 96099e0798 Merge pull request #1732 from stianst/master
KEYCLOAK-1961
2015-10-15 10:57:23 +02:00
Stian Thorgersen e582de2837 KEYCLOAK-1961
Same token can be used multiple times to obtain access token
2015-10-15 09:11:18 +02:00
Stian Thorgersen e1fc863421 Merge pull request #1719 from gautric/french-i18n
French i18n
2015-10-15 08:54:26 +02:00
Stian Thorgersen 7de4051c9b Merge pull request #1737 from thomasdarimont/issue/KEYCLOAK-1918
KEYCLOAK-1918 - Add description field to client definition.
2015-10-15 08:53:47 +02:00
Stian Thorgersen 5b7b5b1b60 Merge pull request #1736 from stianst/test
Add test to make sure expired password is checked on direct grant
2015-10-15 08:53:28 +02:00
Michael Gerber f8effaee58 return null instead of an empty set. 2015-10-15 08:19:18 +02:00
Stian Thorgersen bf7d43fffb Add test to make sure expired password is checked on direct grant 2015-10-15 08:03:54 +02:00
Thomas Darimont 870702fd81 KEYCLOAK-1918 - Add description field to client definition.
Introduced description field with support for i18n for more descriptive client information.
Applications can use the description to display a "slightly" longer gist of
what the client / application is about, especially useful for tooltips.

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

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

No files matched your search

+20
View File
@@ -0,0 +1,20 @@
* text=auto
*.html text eol=lf
*.java text eol=lf
*.js text eol=lf
*.json text eol=lf
*.jsp text eol=lf
*.md text eol=lf
*.properties text eol=lf
*.svg text auto
*.xml text eol=lf
*.xsl text eol=lf
*.png binary
*.jpg binary
*.gif binary
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
+16 -5
View File
@@ -1,10 +1,21 @@
language: java
cache:
directories:
- $HOME/.m2
env:
global:
- MAVEN_SKIP_RC=true
- MAVEN_OPTS="-Xms512m -Xmx2048m"
before_cache:
- rm -rf $HOME/.m2/repository/org/keycloak
jdk:
- oraclejdk8
before_script:
- export MAVEN_SKIP_RC=true
install:
- mvn install -Pdistribution -DskipTests=true -B -V -q
script:
- mvn test -B
- mvn -file testsuite/integration-arquillian test -B -Pno-console
sudo: false
+1 -1
View File
@@ -7,7 +7,7 @@ Keycloak is an SSO Service for web apps and REST services. For more information
Building
--------
Ensure you have JDK 7 (or newer), Maven 3.2.1 (or newer) and Git installed
Ensure you have JDK 8 (or newer), Maven 3.2.1 (or newer) and Git installed
java -version
mvn -version
+54 -50
View File
@@ -1,50 +1,54 @@
<?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.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-core</artifactId>
<name>Keycloak Broker Core</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.8.0.CR1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-core</artifactId>
<name>Keycloak Broker Core</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.annotation</groupId>
<artifactId>jboss-annotations-api_1.1_spec</artifactId>
</dependency>
</dependencies>
</project>
@@ -58,6 +58,11 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
return null;
}
@Override
public Response performLogin(AuthenticationRequest request) {
return null;
}
@Override
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
return null;
@@ -87,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,38 +1,43 @@
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.IdentityProviderMapper;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
@Override
public void close() {
}
@Override
public IdentityProviderMapper create(KeycloakSession session) {
return null;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
}
package org.keycloak.broker.provider;
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>
* @version $Revision: 1 $
*/
public abstract class AbstractIdentityProviderMapper implements IdentityProviderMapper {
@Override
public void close() {
}
@Override
public IdentityProviderMapper create(KeycloakSession session) {
return null;
}
@Override
public void init(org.keycloak.Config.Scope config) {
}
@Override
public void postInit(KeycloakSessionFactory factory) {
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
}
@@ -17,9 +17,14 @@
*/
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;
/**
@@ -43,6 +48,7 @@ public class BrokeredIdentityContext {
private IdentityProviderModel idpConfig;
private IdentityProvider idp;
private Map<String, Object> contextData = new HashMap<>();
private ClientSessionModel clientSession;
public BrokeredIdentityContext(String id) {
if (id == null) {
@@ -150,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;
}
@@ -166,6 +188,14 @@ public class BrokeredIdentityContext {
this.lastName = lastName;
}
public ClientSessionModel getClientSession() {
return clientSession;
}
public void setClientSession(ClientSessionModel clientSession) {
this.clientSession = clientSession;
}
public void setName(String name) {
if (name != null) {
int i = name.lastIndexOf(' ');
@@ -0,0 +1,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);
}
}
}
@@ -0,0 +1,89 @@
package org.keycloak.broker.provider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedAttributeMapper extends AbstractIdentityProviderMapper {
public static final String ATTRIBUTE = "attribute";
public static final String ATTRIBUTE_VALUE = "attribute.value";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE);
property.setLabel("User Attribute");
property.setHelpText("Name of user attribute you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("User Attribute Value");
property.setHelpText("Value you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Attribute";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "hardcoded-attribute-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
context.setUserAttribute(attribute, attributeValue);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
user.setSingleAttribute(attribute, attributeValue);
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a value to a specific user attribute.";
}
}
@@ -1,110 +1,79 @@
package org.keycloak.broker.provider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
public static final String ROLE = "role";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static String[] parseRole(String role) {
int scopeIndex = role.indexOf('.');
if (scopeIndex > -1) {
String appName = role.substring(0, scopeIndex);
role = role.substring(scopeIndex + 1);
String[] rtn = {appName, role};
return rtn;
} else {
String[] rtn = {null, role};
return rtn;
}
}
public static RoleModel getRoleFromString(RealmModel realm, String roleName) {
String[] parsedRole = parseRole(roleName);
RoleModel role = null;
if (parsedRole[0] == null) {
role = realm.getRole(parsedRole[1]);
} else {
ClientModel client = realm.getClientByClientId(parsedRole[0]);
role = client.getRole(parsedRole[1]);
}
return role;
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Role";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(ROLE);
RoleModel role = getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a role mapping for it.";
}
}
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedRoleMapper extends AbstractIdentityProviderMapper {
public static final String ROLE = "role";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded Role";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "oidc-hardcoded-role-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(ROLE);
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a role mapping for it.";
}
}
@@ -0,0 +1,87 @@
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProviderMapper {
public static final String ATTRIBUTE = "attribute";
public static final String ATTRIBUTE_VALUE = "attribute.value";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE);
property.setLabel("User Session Attribute");
property.setHelpText("Name of user session attribute you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("User Session Attribute Value");
property.setHelpText("Value you want to hardcode");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Hardcoded User Session Attribute";
}
public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
public static final String PROVIDER_ID = "hardcoded-user-session-attribute-idp-mapper";
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public void 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);
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(ATTRIBUTE);
String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
context.getClientSession().setUserSessionNote(attribute, attributeValue);
}
@Override
public String getHelpText() {
return "When user is imported from provider, hardcode a value to a specific user session attribute.";
}
}
@@ -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);
}
@@ -1,56 +1,58 @@
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
public static final String ANY_PROVIDER = "*";
String[] getCompatibleProviders();
String getDisplayCategory();
String getDisplayType();
/**
* Called to determine what keycloak username and email to use to process the login request from the external IDP
* Usually used to map BrokeredIdentityContet.username or email.
*
* @param session
* @param realm
* @param mapperModel
* @param context
*/
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called after UserModel is created for first time for this user.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called when this user has logged in before and has already been imported.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
}
package org.keycloak.broker.provider;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ConfiguredProvider;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
public static final String ANY_PROVIDER = "*";
String[] getCompatibleProviders();
String getDisplayCategory();
String getDisplayType();
/**
* Called to determine what keycloak username and email to use to process the login request from the external IDP.
* 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
* @param mapperModel
* @param context
*/
void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called after UserModel is created for first time for this user. Called after "FirstBrokerLogin" flow
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
/**
* Called when this user has logged in before and has already been imported.
*
* @param session
* @param realm
* @param user
* @param mapperModel
* @param context
*/
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
}
@@ -1,5 +1,8 @@
package org.keycloak.broker.provider.util;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -24,6 +27,9 @@ public class SimpleHttp {
private Map<String, String> headers;
private Map<String, String> params;
private SSLSocketFactory sslFactory;
private HostnameVerifier hostnameVerifier;
protected SimpleHttp(String url, String method) {
this.url = url;
this.method = method;
@@ -53,6 +59,15 @@ public class SimpleHttp {
return this;
}
public SimpleHttp sslFactory(SSLSocketFactory factory) {
sslFactory = factory;
return this;
}
public SimpleHttp hostnameVerifier(HostnameVerifier verifier) {
hostnameVerifier = verifier;
return this;
}
public String asString() throws IOException {
boolean get = method.equals("GET");
@@ -85,6 +100,7 @@ public class SimpleHttp {
}
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
setupTruststoreIfApplicable(connection);
OutputStream os = null;
InputStream is = null;
@@ -171,6 +187,7 @@ public class SimpleHttp {
}
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
setupTruststoreIfApplicable(connection);
OutputStream os = null;
InputStream is = null;
@@ -235,4 +252,13 @@ public class SimpleHttp {
return writer.toString();
}
private void setupTruststoreIfApplicable(HttpURLConnection connection) {
if (connection instanceof HttpsURLConnection && sslFactory != null) {
HttpsURLConnection con = (HttpsURLConnection) connection;
con.setSSLSocketFactory(sslFactory);
if (hostnameVerifier != null) {
con.setHostnameVerifier(hostnameVerifier);
}
}
}
}
@@ -1 +1,3 @@
org.keycloak.broker.provider.HardcodedRoleMapper
org.keycloak.broker.provider.HardcodedRoleMapper
org.keycloak.broker.provider.HardcodedAttributeMapper
org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper
@@ -1,2 +1,2 @@
org.keycloak.broker.provider.IdentityProviderSpi
org.keycloak.broker.provider.IdentityProviderSpi
org.keycloak.broker.provider.IdentityProviderMapperSpi
+58 -58
View File
@@ -1,58 +1,58 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-oidc</artifactId>
<name>Keycloak Broker - OpenID Connect Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.8.0.CR1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-oidc</artifactId>
<name>Keycloak Broker - OpenID Connect Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -20,13 +20,14 @@ package org.keycloak.broker.oidc;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.jboss.logging.Logger;
import org.keycloak.ClientConnection;
import org.keycloak.common.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.AbstractIdentityProvider;
import org.keycloak.broker.provider.AuthenticationRequest;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.connections.truststore.JSSETruststoreConfigurator;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
@@ -247,12 +248,15 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
}
public SimpleHttp generateTokenRequest(String authorizationCode) {
JSSETruststoreConfigurator configurator = new JSSETruststoreConfigurator(session);
return SimpleHttp.doPost(getConfig().getTokenUrl())
.param(OAUTH2_PARAMETER_CODE, authorizationCode)
.param(OAUTH2_PARAMETER_CLIENT_ID, getConfig().getClientId())
.param(OAUTH2_PARAMETER_CLIENT_SECRET, getConfig().getClientSecret())
.param(OAUTH2_PARAMETER_REDIRECT_URI, uriInfo.getAbsolutePath().toString())
.param(OAUTH2_PARAMETER_GRANT_TYPE, OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE);
.param(OAUTH2_PARAMETER_GRANT_TYPE, OAUTH2_GRANT_TYPE_AUTHORIZATION_CODE)
.sslFactory(configurator.getSSLSocketFactory())
.hostnameVerifier(configurator.getHostnameVerifier());
}
}
}
@@ -1,114 +1,121 @@
package org.keycloak.broker.oidc;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.adapters.action.AdminAction;
import org.keycloak.representations.adapters.action.LogoutAction;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.security.PublicKey;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
super(config);
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
return new KeycloakEndpoint(callback, realm, event);
}
@Override
protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
JsonWebToken access = validateToken(idpKey, response.getToken());
context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
}
protected class KeycloakEndpoint extends OIDCEndpoint {
public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
super(callback, realm, event);
}
@POST
@Path(AdapterConstants.K_LOGOUT)
public Response backchannelLogout(String input) {
JWSInput token = new JWSInput(input);
PublicKey key = getExternalIdpKey();
if (key != null) {
if (!verify(token, key)) {
logger.warn("Failed to verify logout request");
return Response.status(400).build();
}
}
LogoutAction action = null;
try {
action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!validateAction(action)) return Response.status(400).build();
if (action.getKeycloakSessionIds() != null) {
for (String sessionId : action.getKeycloakSessionIds()) {
String brokerSessionId = getConfig().getAlias() + "." + sessionId;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null
&& userSession.getState() != UserSessionModel.State.LOGGING_OUT
&& userSession.getState() != UserSessionModel.State.LOGGED_OUT
) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
}
}
}
return Response.ok().build();
}
protected boolean validateAction(AdminAction action) {
if (!action.validate()) {
logger.warn("admin request failed, not validated" + action.getAction());
return false;
}
if (action.isExpired()) {
logger.warn("admin request failed, expired token");
return false;
}
if (!getConfig().getClientId().equals(action.getResource())) {
logger.warn("Resource name does not match");
return false;
}
return true;
}
@Override
public SimpleHttp generateTokenRequest(String authorizationCode) {
return super.generateTokenRequest(authorizationCode)
.param(AdapterConstants.CLIENT_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
}
}
}
package org.keycloak.broker.oidc;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.constants.AdapterConstants;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.representations.adapters.action.AdminAction;
import org.keycloak.representations.adapters.action.LogoutAction;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.util.JsonSerialization;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.security.PublicKey;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
public static final String VALIDATED_ACCESS_TOKEN = "VALIDATED_ACCESS_TOKEN";
public KeycloakOIDCIdentityProvider(OIDCIdentityProviderConfig config) {
super(config);
}
@Override
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
return new KeycloakEndpoint(callback, realm, event);
}
@Override
protected void processAccessTokenResponse(BrokeredIdentityContext context, PublicKey idpKey, AccessTokenResponse response) {
JsonWebToken access = validateToken(idpKey, response.getToken());
context.getContextData().put(VALIDATED_ACCESS_TOKEN, access);
}
protected class KeycloakEndpoint extends OIDCEndpoint {
public KeycloakEndpoint(AuthenticationCallback callback, RealmModel realm, EventBuilder event) {
super(callback, realm, event);
}
@POST
@Path(AdapterConstants.K_LOGOUT)
public Response backchannelLogout(String input) {
JWSInput token = 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)) {
logger.warn("Failed to verify logout request");
return Response.status(400).build();
}
}
LogoutAction action = null;
try {
action = JsonSerialization.readValue(token.getContent(), LogoutAction.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
if (!validateAction(action)) return Response.status(400).build();
if (action.getKeycloakSessionIds() != null) {
for (String sessionId : action.getKeycloakSessionIds()) {
String brokerSessionId = getConfig().getAlias() + "." + sessionId;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null
&& userSession.getState() != UserSessionModel.State.LOGGING_OUT
&& userSession.getState() != UserSessionModel.State.LOGGED_OUT
) {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
}
}
}
return Response.ok().build();
}
protected boolean validateAction(AdminAction action) {
if (!action.validate()) {
logger.warn("admin request failed, not validated" + action.getAction());
return false;
}
if (action.isExpired()) {
logger.warn("admin request failed, expired token");
return false;
}
if (!getConfig().getClientId().equals(action.getResource())) {
logger.warn("Resource name does not match");
return false;
}
return true;
}
@Override
public SimpleHttp generateTokenRequest(String authorizationCode) {
return super.generateTokenRequest(authorizationCode)
.param(AdapterConstants.CLIENT_SESSION_STATE, "n/a"); // hack to get backchannel logout to work
}
}
}
@@ -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;
@@ -42,7 +43,7 @@ import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.RealmsResource;
import org.keycloak.util.JsonSerialization;
import org.keycloak.util.PemUtils;
import org.keycloak.common.util.PemUtils;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@@ -282,41 +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 aud = token.getAudience();
String iss = token.getIssuer();
if (aud != null && !aud.equals(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
@@ -1,97 +1,97 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
public static final String CLAIM = "claim";
public static final String CLAIM_VALUE = "claim.value";
public static Object getClaimValue(JsonWebToken token, String claim) {
String[] split = claim.split("\\.");
Map<String, Object> jsonObject = token.getOtherClaims();
for (int i = 0; i < split.length; i++) {
if (i == split.length - 1) {
return jsonObject.get(split[i]);
} else {
Object val = jsonObject.get(split[i]);
if (!(val instanceof Map)) return null;
jsonObject = (Map<String, Object>)val;
}
}
return null;
}
public static Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String claim = mapperModel.getConfig().get(CLAIM);
return getClaimValue(context, claim);
}
public static Object getClaimValue(BrokeredIdentityContext context, String claim) {
{ // search access token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
{ // search ID Token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
return null;
}
protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
Object value = getClaimValue(mapperModel, context);
String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
return valueEquals(desiredValue, value);
}
public boolean valueEquals(String desiredValue, Object value) {
if (value instanceof String) {
if (desiredValue.equals(value)) return true;
} else if (value instanceof Double) {
try {
if (Double.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Integer) {
try {
if (Integer.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Boolean) {
try {
if (Boolean.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof List) {
List list = (List)value;
for (Object val : list) {
return valueEquals(desiredValue, val);
}
}
return false;
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public abstract class AbstractClaimMapper extends AbstractIdentityProviderMapper {
public static final String CLAIM = "claim";
public static final String CLAIM_VALUE = "claim.value";
public static Object getClaimValue(JsonWebToken token, String claim) {
String[] split = claim.split("\\.");
Map<String, Object> jsonObject = token.getOtherClaims();
for (int i = 0; i < split.length; i++) {
if (i == split.length - 1) {
return jsonObject.get(split[i]);
} else {
Object val = jsonObject.get(split[i]);
if (!(val instanceof Map)) return null;
jsonObject = (Map<String, Object>)val;
}
}
return null;
}
public static Object getClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String claim = mapperModel.getConfig().get(CLAIM);
return getClaimValue(context, claim);
}
public static Object getClaimValue(BrokeredIdentityContext context, String claim) {
{ // search access token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
{ // search ID Token
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ID_TOKEN);
if (token != null) {
Object value = getClaimValue(token, claim);
if (value != null) return value;
}
}
return null;
}
protected boolean hasClaimValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
Object value = getClaimValue(mapperModel, context);
String desiredValue = mapperModel.getConfig().get(CLAIM_VALUE);
return valueEquals(desiredValue, value);
}
public boolean valueEquals(String desiredValue, Object value) {
if (value instanceof String) {
if (desiredValue.equals(value)) return true;
} else if (value instanceof Double) {
try {
if (Double.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Integer) {
try {
if (Integer.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof Boolean) {
try {
if (Boolean.valueOf(desiredValue).equals(value)) return true;
} catch (Exception e) {
}
} else if (value instanceof List) {
List list = (List)value;
for (Object val : list) {
if (valueEquals(desiredValue, val)) return true;
}
}
return false;
}
}
@@ -1,206 +1,206 @@
package org.keycloak.broker.oidc.mappers;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.JsonNode;
import org.jboss.logging.Logger;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
/**
* Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user
* attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who
* uses {@link JsonNode} user profile.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper {
protected static final Logger logger = Logger.getLogger(AbstractJsonUserAttributeMapper.class);
protected static final Logger LOGGER_DUMP_USER_PROFILE = Logger.getLogger("org.keycloak.social.user_profile_dump");
private static final String JSON_PATH_DELIMITER = ".";
/**
* Config param where name of mapping source JSON User Profile field is stored.
*/
public static final String CONF_JSON_FIELD = "jsonField";
/**
* Config param where name of mapping target USer attribute is stored.
*/
public static final String CONF_USER_ATTRIBUTE = "userAttribute";
/**
* Key in {@link BrokeredIdentityContext#getContextData()} where {@link JsonNode} with user profile is stored.
*/
public static final String CONTEXT_JSON_NODE = OIDCIdentityProvider.USER_INFO;
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CONF_JSON_FIELD);
property1.setLabel("Social Profile JSON Field Path");
property1.setHelpText("Path of field in Social provider User Profile JSON data to get value from. You can use dot notation for nesting and square brackets for array index. Eg. 'contact.address[0].country'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(CONF_USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store information into.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
/**
* Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure.
*
* @param user context to store profile data into
* @param profile to store into context
* @param provider identification of social provider to be used in log dump
*
* @see #importNewUser(KeycloakSession, RealmModel, UserModel, IdentityProviderMapperModel, BrokeredIdentityContext)
* @see BrokeredIdentityContext#getContextData()
*/
public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
user.getContextData().put(AbstractJsonUserAttributeMapper.CONTEXT_JSON_NODE, profile);
if (LOGGER_DUMP_USER_PROFILE.isDebugEnabled())
LOGGER_DUMP_USER_PROFILE.debug("User Profile JSON Data for provider "+provider+": " + profile);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public String getHelpText() {
return "Import user profile information if it exists in Social provider JSON data into the specified user attribute.";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
if (attribute == null || attribute.trim().isEmpty()) {
logger.debug("Attribute is not configured");
return;
}
attribute = attribute.trim();
String value = getJsonValue(mapperModel, context);
if (value != null) {
user.setAttribute(attribute, value);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
// we do not update user profile from social provider
}
protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
if (jsonField == null || jsonField.trim().isEmpty()) {
logger.debug("JSON field path is not configured");
return null;
}
jsonField = jsonField.trim();
if (jsonField.startsWith(JSON_PATH_DELIMITER) || jsonField.endsWith(JSON_PATH_DELIMITER) || jsonField.startsWith("[")) {
logger.debug("JSON field path is invalid " + jsonField);
return null;
}
JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE);
String value = getJsonValue(profileJsonNode, jsonField);
if (value == null) {
logger.debug("User profile JSON value '" + jsonField + "' is not available.");
}
return value;
}
protected static String getJsonValue(JsonNode baseNode, String fieldPath) {
logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
if (baseNode != null) {
int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
String currentFieldName = fieldPath;
if (idx > 0) {
currentFieldName = fieldPath.substring(0, idx).trim();
if (currentFieldName.isEmpty()) {
logger.debug("JSON path is invalid " + fieldPath);
return null;
}
}
String currentNodeName = currentFieldName;
int arrayIndex = -1;
if (currentFieldName.endsWith("]")) {
int bi = currentFieldName.indexOf("[");
if (bi == -1) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
try {
String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
arrayIndex = Integer.parseInt(is);
} catch (Exception e) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
currentNodeName = currentFieldName.substring(0,bi).trim();
}
JsonNode currentNode = baseNode.get(currentNodeName);
if (arrayIndex > -1 && currentNode.isArray()) {
logger.debug("Going to take array node at index " + arrayIndex);
currentNode = currentNode.get(arrayIndex);
}
if (currentNode == null) {
logger.debug("JsonNode not found for name " + currentFieldName);
return null;
}
if (idx < 0) {
if (!currentNode.isValueNode()) {
logger.debug("JsonNode is not value node for name " + currentFieldName);
return null;
}
String ret = currentNode.asText();
if (ret != null && !ret.trim().isEmpty())
return ret.trim();
} else {
return getJsonValue(currentNode, fieldPath.substring(idx + 1));
}
}
return null;
}
}
package org.keycloak.broker.oidc.mappers;
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.JsonNode;
import org.jboss.logging.Logger;
import org.keycloak.broker.oidc.OIDCIdentityProvider;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
/**
* Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user
* attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who
* uses {@link JsonNode} user profile.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper {
protected static final Logger logger = Logger.getLogger(AbstractJsonUserAttributeMapper.class);
protected static final Logger LOGGER_DUMP_USER_PROFILE = Logger.getLogger("org.keycloak.social.user_profile_dump");
private static final String JSON_PATH_DELIMITER = ".";
/**
* Config param where name of mapping source JSON User Profile field is stored.
*/
public static final String CONF_JSON_FIELD = "jsonField";
/**
* Config param where name of mapping target USer attribute is stored.
*/
public static final String CONF_USER_ATTRIBUTE = "userAttribute";
/**
* Key in {@link BrokeredIdentityContext#getContextData()} where {@link JsonNode} with user profile is stored.
*/
public static final String CONTEXT_JSON_NODE = OIDCIdentityProvider.USER_INFO;
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CONF_JSON_FIELD);
property1.setLabel("Social Profile JSON Field Path");
property1.setHelpText("Path of field in Social provider User Profile JSON data to get value from. You can use dot notation for nesting and square brackets for array index. Eg. 'contact.address[0].country'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(CONF_USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store information into.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
/**
* Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure.
*
* @param user context to store profile data into
* @param profile to store into context
* @param provider identification of social provider to be used in log dump
*
* @see #preprocessFederatedIdentity(KeycloakSession, RealmModel, IdentityProviderMapperModel, BrokeredIdentityContext)
* @see BrokeredIdentityContext#getContextData()
*/
public static void storeUserProfileForMapper(BrokeredIdentityContext user, JsonNode profile, String provider) {
user.getContextData().put(AbstractJsonUserAttributeMapper.CONTEXT_JSON_NODE, profile);
if (LOGGER_DUMP_USER_PROFILE.isDebugEnabled())
LOGGER_DUMP_USER_PROFILE.debug("User Profile JSON Data for provider "+provider+": " + profile);
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public String getHelpText() {
return "Import user profile information if it exists in Social provider JSON data into the specified user attribute.";
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(CONF_USER_ATTRIBUTE);
if (attribute == null || attribute.trim().isEmpty()) {
logger.warnf("Attribute is not configured for mapper %s", mapperModel.getName());
return;
}
attribute = attribute.trim();
String value = getJsonValue(mapperModel, context);
if (value != null) {
context.setUserAttribute(attribute, value);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
// we do not update user profile from social provider
}
protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD);
if (jsonField == null || jsonField.trim().isEmpty()) {
logger.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.warnf("JSON field path is invalid %s", jsonField);
return null;
}
JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE);
String value = getJsonValue(profileJsonNode, jsonField);
if (value == null) {
logger.debugf("User profile JSON value '%s' is not available.", jsonField);
}
return value;
}
protected static String getJsonValue(JsonNode baseNode, String fieldPath) {
logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode);
if (baseNode != null) {
int idx = fieldPath.indexOf(JSON_PATH_DELIMITER);
String currentFieldName = fieldPath;
if (idx > 0) {
currentFieldName = fieldPath.substring(0, idx).trim();
if (currentFieldName.isEmpty()) {
logger.debug("JSON path is invalid " + fieldPath);
return null;
}
}
String currentNodeName = currentFieldName;
int arrayIndex = -1;
if (currentFieldName.endsWith("]")) {
int bi = currentFieldName.indexOf("[");
if (bi == -1) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
try {
String is = currentFieldName.substring(bi+1, currentFieldName.length() - 1).trim();
arrayIndex = Integer.parseInt(is);
} catch (Exception e) {
logger.debug("Invalid array index construct in " + currentFieldName);
return null;
}
currentNodeName = currentFieldName.substring(0,bi).trim();
}
JsonNode currentNode = baseNode.get(currentNodeName);
if (arrayIndex > -1 && currentNode.isArray()) {
logger.debug("Going to take array node at index " + arrayIndex);
currentNode = currentNode.get(arrayIndex);
}
if (currentNode == null) {
logger.debug("JsonNode not found for name " + currentFieldName);
return null;
}
if (idx < 0) {
if (!currentNode.isValueNode()) {
logger.debug("JsonNode is not value node for name " + currentFieldName);
return null;
}
String ret = currentNode.asText();
if (ret != null && !ret.trim().isEmpty())
return ret.trim();
} else {
return getJsonValue(currentNode, fieldPath.substring(idx + 1));
}
}
return null;
}
}
@@ -1,105 +1,106 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClaimToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(CLAIM_VALUE);
property1.setLabel("Claim Value");
property1.setHelpText("Value the claim must have. If the claim is an array, then the value must be contained in the array.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if claim is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Claim to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!hasClaimValue(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ClaimToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(CLAIM_VALUE);
property1.setLabel("Claim Value");
property1.setHelpText("Value the claim must have. If the claim is an array, then the value must be contained in the array.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if claim is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "Claim to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (hasClaimValue(mapperModel, context)) {
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!hasClaimValue(mapperModel, context)) {
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
@@ -1,118 +1,119 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
private static final String EXTERNAL_ROLE = "external.role";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(EXTERNAL_ROLE);
property1.setLabel("External role");
property1.setHelpText("External role to check for. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if external role is present. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "External Role to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role != null) {
user.grantRole(role);
}
}
private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
//if (token == null) return;
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
String[] parseRole = HardcodedRoleMapper.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
String externalRoleName = parseRole[1];
String claimName = null;
if (parseRole[0] == null) {
claimName = "realm_access.roles";
} else {
claimName = "resource_access." + parseRole[0] + ".roles";
}
Object claim = getClaimValue(token, claimName);
if (valueEquals(externalRoleName, claim)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
return role;
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role == null) {
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "Looks for an external role in a keycloak access token. If external role exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProvider;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ExternalKeycloakRoleToRoleMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
private static final String EXTERNAL_ROLE = "external.role";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(EXTERNAL_ROLE);
property1.setLabel("External role");
property1.setHelpText("External role to check for. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user if external role is present. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "keycloak-oidc-role-to-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Importer";
}
@Override
public String getDisplayType() {
return "External Role to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role != null) {
user.grantRole(role);
}
}
private RoleModel hasRole(RealmModel realm,IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
JsonWebToken token = (JsonWebToken)context.getContextData().get(KeycloakOIDCIdentityProvider.VALIDATED_ACCESS_TOKEN);
//if (token == null) return;
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
String[] parseRole = KeycloakModelUtils.parseRole(mapperModel.getConfig().get(EXTERNAL_ROLE));
String externalRoleName = parseRole[1];
String claimName = null;
if (parseRole[0] == null) {
claimName = "realm_access.roles";
} else {
claimName = "resource_access." + parseRole[0] + ".roles";
}
Object claim = getClaimValue(token, claimName);
if (valueEquals(externalRoleName, claim)) {
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
return role;
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
RoleModel role = hasRole(realm, mapperModel, context);
if (role == null) {
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "Looks for an external role in a keycloak access token. If external role exists, grant the user the specified realm or application role.";
}
}
@@ -1,100 +1,98 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
if (value != null) {
user.setAttribute(attribute, value.toString());
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
String current = user.getAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared claim if it exists in ID or access token into the specified user attribute.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
ProviderConfigProperty property1;
property1 = new ProviderConfigProperty();
property1.setName(CLAIM);
property1.setLabel("Claim");
property1.setHelpText("Name of claim to search for in token. You can reference nested claims using a '.', i.e. 'address.locality'.");
property1.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property1);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
if (value != null) {
context.setUserAttribute(attribute, value.toString());
}
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getClaimValue(mapperModel, context);
String current = user.getFirstAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setSingleAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared claim if it exists in ID or access token into the specified user attribute.";
}
}
@@ -1,109 +1,105 @@
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${CLAIM.sub}'. ALIAS is the provider alias. CLAIM.<NAME> references an ID or Access token claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${CLAIM.preferred_username}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.startsWith("CLAIM.")) {
String name = variable.substring("CLAIM.".length());
Object value = AbstractClaimMapper.getClaimValue(context, name);
if (value == null) value = "";
m.appendReplacement(sb, value.toString());
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
String username = sb.toString();
context.setModelUsername(username);
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
package org.keycloak.broker.oidc.mappers;
import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory;
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractClaimMapper {
public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${CLAIM.sub}'. ALIAS is the provider alias. CLAIM.<NAME> references an ID or Access token claim.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${CLAIM.preferred_username}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "oidc-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.startsWith("CLAIM.")) {
String name = variable.substring("CLAIM.".length());
Object value = AbstractClaimMapper.getClaimValue(context, name);
if (value == null) value = "";
m.appendReplacement(sb, value.toString());
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
String username = sb.toString();
context.setModelUsername(username);
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
@@ -1,32 +1,32 @@
package org.keycloak.broker.oidc.util;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.keycloak.broker.provider.util.SimpleHttp;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JsonSimpleHttp extends SimpleHttp {
public JsonSimpleHttp(String url, String method) {
super(url, method);
}
public static JsonSimpleHttp doGet(String url) {
return new JsonSimpleHttp(url, "GET");
}
public static JsonSimpleHttp doPost(String url) {
return new JsonSimpleHttp(url, "POST");
}
private static ObjectMapper mapper = new ObjectMapper();
public static JsonNode asJson(SimpleHttp request) throws IOException {
return mapper.readTree(request.asString());
}
}
package org.keycloak.broker.oidc.util;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.keycloak.broker.provider.util.SimpleHttp;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JsonSimpleHttp extends SimpleHttp {
public JsonSimpleHttp(String url, String method) {
super(url, method);
}
public static JsonSimpleHttp doGet(String url) {
return new JsonSimpleHttp(url, "GET");
}
public static JsonSimpleHttp doPost(String url) {
return new JsonSimpleHttp(url, "POST");
}
private static ObjectMapper mapper = new ObjectMapper();
public static JsonNode asJson(SimpleHttp request) throws IOException {
return mapper.readTree(request.asString());
}
}
@@ -1,2 +1,2 @@
org.keycloak.broker.oidc.OIDCIdentityProviderFactory
org.keycloak.broker.oidc.OIDCIdentityProviderFactory
org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory
@@ -1,4 +1,4 @@
org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
org.keycloak.broker.oidc.mappers.UserAttributeMapper
org.keycloak.broker.oidc.mappers.ClaimToRoleMapper
org.keycloak.broker.oidc.mappers.ExternalKeycloakRoleToRoleMapper
org.keycloak.broker.oidc.mappers.UserAttributeMapper
org.keycloak.broker.oidc.mappers.UsernameTemplateMapper
+23 -23
View File
@@ -1,23 +1,23 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.4.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-parent</artifactId>
<name>Keycloak Broker Parent</name>
<description/>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>oidc</module>
<module>saml</module>
</modules>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.8.0.CR1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-parent</artifactId>
<name>Keycloak Broker Parent</name>
<description/>
<packaging>pom</packaging>
<modules>
<module>core</module>
<module>oidc</module>
<module>saml</module>
</modules>
</project>
+55 -50
View File
@@ -1,50 +1,55 @@
<?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.4.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-saml</artifactId>
<name>Keycloak Broker - SAML Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-protocol</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.8.0.CR1</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-broker-saml</artifactId>
<name>Keycloak Broker - SAML Identity Provider</name>
<description/>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-broker-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-protocol</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-events-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<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);
}
}
}
@@ -1,491 +1,447 @@
package org.keycloak.broker.saml;
import org.jboss.logging.Logger;
import org.keycloak.ClientConnection;
import org.keycloak.VerificationException;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
import org.keycloak.protocol.saml.SAMLRequestParser;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlProtocolUtils;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
import org.keycloak.saml.processing.web.util.PostBindingUtil;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SAMLEndpoint {
protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
public static final String SAML_ASSERTION = "SAML_ASSERTION";
public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
protected RealmModel realm;
protected EventBuilder event;
protected SAMLIdentityProviderConfig config;
protected IdentityProvider.AuthenticationCallback callback;
protected SAMLIdentityProvider provider;
@Context
private UriInfo uriInfo;
@Context
private KeycloakSession session;
@Context
private ClientConnection clientConnection;
@Context
private HttpHeaders headers;
public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
this.realm = realm;
this.config = config;
this.callback = callback;
this.provider = provider;
}
@GET
public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
}
/**
*/
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@FormParam(GeneralConstants.RELAY_STATE) String relayState) {
return new PostBinding().execute(samlRequest, samlResponse, relayState);
}
protected abstract class Binding {
private boolean checkSsl() {
if (uriInfo.getBaseUri().getScheme().equals("https")) {
return true;
} else {
return !realm.getSslRequired().isRequired(clientConnection);
}
}
protected Response basicChecks(String samlRequest, String samlResponse) {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
}
protected abstract String getBindingType();
protected abstract void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException;
protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
protected PublicKey getIDPKey() {
X509Certificate certificate = null;
try {
certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return certificate.getPublicKey();
}
public Response execute(String samlRequest, String samlResponse, String relayState) {
event = new EventBuilder(realm, session, clientConnection);
Response response = basicChecks(samlRequest, samlResponse);
if (response != null) return response;
if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
else return handleSamlResponse(samlResponse, relayState);
}
protected Response handleSamlRequest(String samlRequest, String relayState) {
SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
// validate destination
if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
if (config.isValidateSignature()) {
try {
verifySignature(holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
}
if (requestAbstractType instanceof LogoutRequestType) {
logger.debug("** logout request");
event.event(EventType.LOGOUT);
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
return logoutRequest(logout, relayState);
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
protected Response logoutRequest(LogoutRequestType request, String relayState) {
String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
for (UserSessionModel userSession : userSessions) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
} else {
for (String sessionIndex : request.getSessionIndex()) {
String brokerSessionId = brokerUserId + "." + sessionIndex;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
}
}
String issuerURL = getEntityId(uriInfo, realm);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(request.getID());
builder.destination(config.getSingleLogoutServiceUrl());
builder.issuer(issuerURL);
builder.relayState(relayState);
if (config.isWantAuthnRequestsSigned()) {
builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signDocument();
}
try {
if (config.isPostBindingResponse()) {
return builder.postBinding().response();
} else {
return builder.redirectBinding().response();
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
} catch (ProcessingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getEntityId(UriInfo uriInfo, RealmModel realm) {
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
}
protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
try {
AssertionType assertion = getAssertion(responseType);
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
//Map<String, String> notes = new HashMap<>();
BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
identity.setCode(relayState);
identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
identity.getContextData().put(SAML_ASSERTION, assertion);
identity.setUsername(subjectNameID.getValue());
if (subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
identity.setEmail(subjectNameID.getValue());
}
if (config.isStoreToken()) {
identity.setToken(samlResponse);
}
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType)statement;
identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
break;
}
}
if (assertion.getAttributeStatements() != null ) {
for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
AttributeType attribute = choice.getAttribute();
if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
|| X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
}
}
}
}
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
identity.setBrokerUserId(brokerUserId);
identity.setIdpConfig(config);
identity.setIdp(provider);
if (authn != null && authn.getSessionIndex() != null) {
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
}
return callback.authenticated(identity);
} catch (Exception e) {
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
}
}
private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
if (assertions.isEmpty()) {
throw new IdentityBrokerException("No assertion from response.");
}
ResponseType.RTChoiceType rtChoiceType = assertions.get(0);
EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
if (encryptedAssertion != null) {
decryptAssertion(responseType, realm.getPrivateKey());
}
return responseType.getAssertions().get(0).getAssertion();
}
public Response handleSamlResponse(String samlResponse, String relayState) {
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
// validate destination
if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
if (config.isValidateSignature()) {
try {
verifySignature(holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
}
if (statusResponse instanceof ResponseType) {
return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
} else {
// todo need to check that it is actually a LogoutResponse
return handleLogoutResponse(holder, statusResponse, relayState);
}
//throw new RuntimeException("Unknown response type");
}
protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
if (relayState == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}
protected ResponseType decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ProcessingException {
SAML2Response saml2Response = new SAML2Response();
try {
Document doc = saml2Response.convert(responseType);
Element enc = DocumentUtil.getElement(doc, new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
if (enc == null) {
throw new IdentityBrokerException("No encrypted assertion found.");
}
String oldID = enc.getAttribute(JBossSAMLConstants.ID.get());
Document newDoc = DocumentUtil.createDocument();
Node importedNode = newDoc.importNode(enc, true);
newDoc.appendChild(importedNode);
Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
SAMLParser parser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
.getNodeAsStream(decryptedDocumentElement)));
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
return responseType;
} catch (Exception e) {
throw new IdentityBrokerException("Could not decrypt assertion.", e);
}
}
}
protected class PostBinding extends Binding {
@Override
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestPostBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
byte[] samlBytes = PostBindingUtil.base64Decode(response);
String xml = new String(samlBytes);
return SAMLRequestParser.parseResponseDocument(samlBytes);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_POST_BINDING;
}
}
protected class RedirectBinding extends Binding {
@Override
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
PublicKey publicKey = getIDPKey();
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
return SAMLRequestParser.parseRequestRedirectBinding(response);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_REDIRECT_BINDING;
}
}
}
package org.keycloak.broker.saml;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.VerificationException;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
import org.keycloak.dom.saml.v2.protocol.ResponseType;
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
import org.keycloak.saml.SAML2LogoutResponseBuilder;
import org.keycloak.saml.SAMLRequestParser;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlProtocolUtils;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
import org.keycloak.saml.processing.web.util.PostBindingUtil;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SAMLEndpoint {
protected static final Logger logger = Logger.getLogger(SAMLEndpoint.class);
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
public static final String SAML_ASSERTION = "SAML_ASSERTION";
public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
protected RealmModel realm;
protected EventBuilder event;
protected SAMLIdentityProviderConfig config;
protected IdentityProvider.AuthenticationCallback callback;
protected SAMLIdentityProvider provider;
@Context
private UriInfo uriInfo;
@Context
private KeycloakSession session;
@Context
private ClientConnection clientConnection;
@Context
private HttpHeaders headers;
public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
this.realm = realm;
this.config = config;
this.callback = callback;
this.provider = provider;
}
@GET
@NoCache
@Path("descriptor")
public Response getSPDescriptor() {
return provider.export(uriInfo, realm, null);
}
@GET
public Response redirectBinding(@QueryParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@QueryParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@QueryParam(GeneralConstants.RELAY_STATE) String relayState) {
return new RedirectBinding().execute(samlRequest, samlResponse, relayState);
}
/**
*/
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postBinding(@FormParam(GeneralConstants.SAML_REQUEST_KEY) String samlRequest,
@FormParam(GeneralConstants.SAML_RESPONSE_KEY) String samlResponse,
@FormParam(GeneralConstants.RELAY_STATE) String relayState) {
return new PostBinding().execute(samlRequest, samlResponse, relayState);
}
protected abstract class Binding {
private boolean checkSsl() {
if (uriInfo.getBaseUri().getScheme().equals("https")) {
return true;
} else {
return !realm.getSslRequired().isRequired(clientConnection);
}
}
protected Response basicChecks(String samlRequest, String samlResponse) {
if (!checkSsl()) {
event.event(EventType.LOGIN);
event.error(Errors.SSL_REQUIRED);
return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
}
if (!realm.isEnabled()) {
event.event(EventType.LOGIN_ERROR);
event.error(Errors.REALM_DISABLED);
return ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
}
if (samlRequest == null && samlResponse == null) {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_REQUEST);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
return null;
}
protected abstract String getBindingType();
protected abstract void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException;
protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
protected PublicKey getIDPKey() {
X509Certificate certificate = null;
try {
certificate = XMLSignatureUtil.getX509CertificateFromKeyInfoString(config.getSigningCertificate().replaceAll("\\s", ""));
} catch (ProcessingException e) {
throw new RuntimeException(e);
}
return certificate.getPublicKey();
}
public Response execute(String samlRequest, String samlResponse, String relayState) {
event = new EventBuilder(realm, session, clientConnection);
Response response = basicChecks(samlRequest, samlResponse);
if (response != null) return response;
if (samlRequest != null) return handleSamlRequest(samlRequest, relayState);
else return handleSamlResponse(samlResponse, relayState);
}
protected Response handleSamlRequest(String samlRequest, String relayState) {
SAMLDocumentHolder holder = extractRequestDocument(samlRequest);
RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
// validate destination
if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
if (config.isValidateSignature()) {
try {
verifySignature(GeneralConstants.SAML_REQUEST_KEY, holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_REQUESTER);
}
}
if (requestAbstractType instanceof LogoutRequestType) {
logger.debug("** logout request");
event.event(EventType.LOGOUT);
LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
return logoutRequest(logout, relayState);
} else {
event.event(EventType.LOGIN);
event.error(Errors.INVALID_TOKEN);
return ErrorPage.error(session, Messages.INVALID_REQUEST);
}
}
protected Response logoutRequest(LogoutRequestType request, String relayState) {
String brokerUserId = config.getAlias() + "." + request.getNameID().getValue();
if (request.getSessionIndex() == null || request.getSessionIndex().isEmpty()) {
List<UserSessionModel> userSessions = session.sessions().getUserSessionByBrokerUserId(realm, brokerUserId);
for (UserSessionModel userSession : userSessions) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
} else {
for (String sessionIndex : request.getSessionIndex()) {
String brokerSessionId = brokerUserId + "." + sessionIndex;
UserSessionModel userSession = session.sessions().getUserSessionByBrokerSessionId(realm, brokerSessionId);
if (userSession != null) {
if (userSession.getState() == UserSessionModel.State.LOGGING_OUT || userSession.getState() == UserSessionModel.State.LOGGED_OUT) {
continue;
}
try {
AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, clientConnection, headers, false);
} catch (Exception e) {
logger.warn("failed to do backchannel logout for userSession", e);
}
}
}
}
String issuerURL = getEntityId(uriInfo, realm);
SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
builder.logoutRequestID(request.getID());
builder.destination(config.getSingleLogoutServiceUrl());
builder.issuer(issuerURL);
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(relayState);
if (config.isWantAuthnRequestsSigned()) {
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signatureAlgorithm(provider.getSignatureAlgorithm())
.signDocument();
}
try {
if (config.isPostBindingResponse()) {
return binding.postBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
} else {
return binding.redirectBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
}
} catch (ConfigurationException e) {
throw new RuntimeException(e);
} catch (ProcessingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getEntityId(UriInfo uriInfo, RealmModel realm) {
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
}
protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
try {
AssertionType assertion = AssertionUtil.getAssertion(responseType, realm.getPrivateKey());
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
//Map<String, String> notes = new HashMap<>();
BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
identity.setCode(relayState);
identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
identity.getContextData().put(SAML_ASSERTION, assertion);
identity.setUsername(subjectNameID.getValue());
//SAML Spec 2.2.2 Format is optional
if (subjectNameID.getFormat() != null && subjectNameID.getFormat().toString().equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
identity.setEmail(subjectNameID.getValue());
}
if (config.isStoreToken()) {
identity.setToken(samlResponse);
}
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType)statement;
identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
break;
}
}
if (assertion.getAttributeStatements() != null ) {
for (AttributeStatementType attrStatement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : attrStatement.getAttributes()) {
AttributeType attribute = choice.getAttribute();
if (X500SAMLProfileConstants.EMAIL.getFriendlyName().equals(attribute.getFriendlyName())
|| X500SAMLProfileConstants.EMAIL.get().equals(attribute.getName())) {
if (!attribute.getAttributeValue().isEmpty()) identity.setEmail(attribute.getAttributeValue().get(0).toString());
}
}
}
}
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
identity.setBrokerUserId(brokerUserId);
identity.setIdpConfig(config);
identity.setIdp(provider);
if (authn != null && authn.getSessionIndex() != null) {
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
}
return callback.authenticated(identity);
} catch (Exception e) {
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
}
}
public Response handleSamlResponse(String samlResponse, String relayState) {
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
StatusResponseType statusResponse = (StatusResponseType)holder.getSamlObject();
// validate destination
if (statusResponse.getDestination() != null && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.detail(Details.REASON, "invalid_destination");
event.error(Errors.INVALID_SAML_RESPONSE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
if (config.isValidateSignature()) {
try {
verifySignature(GeneralConstants.SAML_RESPONSE_KEY, holder);
} catch (VerificationException e) {
logger.error("validation failed", e);
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
event.error(Errors.INVALID_SIGNATURE);
return ErrorPage.error(session, Messages.INVALID_FEDERATED_IDENTITY_ACTION);
}
}
if (statusResponse instanceof ResponseType) {
return handleLoginResponse(samlResponse, holder, (ResponseType)statusResponse, relayState);
} else {
// todo need to check that it is actually a LogoutResponse
return handleLogoutResponse(holder, statusResponse, relayState);
}
//throw new RuntimeException("Unknown response type");
}
protected Response handleLogoutResponse(SAMLDocumentHolder holder, StatusResponseType responseType, String relayState) {
if (relayState == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
UserSessionModel userSession = session.sessions().getUserSession(realm, relayState);
if (userSession == null) {
logger.error("no valid user session");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
}
if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
logger.error("usersession in different state");
event.event(EventType.LOGOUT);
event.error(Errors.USER_SESSION_NOT_FOUND);
return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
}
return AuthenticationManager.finishBrowserLogout(session, realm, userSession, uriInfo, clientConnection, headers);
}
}
protected class PostBinding extends Binding {
@Override
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestPostBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
byte[] samlBytes = PostBindingUtil.base64Decode(response);
String xml = new String(samlBytes);
return SAMLRequestParser.parseResponseDocument(samlBytes);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_POST_BINDING;
}
}
protected class RedirectBinding extends Binding {
@Override
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
PublicKey publicKey = getIDPKey();
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo, key);
}
@Override
protected SAMLDocumentHolder extractRequestDocument(String samlRequest) {
return SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
}
@Override
protected SAMLDocumentHolder extractResponseDocument(String response) {
return SAMLRequestParser.parseRequestRedirectBinding(response);
}
@Override
protected String getBindingType() {
return SamlProtocol.SAML_REDIRECT_BINDING;
}
}
}
@@ -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;
@@ -33,20 +34,18 @@ import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.saml.SAML2AuthnRequestBuilder;
import org.keycloak.protocol.saml.SAML2LogoutRequestBuilder;
import org.keycloak.protocol.saml.SAML2NameIDPolicyBuilder;
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
import org.keycloak.saml.SAML2AuthnRequestBuilder;
import org.keycloak.saml.SAML2LogoutRequestBuilder;
import org.keycloak.saml.SAML2NameIDPolicyBuilder;
import org.keycloak.saml.SignatureAlgorithm;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -92,7 +91,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
.issuer(issuerURL)
.forceAuthn(getConfig().isForceAuthn())
.protocolBinding(protocolBinding)
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat))
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat));
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(request.getState());
if (getConfig().isWantAuthnRequestsSigned()) {
@@ -109,14 +109,15 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
KeyPair keypair = new KeyPair(publicKey, privateKey);
authnRequestBuilder.signWith(keypair);
authnRequestBuilder.signDocument();
binding.signWith(keypair);
binding.signatureAlgorithm(getSignatureAlgorithm());
binding.signDocument();
}
if (getConfig().isPostBindingAuthnRequest()) {
return authnRequestBuilder.postBinding().request();
return binding.postBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
} else {
return authnRequestBuilder.redirectBinding().request();
return binding.redirectBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
}
} catch (Exception e) {
throw new IdentityBrokerException("Could not create authentication request.", e);
@@ -153,9 +154,10 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl();
if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("") || !getConfig().isBackchannelSupported()) return;
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
try {
int status = SimpleHttp.doPost(singleLogoutServiceUrl)
.param(GeneralConstants.SAML_REQUEST_KEY, logoutBuilder.postBinding().encoded())
.param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(logoutBuilder.buildDocument()).encoded())
.param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus();
boolean success = status >=200 && status < 400;
if (!success) {
@@ -178,7 +180,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
} else {
try {
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
return logoutBuilder.postBinding().request();
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
return binding.postBinding(logoutBuilder.buildDocument()).request(singleLogoutServiceUrl);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -192,13 +195,19 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
.issuer(getEntityId(uriInfo, realm))
.sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX))
.userPrincipal(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT), userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEFORMAT))
.destination(singleLogoutServiceUrl)
.destination(singleLogoutServiceUrl);
return logoutBuilder;
}
private JaxrsSAML2BindingBuilder buildLogoutBinding(UserSessionModel userSession, RealmModel realm) {
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
.relayState(userSession.getId());
if (getConfig().isWantAuthnRequestsSigned()) {
logoutBuilder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
.signatureAlgorithm(getSignatureAlgorithm())
.signDocument();
}
return logoutBuilder;
return binding;
}
@Override
@@ -220,7 +229,7 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
String descriptor =
"<EntityDescriptor entityID=\"" + getEntityId(uriInfo, realm) + "\">\n" +
"<EntityDescriptor xmlns=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"" + getEntityId(uriInfo, realm) + "\">\n" +
" <SPSSODescriptor AuthnRequestsSigned=\"" + getConfig().isWantAuthnRequestsSigned() + "\"\n" +
" protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol http://schemas.xmlsoap.org/ws/2003/07/secext\">\n" +
" <NameIDFormat>" + getConfig().getNameIDPolicyFormat() + "\n" +
@@ -245,4 +254,18 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
"</EntityDescriptor>\n";
return Response.ok(descriptor, MediaType.APPLICATION_XML_TYPE).build();
}
public SignatureAlgorithm getSignatureAlgorithm() {
String alg = getConfig().getSignatureAlgorithm();
if (alg != null) {
SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(alg);
if (algorithm != null) return algorithm;
}
return SignatureAlgorithm.RSA_SHA256;
}
@Override
public IdentityProviderDataMarshaller getMarshaller() {
return new SAMLDataMarshaller();
}
}
@@ -87,6 +87,14 @@ public class SAMLIdentityProviderConfig extends IdentityProviderModel {
getConfig().put("wantAuthnRequestsSigned", String.valueOf(wantAuthnRequestsSigned));
}
public String getSignatureAlgorithm() {
return getConfig().get("signatureAlgorithm");
}
public void setSignatureAlgorithm(String signatureAlgorithm) {
getConfig().put("signatureAlgorithm", signatureAlgorithm);
}
public String getEncryptionPublicKey() {
return getConfig().get("encryptionPublicKey");
}
@@ -73,75 +73,79 @@ public class SAMLIdentityProviderFactory extends AbstractIdentityProviderFactory
List<EntityDescriptorType.EDTChoiceType> choiceType = entityType.getChoiceType();
if (!choiceType.isEmpty()) {
EntityDescriptorType.EDTChoiceType edtChoiceType = choiceType.get(0);
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
IDPSSODescriptorType idpDescriptor = null;
if (!descriptors.isEmpty()) {
EntityDescriptorType.EDTDescriptorChoiceType edtDescriptorChoiceType = descriptors.get(0);
IDPSSODescriptorType idpDescriptor = edtDescriptorChoiceType.getIdpDescriptor();
//Metadata documents can contain multiple Descriptors (See ADFS metadata documents) such as RoleDescriptor, SPSSODescriptor, IDPSSODescriptor.
//So we need to loop through to find the IDPSSODescriptor.
for(EntityDescriptorType.EDTChoiceType edtChoiceType : entityType.getChoiceType()) {
List<EntityDescriptorType.EDTDescriptorChoiceType> descriptors = edtChoiceType.getDescriptors();
if (idpDescriptor != null) {
SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
String singleSignOnServiceUrl = null;
boolean postBinding = false;
for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleSignOnServiceUrl = endpoint.getLocation().toString();
postBinding = true;
break;
} else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleSignOnServiceUrl = endpoint.getLocation().toString();
}
}
String singleLogoutServiceUrl = null;
for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
} else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
}
}
samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setPostBindingResponse(postBinding);
samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
String defaultCertificate = null;
if (keyDescriptor != null) {
for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
Element keyInfo = keyDescriptorType.getKeyInfo();
Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
} else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
} else if (keyDescriptorType.getUse() == null) {
defaultCertificate = x509KeyInfo.getTextContent();
}
}
}
if (defaultCertificate != null) {
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
}
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
}
}
return samlIdentityProviderConfig.getConfig();
if(!descriptors.isEmpty() && descriptors.get(0).getIdpDescriptor() != null) {
idpDescriptor = descriptors.get(0).getIdpDescriptor();
}
}
if (idpDescriptor != null) {
SAMLIdentityProviderConfig samlIdentityProviderConfig = new SAMLIdentityProviderConfig();
String singleSignOnServiceUrl = null;
boolean postBinding = false;
for (EndpointType endpoint : idpDescriptor.getSingleSignOnService()) {
if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleSignOnServiceUrl = endpoint.getLocation().toString();
postBinding = true;
break;
} else if (endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleSignOnServiceUrl = endpoint.getLocation().toString();
}
}
String singleLogoutServiceUrl = null;
for (EndpointType endpoint : idpDescriptor.getSingleLogoutService()) {
if (postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_POST_BINDING.get())) {
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
} else if (!postBinding && endpoint.getBinding().toString().equals(JBossSAMLURIConstants.SAML_HTTP_REDIRECT_BINDING.get())){
singleLogoutServiceUrl = endpoint.getLocation().toString();
break;
}
}
samlIdentityProviderConfig.setSingleLogoutServiceUrl(singleLogoutServiceUrl);
samlIdentityProviderConfig.setSingleSignOnServiceUrl(singleSignOnServiceUrl);
samlIdentityProviderConfig.setWantAuthnRequestsSigned(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setValidateSignature(idpDescriptor.isWantAuthnRequestsSigned());
samlIdentityProviderConfig.setPostBindingResponse(postBinding);
samlIdentityProviderConfig.setPostBindingAuthnRequest(postBinding);
List<KeyDescriptorType> keyDescriptor = idpDescriptor.getKeyDescriptor();
String defaultCertificate = null;
if (keyDescriptor != null) {
for (KeyDescriptorType keyDescriptorType : keyDescriptor) {
Element keyInfo = keyDescriptorType.getKeyInfo();
Element x509KeyInfo = DocumentUtil.getChildElement(keyInfo, new QName("dsig", "X509Certificate"));
if (KeyTypes.SIGNING.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setSigningCertificate(x509KeyInfo.getTextContent());
} else if (KeyTypes.ENCRYPTION.equals(keyDescriptorType.getUse())) {
samlIdentityProviderConfig.setEncryptionPublicKey(x509KeyInfo.getTextContent());
} else if (keyDescriptorType.getUse() == null) {
defaultCertificate = x509KeyInfo.getTextContent();
}
}
}
if (defaultCertificate != null) {
if (samlIdentityProviderConfig.getSigningCertificate() == null) {
samlIdentityProviderConfig.setSigningCertificate(defaultCertificate);
}
if (samlIdentityProviderConfig.getEncryptionPublicKey() == null) {
samlIdentityProviderConfig.setEncryptionPublicKey(defaultCertificate);
}
}
return samlIdentityProviderConfig.getConfig();
}
}
} catch (ParsingException pe) {
throw new RuntimeException("Could not parse IdP SAML Metadata", pe);
@@ -1,140 +1,141 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String ATTRIBUTE_VALUE = "attribute.value";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("Attribute Value");
property.setHelpText("Value the attribute must have. If the attribute is a list, then the value must be contained in the list.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Mapper";
}
@Override
public String getDisplayType() {
return "SAML Attribute to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
for (Object val : attr.getAttributeValue()) {
if (val.equals(desiredValue)) return true;
}
}
}
return false;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!isAttributePresent(mapperModel, context)) {
RoleModel role = HardcodedRoleMapper.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.HardcodedRoleMapper;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AttributeToRoleMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String ATTRIBUTE_VALUE = "attribute.value";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_VALUE);
property.setLabel("Attribute Value");
property.setHelpText("Value the attribute must have. If the attribute is a list, then the value must be contained in the list.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(HardcodedRoleMapper.ROLE);
property.setLabel("Role");
property.setHelpText("Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
property.setType(ProviderConfigProperty.ROLE_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-role-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Role Mapper";
}
@Override
public String getDisplayType() {
return "SAML Attribute to Role";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (isAttributePresent(mapperModel, context)) {
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.grantRole(role);
}
}
protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
for (Object val : attr.getAttributeValue()) {
if (val.equals(desiredValue)) return true;
}
}
}
return false;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String roleName = mapperModel.getConfig().get(HardcodedRoleMapper.ROLE);
if (!isAttributePresent(mapperModel, context)) {
RoleModel role = KeycloakModelUtils.getRoleFromString(realm, roleName);
if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
user.deleteRoleMapping(role);
}
}
@Override
public String getHelpText() {
return "If a claim exists, grant the user the specified realm or application role.";
}
}
@@ -1,132 +1,129 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.ClientModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store saml attribute.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
if (value != null) {
user.setAttribute(attribute, value.toString());
}
}
protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue == null || attributeValue.isEmpty()) return null;
return attributeValue.get(0).toString();
}
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
String current = user.getAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
}
}
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserAttributeMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String ATTRIBUTE_NAME = "attribute.name";
public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
public static final String USER_ATTRIBUTE = "user.attribute";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_NAME);
property.setLabel("Attribute Name");
property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(ATTRIBUTE_FRIENDLY_NAME);
property.setLabel("Friendly Name");
property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(USER_ATTRIBUTE);
property.setLabel("User Attribute Name");
property.setHelpText("User attribute name to store saml attribute.");
property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-user-attribute-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Attribute Importer";
}
@Override
public String getDisplayType() {
return "Attribute Importer";
}
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
if (value != null) {
context.setUserAttribute(attribute, value.toString());
}
}
protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
if (name != null && name.trim().equals("")) name = null;
String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
if (friendly != null && friendly.trim().equals("")) friendly = null;
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name != null && !name.equals(attr.getName())) continue;
if (friendly != null && !friendly.equals(attr.getFriendlyName())) continue;
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue == null || attributeValue.isEmpty()) return null;
return attributeValue.get(0).toString();
}
}
return null;
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE);
Object value = getAttribute(mapperModel, context);
String current = user.getFirstAttribute(attribute);
if (value != null && !value.equals(current)) {
user.setSingleAttribute(attribute, value.toString());
} else if (value == null) {
user.removeAttribute(attribute);
}
}
@Override
public String getHelpText() {
return "Import declared saml attribute if it exists in assertion into the specified user attribute.";
}
}
@@ -1,133 +1,128 @@
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${NAMEID}'. ALIAS is the provider alias. NAMEID is that SAML name id assertion. ATTRIBUTE.<NAME> references a SAML attribute where name is the attribute name or friendly name.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${NAMEID}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.equals("NAMEID")) {
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
m.appendReplacement(sb, subjectNameID.getValue());
} else if (variable.startsWith("ATTRIBUTE.")) {
String name = variable.substring("ATTRIBUTE.".length());
String value = "";
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name.equals(attr.getName()) || name.equals(attr.getFriendlyName())) {
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue != null && !attributeValue.isEmpty()) {
value = attributeValue.get(0).toString();
}
break;
}
}
}
m.appendReplacement(sb, value);
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
context.setModelUsername(sb.toString());
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
package org.keycloak.broker.saml.mappers;
import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.saml.SAMLEndpoint;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
import org.keycloak.dom.saml.v2.assertion.AttributeType;
import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.assertion.SubjectType;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UsernameTemplateMapper extends AbstractIdentityProviderMapper {
public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String TEMPLATE = "template";
static {
ProviderConfigProperty property;
property = new ProviderConfigProperty();
property.setName(TEMPLATE);
property.setLabel("Template");
property.setHelpText("Template to use to format the username to import. Substitutions are enclosed in ${}. For example: '${ALIAS}.${NAMEID}'. ALIAS is the provider alias. NAMEID is that SAML name id assertion. ATTRIBUTE.<NAME> references a SAML attribute where name is the attribute name or friendly name.");
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setDefaultValue("${ALIAS}.${NAMEID}");
configProperties.add(property);
}
public static final String PROVIDER_ID = "saml-username-idp-mapper";
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return configProperties;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public String[] getCompatibleProviders() {
return COMPATIBLE_PROVIDERS;
}
@Override
public String getDisplayCategory() {
return "Preprocessor";
}
@Override
public String getDisplayType() {
return "Username Template Importer";
}
@Override
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
}
static Pattern substitution = Pattern.compile("\\$\\{([^}]+)\\}");
@Override
public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
String template = mapperModel.getConfig().get(TEMPLATE);
Matcher m = substitution.matcher(template);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String variable = m.group(1);
if (variable.equals("ALIAS")) {
m.appendReplacement(sb, context.getIdpConfig().getAlias());
} else if (variable.equals("UUID")) {
m.appendReplacement(sb, KeycloakModelUtils.generateId());
} else if (variable.equals("NAMEID")) {
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
m.appendReplacement(sb, subjectNameID.getValue());
} else if (variable.startsWith("ATTRIBUTE.")) {
String name = variable.substring("ATTRIBUTE.".length());
String value = "";
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
AttributeType attr = choice.getAttribute();
if (name.equals(attr.getName()) || name.equals(attr.getFriendlyName())) {
List<Object> attributeValue = attr.getAttributeValue();
if (attributeValue != null && !attributeValue.isEmpty()) {
value = attributeValue.get(0).toString();
}
break;
}
}
}
m.appendReplacement(sb, value);
} else {
m.appendReplacement(sb, m.group(1));
}
}
m.appendTail(sb);
context.setModelUsername(sb.toString());
}
@Override
public String getHelpText() {
return "Format the username to import.";
}
}
@@ -1,3 +1,3 @@
org.keycloak.broker.saml.mappers.AttributeToRoleMapper
org.keycloak.broker.saml.mappers.UserAttributeMapper
org.keycloak.broker.saml.mappers.AttributeToRoleMapper
org.keycloak.broker.saml.mappers.UserAttributeMapper
org.keycloak.broker.saml.mappers.UsernameTemplateMapper
@@ -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);
}
}
+26
View File
@@ -0,0 +1,26 @@
<?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.8.0.CR1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-client-registration-api</artifactId>
<name>Keycloak Client Registration API</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</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,16 @@
package org.keycloak.client.registration;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class ClientRegistrationException extends Exception {
public ClientRegistrationException(String s, Throwable throwable) {
super(s, throwable);
}
public ClientRegistrationException(String s) {
super(s);
}
}
@@ -0,0 +1,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,22 @@
package org.keycloak.client.registration;
import org.apache.http.StatusLine;
import java.io.IOException;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class HttpErrorException extends IOException {
private StatusLine statusLine;
public HttpErrorException(StatusLine statusLine) {
this.statusLine = statusLine;
}
public StatusLine getStatusLine() {
return statusLine;
}
}
@@ -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.CR1</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>
Executable
+94
View File
@@ -0,0 +1,94 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.8.0.CR1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-common</artifactId>
<name>Keycloak Common</name>
<packaging>jar</packaging>
<description>Common library and dependencies shared with server and all adapters</description>
<properties>
<timestamp>${maven.build.timestamp}</timestamp>
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
<keycloak.osgi.export>
org.keycloak.common.*
</keycloak.osgi.export>
<keycloak.osgi.import>
*;resolution:=optional
</keycloak.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-ClassPath>.</Bundle-ClassPath>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Import-Package>${keycloak.osgi.import}</Import-Package>
<Export-Package>${keycloak.osgi.export}</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,13 +1,13 @@
package org.keycloak;
/**
* Information about the client connection
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientConnection {
String getRemoteAddr();
String getRemoteHost();
int getReportPort();
}
package org.keycloak.common;
/**
* Information about the client connection
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface ClientConnection {
String getRemoteAddr();
String getRemoteHost();
int getReportPort();
}
@@ -1,4 +1,4 @@
package org.keycloak;
package org.keycloak.common;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+41
View File
@@ -0,0 +1,41 @@
package org.keycloak.common;
import org.keycloak.common.util.Time;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Version {
public static final String UNKNOWN = "UNKNOWN";
public static String NAME;
public static String NAME_HTML;
public static String VERSION;
public static String RESOURCES_VERSION;
public static String BUILD_TIME;
static {
Properties props = new Properties();
InputStream is = Version.class.getResourceAsStream("/keycloak-version.properties");
try {
props.load(is);
Version.NAME = props.getProperty("name");
Version.NAME_HTML = props.getProperty("name-html");
Version.VERSION = props.getProperty("version");
Version.BUILD_TIME = props.getProperty("build-time");
Version.RESOURCES_VERSION = Version.VERSION.toLowerCase();
if (Version.RESOURCES_VERSION.endsWith("-snapshot")) {
Version.RESOURCES_VERSION = Version.RESOURCES_VERSION.replace("-snapshot", "-" + Time.currentTime());
}
} catch (IOException e) {
Version.VERSION= Version.UNKNOWN;
Version.BUILD_TIME= Version.UNKNOWN;
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.constants;
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,4 +1,4 @@
package org.keycloak.constants;
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -0,0 +1,19 @@
package org.keycloak.common.constants;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface ServiceAccountConstants {
String CLIENT_AUTH = "client_auth";
String SERVICE_ACCOUNT_USER_PREFIX = "service-account-";
String CLIENT_ID_PROTOCOL_MAPPER = "Client ID";
String CLIENT_HOST_PROTOCOL_MAPPER = "Client Host";
String CLIENT_ADDRESS_PROTOCOL_MAPPER = "Client IP Address";
String CLIENT_ID = "clientId";
String CLIENT_HOST = "clientHost";
String CLIENT_ADDRESS = "clientAddress";
}
@@ -1,4 +1,4 @@
package org.keycloak.enums;
package org.keycloak.common.enums;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -1,6 +1,6 @@
package org.keycloak.enums;
package org.keycloak.common.enums;
import org.keycloak.ClientConnection;
import org.keycloak.common.ClientConnection;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -14,8 +14,6 @@ public enum SslRequired {
EXTERNAL,
NONE;
private static final long serialVersionUID = 1L;
public boolean isRequired(ClientConnection connection) {
return isRequired(connection.getRemoteAddr());
}
File diff suppressed because it is too large. Load diff
@@ -1,44 +1,42 @@
package org.keycloak.util;
import net.iharder.Base64;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Base64Url {
public static String encode(byte[] bytes) {
String s = Base64.encodeBytes(bytes);
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
public static byte[] decode(String s) {
s = s.replace('-', '+'); // 62nd char of encoding
s = s.replace('_', '/'); // 63rd char of encoding
switch (s.length() % 4) // Pad with trailing '='s
{
case 0:
break; // No pad chars in this case
case 2:
s += "==";
break; // Two pad chars
case 3:
s += "=";
break; // One pad char
default:
throw new RuntimeException(
"Illegal base64url string!");
}
try {
return Base64.decode(s);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package org.keycloak.common.util;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Base64Url {
public static String encode(byte[] bytes) {
String s = Base64.encodeBytes(bytes);
s = s.split("=")[0]; // Remove any trailing '='s
s = s.replace('+', '-'); // 62nd char of encoding
s = s.replace('/', '_'); // 63rd char of encoding
return s;
}
public static byte[] decode(String s) {
s = s.replace('-', '+'); // 62nd char of encoding
s = s.replace('_', '/'); // 63rd char of encoding
switch (s.length() % 4) // Pad with trailing '='s
{
case 0:
break; // No pad chars in this case
case 2:
s += "==";
break; // Two pad chars
case 3:
s += "=";
break; // One pad char
default:
throw new RuntimeException(
"Illegal base64url string!");
}
try {
return Base64.decode(s);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -1,166 +1,165 @@
package org.keycloak.util;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
* @version $Revision: 2 $
*/
public class CertificateUtils {
static {
BouncyIntegration.init();
}
/**
* Generates version 3 {@link java.security.cert.X509Certificate}.
*
* @param keyPair the key pair
* @param caPrivateKey the CA private key
* @param caCert the CA certificate
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
// Serial Number
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
// Validity
Date notBefore = new Date(System.currentTimeMillis());
Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
// SubjectPublicKeyInfo
SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
.getEncoded()));
X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
DigestCalculator digCalc = new BcDigestCalculatorProvider()
.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
// Subject Key Identifier
certGen.addExtension(Extension.subjectKeyIdentifier, false,
x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
// Authority Key Identifier
certGen.addExtension(Extension.authorityKeyIdentifier, false,
x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
// Key Usage
certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
| KeyUsage.cRLSign));
// Extended Key Usage
KeyPurposeId[] EKU = new KeyPurposeId[2];
EKU[0] = KeyPurposeId.id_kp_emailProtection;
EKU[1] = KeyPurposeId.id_kp_serverAuth;
certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
// Basic Constraints
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
// Content Signer
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
// Certificate
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
} catch (Exception e) {
throw new RuntimeException("Error creating X509v3Certificate.", e);
}
}
/**
* Generate version 1 self signed {@link java.security.cert.X509Certificate}..
*
* @param caKeyPair the CA key pair
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
Date validityEndDate = new Date(calendar.getTime().getTime());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
validityEndDate, subjectDN, subPubKeyInfo);
X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
return new JcaX509CertificateConverter().getCertificate(holder);
} catch (Exception e) {
throw new RuntimeException("Error creating X509v1Certificate.", e);
}
}
/**
* Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
*
* @param privateKey the private key
*
* @return the content signer
*/
public static ContentSigner createSigner(PrivateKey privateKey) {
try {
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
} catch (Exception e) {
throw new RuntimeException("Could not create content signer.", e);
}
}
}
package org.keycloak.common.util;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509ExtensionUtils;
import org.bouncycastle.cert.X509v1CertificateBuilder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DigestCalculator;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
/**
* The Class CertificateUtils provides utility functions for generation of V1 and V3 {@link java.security.cert.X509Certificate}
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @author <a href="mailto:giriraj.sharma27@gmail.com">Giriraj Sharma</a>
* @version $Revision: 2 $
*/
public class CertificateUtils {
static {
BouncyIntegration.init();
}
/**
* Generates version 3 {@link java.security.cert.X509Certificate}.
*
* @param keyPair the key pair
* @param caPrivateKey the CA private key
* @param caCert the CA certificate
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV3Certificate(KeyPair keyPair, PrivateKey caPrivateKey, X509Certificate caCert,
String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
// Serial Number
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
BigInteger serialNumber = BigInteger.valueOf(Math.abs(random.nextInt()));
// Validity
Date notBefore = new Date(System.currentTimeMillis());
Date notAfter = new Date(System.currentTimeMillis() + (((1000L * 60 * 60 * 24 * 30)) * 12) * 3);
// SubjectPublicKeyInfo
SubjectPublicKeyInfo subjPubKeyInfo = new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keyPair.getPublic()
.getEncoded()));
X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(new X500Name(caCert.getSubjectDN().getName()),
serialNumber, notBefore, notAfter, subjectDN, subjPubKeyInfo);
DigestCalculator digCalc = new BcDigestCalculatorProvider()
.get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
X509ExtensionUtils x509ExtensionUtils = new X509ExtensionUtils(digCalc);
// Subject Key Identifier
certGen.addExtension(Extension.subjectKeyIdentifier, false,
x509ExtensionUtils.createSubjectKeyIdentifier(subjPubKeyInfo));
// Authority Key Identifier
certGen.addExtension(Extension.authorityKeyIdentifier, false,
x509ExtensionUtils.createAuthorityKeyIdentifier(subjPubKeyInfo));
// Key Usage
certGen.addExtension(Extension.keyUsage, false, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyCertSign
| KeyUsage.cRLSign));
// Extended Key Usage
KeyPurposeId[] EKU = new KeyPurposeId[2];
EKU[0] = KeyPurposeId.id_kp_emailProtection;
EKU[1] = KeyPurposeId.id_kp_serverAuth;
certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(EKU));
// Basic Constraints
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(0));
// Content Signer
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1WithRSAEncryption").setProvider("BC").build(caPrivateKey);
// Certificate
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certGen.build(sigGen));
} catch (Exception e) {
throw new RuntimeException("Error creating X509v3Certificate.", e);
}
}
/**
* Generate version 1 self signed {@link java.security.cert.X509Certificate}..
*
* @param caKeyPair the CA key pair
* @param subject the subject name
*
* @return the x509 certificate
*
* @throws Exception the exception
*/
public static X509Certificate generateV1SelfSignedCertificate(KeyPair caKeyPair, String subject) throws Exception {
try {
X500Name subjectDN = new X500Name("CN=" + subject);
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
Date validityStartDate = new Date(System.currentTimeMillis() - 100000);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 10);
Date validityEndDate = new Date(calendar.getTime().getTime());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(caKeyPair.getPublic().getEncoded());
X509v1CertificateBuilder builder = new X509v1CertificateBuilder(subjectDN, serialNumber, validityStartDate,
validityEndDate, subjectDN, subPubKeyInfo);
X509CertificateHolder holder = builder.build(createSigner(caKeyPair.getPrivate()));
return new JcaX509CertificateConverter().getCertificate(holder);
} catch (Exception e) {
throw new RuntimeException("Error creating X509v1Certificate.", e);
}
}
/**
* Creates the content signer for generation of Version 1 {@link java.security.cert.X509Certificate}.
*
* @param privateKey the private key
*
* @return the content signer
*/
public static ContentSigner createSigner(PrivateKey privateKey) {
try {
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA256WithRSAEncryption");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
return new BcRSAContentSignerBuilder(sigAlgId, digAlgId)
.build(PrivateKeyFactory.createKey(privateKey.getEncoded()));
} catch (Exception e) {
throw new RuntimeException("Could not create content signer.", e);
}
}
}
@@ -0,0 +1,41 @@
package org.keycloak.common.util;
import java.util.Collection;
import java.util.Iterator;
/**
* @author <a href="mailto:jeroen.rosenberg@gmail.com">Jeroen Rosenberg</a>
*/
public class CollectionUtil {
public static String join(Collection<String> strings) {
return join(strings, ", ");
}
public static String join(Collection<String> strings, String separator) {
Iterator<String> iter = strings.iterator();
StringBuilder sb = new StringBuilder();
if(iter.hasNext()){
sb.append(iter.next());
while(iter.hasNext()){
sb.append(separator).append(iter.next());
}
}
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;
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.DataInputStream;
import java.io.InputStream;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
@@ -1,37 +1,37 @@
package org.keycloak.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class EnvUtil {
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
private EnvUtil() {
}
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val) {
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
}
package org.keycloak.common.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class EnvUtil {
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
private EnvUtil() {
}
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val) {
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
}
@@ -1,37 +1,37 @@
package org.keycloak.util;
import org.keycloak.constants.GenericConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FindFile {
public static InputStream findFile(String keycloakConfigFile) {
if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
// Try current class classloader first
InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
}
if (is != null) {
return is;
} else {
throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
}
} else {
// Fallback to file
try {
return new FileInputStream(keycloakConfigFile);
} catch (FileNotFoundException fnfe) {
throw new RuntimeException(fnfe);
}
}
}
}
package org.keycloak.common.util;
import org.keycloak.common.constants.GenericConstants;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class FindFile {
public static InputStream findFile(String keycloakConfigFile) {
if (keycloakConfigFile.startsWith(GenericConstants.PROTOCOL_CLASSPATH)) {
String classPathLocation = keycloakConfigFile.replace(GenericConstants.PROTOCOL_CLASSPATH, "");
// Try current class classloader first
InputStream is = FindFile.class.getClassLoader().getResourceAsStream(classPathLocation);
if (is == null) {
is = Thread.currentThread().getContextClassLoader().getResourceAsStream(classPathLocation);
}
if (is != null) {
return is;
} else {
throw new RuntimeException("Unable to find config from classpath: " + keycloakConfigFile);
}
} else {
// Fallback to file
try {
return new FileInputStream(keycloakConfigFile);
} catch (FileNotFoundException fnfe) {
throw new RuntimeException(fnfe);
}
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.util;
package org.keycloak.common.util;
/**
* @author pedroigor
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -12,13 +12,12 @@ import java.lang.reflect.Method;
import javax.security.auth.kerberos.KerberosTicket;
import net.iharder.Base64;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.Oid;
import org.keycloak.constants.KerberosConstants;
import org.keycloak.util.reflections.Reflections;
import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.reflections.Reflections;
import sun.security.jgss.GSSCredentialImpl;
import sun.security.jgss.GSSManagerImpl;
import sun.security.jgss.krb5.Krb5InitCredential;
@@ -0,0 +1,56 @@
package org.keycloak.common.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import org.keycloak.common.constants.GenericConstants;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeystoreUtil {
static {
BouncyIntegration.init();
}
public enum KeystoreFormat {
JKS,
PKCS12
}
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream trustStream = (filename.startsWith(GenericConstants.PROTOCOL_CLASSPATH))
?KeystoreUtil.class.getResourceAsStream(filename.replace(GenericConstants.PROTOCOL_CLASSPATH, ""))
:new FileInputStream(new File(filename));
trustStore.load(trustStream, password.toCharArray());
trustStream.close();
return trustStore;
}
public static PrivateKey loadPrivateKeyFromKeystore(String keystoreFile, String storePassword, String keyPassword, String keyAlias, KeystoreFormat format) {
InputStream stream = FindFile.findFile(keystoreFile);
try {
KeyStore keyStore = null;
if (format == KeystoreFormat.JKS) {
keyStore = KeyStore.getInstance(format.toString());
} else {
keyStore = KeyStore.getInstance(format.toString(), "BC");
}
keyStore.load(stream, storePassword.toCharArray());
PrivateKey key = (PrivateKey) keyStore.getKey(keyAlias, keyPassword.toCharArray());
if (key == null) {
throw new RuntimeException("Couldn't load key with alias '" + keyAlias + "' from keystore");
}
return key;
} catch (Exception e) {
throw new RuntimeException("Failed to load private key: " + e.getMessage(), e);
}
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import javax.activation.MimetypesFileTypeMap;
import java.io.File;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.ArrayList;
import java.util.Collection;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
/*
* JBoss, Home of Professional Open Source.
@@ -0,0 +1,31 @@
package org.keycloak.common.util;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ObjectUtil {
private ObjectUtil() {}
/**
*
* @param str1
* @param str2
* @return true if both strings are null or equal
*/
public static boolean isEqualOrBothNull(Object str1, Object str2) {
if (str1 == null && str2 == null) {
return true;
}
if ((str1 != null && str2 == null) || (str1 == null && str2 != null)) {
return false;
}
return str1.equals(str2);
}
public static String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
@@ -1,7 +1,7 @@
/**
*
*/
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.regex.Pattern;
@@ -1,110 +1,108 @@
package org.keycloak.util;
import net.iharder.Base64;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
/**
* Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class PemUtils {
static {
BouncyIntegration.init();
}
private PemUtils() {
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(String cert) throws Exception {
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException {
String pem = pemFromStream(is);
return pemToDer(pem);
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException {
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
public static String removeBeginEnd(String pem) {
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String pemFromStream(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
}
package org.keycloak.common.util;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
/**
* Utility classes to extract PublicKey, PrivateKey, and X509Certificate from openssl generated PEM files
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class PemUtils {
static {
BouncyIntegration.init();
}
private PemUtils() {
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(String cert) throws Exception {
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException {
String pem = pemFromStream(is);
return pemToDer(pem);
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException {
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
public static String removeBeginEnd(String pem) {
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String pemFromStream(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
}
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.Serializable;
import java.text.DateFormat;
@@ -1,35 +1,35 @@
package org.keycloak.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class StreamUtil {
private StreamUtil() {
}
public static String readString(InputStream in) throws IOException
{
char[] buffer = new char[1024];
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int wasRead;
do
{
wasRead = reader.read(buffer, 0, 1024);
if (wasRead > 0)
{
builder.append(buffer, 0, wasRead);
}
}
while (wasRead > -1);
return builder.toString();
}
}
package org.keycloak.common.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public final class StreamUtil {
private StreamUtil() {
}
public static String readString(InputStream in) throws IOException
{
char[] buffer = new char[1024];
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int wasRead;
do
{
wasRead = reader.read(buffer, 0, 1024);
if (wasRead > 0)
{
builder.append(buffer, 0, wasRead);
}
}
while (wasRead > -1);
return builder.toString();
}
}
@@ -19,7 +19,7 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.File;
import java.util.Properties;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.Properties;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.util.Date;
@@ -1,4 +1,4 @@
package org.keycloak.util;
package org.keycloak.common.util;
import java.io.UnsupportedEncodingException;
import java.net.URI;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.beans.Introspector;
import java.io.Serializable;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.lang.reflect.AccessibleObject;
import java.security.PrivilegedAction;
@@ -1,4 +1,4 @@
package org.keycloak.util.reflections;
package org.keycloak.common.util.reflections;
import java.lang.reflect.Type;
+4
View File
@@ -0,0 +1,4 @@
name=${product.name}
name-html=${product.name-html}
version=${product.version}
build-time=${product.build-time}
-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.4.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,221 +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());
List<RealmRepresentation> realmReps = new ArrayList<RealmRepresentation>();
for (RealmRepresentation realmRep : model.getRealms()) {
if (Config.getAdminRealm().equals(realmRep.getRealm())) {
realmReps.add(0, realmRep);
} else {
realmReps.add(realmRep);
}
}
for (RealmRepresentation realmRep : realmReps) {
ImportUtils.importRealm(session, realmRep, Strategy.IGNORE_EXISTING);
}
} 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,31 +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;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.provider.Provider;
/**
* @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc.
*/
public interface FileConnectionProvider extends Provider, KeycloakTransaction {
InMemoryModel getModel();
void sessionClosed(KeycloakSession session);
}
Loaded 100 of 4896 files, more files were not shown because too many files have changed in this diff. Show more