Compare commits

...
525 Commits
Author SHA1 Message Date
Stian Thorgersen 7c07f7bb1e Set version to 1.0-beta-3 2014-06-18 14:45:21 +01:00
Stian Thorgersen d1c890db18 Merge pull request #472 from mposolda/db-fixes
KEYCLOAK-534 Fix MS-SQL, Oracle and Sybase
2014-06-18 13:32:57 +01:00
Stian Thorgersen 0be4a4b71d Merge pull request #473 from stianst/master
Documentation to reverse proxy config
2014-06-18 13:13:11 +01:00
mposolda 19a545049b KEYCLOAK-536 Fix Sybase - role can't be used as column name as it's keyword in sybase 2014-06-18 12:31:55 +02:00
Stian Thorgersen 34eb34c5fc Added documentation to specify https redirect port 2014-06-18 11:08:06 +01:00
Stian Thorgersen 28adc28a56 Add instructions to configure a reverse proxy with KC 2014-06-18 09:59:23 +01:00
mposolda 5d8c803da6 Remove duplicite dependency declarations to remove maven warnings 2014-06-18 10:31:56 +02:00
mposolda 2fd7fdaa74 KEYCLOAK-535 Fix Keycloak with Oracle 2014-06-18 10:29:57 +02:00
mposolda f9cb99a1ee KEYCLOAK-534 Fix MS-SQL 2014-06-17 19:41:19 +02:00
Stian Thorgersen 37bfb2c594 Merge pull request #471 from stianst/master
KEYCLOAK-533
2014-06-17 15:38:16 +01:00
Stian Thorgersen 3b55248e6c KEYCLOAK-533 2014-06-17 15:30:50 +01:00
Stian Thorgersen b35bccdad2 Merge pull request #470 from stianst/master
KEYCLOAK-530
2014-06-17 14:11:48 +01:00
Stian Thorgersen 6cabf3e57d KEYCLOAK-530 2014-06-17 14:11:31 +01:00
Stian Thorgersen b31b54e17c Merge pull request #469 from stianst/master
KEYCLOAK-532
2014-06-17 14:07:26 +01:00
Stian Thorgersen 469d044254 KEYCLOAK-532 2014-06-17 14:07:07 +01:00
Stian Thorgersen 9a26d7078f Merge pull request #468 from stianst/master
KEYCLOAK-520
2014-06-17 11:21:54 +01:00
Stian Thorgersen 896c32a660 KEYCLOAK-520 2014-06-17 11:21:36 +01:00
Stian Thorgersen 6e23613b9e Merge pull request #467 from stianst/master
Disable cache provider for beta-3 release
2014-06-17 11:07:27 +01:00
Stian Thorgersen d15324110e Disable cache provider for beta-3 release 2014-06-17 11:06:08 +01:00
Stian Thorgersen 153de54fe8 Merge pull request #466 from stianst/master
KEYCLOAK-526 Fix iframe origin when auth server url is relative
2014-06-16 17:55:27 +01:00
Stian Thorgersen 2866f6fc23 KEYCLOAK-526 Fix iframe origin when auth server url is relative 2014-06-16 17:55:03 +01:00
Bill Burke 9228f0c076 Merge pull request #465 from patriot1burke/master
keycloak-521
2014-06-16 11:59:52 -04:00
Bill Burke 1eafb01c8d keycloak-521 2014-06-16 11:59:27 -04:00
Bill Burke 44f446e745 Merge pull request #464 from patriot1burke/master
keycloak-518
2014-06-16 10:48:34 -04:00
Bill Burke c71fdc72c7 keycloak-518 2014-06-16 10:43:50 -04:00
Bill Burke bbf944a225 Merge pull request #463 from patriot1burke/master
oops show-sql=false
2014-06-16 10:28:28 -04:00
Bill Burke dbc5641144 oops show-sql=false 2014-06-16 10:28:06 -04:00
Bill Burke 9080a64fcd Merge pull request #462 from patriot1burke/master
better fetch for role mappings
2014-06-16 10:16:22 -04:00
Bill Burke f50177996d better fetch for role mappings 2014-06-16 10:15:53 -04:00
Bill Burke b649dd39d9 Merge pull request #461 from patriot1burke/master
caching
2014-06-13 20:09:03 -04:00
Bill Burke ab87c03732 cache 1st iteration finished 2014-06-13 19:39:20 -04:00
Bill Burke 8eaf77b3c1 cache impl again 2014-06-13 19:05:05 -04:00
Bill Burke cbea141a54 cache impl 2014-06-13 17:17:45 -04:00
Bill Burke 60a040a141 Merge pull request #460 from patriot1burke/master
refactor for caching
2014-06-13 09:49:08 -04:00
Bill Burke 4a518c964b mongo refactor for caching 2014-06-12 16:51:19 -04:00
Bill Burke bb2ad656a3 cache implement 2014-06-12 11:45:50 -04:00
Bill Burke 30b95e0a57 Merge remote-tracking branch 'upstream/master' 2014-06-12 11:12:22 -04:00
Bill Burke 852c631eff Merge pull request #459 from ssilvert/master
KEYCLOAK-522 Refactor Undertow Adapter so that it can optionally be used without the Servlet API.
2014-06-12 11:12:07 -04:00
Bill Burke 211a279248 Merge remote-tracking branch 'upstream/master' 2014-06-12 11:11:27 -04:00
Bill Burke 2ae2067841 refactor for caching again 2014-06-12 11:11:14 -04:00
Bill Burke 0dd06e3343 model refactor for caching 2014-06-10 18:50:08 -04:00
Stan Silvert 4e9bec69e4 Add Apache 2.0 license 2014-06-09 16:43:45 -04:00
Stan Silvert 70392d9f1a KEYCLOAK-522 Refactor Undertow Adapter so that it can optionally be used
without the Servlet API.
2014-06-09 16:43:44 -04:00
Bill Burke 9a3abf6a6a Merge pull request #458 from mposolda/master
Support for Active Directory and RHDS
2014-06-09 15:15:15 -04:00
mposolda 0bfcbdb359 Support for Active Directory and RHDS 2014-06-09 16:20:19 +02:00
Bill Burke 2f3c8bf079 cache refactor 2014-06-06 15:12:58 -04:00
Stian Thorgersen e7bde986aa Merge pull request #457 from stianst/master
KEYCLOAK-504 Using https results in RuntimeException if sslRequired is set to false
2014-06-06 14:54:40 +01:00
Stian Thorgersen f3211bf34d KEYCLOAK-504
Using https results in RuntimeException if sslRequired is set to false
2014-06-06 14:54:11 +01:00
Stian Thorgersen c086e0a502 Merge pull request #456 from stianst/master
KEYCLOAK-500
2014-06-06 09:53:08 +01:00
Stian Thorgersen 80f4b668b2 KEYCLOAK-500
Redundant condition in keycloak.js
2014-06-06 09:52:25 +01:00
Stian Thorgersen 01606ab5e0 Merge pull request #455 from stianst/master
KEYCLOAK-496 Dependency jira alignments with other JBoss projects
2014-06-05 15:25:37 +01:00
Stian Thorgersen 91e29d9710 KEYCLOAK-496 Dependency jira alignments with other JBoss projects 2014-06-05 13:33:48 +01:00
Stian Thorgersen 23d101f8fa Merge pull request #454 from rodrigopsasaki/issue-keycloak-519
Issue KEYCLOAK-519
2014-06-05 13:30:00 +01:00
Rodrigo Sasaki e08b3e7dec flipped comparison operands to avoid NPE 2014-06-05 09:24:06 -03:00
Stian Thorgersen c4e32b7c45 Merge pull request #453 from stianst/stateless-social
Fix
2014-06-05 11:13:38 +01:00
Stian Thorgersen 14ece40054 Removed file that shouldn't have been committed 2014-06-05 11:12:47 +01:00
Stian Thorgersen eaa6be55d7 KEYCLOAK-496 Removed commons-io 2014-06-05 10:41:37 +01:00
Stian Thorgersen 2ae714aea2 Merge pull request #452 from stianst/stateless-social
KEYCLOAK-244 Social should be stateless
2014-06-05 10:40:07 +01:00
Stian Thorgersen 5f6687ec62 KEYCLOAK-244 Social should be stateless 2014-06-05 10:09:17 +01:00
Stian Thorgersen 06053fad85 Merge pull request #451 from stianst/master
KEYCLOAK-510
2014-06-04 12:34:29 +01:00
Stian Thorgersen d0c06ab0ce KEYCLOAK-510
NPE in ExtendingThemeManager
2014-06-04 12:26:24 +01:00
Stian Thorgersen cfb6f927b2 Merge pull request #450 from jimbo1007/jsfix
add missing initPromise.setSuccess()
2014-06-03 15:02:18 +01:00
unknown 8d33894989 add missing initPromise.setSuccess() 2014-06-03 09:28:01 -04:00
Bill Burke ba13cbe004 Merge pull request #449 from patriot1burke/master
fix deadlocks
2014-06-02 21:34:43 -04:00
Bill Burke 9410adf9ce fix deadlocks 2014-06-02 21:33:43 -04:00
Bill Burke 7443c78087 Merge pull request #448 from patriot1burke/master
bump version again
2014-06-02 14:22:10 -04:00
Bill Burke d5b34a0b41 bump version again 2014-06-02 13:12:04 -04:00
Bill Burke 0cd64e297a Merge pull request #447 from patriot1burke/master
bump version
2014-06-02 12:22:40 -04:00
Bill Burke 0fcf80dd6e bump version 2014-06-02 12:21:58 -04:00
Bill Burke 56e9e0b4f9 Merge pull request #446 from patriot1burke/master
NPE in as7 adapter logout
2014-06-02 12:03:09 -04:00
Bill Burke dfcd3267e4 NPE in as7 adapter logout 2014-06-02 12:02:42 -04:00
Bill Burke f689747fd6 Merge pull request #445 from patriot1burke/master
wildfly ssl fixes
2014-06-02 11:22:51 -04:00
Bill Burke bb11165568 wildfly ssl fixes 2014-06-02 11:22:19 -04:00
Bill Burke a180c6b896 Merge remote-tracking branch 'upstream/master' 2014-06-02 09:37:30 -04:00
Bill Burke 34d3be244d bump undertow version 2014-06-02 09:37:18 -04:00
Stian Thorgersen 4662781213 Merge pull request #443 from lnewson/master
Fixed an integer overflow that caused the token to be refreshed too often
2014-06-02 09:35:11 +01:00
Stian Thorgersen 5bd12a708f Merge pull request #444 from lnewson/social-fix
Fixed an NPE when the social users name is null
2014-06-02 09:34:32 +01:00
Bill Burke e39149c954 Merge remote-tracking branch 'upstream/master' 2014-06-01 18:03:49 -04:00
Bill Burke b925a97b5d bump wildfly version 2014-06-01 18:03:39 -04:00
Lee Newson 3bcf2c81da Fixed an NPE when the users name is null 2014-05-31 10:39:34 +10:00
Lee Newson b52801de25 Fixed an integer overflow that caused the token to always be refreshed 2014-05-31 10:26:06 +10:00
Stian Thorgersen 4d8c3d7d73 Merge pull request #442 from stianst/master
Cache for FreeMarker templates and set cache-control for static resources from themes
2014-05-30 17:03:37 +01:00
Stian Thorgersen ea1f10361a Cache FreeMarker templates 2014-05-30 16:59:25 +01:00
Stian Thorgersen 5dafad71ac Set cache-control on static resources from themes 2014-05-30 16:59:25 +01:00
Bill Burke df28fb97ed Merge pull request #440 from stianst/master
Bump version to 1.0.beta2-SNAPSHOT
2014-05-30 08:56:00 -04:00
Stian Thorgersen 5600018a56 Merge pull request #441 from mposolda/master
Basic fix of performance tests and added README. Still requires work...
2014-05-30 10:37:05 +01:00
mposolda 441c00c06f Basic fix of performance tests and added README. Still requires work... 2014-05-30 11:03:16 +02:00
Stian Thorgersen 9533bbc47d Merge pull request #439 from mposolda/master
Fix js-console on FF
2014-05-30 08:55:33 +01:00
Stian Thorgersen 2025d314ec Bump version to 1.0.beta2-SNAPSHOT 2014-05-30 08:52:03 +01:00
mposolda 772f991545 Fix js-console on FF 2014-05-29 18:56:34 +02:00
Bill Burke f6b59b03bb Merge pull request #438 from patriot1burke/master
bump version
2014-05-29 12:16:30 -04:00
Bill Burke 2ae3775841 bump version 2014-05-29 12:12:33 -04:00
Stian Thorgersen 8573c13b8c Merge pull request #437 from mposolda/master
Improve PropertiesAuthenticationProvider to support retrieving user pass...
2014-05-29 16:10:11 +01:00
mposolda db1c6e9afd Improve PropertiesAuthenticationProvider to support retrieving user passwords from custom location and persisting password updates 2014-05-29 16:55:41 +02:00
Stian Thorgersen 429f003578 Merge pull request #436 from stianst/master
Fix audit provider example
2014-05-29 15:08:48 +01:00
Stian Thorgersen dd684858f2 Fix audit provider example 2014-05-29 15:08:27 +01:00
Stian Thorgersen 2e82d56634 Merge pull request #435 from stianst/master
Demo fixes
2014-05-29 14:04:40 +01:00
Stian Thorgersen 1ede6e70b7 Fix customer-portal-cli example 2014-05-29 14:04:10 +01:00
Stian Thorgersen 8908fbef58 Fix instructions for deploying demo to use jboss-as:deploy or wildfly:deploy 2014-05-29 14:03:50 +01:00
Stian Thorgersen 09a96b3a2b Merge pull request #434 from stianst/master
Added sunrise theme to examples, including instructions on how to deploy
2014-05-29 13:15:14 +01:00
Stian Thorgersen 5b7c8b6920 Added sunrise theme to examples, including instructions on how to deploy 2014-05-29 13:14:39 +01:00
Stian Thorgersen 409b46963e Merge pull request #433 from mposolda/master
Add more scopes into testrealm.json to ensure that admin is able to acce...
2014-05-29 13:03:04 +01:00
mposolda 53cf574735 Add more scopes into testrealm.json to ensure that admin is able to access all things he needs 2014-05-29 13:06:47 +02:00
Stian Thorgersen fe236cabd3 Merge pull request #431 from mposolda/master
Change default timeouts for testrealm.json bundled in examples, Fix admin-access-app example
2014-05-29 10:55:35 +01:00
Stian Thorgersen d25536569a Merge pull request #430 from PatrickMadden/master
Added bindIp support to embedmongo-maven-plugin configuration. Solves is...
2014-05-29 10:54:46 +01:00
mposolda 06b9499805 Fixing typo in admin console causing errors when change passwordCredentialsGrant 2014-05-29 11:42:54 +02:00
Stian Thorgersen 2a2e57467d Merge pull request #432 from stianst/master
Fix themes displayed multiple times in admin console
2014-05-29 10:28:22 +01:00
Stian Thorgersen 24ac6cbbac Fix themes displayed multiple times in admin console 2014-05-29 10:28:05 +01:00
Stian Thorgersen 0b68e52b83 Fix Cannot read property 'realm' of undefined 2014-05-29 10:20:49 +01:00
Stian Thorgersen cf1393ffe1 Updated sunrise theme example 2014-05-29 09:42:17 +01:00
mposolda c4808a3e61 Fix admin-App example 2014-05-29 10:29:06 +02:00
mposolda f0d37b19e2 Fix typo in docs 2014-05-29 10:28:54 +02:00
mposolda 65206a72b2 Change default timeouts for testrealm.json bundled in examples 2014-05-29 09:30:22 +02:00
Stian Thorgersen a91d4c06ee Merge pull request #429 from mposolda/master
Fixes in JS examples
2014-05-29 07:52:46 +01:00
PatrickMadden e8ad08bd28 Reuse bindIp of model for audit in integration test suite. 2014-05-28 20:02:42 -05:00
PatrickMadden 7a3b1ddd18 Added bindIp support to embedmongo-maven-plugin configuration. Solves issue of firewall pop-ups consistently displaying on every Microsoft Windows build. 2014-05-28 19:14:23 -05:00
mposolda db939ee076 Fix angular-product example 2014-05-28 23:30:34 +02:00
mposolda 5ede17d8b8 Replace innerText with innerHTML as innerText doesn't work on FF 2014-05-28 21:50:23 +02:00
Bill Burke 0ff992e04e Merge pull request #428 from patriot1burke/master
docs
2014-05-28 12:34:11 -04:00
Bill Burke 34a579821a docs 2014-05-28 12:33:49 -04:00
Stian Thorgersen dd30a35e1e Disable session iframe in Corodova 2014-05-28 17:29:13 +01:00
Stian Thorgersen 2074e1423f Fixes for example/cordova 2014-05-28 17:10:28 +01:00
Stian Thorgersen d5476b78ec Merge pull request #427 from stianst/master
Deploy server war and dist bundles to Maven repo. Also added '-parent' to some parent poms where this was missing
2014-05-28 15:32:58 +01:00
Stian Thorgersen df19700f69 Deploy server war and dist bundles to Maven repo. Also added '-parent' to some parent poms where this was missing 2014-05-28 15:32:20 +01:00
Bill Burke 3c605a7740 Merge pull request #426 from patriot1burke/master
docs and master realm rename
2014-05-28 09:51:56 -04:00
Bill Burke a64b35d72f doc merge 2014-05-28 09:33:42 -04:00
Bill Burke e880b77692 update docs 2014-05-28 09:31:33 -04:00
Stian Thorgersen e8fe26ff1c Merge pull request #425 from stianst/master
Fix for WildFly 8.1.0.CR2
2014-05-28 14:20:53 +01:00
Stian Thorgersen 108ccd98d0 Fix for WildFly 8.1.0.CR2 2014-05-28 14:20:29 +01:00
Stian Thorgersen 5fddc28cd6 Updated jboss maven plugin and added wildfly maven plugin. Both are skipped by default, so only needs to be specified in modules that should be deployed 2014-05-28 11:00:36 +01:00
Stian Thorgersen 63001d5e16 Merge pull request #424 from mposolda/master
Fix configuration of maven plugins in authentication-properties example
2014-05-28 09:59:36 +01:00
mposolda caccf76ea4 Fix configuration of maven plugins in authentication-properties example 2014-05-28 10:56:00 +02:00
Stian Thorgersen 5120549005 Merge pull request #423 from mposolda/master
Updated documentation and added example for Authentication SPI
2014-05-28 09:12:01 +01:00
mposolda e67032a9d7 Documentation about Authentication SPI, LDAP and Export/import 2014-05-27 22:37:25 +02:00
mposolda a903eb7605 Added example for AuthenticationProvider SPI 2014-05-27 22:37:25 +02:00
Bill Burke 5b431338c2 Merge pull request #422 from patriot1burke/master
admin console mistake
2014-05-27 14:56:14 -04:00
Bill Burke c20d488648 admin console mistake 2014-05-27 14:38:03 -04:00
Stian Thorgersen 57a8f3f5ee Added to migration guid for beta1 2014-05-27 15:29:04 +01:00
Stian Thorgersen 6dda7fc356 Added example providers for audit listener and audit provider 2014-05-27 15:11:52 +01:00
Stian Thorgersen 9261c1608f Fix missing @Path in admin console 2014-05-27 13:40:32 +01:00
Stian Thorgersen 80cd43390b Added doc for audit 2014-05-27 13:40:23 +01:00
Stian Thorgersen c196849574 Updated doc for themes 2014-05-27 13:08:00 +01:00
Stian Thorgersen 1007d19860 Updated instructions to configure Mongo through keycloak-server.json 2014-05-27 12:05:35 +01:00
Stian Thorgersen 374a7b8848 Updated url for OpenShift cartridge 2014-05-27 12:05:22 +01:00
Stian Thorgersen 8ae57fd117 Include all themes in configuration/themes to make it easy to modify/create themes 2014-05-27 12:05:09 +01:00
Bill Burke 5a2fd16b92 Merge pull request #421 from patriot1burke/master
jaxrs-doclet, more javadocs
2014-05-26 20:51:53 -04:00
Bill Burke 3545ac130b jax-doclet 2014-05-26 20:50:42 -04:00
Bill Burke 199c786e22 jaxrs-doclet support 2014-05-26 20:41:33 -04:00
Bill Burke 38b52283a5 Merge remote-tracking branch 'upstream/master' 2014-05-26 12:50:09 -04:00
Bill Burke 1f8b2d4c7b stuff 2014-05-26 12:49:56 -04:00
Bill Burke 9c0fa93510 Merge pull request #420 from patriot1burke/master
admin rest example, default origins, effect roles
2014-05-23 19:03:25 -04:00
Bill Burke ab2932f75e effective roles to oauth 2014-05-23 19:01:09 -04:00
Bill Burke 81083ef470 Merge remote-tracking branch 'upstream/master' 2014-05-23 18:22:34 -04:00
Bill Burke e4232c73c6 admin rest api example 2014-05-23 18:20:55 -04:00
Bill Burke 29070cec77 add KeycloakSecurityContext to principal 2014-05-23 16:26:44 -04:00
Bill Burke fbef9f7691 default web origins 2014-05-23 16:15:00 -04:00
Bill Burke 97f3a3feef Merge pull request #419 from patriot1burke/master
admin cors
2014-05-23 16:12:08 -04:00
Bill Burke 54cc095ff5 admin cors support 2014-05-23 16:02:14 -04:00
Stian Thorgersen 0ad4d5cc47 Change 'Composite roles' to 'Effective roles' on role mapping/scope pages 2014-05-23 16:44:55 +01:00
Bill Burke 236f3ab768 admin cors 2014-05-23 09:37:07 -04:00
Stian Thorgersen 6de7c42ac9 Merge pull request #418 from mposolda/master
Fixing typo
2014-05-23 10:21:44 +01:00
mposolda bb7a809ab5 Fixing typo 2014-05-23 11:19:17 +02:00
Stian Thorgersen 142b155460 Merge pull request #417 from mposolda/master
At least one redirect_uri must be available for oauthClients and applica...
2014-05-23 10:11:06 +01:00
Stian Thorgersen 0f6bc9c5c7 KEYCLOAK-492
Can't add scope on application role to application
2014-05-23 10:10:19 +01:00
mposolda e600d7c449 At least one redirect_uri must be available for oauthClients and applications, which are not bearer-only 2014-05-23 10:55:43 +02:00
Stian Thorgersen 37327be521 KEYCLOAK-482
Cannot read property 'realm' of undefined
2014-05-23 09:36:14 +01:00
Stian Thorgersen 07d2bf988a Merge pull request #416 from mposolda/master
Fix logging typo when importing roles
2014-05-23 09:14:10 +01:00
mposolda df06a0c878 Fix logging typo when importing roles 2014-05-23 09:46:50 +02:00
Stian Thorgersen cee3fea98f Merge pull request #415 from mposolda/master
Invalid active tab when on token-settings page
2014-05-23 08:39:49 +01:00
mposolda 5c378cbd9d Invalid active tab when on token-settings page 2014-05-23 08:51:06 +02:00
Stian Thorgersen 37099f3177 KEYCLOAK-494
Session state iframe uses first redirect uri for a client
2014-05-22 17:51:51 +01:00
Stian Thorgersen 128cc7eadb Fixes to js-console example 2014-05-22 17:07:40 +01:00
Stian Thorgersen de36973716 Redirect to login form automatically in keycloak.js if login-required is set 2014-05-22 16:59:38 +01:00
Stian Thorgersen 08b1996149 Removed jboss.as.jpa.managed property from persistence.xml as it's causing problems on AS 7.1 2014-05-22 16:01:05 +01:00
Stian Thorgersen 0574302840 Fix dialog for resetting user password 2014-05-22 15:39:31 +01:00
Stian Thorgersen fad0a7728c Make add redirect-uri and web-origin use same l&f 2014-05-22 15:10:22 +01:00
Stian Thorgersen 86ad7292af Fix updating sessions after logout session 2014-05-22 14:51:36 +01:00
Stian Thorgersen 74e2bfd9bd Merge pull request #414 from mposolda/master
Extract some version numbers into properties
2014-05-22 11:21:55 +01:00
mposolda 0c60bd80df Extract some versions into properties 2014-05-22 12:04:13 +02:00
Stian Thorgersen 46f81a331a Merge pull request #413 from mposolda/master
Fixing location of folder for FolderThemeProvider
2014-05-22 08:54:22 +01:00
mposolda b0ba7ed188 Fixing location of FolderThemeProvider 2014-05-22 09:21:42 +02:00
Bill Burke 0d9e14d4c7 Merge remote-tracking branch 'upstream/master' 2014-05-21 10:56:21 -04:00
Stian Thorgersen 10ae457237 Fixes to admin console 2014-05-21 14:10:59 +01:00
Stian Thorgersen 73f59417bd Remove index.html from redirect on '/auth/admin/' 2014-05-21 12:47:07 +01:00
Stian Thorgersen 6814230193 Fix NPE in account service 2014-05-21 12:13:00 +01:00
Stian Thorgersen d68131ac00 KEYCLOAK-475
Log is shown in menu when audit is disabled for realm
2014-05-21 12:05:32 +01:00
Stian Thorgersen 952f098440 KEYCLOAK-483
Remove 'index.html' from console url
2014-05-21 11:16:48 +01:00
Stian Thorgersen f08477ea66 Run import before creating default realm 2014-05-21 11:16:47 +01:00
Stian Thorgersen 8544dd66d8 Merge pull request #412 from mposolda/master
Mongo related fixes
2014-05-21 10:50:31 +01:00
Stian Thorgersen a5a2848251 KEYCLOAK-476
theme/account/patternfly/img/icon-sidebar-active.svg not found
2014-05-21 10:40:15 +01:00
mposolda 7232535729 More mongo fixes 2014-05-21 11:34:27 +02:00
mposolda 271292dbd4 Mongo related fixes 2014-05-21 11:34:27 +02:00
Stian Thorgersen eb47d43497 For installed app urn redirect to a page instead of returning the html, this is to prevent NPE if page is refreshed 2014-05-21 10:32:03 +01:00
Stian Thorgersen fd9317a295 KEYCLOAK-474
Code not visible for urn:ietf:wg:oauth:2.0:oob
2014-05-21 09:52:02 +01:00
Stian Thorgersen 11fc6d5321 KEYCLOAK-477
Remove keycloak.js debug statements
2014-05-21 09:39:02 +01:00
Stian Thorgersen 64a36aee03 Merge pull request #411 from stianst/master
Twitter fix and read keycloak-sever.json from standalone/configuration
2014-05-21 09:35:49 +01:00
Stian Thorgersen 59440840fe Read keycloak-sever.json from <JBOSS_HOME>/standalone/configuration if it exists 2014-05-21 09:35:01 +01:00
Stian Thorgersen c2075af7f7 Fix Twitter for localhost 2014-05-21 08:47:58 +01:00
Stian Thorgersen ab85f09608 Merge pull request #410 from ssilvert/master
Make UndertowUserSessionManagement class usable without the Servlet API.
2014-05-21 07:56:17 +01:00
Stan Silvert da799b18c3 Make UndertowUserSessionManagement class usable without the Servlet API. 2014-05-20 19:58:08 -04:00
Bill Burke ca6de3e486 simpler applicaiton create page 2014-05-20 17:45:14 -04:00
Bill Burke ae3c4e8459 default web origin is redirect uris 2014-05-20 17:40:45 -04:00
Bill Burke 8e79f550b0 Merge remote-tracking branch 'upstream/master' 2014-05-20 16:49:28 -04:00
Bill Burke 0137918701 urn 2014-05-20 16:49:25 -04:00
Bill Burke 79828ddc78 Merge pull request #409 from patriot1burke/master
fix urn redirect uri
2014-05-20 16:15:40 -04:00
Bill Burke fcca9dd90a fix urn redirect uri 2014-05-20 16:15:13 -04:00
Stian Thorgersen 1b4b537043 Merge pull request #408 from stianst/email-events
Email audit listener
2014-05-20 17:29:45 +01:00
Stian Thorgersen b09e2f697e Email audit listener 2014-05-20 17:04:17 +01:00
Bill Burke 2855baecef Merge pull request #407 from patriot1burke/master
check redirect uri exists in token service
2014-05-20 11:39:22 -04:00
Bill Burke b7cf1bb215 Merge remote-tracking branch 'upstream/master' 2014-05-20 11:38:50 -04:00
Bill Burke b3dd349342 check redirect uri exists in token service 2014-05-20 11:38:35 -04:00
Stian Thorgersen 357337047b Merge pull request #406 from stianst/master
Fix config for folder theme provider£
2014-05-20 14:42:39 +01:00
Stian Thorgersen 5496f043a5 Fix config for folder theme provider£ 2014-05-20 14:42:07 +01:00
Bill Burke a22aa8055f Merge pull request #405 from patriot1burke/master
redirect uris not required with bearer only
2014-05-20 09:31:23 -04:00
Bill Burke 57f0ea0638 Merge remote-tracking branch 'upstream/master' 2014-05-20 09:27:18 -04:00
Bill Burke f723ac79d1 redirect not required with bearer only 2014-05-20 09:19:04 -04:00
Stian Thorgersen 3a15b416a9 Merge pull request #404 from stianst/master
Add realm option to enable/disable Resource Owner Password Credentials G...
2014-05-20 11:33:07 +01:00
Stian Thorgersen cc97265c06 Add realm option to enable/disable Resource Owner Password Credentials Grant 2014-05-20 11:32:22 +01:00
Stian Thorgersen 665038d0ce Merge pull request #403 from stianst/master
Add email theme config for realm
2014-05-20 11:01:07 +01:00
Stian Thorgersen 8d1149dc07 Add email theme config for realm 2014-05-20 11:00:43 +01:00
Bill Burke ebea9e9270 Merge pull request #402 from patriot1burke/master
fix remove expired token
2014-05-19 18:53:54 -04:00
Bill Burke b5aa9efefb fix remove expired sessions 2014-05-19 18:53:28 -04:00
Bill Burke 95f56e2e62 fix removeexpired sessions 2014-05-19 18:33:54 -04:00
Bill Burke 273775d848 Merge pull request #401 from patriot1burke/master
fix aerogear again
2014-05-19 18:14:16 -04:00
Bill Burke 8606f344a8 fix aerogear again 2014-05-19 18:13:54 -04:00
Bill Burke 53c3696cbb Merge pull request #400 from patriot1burke/master
aerogear fix
2014-05-19 18:09:54 -04:00
Bill Burke 7203d9ba12 aerogear fix 2014-05-19 18:09:36 -04:00
Bill Burke 26d3e48555 Merge pull request #399 from patriot1burke/master
don't allow bearer-only to login
2014-05-19 15:09:18 -04:00
Bill Burke a53206995a stuff 2014-05-19 15:08:38 -04:00
Bill Burke b2c8f48af9 Merge pull request #398 from patriot1burke/master
require redirect
2014-05-19 14:54:31 -04:00
Bill Burke 11c23a7945 require redirect 2014-05-19 14:44:36 -04:00
Stian Thorgersen 3be4579204 Merge pull request #397 from stianst/email-themes
Email themes
2014-05-19 17:40:52 +01:00
Stian Thorgersen a3d08e7191 Added theme support to emails 2014-05-19 17:34:58 +01:00
Bill Burke 7e8b16f975 acct svc + sessions 2014-05-19 17:34:48 +01:00
Bill Burke 966eb2fe47 Merge pull request #396 from patriot1burke/master
acct svc + sessions
2014-05-19 11:46:04 -04:00
Bill Burke 5826f02ebe acct svc + sessions 2014-05-19 11:45:42 -04:00
Bill Burke 2b525c6016 Merge pull request #395 from patriot1burke/master
fix brute shutdown
2014-05-19 10:35:49 -04:00
Bill Burke dc7923c436 fix brute shutdown 2014-05-19 10:33:49 -04:00
Stian Thorgersen 00a64eeb89 Merge pull request #394 from stianst/master
Added keycloak-server.json for project-integrations/aerogear-ups
2014-05-19 10:47:15 +01:00
Stian Thorgersen 76c9f2c4ec Added keycloak-server.json for project-integrations/aerogear-ups 2014-05-19 10:46:33 +01:00
Bill Burke dafa52ea93 Merge pull request #393 from patriot1burke/master
user-session client association
2014-05-17 14:32:46 -04:00
Bill Burke c2bf6c3822 Merge remote-tracking branch 'upstream/master' 2014-05-17 14:24:37 -04:00
Bill Burke ab8de6ba25 client user-session association 2014-05-17 14:24:32 -04:00
Stian Thorgersen 6714e2b87f Merge pull request #392 from stianst/master
Server config
2014-05-16 17:34:13 +01:00
Stian Thorgersen 855269f35d Added 'keycloak-server.json' for configuring the server
Added SPI interface to detect SPI's
Converted Model to SPI/Provider to be loaded through ProviderSessionFactory
2014-05-16 17:33:22 +01:00
Stian Thorgersen a3ed02ea16 Merge pull request #391 from jeroenr/master
CORS improvements and clean up
2014-05-16 16:06:43 +01:00
Jeroen Rosenberg 84f13eadc1 * Possibility to add exposed headers
* Default allow headers
* Fix warnings, unused import, redundancies
2014-05-16 16:39:17 +02:00
Jeroen Rosenberg cedf43c084 Refactored joining of allowed headers to be more efficient 2014-05-16 14:28:49 +02:00
Jeroen Rosenberg 4c281a39bb Unused import 2014-05-16 14:10:13 +02:00
Jeroen Rosenberg 5533357c46 Added HEAD as default allowed method for Cors 2014-05-16 14:09:50 +02:00
Stian Thorgersen ae4d83107a Merge pull request #390 from jeroenr/master
Fixed URI encoding for clientId and parse optional client secret from config file
2014-05-16 13:02:41 +01:00
Jeroen Rosenberg b92494f023 Refactored to use switch with fall through for readability 2014-05-16 13:52:59 +02:00
Jeroen Rosenberg d3a2617d3c Read optional client secret configuration to ensure we can use Basic auth as well 2014-05-16 13:49:28 +02:00
Jeroen Rosenberg 740943290c URI encode clientId for referrer parameter 2014-05-16 13:46:46 +02:00
Bill Burke c51c7fe189 Merge pull request #389 from jeroenr/master
Improved exception handling. Don't swallow exception
2014-05-16 06:34:18 -04:00
Bill Burke 610eaaaaff Merge pull request #387 from cardosogabriel/POLISHING_UI
UI POLISHING: design styles and content
2014-05-16 06:34:09 -04:00
Jeroen Rosenberg bde9944449 Improved exception handling. Don't swallow exception 2014-05-16 09:35:19 +02:00
Bill Burke 1318ea85be Merge pull request #388 from patriot1burke/master
session idle and max lifespan
2014-05-15 23:18:43 -04:00
Bill Burke 67e3e60f28 test sso idle, logout on idle 2014-05-15 23:10:14 -04:00
Bill Burke bc2360e985 sso session idle and max lifespan 2014-05-15 17:25:57 -04:00
Gabriel Cardoso 8e7b0022a6 UI POLISHING: design styles and content 2014-05-15 15:22:38 -03:00
Bill Burke 27efd3c0a4 ssoSessionIdleTimeout refactor 2014-05-15 13:53:28 -04:00
Bill Burke 07a31d3f35 Merge pull request #386 from patriot1burke/master
check ssl required in adapter
2014-05-14 15:24:22 -04:00
Bill Burke 07dbb7d7b7 check ssl required in adapter 2014-05-14 15:23:45 -04:00
Bill Burke 26f6da10dd Merge pull request #385 from patriot1burke/master
Improved role and scope mapping screens
2014-05-14 14:50:52 -04:00
Bill Burke 7ba8e09aef improved scope screen 2014-05-14 14:50:11 -04:00
Stian Thorgersen d95372c993 Merge pull request #384 from stianst/master
Updated session status iframe for JavaScript adapter
2014-05-14 17:54:58 +01:00
Stian Thorgersen 643daadf60 Updated session status iframe for JavaScript adapter to be created automatically, and to invoke onAuthLogout callback if user is logged out 2014-05-14 17:46:30 +01:00
Stian Thorgersen 7bea4af6c9 Redirect to login page if logged out and submitting forms in acct mngmt 2014-05-14 17:46:30 +01:00
Stian Thorgersen b27776b3c6 Merge pull request #383 from matzew/master
removing java7 ctor usage of runtimeexception
2014-05-14 16:48:15 +01:00
Matthias Wessendorf d9c8dedcfb removing JavaSE6 incompatible ctor 2014-05-14 17:43:36 +02:00
Matthias Wessendorf 9e0bf9e7dc Removing exception ctor that does not work w/ java 6 2014-05-14 17:40:27 +02:00
Bill Burke 0e0dfb60e0 composite role mapping listing 2014-05-14 10:37:50 -04:00
Stian Thorgersen b95fd0d0b0 Merge pull request #382 from stianst/master
KEYCLOAK-431 View open sessions, and logout all sessions, through accoun...
2014-05-14 11:56:52 +01:00
Stian Thorgersen f4f9b1e323 KEYCLOAK-431 View open sessions, and logout all sessions, through account management 2014-05-14 11:56:28 +01:00
Bill Burke f7c3373f75 Merge pull request #381 from patriot1burke/master
IE fixes
2014-05-13 22:47:46 -04:00
Bill Burke 639b7c5610 fix IE problems 2014-05-13 22:33:46 -04:00
Bill Burke b30809d681 httponly, ie keycloak.js fix 2014-05-13 22:06:32 -04:00
Bill Burke 0731f9977b Merge pull request #380 from patriot1burke/master
cors example
2014-05-13 17:17:51 -04:00
Bill Burke e8f8829a76 cors example 2014-05-13 17:17:27 -04:00
Bill Burke 663ff30eae Merge pull request #379 from patriot1burke/master
angular example
2014-05-13 12:07:59 -04:00
Bill Burke 01d22c3aab angular example 2014-05-13 12:07:28 -04:00
Bill Burke 9b24369b92 Merge pull request #378 from patriot1burke/master
update ups writeup
2014-05-12 19:45:24 -04:00
Bill Burke f6645eea92 update ups writeup 2014-05-12 19:45:01 -04:00
Bill Burke 634f61281d Merge pull request #377 from patriot1burke/master
aerogear template
2014-05-12 19:40:00 -04:00
Bill Burke c560a739b1 aerogear readme 2014-05-12 19:39:29 -04:00
Bill Burke ea672e36ae rename realm management app 2014-05-12 19:28:34 -04:00
Bill Burke eb9335f706 aerogear 2014-05-12 18:34:17 -04:00
Bill Burke d429525620 Merge pull request #376 from patriot1burke/master
fix create realm
2014-05-12 15:42:42 -04:00
Bill Burke b1a480c20d fix create realm 2014-05-12 15:42:10 -04:00
Bill Burke 0fcebb8670 remove bundled app 2014-05-12 15:38:15 -04:00
Bill Burke 3e32bd116b aerogear demo update 2014-05-12 15:35:54 -04:00
Bill Burke a4cb268703 Merge pull request #375 from patriot1burke/master
per-realm admin console
2014-05-12 10:13:18 -04:00
Bill Burke 06b98589eb Merge remote-tracking branch 'upstream/master' 2014-05-12 10:12:42 -04:00
Bill Burke 1e1991e285 per-realm admin 2014-05-12 10:12:31 -04:00
Bill Burke b0446fab0c Merge pull request #374 from patriot1burke/master
iframe check login
2014-05-10 11:28:24 -04:00
Bill Burke 1194e40ef2 iframe check login 2014-05-10 11:23:44 -04:00
Stian Thorgersen 2a820c73b1 Merge pull request #373 from stianst/master
KEYCLOAK-421 Set realm admin apps to bearer-only
2014-05-09 12:03:56 +01:00
Stian Thorgersen 624fcf6197 KEYCLOAK-421 Set realm admin apps to bearer-only 2014-05-09 12:03:39 +01:00
Stian Thorgersen 59747500aa Merge pull request #372 from stianst/login-session
KEYCLOAK-432 Added user sessions
2014-05-09 11:53:23 +01:00
Stian Thorgersen 6f0b12174c KEYCLOAK-432 Added user sessions 2014-05-09 11:52:45 +01:00
Bill Burke 5568c8dc7d Merge pull request #371 from patriot1burke/master
keycloak.js admin login
2014-05-08 20:08:52 -04:00
Bill Burke d957cc4883 Merge remote-tracking branch 'upstream/master' 2014-05-08 20:03:20 -04:00
Bill Burke 2d949b63b5 keycloak.js login for admin 2014-05-08 19:55:57 -04:00
Stian Thorgersen abdbef6a51 Merge pull request #370 from mposolda/master
Social fixes and improvements
2014-05-07 16:50:19 +01:00
mposolda c51011acef KEYCLOAK-354 Possibility for admin to see social links of some user in admin console 2014-05-07 17:28:13 +02:00
mposolda 6b1e0401ba KEYCLOAK-361 it shouldn't be possible to remove last social link if user don't have password 2014-05-07 17:28:13 +02:00
Stian Thorgersen d523242dbb Merge pull request #368 from mposolda/master
A bit more cleanup of dependencies
2014-05-07 12:52:22 +01:00
Stian Thorgersen 92058b16c9 Merge pull request #369 from abstractj/cleanup
Little code clean up
2014-05-07 12:52:09 +01:00
Bruno Oliveira 4424c425a6 Redundant initialization 2014-05-07 08:15:31 -03:00
Bruno Oliveira 5f7b0aae06 Variables will be never used 2014-05-07 08:15:02 -03:00
Bruno Oliveira f77e3b5532 Unused imports 2014-05-07 08:14:32 -03:00
Bruno Oliveira 334b981741 notBefore wasn't being assigned 2014-05-07 08:10:03 -03:00
Bruno Oliveira 957ff7d206 Make it final 2014-05-07 08:05:57 -03:00
Bruno Oliveira 5973ccd522 Scope can be private 2014-05-07 08:03:21 -03:00
Bruno Oliveira 1ea1f0af96 Removing redundant local variable 2014-05-07 07:49:45 -03:00
Bruno Oliveira f5ac81db41 Return not necessary here 2014-05-07 07:48:42 -03:00
Bruno Oliveira 9e7f52ccda extends Object isn't necessary 2014-05-07 07:47:39 -03:00
mposolda f8173e6a5a A bit more cleanup of dependencies 2014-05-07 11:08:47 +02:00
Bill Burke 5edf05d569 Merge pull request #366 from mposolda/export-import-rebased
Full export-import implemented. Remove dependency of mongo on picketlink...
2014-05-06 21:17:51 -04:00
Bill Burke 4666bcbfb2 Merge pull request #367 from patriot1burke/master
remove /rest from RealmsResource - pom fixes
2014-05-06 21:09:11 -04:00
Bill Burke a374e52ea5 /rest removal web.xml fixes 2014-05-06 21:08:27 -04:00
Bill Burke f987d331b7 /rest removal and pom fixes 2014-05-06 20:43:01 -04:00
Bill Burke 314f177fe7 Merge remote-tracking branch 'upstream/master' 2014-05-06 20:21:59 -04:00
Bill Burke 64f591769a remove /rest from RealmsResource 2014-05-06 20:21:49 -04:00
mposolda 0801c9c120 Full export-import implemented. Remove dependency of mongo on picketlink-common 2014-05-06 22:15:57 +02:00
Bill Burke e4e02a2615 Merge pull request #365 from patriot1burke/master
aerogear fix
2014-05-06 10:41:42 -04:00
Bill Burke ff69607f52 aerogear fix 2014-05-06 10:41:17 -04:00
Bill Burke a23b213736 Merge pull request #362 from matzew/JSP-Error
Removing JSP code, adding simple text for a simple demo...
2014-05-06 10:33:27 -04:00
Bill Burke 36ce4e04d9 Merge pull request #364 from patriot1burke/master
add aerogear stuff
2014-05-06 10:10:45 -04:00
Bill Burke 3b6593b476 add aerogear stuff 2014-05-06 10:10:17 -04:00
Bill Burke 6ef3102cd1 Merge pull request #361 from patriot1burke/master
remove ups social dependencies
2014-05-06 10:08:08 -04:00
Bill Burke 39381c104c merge fixes 2014-05-06 10:07:48 -04:00
Bill Burke c04b490f29 port fix 2014-05-06 09:59:52 -04:00
Stian Thorgersen e1f2d296bf Merge pull request #363 from stianst/master
Removed org.json
2014-05-06 13:05:30 +01:00
Stian Thorgersen 1d760388de KEYCLOAK-441 Remove org.json 2014-05-06 12:32:29 +01:00
Stian Thorgersen 8286d1ce34 Fix breadcrumb for audit pages£ 2014-05-06 12:26:17 +01:00
Matthias Wessendorf 7b14d29dee Removing JSP code, adding simple text for a simple demo... 2014-05-06 11:29:08 +02:00
Bill Burke 75224d25b0 remove picketlink dependencies 2014-05-05 18:50:41 -04:00
Bill Burke 3a3ae742a4 Merge pull request #360 from patriot1burke/master
adatper deployment context fixes, picketlink abstraction
2014-05-05 18:21:45 -04:00
Bill Burke e7c64b7812 adatper deployment context fixes, picketlink abstraction 2014-05-05 18:20:52 -04:00
Bill Burke e55eb73fb9 Merge pull request #359 from patriot1burke/master
fix tomcat7 build
2014-05-02 13:00:32 -04:00
Bill Burke 201b35be54 fix tomcat7 build 2014-05-02 13:00:12 -04:00
Bill Burke e25b2b05ae Merge pull request #352 from ungarida/master
Tomcat7 adapter
2014-05-02 12:36:06 -04:00
Bill Burke 6b470f826e Merge pull request #358 from patriot1burke/master
dynamic key lookup, relative uris
2014-05-02 12:34:18 -04:00
Bill Burke 4517d9d707 Merge remote-tracking branch 'upstream/master' 2014-05-02 12:30:31 -04:00
Bill Burke 7ff2c77a82 relative uri tests and fixes 2014-05-02 12:30:08 -04:00
Bill Burke e5e43173bc relative redirect uris 2014-05-02 10:58:29 -04:00
Bill Burke 6f3822e6ea relative adapter urls 2014-05-02 10:17:40 -04:00
Bill Burke 95bafc416d Merge pull request #357 from patriot1burke/master
fix mime type
2014-04-30 14:26:12 -04:00
Bill Burke 2576975988 fix mimetype 2014-04-30 14:25:23 -04:00
Bill Burke 8c5ae9d052 fix mimetype 2014-04-30 14:24:37 -04:00
Stian Thorgersen 8ed5282da5 Merge pull request #356 from stianst/master
Documentation
2014-04-30 14:38:27 +01:00
Stian Thorgersen 9b6d9fda43 Updated documentation for js adapter 2014-04-30 14:38:02 +01:00
Stian Thorgersen 77c6b391c4 Document how to enable social only login 2014-04-30 14:07:03 +01:00
Stian Thorgersen c8432f74f6 Merge pull request #355 from stianst/master
KEYCLOAK-211 Enable social only login
2014-04-30 13:36:25 +01:00
Stian Thorgersen 8fa3425886 KEYCLOAK-211 Enable social only login 2014-04-30 11:57:44 +01:00
Stian Thorgersen 84396d0da1 Merge pull request #354 from stianst/master
KEYCLOAK-333 Removed use of RestEasy's Logger
2014-04-30 11:06:51 +01:00
Stian Thorgersen 38e6bde07e KEYCLOAK-415 Make sure query params are included when navigating in acct mngmt 2014-04-30 11:03:13 +01:00
Stian Thorgersen 9811aaeecc KEYCLOAK-333 Removed use of RestEasy's Logger 2014-04-30 10:13:53 +01:00
Stian Thorgersen 7284aae4df Merge pull request #353 from stianst/constraints
Ensure role name unique within realm/app
2014-04-30 09:50:58 +01:00
Stian Thorgersen 316431c4d1 Ensure role name unique within realm/app 2014-04-30 09:50:29 +01:00
Stian Thorgersen bb039576d4 Merge pull request #351 from stianst/constraints
Ensure application and client names are unique within realm
2014-04-29 17:16:25 +01:00
Stian Thorgersen 646e762cbe Ensure user loginName and email unique within realm 2014-04-29 17:15:28 +01:00
Stian Thorgersen 1d94649b96 Ensure application and client names are unique within realm 2014-04-29 12:03:09 +01:00
Stian Thorgersen 1fa019e9dd Merge pull request #350 from stianst/constraints
Enforce that realm name is unique in model
2014-04-29 10:44:42 +01:00
Stian Thorgersen 364998b34b Enforce that realm name is unique in model 2014-04-29 10:43:27 +01:00
Stian Thorgersen 6778fbfa3b Merge pull request #349 from mposolda/master
Fix testsuite with mongo. Upgrade picketlink and enable connection pooling for LDAP
2014-04-29 10:23:22 +01:00
mposolda bb11ad2ec1 KEYCLOAK-419 Upgrade picketlink dependency and enable ldap connection pooling 2014-04-29 11:10:10 +02:00
mposolda b6386630fb Fix testsuite with mongo 2014-04-29 10:37:43 +02:00
Bill Burke 363e5cdf64 Merge pull request #348 from patriot1burke/master
KeycloakApplication refactor
2014-04-28 18:05:59 -04:00
Bill Burke 7594be8014 merge 2014-04-28 18:05:03 -04:00
Bill Burke 62f8811a46 Merge remote-tracking branch 'upstream/master'
Conflicts:
	bundled-war-example/src/main/java/org/keycloak/server/KeycloakServerApplication.java
	bundled-war-example/src/main/webapp/WEB-INF/web.xml
2014-04-28 18:04:50 -04:00
Bill Burke 2d1dc4a874 application refactor 2014-04-28 17:34:06 -04:00
Stian Thorgersen 0546aebc84 More fixes to bundled war example 2014-04-28 14:32:25 +01:00
Stian Thorgersen c06009d5fb KEYCLOAK-430 Fix bundled war example 2014-04-28 13:36:34 +01:00
Stian Thorgersen 3d02fd5d0e KEYCLOAK-429 Remove role from composite roles when deleted 2014-04-28 12:55:04 +01:00
Bill Burke 562f6703b6 Merge remote-tracking branch 'upstream/master' 2014-04-25 13:15:00 -04:00
Stian Thorgersen 573c88564b Temporarily disabled unique constraint on Realm names as it breakes tests 2014-04-25 17:58:49 +01:00
Stian Thorgersen dabf101d96 Merge pull request #347 from stianst/master
Ensure Realm names are unique
2014-04-25 17:02:29 +01:00
Stian Thorgersen 292089cee8 Ensure Realm names are unique 2014-04-25 17:02:03 +01:00
Bill Burke 5594c73ceb Merge remote-tracking branch 'upstream/master' 2014-04-25 10:34:35 -04:00
Stian Thorgersen ce6652efb1 Merge pull request #346 from stianst/master
KEYCLOAK-347 Link realm and realm-permissions application
2014-04-25 15:32:47 +01:00
Stian Thorgersen f64f55a4c6 KEYCLOAK-347 Link realm and realm-permissions application 2014-04-25 15:32:28 +01:00
Bill Burke 9a3a8c39f4 merge 2014-04-25 10:03:56 -04:00
Bill Burke 1de4c31750 wtf 2014-04-25 10:02:49 -04:00
Bill Burke bda85f700a Merge pull request #343 from matzew/master
Adding simple CDI injection into resources
2014-04-25 09:58:59 -04:00
Stian Thorgersen 3471ce6c63 Merge pull request #345 from stianst/master
KEYCLOAK-385 Add CORS support to refresh token
2014-04-25 14:09:56 +01:00
Stian Thorgersen b8dfac391a KEYCLOAK-385 Add CORS support to refresh token 2014-04-25 14:09:39 +01:00
Stian Thorgersen 28546ad031 Merge pull request #344 from stianst/master
Theme support for admin
2014-04-25 13:59:41 +01:00
Stian Thorgersen d6e5e376bf Theme support for admin 2014-04-25 13:58:58 +01:00
Matthias Wessendorf 9b055c6ad6 Adding simple CDI injection into resources 2014-04-25 13:24:21 +02:00
Stian Thorgersen a3c17d1071 Merge pull request #342 from stianst/master
Added support for common resources to themes
2014-04-24 09:27:02 +01:00
Stian Thorgersen d57cd1aa91 Added support for common resources to themes 2014-04-24 09:26:19 +01:00
Bill Burke 3405330d92 Merge pull request #341 from patriot1burke/master
brute force fixes
2014-04-23 17:56:34 -04:00
Bill Burke 541e865fe8 brute force fixes 2014-04-23 17:55:13 -04:00
Davide Ungari c03b97d2d4 #cfg update version 2014-04-20 12:06:31 +02:00
Davide Ungari 5d275de8b2 #dev integrated adapter tomcat7 2014-04-18 08:32:42 +02:00
Bill Burke 80f3a3152c Merge pull request #340 from patriot1burke/master
brute force settings
2014-04-15 11:37:49 -04:00
Bill Burke 54abfb670c brute force settings 2014-04-15 11:37:27 -04:00
Bill Burke b41bf9f231 Merge pull request #339 from patriot1burke/master
more brute force detection
2014-04-14 18:59:09 -04:00
Bill Burke 2b8d2288fb more brute force detection 2014-04-14 18:58:45 -04:00
Bill Burke b556ff8a83 Merge pull request #338 from patriot1burke/master
move things around
2014-04-14 16:53:51 -04:00
Bill Burke 4c8471ef43 move things around 2014-04-14 16:51:53 -04:00
Bill Burke 1aa58ec580 Merge pull request #337 from patriot1burke/master
app/keycloak self bootstrapping bundle
2014-04-11 13:26:22 -04:00
Bill Burke 272806a3f3 app/keycloak self bootstrapping bundle 2014-04-11 13:24:07 -04:00
Bill Burke 51a718f337 Merge pull request #336 from patriot1burke/master
workarounds for resteasy 2.3.7 bugs
2014-04-10 22:34:19 -04:00
Bill Burke cc982cf246 workarounds for resteasy 2.3.7 bugs 2014-04-11 10:33:53 -04:00
Bill Burke 0896808625 Merge pull request #334 from mposolda/master
Reenable AuthProvidersIntegrationTest.registerUserLdapSuccess. Add varia...
2014-04-10 12:16:08 -04:00
Bill Burke c562e88e75 Merge pull request #335 from patriot1burke/master
fix server jboss-deployment-structure
2014-04-10 12:15:57 -04:00
Bill Burke abd7163205 fix server jboss-deployment-structure 2014-04-11 00:15:35 -04:00
mposolda 1701afb6d4 Fix standalone KeycloakServer 2014-04-10 14:59:54 +02:00
mposolda d8937b11cf Reenable AuthProvidersIntegrationTest.registerUserLdapSuccess. Add variable sleep after undertow stop in testsuite (some windows envs have issues when server is not fully stopped) 2014-04-10 10:29:13 +02:00
Bill Burke de871585e0 Merge pull request #333 from patriot1burke/master
remove transitive dependencies
2014-04-09 23:30:16 -04:00
Bill Burke b41c45d40a remove transitive dependencies 2014-04-10 11:29:47 -04:00
Bill Burke ecaa0d1401 use resteasy 2.3.7 2014-04-10 05:21:07 -04:00
Bill Burke cdc35d99bc cleanup 2014-04-09 22:34:36 -04:00
Bill Burke f5f96c5021 Merge pull request #332 from patriot1burke/master
use resteasy 2.3.7
2014-04-09 17:21:37 -04:00
Bill Burke 29a139f56b Merge pull request #331 from patriot1burke/master
cleanup
2014-04-09 14:00:19 -04:00
Stian Thorgersen daf1f2ed45 Merge pull request #330 from mposolda/master
Fix LDAP test on windows. Ensure that directory with data for embedded A...
2014-04-09 18:44:57 +01:00
mposolda eb37890924 Fix LDAP test on windows. Ensure that directory with data for embedded ApacheDS is deleted 2014-04-09 18:56:36 +02:00
Stian Thorgersen eb3e69d5d7 Updated audit timer 2014-04-09 06:40:15 +01:00
mposolda 5aefe52ccc Refactoring of Authentication SPI and Picketlink to use ProviderSessions
Refactoring of ProviderSessionFactory to support dependencies between components
Calling lifecycle methods
Removing KeycloakRegistry
2014-04-09 00:34:01 +02:00
mposolda 0d00db281a Fix the case when user is directly deleted in LDAP server 2014-04-09 00:06:04 +02:00
mposolda c8c4cfbaae Restructure of authentication module and packages 2014-04-09 00:06:04 +02:00
Bill Burke d5be56fa21 Merge pull request #328 from patriot1burke/master
fix broken build
2014-04-08 11:33:38 -04:00
Bill Burke 1d55a4f1e9 fix broken build 2014-04-08 23:32:26 -04:00
Stian Thorgersen 83bc115b63 Merge pull request #327 from stianst/master
Add timer jars to server
2014-04-08 13:09:26 +01:00
Stian Thorgersen e952ff142d Add timer jars to server 2014-04-08 13:09:06 +01:00
Stian Thorgersen b94bad7f58 Merge pull request #326 from stianst/master
Clearing audit events through admin console and through timer
2014-04-08 12:43:52 +01:00
Stian Thorgersen 354cf02aaa Fix audit mongo tests 2014-04-08 12:43:01 +01:00
Stian Thorgersen 7f0cf3eda8 Allow clearing audit events through admin console, and added timer to clear expired events 2014-04-08 11:32:20 +01:00
Stian Thorgersen 9bc0bd452d Merge pull request #325 from mposolda/master
Logging message during ldap bootstrap
2014-04-08 09:43:05 +01:00
mposolda d124f43423 Logging message during ldap bootstrap 2014-04-07 19:40:02 +02:00
Stian Thorgersen a197bda363 Merge pull request #324 from stianst/master
Audit configurable through admin console
2014-04-07 18:06:43 +01:00
Stian Thorgersen 8ca46fa35d Audit configurable through admin console 2014-04-07 17:58:52 +01:00
Stian Thorgersen aec8feab49 Merge pull request #323 from stianst/master
Move setting cors properties
2014-04-07 13:59:39 +01:00
Stian Thorgersen e7c30fff48 Move setting cors properties 2014-04-07 13:58:35 +01:00
Stian Thorgersen 2916cce6fb Merge pull request #322 from stianst/master
KEYCLOAK-411 Set cors properties in KeycloakDeployment
2014-04-07 13:39:53 +01:00
Stian Thorgersen bf95c2ba85 KEYCLOAK-411 Set cors properties in KeycloakDeployment 2014-04-07 13:39:32 +01:00
Stian Thorgersen 6081572179 Merge pull request #321 from stianst/master
Fix testsuite for mongo
2014-04-07 13:38:01 +01:00
Stian Thorgersen bbf5fee320 Fix testsuite for mongo 2014-04-07 13:35:26 +01:00
Stian Thorgersen d66862fd26 Merge pull request #320 from matzew/master
Adding JPA-Audit PU
2014-04-07 13:21:26 +01:00
Matthias Wessendorf 1c0ef4621e Adding JPA-Audit PU 2014-04-07 14:01:31 +02:00
Stian Thorgersen 323e032287 Merge pull request #319 from stianst/master
Update admin console to allow changing context-path for KC
2014-04-07 11:21:48 +01:00
Stian Thorgersen 948960f33f Allow changing base url for Keycloak 2014-04-07 10:54:27 +01:00
Stian Thorgersen abde247e14 Moved admin-ui-styles into admin-ui 2014-04-07 10:37:21 +01:00
Stian Thorgersen a0cd2bf5a7 Merge pull request #318 from mposolda/ldap
Basic support for registration of new users in AuthenticationProvider (like LDAP). Other improvements in auth SPI
2014-04-07 09:35:35 +01:00
mposolda 58083fbb96 Hide password tab in acct management if passwordUpdate not supported 2014-04-04 23:47:12 +02:00
mposolda ad068a300b Basic support for registration of new users in AuthenticationProvider 2014-04-04 19:53:02 +02:00
mposolda be320e11a5 Improve handling of exceptions thrown from picketlink 2014-04-04 16:35:26 +02:00
Stian Thorgersen b7826be103 Merged humanfriendly filter with capitalize 2014-04-04 15:30:06 +01:00
Stian Thorgersen 216e24864a Merge branch 'ldap' of https://github.com/mposolda/keycloak into mposolda-ldap
Conflicts:
	admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
	admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
2014-04-04 15:29:03 +01:00
Stian Thorgersen afea032322 Merge pull request #317 from stianst/master
Added audit to admin console
2014-04-04 15:19:40 +01:00
Stian Thorgersen 88ddc8ebca Added audit to admin console 2014-04-04 15:16:08 +01:00
mposolda 2aac603fad Added configuration of authentication providers into admin console 2014-04-04 13:20:12 +02:00
Stian Thorgersen 8caf3fa83a Added details to log view in acct mngmt 2014-04-04 11:01:18 +01:00
Stian Thorgersen 42975f0edf Merge pull request #315 from stianst/master
Added audit log to account mngmt
2014-04-03 18:24:11 +01:00
Stian Thorgersen 3433227fa7 Added audit log to account mngmt 2014-04-03 16:27:31 +01:00
Stian Thorgersen e6067c915d Added ProviderSession to requests 2014-04-03 16:27:31 +01:00
Stian Thorgersen fcfbf156ce Merge pull request #314 from mposolda/ldap
Fixing testsuite failures with mongo model
2014-04-03 10:26:54 +01:00
mposolda d564955cab Fixing testsuite failures with mongo model 2014-04-03 10:58:39 +02:00
Bill Burke 30d523a5c2 Merge pull request #313 from patriot1burke/master
brute force protection
2014-04-02 20:27:15 -04:00
Bill Burke 126b444d77 brute force merge 2014-04-02 20:26:33 -04:00
Bill Burke d58870545f brute force protection 2014-04-02 20:09:14 -04:00
Bill Burke 231e8895a5 Merge pull request #309 from vibe13/master
Cleaning of pom.xml files
2014-04-02 11:39:04 -04:00
Bill Burke 7d7b9e5b73 Merge pull request #312 from mposolda/ldap
Refactoring of AuthenticationProvider SPI. Add Ldap settings into admin console
2014-04-02 11:37:11 -04:00
mposolda 25bf6d63b4 Refactoring of AuthenticationProvider SPI 2014-04-02 17:27:07 +02:00
mposolda 05cd8a82e5 Storing default AuthenticationProvider at the realm creation time 2014-04-02 17:17:33 +02:00
mposolda 1c218c8e9b Add Ldap settings into admin console 2014-04-02 17:17:32 +02:00
Stian Thorgersen 8af81cd290 Merge pull request #311 from stianst/master
Added JPA and Mongo audit providers. Add audit deps to server war.
2014-04-02 14:05:07 +01:00
Stian Thorgersen 869601d041 Added audit deps to server war 2014-04-02 11:37:22 +01:00
Stian Thorgersen 21239fbab9 Added Mongo audit provider 2014-04-01 18:00:35 +01:00
Stian Thorgersen 722a077de7 Added JPA audit provider£ 2014-04-01 15:13:53 +01:00
Stian Thorgersen 1e15e97d17 Merge pull request #310 from stianst/audit
Started audit
2014-03-31 17:43:42 +01:00
Stian Thorgersen 225307e855 KEYCLOAK-389 Added AuditListener SPI
KEYCLOAK-390 Added JBoss Logging AuditListener
KEYCLOAK-391 Audit Token events
2014-03-31 17:35:14 +01:00
Andrea Vibelli 84f1e1b56e Extraction into properties of maven-compiler-plugin source and target 2014-03-31 11:17:16 +02:00
Andrea Vibelli bdf1c1f495 Remove unnecessary version declaration and insertion of groupId 2014-03-31 10:45:11 +02:00
Andrea Vibelli 5e1da96177 Remove unnecessary version declarations 2014-03-31 10:44:59 +02:00
Andrea Vibelli 3ddb2084cd Remove duplicated dead code 2014-03-31 10:44:47 +02:00
Andrea Vibelli d831e25366 Remove unnecessary groupId declarations 2014-03-31 10:44:34 +02:00
Andrea Vibelli 37fdc50fb4 Remove warnings about no schema definition in pom.xml files 2014-03-31 10:44:22 +02:00
Bill Burke d8a3025ea1 Merge remote-tracking branch 'upstream/master' 2014-03-27 14:10:01 -04:00
Bill Burke 911cf2ae45 Merge pull request #307 from jpkrohling/JavascriptCharset
Fixed charset issue while decoding token with atob
2014-03-27 11:40:48 -04:00
Bill Burke 60ba41e82f Merge pull request #308 from mposolda/ldap
Fix LDAP tests and teststuite on windows. Set initial password directly ...
2014-03-27 11:40:28 -04:00
mposolda 129eb6a3be Fix LDAP tests and teststuite on windows. Set initial password directly in code as import from LDIF is problematic on windows 2014-03-27 16:20:03 +01:00
Juraci Paixão Kröhling 34fbdf4358 Fixed charset issue while decoding token with atob 2014-03-27 09:48:16 +01:00
Bill Burke 51b3de7383 unfix uribuilder 2014-03-26 10:19:56 -04:00
Bill Burke 0ec19c9ec9 uribuilder fix 2014-03-26 10:09:41 -04:00
Bill Burke 4711dd083f Merge pull request #306 from mposolda/master
Remove unfinished ldap-settings tab, which I've added accidentally in pr...
2014-03-26 09:42:57 -04:00
mposolda bcc0bcd219 Remove unfinished ldap-settings tab, which I've added accidentally in previous PR 2014-03-26 14:38:11 +01:00
Stian Thorgersen 00aaefb926 Merge pull request #305 from mposolda/master
Added Authentication SPI dependencies to auth-server.war
2014-03-26 12:45:51 +00:00
mposolda 3302c54c43 Added Authentication SPI dependencies to auth-server.war 2014-03-26 12:57:11 +01:00
Stian Thorgersen 434dec2318 Merge pull request #304 from mposolda/ldap
KEYCLOAK-388 - Auth SPI should be able to differentiate between the INVA...
2014-03-26 11:55:34 +00:00
mposolda 96a05a9b77 Console: work in progress 2014-03-26 12:25:46 +01:00
mposolda 77a44751a6 KEYCLOAK-388 - Auth SPI should be able to differentiate between the INVALID_USERNAME and INVALID_CREDENTIALS 2014-03-26 09:49:47 +01:00
Stian Thorgersen 51b95b1b91 Merge pull request #303 from mposolda/ldap
Fixes in AuthenticationProvider. Fixing testsuite
2014-03-25 14:17:31 +00:00
mposolda ab02dea902 Fixes in AuthenticationProvider. Fixing testsuite 2014-03-25 15:05:08 +01:00
Bill Burke 28a1bd8535 Merge pull request #302 from mposolda/ldap
Authentication SPI. Implementations based on Picketlink+LDAP, model and ...
2014-03-25 08:42:27 -04:00
Stian Thorgersen a2a8e72e20 Merge pull request #301 from stianst/master
Fixes to JS sdk
2014-03-25 10:37:48 +00:00
Stian Thorgersen 4788dd8bd2 Fixes to JS sdk 2014-03-25 10:37:20 +00:00
mposolda 793f69d4b6 Authentication SPI. Implementations based on Picketlink+LDAP, model and external model (other realm). Added KeycloakRegistry 2014-03-24 23:11:11 +01:00
Stian Thorgersen 0879013a90 Merge pull request #300 from corinnekrych/readme.instructions.improvement
fix typos and formatting
2014-03-24 09:36:35 +00:00
corinnekrych 877a552f3b fix typos and formatting 2014-03-21 17:34:24 +01:00
Stian Thorgersen 2403e1f465 Merge pull request #299 from stianst/master
Added support for Cordova to keycloak.js
2014-03-19 17:02:05 +00:00
Stian Thorgersen 119423895d Removed files that shouldn't have been committed 2014-03-19 16:54:20 +00:00
Stian Thorgersen 702ae0307e Fixes to account referrer to allow configurable referrer uri based on app redirect uri 2014-03-19 16:52:41 +00:00
Stian Thorgersen b5bdeae2a2 Updates to keycloak.js, including adding support for Cordova
Conflicts:
	examples/cordova/example-realm.json
	examples/js-console/src/main/webapp/index.html
	integration/js/src/main/resources/META-INF/resources/js/keycloak.js
2014-03-19 16:52:41 +00:00
Stian Thorgersen 4159a97881 Merge pull request #298 from stianst/master
Updates to keycloak.js
2014-03-18 14:44:42 +00:00
Stian Thorgersen 2d5e6520db Updates to keycloak.js 2014-03-18 14:43:48 +00:00
Stian Thorgersen 331ab71427 KEYCLOAK-380 Added OAuth2Constants 2014-03-15 10:43:52 +00:00
Stian Thorgersen f9aaa16cfe KEYCLOAK-378 KEYCLOAK-379 KEYCLOAK-381 Fix refresh token if token contains app roles. Changed long time fields in AccessCode and AccessToken to int 2014-03-15 10:15:10 +00:00
Stian Thorgersen 2ebc32793a Started installed application adapter 2014-03-14 17:01:08 +00:00
Bill Burke cec948ffb4 Merge pull request #297 from patriot1burke/master
further adapter tests
2014-03-14 11:21:53 -04:00
Bill Burke 466b6762d9 further adapter tests 2014-03-14 11:21:32 -04:00
Bill Burke e03737c665 Merge pull request #296 from patriot1burke/master
adapter testing
2014-03-13 21:48:14 -04:00
Bill Burke 3f1b7a0335 adapter testing 2014-03-13 21:47:46 -04:00
Bill Burke f26f2faa72 Merge pull request #295 from patriot1burke/master
bump version to beta-1 snapshot
2014-03-13 11:25:01 -04:00
Bill Burke 7763da1273 bump version to beta-1 snapshot 2014-03-13 11:24:38 -04:00
Bill Burke bb6791d6eb Merge pull request #294 from patriot1burke/master
bump version
2014-03-13 10:58:48 -04:00
Bill Burke 1c6b867079 bump version 2014-03-13 10:58:22 -04:00
Bill Burke 6b57684c52 Merge pull request #293 from patriot1burke/master
NPE in create user
2014-03-13 10:57:13 -04:00
Bill Burke 08769a2daa NPE in create user 2014-03-13 10:56:09 -04:00
Stian Thorgersen 7fff2588b2 Merge pull request #292 from stianst/master
Set next version
2014-03-13 09:12:18 +00:00
Stian Thorgersen ee5cab04e0 Set next version 2014-03-13 09:10:42 +00:00
1175 changed files with 173187 additions and 34794 deletions

No files matched your search

-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-admin-ui-styles</artifactId>
<name>Keycloak Admin UI Styles</name>
<description />
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,71 +0,0 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* Clearfix */
.clearfix:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix {
display: inline-block;
}
html[xmlns] .clearfix {
display: block;
}
* html .clearfix {
height: 1%;
}
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="23px" height="14px" viewBox="0 0 23 14" enable-background="new 0 0 23 14" xml:space="preserve">
<polyline fill="none" stroke="#009AD8" stroke-miterlimit="10" points="1,13 7,7 1,1 "/>
</svg>

Before

Width:  |  Height:  |  Size: 573 B

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="22px" height="52px" viewBox="0 0 22 52" enable-background="new 0 0 22 52" xml:space="preserve">
<polygon fill="#828487" points="11,16 6.818,11.818 7.525,11.111 11,14.586 14.475,11.111 15.182,11.818 "/>
<polygon fill="#DBDADA" points="11,42 6.818,37.818 7.525,37.111 11,40.586 14.475,37.111 15.182,37.818 "/>
</svg>

Before

Width:  |  Height:  |  Size: 699 B

File diff suppressed because it is too large. Load diff

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 269 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-admin-ui</artifactId>
<name>Keycloak Admin UI</name>
<description />
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,192 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<style>
.mock_view {
padding: 2em 2em;
}
</style>
<meta charset="utf-8">
<title>Keycloak Admin Console</title>
<link rel="icon" href="/auth/admin-ui/img/favicon.ico">
<!-- Frameworks -->
<!--link rel="stylesheet" href="/auth/admin-ui/bootstrap/css/bootstrap.css"-->
<link rel="stylesheet" href="/auth/admin-ui/patternfly/css/patternfly.css">
<!-- Page styles -->
<link rel="stylesheet" href="/auth/admin-ui/css/admin-console.css">
<link href="lib/select2-3.4.1/select2.css" rel="stylesheet">
<script src="lib/jquery/jquery-1.10.2.js" type="text/javascript"></script>
<script src="lib/select2-3.4.1/select2.js" type="text/javascript"></script>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-resource.js"></script>
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
<script src="lib/angular/select2.js" type="text/javascript"></script>
<script src="lib/fileupload/angular-file-upload.min.js"></script> <!--
<script src="/auth/admin-ui/bootstrap-3.0.0-wip/js/dropdown.js"></script>
<script src="/auth/admin-ui/bootstrap-3.0.0-wip/js/tooltip.js"></script>
-->
<script src="/auth/admin-ui/js/bootstrap-tokenfield.js"></script>
<script src="/auth/admin-ui/bootstrap/js/bootstrap.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers/realm.js"></script>
<script src="js/controllers/applications.js"></script>
<script src="js/controllers/oauth-clients.js"></script>
<script src="js/controllers/users.js"></script>
<script src="js/loaders.js"></script>
<script src="js/services.js"></script>
<style>
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
</style>
</head>
<body class="admin-console" data-ng-controller="GlobalCtrl" ng-cloak>
<div id="idletimeout">
You will be logged off in <strong><span></span> seconds</strong> due to inactivity.
<a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.
</div>
<div class="feedback-aligner" data-ng-show="notification" data-ng-click="notification = null">
<div class="alert alert-{{notification.type}}"><strong>{{notification.header}}</strong> {{notification.message}}</div>
</div>
<header class="navbar navbar-default navbar-pf navbar-main header">
<nav id="kc-navigation" class="navbar" role="navigation">
<div class="navbar-header">
<div class="container">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<h1 class="navbar-title"><Strong>KeyCloak</Strong> Central Login</h1>
</div>
</div>
<div class="collapse navbar-collapse navbar-collapse-1">
<div class="container">
<ul class="nav navbar-nav navbar-utility" data-ng-show="auth.loggedIn">
<li class="dropdown">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
<span class="pficon pficon-user"></span>
{{auth.user.displayName}}<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/auth/rest/realms/keycloak-admin/account?referrer=admin-console">Manage Account</a></li>
<li class="separator"><a href="/auth/rest/admin/logout">Sign Out</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-primary persistent-secondary" data-ng-controller="RealmDropdownCtrl">
<li class="dropdown context" data-ng-show="showNav()">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Realm: {{current.realm.id}}
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li data-ng-repeat="realm in current.realms">
<a href="" ng-click="changeRealm(realm.id)" >{{realm.id}}</a>
</li>
</ul>
</li>
<!--------------------------------------->
<li class="active">
<a href="#">Settings</a>
<ul class="nav navbar-nav navbar-persistent">
<li class="active">
<a href="#">General</a>
</li>
<li>
<a href="#">Roles</a>
</li>
<li>
<a href="#">Default Roles</a>
</li>
<li>
<a href="#">Credentials</a>
</li>
<li>
<a href="#">Token</a>
</li>
<li>
<a href="#">Keys</a>
</li>
<li>
<a href="#">Email</a>
</li>
</ul>
</li>
<li>
<a href="#">User</a>
</li>
<li>
<a href="#">Applications</a>
</li>
<li>
<a href="#">OAuth Clients</a>
</li>
<!--------------------------------------->
<li class="active pull-right" data-ng-show="auth.loggedIn">
<a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
data-ng-show="auth.loggedIn">Add Realm</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<div class="mock_view" data-ng-view id="view"></div>
<div id="loading" class="loading-backdrop">
<div class="loading">
<span>Loading...</span>
</div>
</div>
</div>
<script type="text/javascript">
$.idleTimeout('#idletimeout', '#idletimeout a', {
idleAfter: 300,
pollingInterval: 60,
keepAliveURL: '/auth/rest/admin/keepalive',
serverResponseEquals: '',
failedRequests: 1,
onTimeout: function(){
$(this).slideUp();
window.location = "/auth/rest/admin/logout";
},
onIdle: function(){
$(this).slideDown(); // show the warning bar
},
onCountdown: function( counter ){
$(this).find("span").html( counter ); // update the counter
},
onResume: function(){
$(this).slideUp(); // hide the warning bar
}
});
</script>
</body>
</html>
@@ -1,14 +0,0 @@
<div class="modal-dialog" tabindex="-1" role="dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span>
</button>
<h4 class="modal-title" id="myModalLabel">{{ title }}</h4>
</div>
<div class="modal-body"><p ng-bind-html-unsafe="message"></p></div>
<div class="modal-footer">
<button ng-repeat="btn in buttons" ng-click="close(btn.result)" class="" ng-class="btn.cssClass">{{ btn.label }}</button>
</div>
</div>
</div>
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
</web-fragment>
+40
View File
@@ -0,0 +1,40 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-api</artifactId>
<name>Keycloak Audit API</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,149 @@
package org.keycloak.audit;
import org.jboss.logging.Logger;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import java.util.HashMap;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Audit {
private static final Logger log = Logger.getLogger(Audit.class);
private List<AuditListener> listeners;
private Event event;
public Audit(List<AuditListener> listeners, RealmModel realm, String ipAddress) {
this.listeners = listeners;
this.event = new Event();
realm(realm);
ipAddress(ipAddress);
}
Audit() {
}
public Audit realm(RealmModel realm) {
event.setRealmId(realm.getId());
return this;
}
public Audit realm(String realmId) {
event.setRealmId(realmId);
return this;
}
public Audit client(ClientModel client) {
event.setClientId(client.getClientId());
return this;
}
public Audit client(String clientId) {
event.setClientId(clientId);
return this;
}
public Audit user(UserModel user) {
event.setUserId(user.getId());
return this;
}
public Audit user(String userId) {
event.setUserId(userId);
return this;
}
public Audit session(UserSessionModel session) {
event.setSessionId(session.getId());
return this;
}
public Audit session(String sessionId) {
event.setSessionId(sessionId);
return this;
}
public Audit ipAddress(String ipAddress) {
event.setIpAddress(ipAddress);
return this;
}
public Audit event(EventType e) {
event.setEvent(e);
return this;
}
public Audit detail(String key, String value) {
if (value == null || value.equals("")) {
return this;
}
if (event.getDetails() == null) {
event.setDetails(new HashMap<String, String>());
}
event.getDetails().put(key, value);
return this;
}
public Audit removeDetail(String key) {
if (event.getDetails() != null) {
event.getDetails().remove(key);
}
return this;
}
public Event getEvent() {
return event;
}
public void success() {
send();
}
public void error(String error) {
event.setEvent(EventType.valueOf(event.getEvent().name() + "_ERROR"));
event.setError(error);
send();
}
public Audit clone() {
Audit clone = new Audit();
clone.listeners = listeners;
clone.event = event.clone();
return clone;
}
public Audit reset() {
Event old = event;
event = new Event();
event.setRealmId(old.getRealmId());
event.setIpAddress(old.getIpAddress());
event.setClientId(old.getClientId());
event.setUserId(old.getUserId());
return this;
}
private void send() {
event.setTime(System.currentTimeMillis());
if (listeners != null) {
for (AuditListener l : listeners) {
try {
l.onEvent(event);
} catch (Throwable t) {
log.error("Failed to send event to " + l, t);
}
}
}
}
}
@@ -0,0 +1,12 @@
package org.keycloak.audit;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface AuditListener extends Provider {
public void onEvent(Event event);
}
@@ -0,0 +1,10 @@
package org.keycloak.audit;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface AuditListenerFactory extends ProviderFactory<AuditListener> {
}
@@ -0,0 +1,27 @@
package org.keycloak.audit;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class AuditListenerSpi implements Spi {
@Override
public String getName() {
return "audit-listener";
}
@Override
public Class<? extends Provider> getProviderClass() {
return AuditListener.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuditListenerFactory.class;
}
}
@@ -0,0 +1,16 @@
package org.keycloak.audit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface AuditProvider extends AuditListener {
public EventQuery createQuery();
public void clear();
public void clear(String realmId);
public void clear(String realmId, long olderThan);
}
@@ -0,0 +1,10 @@
package org.keycloak.audit;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface AuditProviderFactory extends ProviderFactory<AuditProvider> {
}
@@ -0,0 +1,27 @@
package org.keycloak.audit;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class AuditProviderSpi implements Spi {
@Override
public String getName() {
return "audit";
}
@Override
public Class<? extends Provider> getProviderClass() {
return AuditProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuditProviderFactory.class;
}
}
@@ -0,0 +1,22 @@
package org.keycloak.audit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface Details {
String EMAIL = "email";
String PREVIOUS_EMAIL = "previous_email";
String UPDATED_EMAIL = "updated_email";
String CODE_ID = "code_id";
String REDIRECT_URI = "redirect_uri";
String RESPONSE_TYPE = "response_type";
String AUTH_METHOD = "auth_method";
String REGISTER_METHOD = "register_method";
String USERNAME = "username";
String REMEMBER_ME = "remember_me";
String TOKEN_ID = "token_id";
String REFRESH_TOKEN_ID = "refresh_token_id";
String UPDATED_REFRESH_TOKEN_ID = "updated_refresh_token_id";
}
+41
View File
@@ -0,0 +1,41 @@
package org.keycloak.audit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface Errors {
String REALM_DISABLED = "realm_disabled";
String CLIENT_NOT_FOUND = "client_not_found";
String CLIENT_DISABLED = "client_disabled";
String INVALID_CLIENT_CREDENTIALS = "invalid_client_credentials";
String USER_NOT_FOUND = "user_not_found";
String USER_DISABLED = "user_disabled";
String USER_TEMPORARILY_DISABLED = "user_temporarily_disabled";
String INVALID_USER_CREDENTIALS = "invalid_user_credentials";
String USERNAME_MISSING = "username_missing";
String USERNAME_IN_USE = "username_in_use";
String INVALID_REDIRECT_URI = "invalid_redirect_uri";
String INVALID_CODE = "invalid_code";
String INVALID_TOKEN = "invalid_token";
String INVALID_REGISTRATION = "invalid_registration";
String INVALID_FORM = "invalid_form";
String REGISTRATION_DISABLED = "registration_disabled";
String REJECTED_BY_USER = "rejected_by_user";
String NOT_ALLOWED = "not_allowed";
String SOCIAL_PROVIDER_NOT_FOUND = "social_provider_not_found";
String SOCIAL_ID_IN_USE = "social_id_in_use";
String USER_NOT_LOGGED_IN = "user_not_logged_in";
String USER_SESSION_NOT_FOUND = "user_session_not_found";
}
@@ -0,0 +1,115 @@
package org.keycloak.audit;
import java.util.HashMap;
import java.util.Map;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Event {
private long time;
private EventType event;
private String realmId;
private String clientId;
private String userId;
private String sessionId;
private String ipAddress;
private String error;
private Map<String, String> details;
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public EventType getEvent() {
return event;
}
public void setEvent(EventType event) {
this.event = event;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public Map<String, String> getDetails() {
return details;
}
public void setDetails(Map<String, String> details) {
this.details = details;
}
public Event clone() {
Event clone = new Event();
clone.time = time;
clone.event = event;
clone.realmId = realmId;
clone.clientId = clientId;
clone.userId = userId;
clone.sessionId = sessionId;
clone.ipAddress = ipAddress;
clone.error = error;
clone.details = details != null ? new HashMap<String, String>(details) : null;
return clone;
}
}
@@ -0,0 +1,26 @@
package org.keycloak.audit;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface EventQuery {
public EventQuery event(EventType... events);
public EventQuery realm(String realmId);
public EventQuery client(String clientId);
public EventQuery user(String userId);
public EventQuery ipAddress(String ipAddress);
public EventQuery firstResult(int result);
public EventQuery maxResults(int results);
public List<Event> getResultList();
}
@@ -0,0 +1,42 @@
package org.keycloak.audit;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public enum EventType {
LOGIN,
LOGIN_ERROR,
REGISTER,
REGISTER_ERROR,
LOGOUT,
LOGOUT_ERROR,
CODE_TO_TOKEN,
CODE_TO_TOKEN_ERROR,
REFRESH_TOKEN,
REFRESH_TOKEN_ERROR,
SOCIAL_LINK,
SOCIAL_LINK_ERROR,
REMOVE_SOCIAL_LINK,
REMOVE_SOCIAL_LINK_ERROR,
UPDATE_EMAIL,
UPDATE_EMAIL_ERROR,
UPDATE_PROFILE,
UPDATE_PROFILE_ERROR,
UPDATE_PASSWORD,
UPDATE_PASSWORD_ERROR,
UPDATE_TOTP,
UPDATE_TOTP_ERROR,
VERIFY_EMAIL,
VERIFY_EMAIL_ERROR,
REMOVE_TOTP,
REMOVE_TOTP_ERROR,
SEND_VERIFY_EMAIL,
SEND_VERIFY_EMAIL_ERROR,
SEND_RESET_PASSWORD,
SEND_RESET_PASSWORD_ERROR
}
@@ -0,0 +1,2 @@
org.keycloak.audit.AuditProviderSpi
org.keycloak.audit.AuditListenerSpi
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-email</artifactId>
<name>Keycloak Audit Email Provider</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-email-api</artifactId>
<version>${project.version}</version>
<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,57 @@
package org.keycloak.audit.email;
import org.jboss.logging.Logger;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventType;
import org.keycloak.email.EmailException;
import org.keycloak.email.EmailProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class EmailAuditListener implements AuditListener {
private static final Logger log = Logger.getLogger(EmailAuditListener.class);
private KeycloakSession keycloakSession;
private EmailProvider emailProvider;
private Set<EventType> includedEvents;
public EmailAuditListener(KeycloakSession keycloakSession, EmailProvider emailProvider, Set<EventType> includedEvents) {
this.keycloakSession = keycloakSession;
this.emailProvider = emailProvider;
this.includedEvents = includedEvents;
}
@Override
public void onEvent(Event event) {
if (includedEvents.contains(event.getEvent())) {
if (event.getRealmId() != null && event.getUserId() != null) {
RealmModel realm = keycloakSession.getRealm(event.getRealmId());
UserModel user = realm.getUserById(event.getUserId());
if (user != null && user.getEmail() != null && user.isEmailVerified()) {
try {
emailProvider.setRealm(realm).setUser(user).sendEvent(event);
} catch (EmailException e) {
log.error("Failed to send event mail", e);
}
}
}
}
}
@Override
public void close() {
}
}
@@ -0,0 +1,62 @@
package org.keycloak.audit.email;
import org.keycloak.Config;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.AuditListenerFactory;
import org.keycloak.audit.EventType;
import org.keycloak.email.EmailProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.ProviderSession;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class EmailAuditListenerFactory implements AuditListenerFactory {
private static final Set<EventType> SUPPORTED_EVENTS = new HashSet<EventType>();
static {
Collections.addAll(SUPPORTED_EVENTS, EventType.LOGIN_ERROR, EventType.UPDATE_PASSWORD, EventType.REMOVE_TOTP, EventType.UPDATE_TOTP);
}
private Set<EventType> includedEvents = new HashSet<EventType>();
@Override
public AuditListener create(ProviderSession providerSession) {
KeycloakSession keycloakSession = providerSession.getProvider(KeycloakSession.class);
EmailProvider emailProvider = providerSession.getProvider(EmailProvider.class);
return new EmailAuditListener(keycloakSession, emailProvider, includedEvents);
}
@Override
public void init(Config.Scope config) {
String[] include = config.getArray("include-events");
if (include != null) {
for (String i : include) {
includedEvents.add(EventType.valueOf(i.toUpperCase()));
}
} else {
includedEvents.addAll(SUPPORTED_EVENTS);
}
String[] exclude = config.getArray("exclude-events");
if (exclude != null) {
for (String e : exclude) {
includedEvents.remove(EventType.valueOf(e.toUpperCase()));
}
}
}
@Override
public void close() {
}
@Override
public String getId() {
return "email";
}
}
@@ -0,0 +1 @@
org.keycloak.audit.email.EmailAuditListenerFactory
+40
View File
@@ -0,0 +1,40 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-jboss-logging</artifactId>
<name>Keycloak Audit JBoss Logging Provider</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,66 @@
package org.keycloak.audit.log;
import org.jboss.logging.Logger;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.Event;
import java.util.Map;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JBossLoggingAuditListener implements AuditListener {
private final Logger logger;
public JBossLoggingAuditListener(Logger logger) {
this.logger = logger;
}
@Override
public void onEvent(Event event) {
Logger.Level level = event.getError() != null ? Logger.Level.WARN : Logger.Level.INFO;
if (logger.isEnabled(level)) {
StringBuilder sb = new StringBuilder();
sb.append("event=");
sb.append(event.getEvent());
sb.append(", realmId=");
sb.append(event.getRealmId());
sb.append(", clientId=");
sb.append(event.getClientId());
sb.append(", userId=");
sb.append(event.getUserId());
sb.append(", ipAddress=");
sb.append(event.getIpAddress());
if (event.getError() != null) {
sb.append(", error=");
sb.append(event.getError());
}
if (event.getDetails() != null) {
for (Map.Entry<String, String> e : event.getDetails().entrySet()) {
sb.append(", ");
sb.append(e.getKey());
if (e.getValue() == null || e.getValue().indexOf(' ') == -1) {
sb.append("=");
sb.append(e.getValue());
} else {
sb.append("='");
sb.append(e.getValue());
sb.append("'");
}
}
}
logger.log(level, sb.toString());
}
}
@Override
public void close() {
}
}
@@ -0,0 +1,36 @@
package org.keycloak.audit.log;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.audit.AuditListener;
import org.keycloak.audit.AuditListenerFactory;
import org.keycloak.provider.ProviderSession;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JBossLoggingAuditListenerFactory implements AuditListenerFactory {
public static final String ID = "jboss-logging";
private static final Logger logger = Logger.getLogger("org.keycloak.audit");
@Override
public AuditListener create(ProviderSession providerSession) {
return new JBossLoggingAuditListener(logger);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return ID;
}
}
@@ -0,0 +1 @@
org.keycloak.audit.log.JBossLoggingAuditListenerFactory
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-jpa</artifactId>
<name>Keycloak Audit JPA Provider</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-tests</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.entitymanager.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,115 @@
package org.keycloak.audit.jpa;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@Entity
public class EventEntity {
@Id
private String id;
private long time;
private String event;
private String realmId;
private String clientId;
private String userId;
private String sessionId;
private String ipAddress;
private String error;
@Column(length = 2550)
private String detailsJson;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
public String getRealmId() {
return realmId;
}
public void setRealmId(String realmId) {
this.realmId = realmId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getDetailsJson() {
return detailsJson;
}
public void setDetailsJson(String detailsJson) {
this.detailsJson = detailsJson;
}
}
@@ -0,0 +1,122 @@
package org.keycloak.audit.jpa;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
import org.jboss.logging.Logger;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventQuery;
import org.keycloak.audit.EventType;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaAuditProvider implements AuditProvider {
private static final ObjectMapper mapper = new ObjectMapper();
private static final TypeReference<Map<String, String>> mapType = new TypeReference<Map<String, String>>() {
};
private static final Logger logger = Logger.getLogger(JpaAuditProvider.class);
private EntityManager em;
private EntityTransaction tx;
private Set<EventType> includedEvents;
public JpaAuditProvider(EntityManager em, Set<EventType> includedEvents) {
this.em = em;
this.includedEvents = includedEvents;
}
@Override
public EventQuery createQuery() {
return new JpaEventQuery(em);
}
@Override
public void clear() {
beginTx();
em.createQuery("delete from EventEntity").executeUpdate();
}
@Override
public void clear(String realmId) {
beginTx();
em.createQuery("delete from EventEntity where realmId = :realmId").setParameter("realmId", realmId).executeUpdate();
}
@Override
public void clear(String realmId, long olderThan) {
beginTx();
em.createQuery("delete from EventEntity where realmId = :realmId and time < :time").setParameter("realmId", realmId).setParameter("time", olderThan).executeUpdate();
}
@Override
public void onEvent(Event event) {
if (includedEvents.contains(event.getEvent())) {
beginTx();
em.persist(convert(event));
}
}
@Override
public void close() {
if (tx != null) {
tx.commit();
}
em.close();
}
private void beginTx() {
if (tx == null) {
tx = em.getTransaction();
tx.begin();
}
}
static EventEntity convert(Event o) {
EventEntity e = new EventEntity();
e.setId(UUID.randomUUID().toString());
e.setTime(o.getTime());
e.setEvent(o.getEvent().toString());
e.setRealmId(o.getRealmId());
e.setClientId(o.getClientId());
e.setUserId(o.getUserId());
e.setSessionId(o.getSessionId());
e.setIpAddress(o.getIpAddress());
e.setError(o.getError());
try {
e.setDetailsJson(mapper.writeValueAsString(o.getDetails()));
} catch (IOException ex) {
logger.error("Failed to write log details", ex);
}
return e;
}
static Event convert(EventEntity o) {
Event e = new Event();
e.setTime(o.getTime());
e.setEvent(EventType.valueOf(o.getEvent()));
e.setRealmId(o.getRealmId());
e.setClientId(o.getClientId());
e.setUserId(o.getUserId());
e.setSessionId(o.getSessionId());
e.setIpAddress(o.getIpAddress());
e.setError(o.getError());
try {
Map<String, String> details = mapper.readValue(o.getDetailsJson(), mapType);
e.setDetails(details);
} catch (IOException ex) {
logger.error("Failed to read log details", ex);
}
return e;
}
}
@@ -0,0 +1,63 @@
package org.keycloak.audit.jpa;
import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.audit.EventType;
import org.keycloak.provider.ProviderSession;
import org.keycloak.util.JpaUtils;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaAuditProviderFactory implements AuditProviderFactory {
public static final String ID = "jpa";
private EntityManagerFactory emf;
private Set<EventType> includedEvents = new HashSet<EventType>();
@Override
public AuditProvider create(ProviderSession providerSession) {
return new JpaAuditProvider(emf.createEntityManager(), includedEvents);
}
@Override
public void init(Config.Scope config) {
emf = Persistence.createEntityManagerFactory("jpa-keycloak-audit-store", JpaUtils.getHibernateProperties());
String[] include = config.getArray("include-events");
if (include != null) {
for (String i : include) {
includedEvents.add(EventType.valueOf(i.toUpperCase()));
}
} else {
for (EventType i : EventType.values()) {
includedEvents.add(i);
}
}
String[] exclude = config.getArray("exclude-events");
if (exclude != null) {
for (String e : exclude) {
includedEvents.remove(EventType.valueOf(e.toUpperCase()));
}
}
}
@Override
public void close() {
emf.close();
}
@Override
public String getId() {
return ID;
}
}
@@ -0,0 +1,111 @@
package org.keycloak.audit.jpa;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventQuery;
import org.keycloak.audit.EventType;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaEventQuery implements EventQuery {
private final EntityManager em;
private final CriteriaBuilder cb;
private final CriteriaQuery<EventEntity> cq;
private final Root<EventEntity> root;
private final ArrayList<Predicate> predicates;
private Integer firstResult;
private Integer maxResults;
public JpaEventQuery(EntityManager em) {
this.em = em;
cb = em.getCriteriaBuilder();
cq = cb.createQuery(EventEntity.class);
root = cq.from(EventEntity.class);
predicates = new ArrayList<Predicate>(4);
}
@Override
public EventQuery event(EventType... events) {
List<String> eventStrings = new LinkedList<String>();
for (EventType e : events) {
eventStrings.add(e.toString());
}
predicates.add(root.get("event").in(eventStrings));
return this;
}
@Override
public EventQuery realm(String realmId) {
predicates.add(cb.equal(root.get("realmId"), realmId));
return this;
}
@Override
public EventQuery client(String clientId) {
predicates.add(cb.equal(root.get("clientId"), clientId));
return this;
}
@Override
public EventQuery user(String userId) {
predicates.add(cb.equal(root.get("userId"), userId));
return this;
}
@Override
public EventQuery ipAddress(String ipAddress) {
predicates.add(cb.equal(root.get("ipAddress"), ipAddress));
return this;
}
@Override
public EventQuery firstResult(int firstResult) {
this.firstResult = firstResult;
return this;
}
@Override
public EventQuery maxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
@Override
public List<Event> getResultList() {
if (!predicates.isEmpty()) {
cq.where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
cq.orderBy(cb.desc(root.get("time")));
TypedQuery<EventEntity> query = em.createQuery(cq);
if (firstResult != null) {
query.setFirstResult(firstResult);
}
if (maxResults != null) {
query.setMaxResults(maxResults);
}
List<Event> events = new LinkedList<Event>();
for (EventEntity e : query.getResultList()) {
events.add(JpaAuditProvider.convert(e));
}
return events;
}
}
@@ -0,0 +1 @@
org.keycloak.audit.jpa.JpaAuditProviderFactory
@@ -0,0 +1,15 @@
package org.keycloak.audit.jpa;
import org.keycloak.audit.tests.AbstractAuditProviderTest;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class JpaAuditProviderTest extends AbstractAuditProviderTest {
@Override
protected String getProviderId() {
return JpaAuditProviderFactory.ID;
}
}
+22
View File
@@ -0,0 +1,22 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="jpa-keycloak-audit-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.audit.jpa.EventEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0"?>
<project>
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-mongo</artifactId>
<name>Keycloak Audit Mongo Provider</name>
<description/>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-tests</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<keycloak.audit.mongo.host>localhost</keycloak.audit.mongo.host>
<keycloak.audit.mongo.port>27018</keycloak.audit.mongo.port>
<keycloak.audit.mongo.db>keycloak</keycloak.audit.mongo.db>
<keycloak.audit.mongo.clearOnStartup>true</keycloak.audit.mongo.clearOnStartup>
<keycloak.audit.mongo.bindIp>127.0.0.1</keycloak.audit.mongo.bindIp>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<!-- Postpone tests to "integration-test" phase, so that we can bootstrap embedded mongo on 27018 before running tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<keycloak.audit.mongo.host>${keycloak.audit.mongo.host}</keycloak.audit.mongo.host>
<keycloak.audit.mongo.port>${keycloak.audit.mongo.port}</keycloak.audit.mongo.port>
<keycloak.audit.mongo.db>${keycloak.audit.mongo.db}</keycloak.audit.mongo.db>
<keycloak.audit.mongo.clearOnStartup>${keycloak.audit.mongo.clearOnStartup}</keycloak.audit.mongo.clearOnStartup>
<keycloak.audit.mongo.bindIp>${keycloak.model.mongo.bindIp}</keycloak.audit.mongo.bindIp>
</systemPropertyVariables>
</configuration>
</execution>
<execution>
<id>default-test</id>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>
<!-- Embedded mongo -->
<plugin>
<groupId>com.github.joelittlejohn.embedmongo</groupId>
<artifactId>embedmongo-maven-plugin</artifactId>
<executions>
<execution>
<id>start-mongodb</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
<configuration>
<port>${keycloak.audit.mongo.port}</port>
<logging>file</logging>
<logFile>${project.build.directory}/mongodb.log</logFile>
<bindIp>${keycloak.audit.mongo.bindIp}</bindIp>
</configuration>
</execution>
<execution>
<id>stop-mongodb</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,107 @@
package org.keycloak.audit.mongo;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventQuery;
import org.keycloak.audit.EventType;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoAuditProvider implements AuditProvider {
private DBCollection audit;
private Set<EventType> includedEvents;
public MongoAuditProvider(DBCollection audit, Set<EventType> includedEvents) {
this.audit = audit;
this.includedEvents = includedEvents;
}
@Override
public EventQuery createQuery() {
return new MongoEventQuery(audit);
}
@Override
public void clear() {
audit.remove(new BasicDBObject());
}
@Override
public void clear(String realmId) {
audit.remove(new BasicDBObject("realmId", realmId));
}
@Override
public void clear(String realmId, long olderThan) {
BasicDBObject q = new BasicDBObject();
q.put("realmId", realmId);
q.put("time", new BasicDBObject("$lt", olderThan));
audit.remove(q);
}
@Override
public void onEvent(Event event) {
if (includedEvents.contains(event.getEvent())) {
audit.insert(convert(event));
}
}
@Override
public void close() {
}
static DBObject convert(Event o) {
BasicDBObject e = new BasicDBObject();
e.put("time", o.getTime());
e.put("event", o.getEvent().toString());
e.put("realmId", o.getRealmId());
e.put("clientId", o.getClientId());
e.put("userId", o.getUserId());
e.put("sessionId", o.getSessionId());
e.put("ipAddress", o.getIpAddress());
e.put("error", o.getError());
BasicDBObject details = new BasicDBObject();
if (o.getDetails() != null) {
for (Map.Entry<String, String> entry : o.getDetails().entrySet()) {
details.put(entry.getKey(), entry.getValue());
}
}
e.put("details", details);
return e;
}
static Event convert(BasicDBObject o) {
Event e = new Event();
e.setTime(o.getLong("time"));
e.setEvent(EventType.valueOf(o.getString("event")));
e.setRealmId(o.getString("realmId"));
e.setClientId(o.getString("clientId"));
e.setUserId(o.getString("userId"));
e.setSessionId(o.getString("sessionId"));
e.setIpAddress(o.getString("ipAddress"));
e.setError(o.getString("error"));
BasicDBObject d = (BasicDBObject) o.get("details");
if (d != null) {
Map<String, String> details = new HashMap<String, String>();
for (Object k : d.keySet()) {
details.put((String) k, d.getString((String) k));
}
e.setDetails(details);
}
return e;
}
}
@@ -0,0 +1,96 @@
package org.keycloak.audit.mongo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.audit.EventType;
import org.keycloak.provider.ProviderSession;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoAuditProviderFactory implements AuditProviderFactory {
protected static final Logger logger = Logger.getLogger(MongoAuditProviderFactory.class);
public static final String ID = "mongo";
private MongoClient client;
private DB db;
private Set<EventType> includedEvents = new HashSet<EventType>();
@Override
public AuditProvider create(ProviderSession providerSession) {
return new MongoAuditProvider(db.getCollection("audit"), includedEvents);
}
@Override
public void init(Config.Scope config) {
try {
String host = config.get("host", ServerAddress.defaultHost());
int port = config.getInt("port", ServerAddress.defaultPort());
String dbName = config.get("db", "keycloak-audit");
boolean clearOnStartup = config.getBoolean("clearOnStartup", false);
String user = config.get("user");
String password = config.get("password");
if (user != null && password != null) {
MongoCredential credential = MongoCredential.createMongoCRCredential(user, dbName, password.toCharArray());
client = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential));
} else {
client = new MongoClient(host, port);
}
client.setWriteConcern(WriteConcern.UNACKNOWLEDGED);
db = client.getDB(dbName);
if (clearOnStartup) {
db.getCollection("audit").drop();
}
logger.infof("Initialized mongo audit. host: %s, port: %d, db: %s, clearOnStartup: %b", host, port, dbName, clearOnStartup);
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
String[] include = config.getArray("include-events");
if (include != null) {
for (String i : include) {
includedEvents.add(EventType.valueOf(i.toUpperCase()));
}
} else {
for (EventType i : EventType.values()) {
includedEvents.add(i);
}
}
String[] exclude = config.getArray("exclude-events");
if (exclude != null) {
for (String e : exclude) {
includedEvents.remove(EventType.valueOf(e.toUpperCase()));
}
}
}
@Override
public void close() {
client.close();
}
@Override
public String getId() {
return ID;
}
}
@@ -0,0 +1,93 @@
package org.keycloak.audit.mongo;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventQuery;
import org.keycloak.audit.EventType;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoEventQuery implements EventQuery {
private Integer firstResult;
private Integer maxResults;
private DBCollection audit;
private final BasicDBObject query;
public MongoEventQuery(DBCollection audit) {
this.audit = audit;
query = new BasicDBObject();
}
@Override
public EventQuery event(EventType... events) {
List<String> eventStrings = new LinkedList<String>();
for (EventType e : events) {
eventStrings.add(e.toString());
}
query.put("event", new BasicDBObject("$in", eventStrings));
return this;
}
@Override
public EventQuery realm(String realmId) {
query.put("realmId", realmId);
return this;
}
@Override
public EventQuery client(String clientId) {
query.put("clientId", clientId);
return this;
}
@Override
public EventQuery user(String userId) {
query.put("userId", userId);
return this;
}
@Override
public EventQuery ipAddress(String ipAddress) {
query.put("ipAddress", ipAddress);
return this;
}
@Override
public EventQuery firstResult(int firstResult) {
this.firstResult = firstResult;
return this;
}
@Override
public EventQuery maxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
@Override
public List<Event> getResultList() {
DBCursor cur = audit.find(query).sort(new BasicDBObject("time", -1));
if (firstResult != null) {
cur.skip(firstResult);
}
if (maxResults != null) {
cur.limit(maxResults);
}
List<Event> events = new LinkedList<Event>();
while (cur.hasNext()) {
events.add(MongoAuditProvider.convert((BasicDBObject) cur.next()));
}
return events;
}
}
@@ -0,0 +1 @@
org.keycloak.audit.mongo.MongoAuditProviderFactory
@@ -0,0 +1,15 @@
package org.keycloak.audit.mongo;
import org.keycloak.audit.tests.AbstractAuditProviderTest;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class MongoAuditProviderTest extends AbstractAuditProviderTest {
@Override
protected String getProviderId() {
return MongoAuditProviderFactory.ID;
}
}
Executable
+26
View File
@@ -0,0 +1,26 @@
<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.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Audit Parent</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>email</module>
<module>jpa</module>
<module>jboss-logging</module>
<module>mongo</module>
<module>tests</module>
</modules>
</project>
+47
View File
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>keycloak-audit-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-audit-tests</artifactId>
<name>Keycloak Audit Tests</name>
<description/>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-audit-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,139 @@
package org.keycloak.audit.tests;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.Config;
import org.keycloak.audit.AuditProvider;
import org.keycloak.audit.AuditProviderFactory;
import org.keycloak.audit.Event;
import org.keycloak.audit.EventType;
import org.keycloak.provider.ProviderFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public abstract class AbstractAuditProviderTest {
private ProviderFactory<AuditProvider> factory;
private AuditProvider provider;
@Before
public void before() {
String providerId = getProviderId();
ServiceLoader<AuditProviderFactory> factories = ServiceLoader.load(AuditProviderFactory.class);
for (AuditProviderFactory f : factories) {
if (f.getId().equals(providerId)) {
factory = f;
factory.init(Config.scope("audit", providerId));
}
}
provider = factory.create(null);
}
protected abstract String getProviderId();
@After
public void after() {
provider.clear();
provider.close();
factory.close();
}
@Test
public void save() {
provider.onEvent(create(EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
}
@Test
public void query() {
long oldest = System.currentTimeMillis() - 30000;
long newest = System.currentTimeMillis() + 30000;
provider.onEvent(create(EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(newest, EventType.REGISTER, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(newest, EventType.REGISTER, "realmId", "clientId", "userId2", "127.0.0.1", "error"));
provider.onEvent(create(EventType.LOGIN, "realmId2", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(oldest, EventType.LOGIN, "realmId", "clientId2", "userId", "127.0.0.1", "error"));
provider.onEvent(create(EventType.LOGIN, "realmId", "clientId", "userId2", "127.0.0.1", "error"));
provider.close();
provider = factory.create(null);
Assert.assertEquals(5, provider.createQuery().client("clientId").getResultList().size());
Assert.assertEquals(5, provider.createQuery().realm("realmId").getResultList().size());
Assert.assertEquals(4, provider.createQuery().event(EventType.LOGIN).getResultList().size());
Assert.assertEquals(6, provider.createQuery().event(EventType.LOGIN, EventType.REGISTER).getResultList().size());
Assert.assertEquals(4, provider.createQuery().user("userId").getResultList().size());
Assert.assertEquals(1, provider.createQuery().user("userId").event(EventType.REGISTER).getResultList().size());
Assert.assertEquals(2, provider.createQuery().maxResults(2).getResultList().size());
Assert.assertEquals(1, provider.createQuery().firstResult(5).getResultList().size());
Assert.assertEquals(newest, provider.createQuery().maxResults(1).getResultList().get(0).getTime());
Assert.assertEquals(oldest, provider.createQuery().firstResult(5).maxResults(1).getResultList().get(0).getTime());
}
@Test
public void clear() {
provider.onEvent(create(System.currentTimeMillis() - 30000, EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis() - 20000, EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis(), EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis(), EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis() - 30000, EventType.LOGIN, "realmId2", "clientId", "userId", "127.0.0.1", "error"));
provider.close();
provider = factory.create(null);
provider.clear("realmId");
Assert.assertEquals(1, provider.createQuery().getResultList().size());
}
@Test
public void clearOld() {
provider.onEvent(create(System.currentTimeMillis() - 30000, EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis() - 20000, EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis(), EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis(), EventType.LOGIN, "realmId", "clientId", "userId", "127.0.0.1", "error"));
provider.onEvent(create(System.currentTimeMillis() - 30000, EventType.LOGIN, "realmId2", "clientId", "userId", "127.0.0.1", "error"));
provider.close();
provider = factory.create(null);
provider.clear("realmId", System.currentTimeMillis() - 10000);
Assert.assertEquals(3, provider.createQuery().getResultList().size());
}
private Event create(EventType event, String realmId, String clientId, String userId, String ipAddress, String error) {
return create(System.currentTimeMillis(), event, realmId, clientId, userId, ipAddress, error);
}
private Event create(long time, EventType event, String realmId, String clientId, String userId, String ipAddress, String error) {
Event e = new Event();
e.setTime(time);
e.setEvent(event);
e.setRealmId(realmId);
e.setClientId(clientId);
e.setUserId(userId);
e.setIpAddress(ipAddress);
e.setError(error);
Map<String, String> details = new HashMap<String, String>();
details.put("key1", "value1");
details.put("key2", "value2");
e.setDetails(details);
return e;
}
}
+48
View File
@@ -0,0 +1,48 @@
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>keycloak-authentication-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-authentication-api</artifactId>
<name>Keycloak Authentication SPI</name>
<description />
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<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>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
package org.keycloak.authentication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthProviderConstants {
// Model is default provider. See AuthenticationProviderModel.DEFAULT_PROVIDER
public static final String PROVIDER_NAME_MODEL = "model";
public static final String PROVIDER_NAME_EXTERNAL_MODEL = "externalModel";
public static final String PROVIDER_NAME_PICKETLINK = "picketlink";
// Used in external-model provider
public static final String EXTERNAL_REALM_ID = "externalRealmId";
}
@@ -0,0 +1,12 @@
package org.keycloak.authentication;
/**
* Result of authentication by AuthenticationProvider
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public enum AuthProviderStatus {
SUCCESS, INVALID_CREDENTIALS, FAILED
}
@@ -0,0 +1,83 @@
package org.keycloak.authentication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthUser {
private String id;
private String username;
private String firstName;
private String lastName;
private String email;
private String providerName;
public AuthUser(String id, String username, String providerName) {
this.id = id;
this.username = username;
this.providerName = providerName;
}
public String getId() {
return id;
}
public AuthUser setId(String id) {
this.id = id;
return this;
}
public String getUsername() {
return username;
}
public AuthUser setUsername(String username) {
this.username = username;
return this;
}
public String getFirstName() {
return firstName;
}
public AuthUser setName(String name) {
int i = name.lastIndexOf(' ');
if (i != -1) {
firstName = name.substring(0, i);
lastName = name.substring(i + 1);
} else {
firstName = name;
}
return this;
}
public AuthUser setName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
return this;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
public AuthUser setEmail(String email) {
this.email = email;
return this;
}
public String getProviderName() {
return providerName;
}
public AuthUser setProviderName(String providerName) {
this.providerName = providerName;
return this;
}
}
@@ -0,0 +1,68 @@
package org.keycloak.authentication;
import java.util.List;
import java.util.Map;
import org.keycloak.models.RealmModel;
import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface AuthenticationProvider extends Provider {
String getName();
/**
* Get names of all available configuration options of current provider
*
* @return options or empty list if no options available
*/
List<String> getAvailableOptions();
/**
* Get user by given username or email. Return user instance or null if user doesn't exists in this authentication provider
*
* @param realm
* @param configuration
* @param username or email
* @return found user or null if user with given username doesn't exists
* @throws AuthenticationProviderException
*/
AuthUser getUser(RealmModel realm, Map<String, String> configuration, String username) throws AuthenticationProviderException;
/**
* Try to register user with this authentication provider
*
* @param realm
* @param configuration
* @param username
* @return ID of newly created user (For example ID from LDAP)
* @throws AuthenticationProviderException if user creation couldn't happen
*/
String registerUser(RealmModel realm, Map<String, String> configuration, String username) throws AuthenticationProviderException;
/**
* Standard Authentication flow
*
* @param username
* @param password
* @return result of authentication, which might eventually encapsulate info about authenticated user and provider which successfully authenticated
*/
AuthProviderStatus validatePassword(RealmModel realm, Map<String, String> configuration, String username, String password) throws AuthenticationProviderException;
/**
* Update credential
*
* @param realm
* @param configuration
* @param username
* @param password
* @return true if credential has been successfully updated
* @throws AuthenticationProviderException
*/
boolean updateCredential(RealmModel realm, Map<String, String> configuration, String username, String password) throws AuthenticationProviderException;
}
@@ -0,0 +1,24 @@
package org.keycloak.authentication;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationProviderException extends Exception {
private static final long serialVersionUID = 15L;
protected AuthenticationProviderException() {
}
public AuthenticationProviderException(String message) {
super(message);
}
public AuthenticationProviderException(Throwable cause) {
super(cause);
}
public AuthenticationProviderException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -0,0 +1,9 @@
package org.keycloak.authentication;
import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface AuthenticationProviderFactory extends ProviderFactory<AuthenticationProvider> {
}
@@ -0,0 +1,219 @@
package org.keycloak.authentication;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jboss.logging.Logger;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.ProviderSession;
import org.keycloak.util.ProviderLoader;
/**
* Access point to authentication SPI. It finds configured and available {@link AuthenticationProvider} instances for current realm
* and then delegates method call to them.
*
* Example of usage: AuthenticationProviderManager.getManager(realm).validateUser("joe", "password");
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationProviderManager {
private static final Logger logger = Logger.getLogger(AuthenticationProviderManager.class);
private final RealmModel realm;
private final Map<String, AuthenticationProvider> delegates;
public static AuthenticationProviderManager getManager(RealmModel realm, ProviderSession providerSession) {
Iterable<AuthenticationProvider> providers = providerSession.getAllProviders(AuthenticationProvider.class);
Map<String, AuthenticationProvider> providersMap = new HashMap<String, AuthenticationProvider>();
for (AuthenticationProvider provider : providers) {
providersMap.put(provider.getName(), provider);
}
return new AuthenticationProviderManager(realm, providersMap);
}
public AuthenticationProviderManager(RealmModel realm, Map<String, AuthenticationProvider> delegates) {
this.realm = realm;
this.delegates = delegates;
}
public AuthUser getUser(String username) {
List<AuthenticationProviderModel> authProviderModels = getConfiguredProviderModels(realm);
for (AuthenticationProviderModel providerModel : authProviderModels) {
AuthenticationProvider delegate = getProvider(providerModel.getProviderName());
if (delegate == null) {
continue;
}
try {
AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), username);
if (authUser != null) {
logger.debugf("User '%s' found with provider '%s'", username, providerModel.getProviderName());
return authUser;
}
} catch (AuthenticationProviderException ape) {
logger.warn(ape.getMessage(), ape);
}
}
logger.debugf("User '%s' not found with any provider", username);
return null;
}
public AuthProviderStatus validatePassword(UserModel user, String password) {
AuthenticationLinkModel authLink = user.getAuthenticationLink();
if (authLink == null) {
// User not yet linked with any authenticationProvider. Find provider with biggest priority where he is and link
AuthUser authUser = getUser(user.getLoginName());
authLink = new AuthenticationLinkModel(authUser.getProviderName(), authUser.getId());
user.setAuthenticationLink(authLink);
logger.infof("User '%s' linked with provider '%s'", authUser.getUsername(), authUser.getProviderName());
}
String providerName = authLink.getAuthProvider();
AuthenticationProviderModel providerModel = getConfiguredProviderModel(realm, providerName);
AuthenticationProvider delegate = getProvider(providerName);
if (delegate == null || providerModel == null) {
return AuthProviderStatus.FAILED;
}
try {
checkCorrectAuthLink(delegate, providerModel, authLink, user.getLoginName());
AuthProviderStatus currentResult = delegate.validatePassword(realm, providerModel.getConfig(), user.getLoginName(), password);
logger.debugf("Authentication provider '%s' finished with '%s' for authentication of '%s'", delegate.getName(), currentResult.toString(), user.getLoginName());
return currentResult;
} catch (AuthenticationProviderException ape) {
logger.warn(ape.getMessage(), ape);
return AuthProviderStatus.FAILED;
}
}
public boolean updatePassword(UserModel user, String password) throws AuthenticationProviderException {
AuthenticationLinkModel authLink = user.getAuthenticationLink();
if (authLink == null) {
// Find provider with biggest priority where password update is supported. Then register user here and link him
List<AuthenticationProviderModel> configuredProviders = getConfiguredProviderModels(realm);
for (AuthenticationProviderModel providerModel : configuredProviders) {
if (providerModel.isPasswordUpdateSupported()) {
AuthenticationProvider delegate = getProvider(providerModel.getProviderName());
if (delegate != null) {
AuthUser authUser = delegate.getUser(realm, providerModel.getConfig(), user.getLoginName());
if (authUser != null) {
// Linking existing user supported just for "model" provider. In other cases throw exception
if (providerModel.getProviderName().equals(AuthenticationProviderModel.DEFAULT_PROVIDER.getProviderName())) {
authLink = new AuthenticationLinkModel(providerModel.getProviderName(), authUser.getId());
user.setAuthenticationLink(authLink);
logger.infof("User '%s' linked with provider '%s'", authUser.getUsername(), authUser.getProviderName());
} else {
throw new AuthenticationProviderException("User " + authUser.getUsername() + " exists in provider "
+ authUser.getProviderName() + " but is not linked with model user");
}
} else {
String userIdInProvider = delegate.registerUser(realm, providerModel.getConfig(), user.getLoginName());
authLink = new AuthenticationLinkModel(providerModel.getProviderName(), userIdInProvider);
user.setAuthenticationLink(authLink);
logger.infof("User '%s' registered in provider '%s' and linked", user.getLoginName(), providerModel.getProviderName());
}
break;
}
}
}
if (authLink == null) {
logger.warnf("No providers found where password update is supported for user '%s'", user.getLoginName());
return false;
}
}
String providerName = authLink.getAuthProvider();
AuthenticationProviderModel providerModel = getConfiguredProviderModel(realm, providerName);
if (providerModel == null) {
return false;
}
String username = user.getLoginName();
// Update just those, which support password update
if (providerModel.isPasswordUpdateSupported()) {
try {
AuthenticationProvider delegate = getProvider(providerName);
if (delegate == null) {
return false;
}
checkCorrectAuthLink(delegate, providerModel, authLink, username);
if (delegate.updateCredential(realm,providerModel.getConfig(), user.getLoginName(), password)) {
logger.debugf("Updated password in authentication provider '%s' for user '%s'", providerName, username);
return true;
} else {
logger.warnf("Password not updated in authentication provider '%s' for user '%s'", providerName, username);
return false;
}
} catch (AuthenticationProviderException ape) {
// Rethrow it to upper layer
logger.warn("Failed to update password: " + ape.getMessage());
throw ape;
}
} else {
logger.warnf("Skip password update for authentication provider '%s' for user '%s'", providerName, username);
return false;
}
}
private AuthenticationProvider getProvider(String providerName) {
AuthenticationProvider delegate = delegates.get(providerName);
if (delegate == null) {
logger.warnf("Provider '%s' not available on classpath", providerName);
}
return delegate;
}
private static List<AuthenticationProviderModel> getConfiguredProviderModels(RealmModel realm) {
List<AuthenticationProviderModel> configuredProviders = realm.getAuthenticationProviders();
// Use model based authentication of current realm by default
if (configuredProviders == null || configuredProviders.isEmpty()) {
configuredProviders = Collections.EMPTY_LIST;
logger.warnf("No authentication providers found");
}
return configuredProviders;
}
public static AuthenticationProviderModel getConfiguredProviderModel(RealmModel realm, String providerName) {
List<AuthenticationProviderModel> providers = getConfiguredProviderModels(realm);
for (AuthenticationProviderModel provider : providers) {
if (providerName.equals(provider.getProviderName())) {
return provider;
}
}
logger.warnf("Provider '%s' not configured in realm", providerName);
return null;
}
// Check if ID of linked AuthUser is same as expected ID from authenticationLink . It should catch the case when for example user "john" was deleted in LDAP
// and then user "john" has been created again, but it's actually different user with different ID
private void checkCorrectAuthLink(AuthenticationProvider authProvider, AuthenticationProviderModel providerModel,
AuthenticationLinkModel authLinkModel, String username) throws AuthenticationProviderException {
AuthUser authUser = authProvider.getUser(realm, providerModel.getConfig(), username);
if (authUser == null) {
throw new AuthenticationProviderException("User " + username + " not found in authentication provider " + providerModel.getProviderName());
}
String userExternalId = authUser.getId();
if (!userExternalId.equals(authLinkModel.getAuthUserId())) {
throw new AuthenticationProviderException("ID did not match! ID from provider: " + userExternalId + ", ID from authentication link: " + authLinkModel.getAuthUserId());
}
}
}
@@ -0,0 +1,27 @@
package org.keycloak.authentication;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class AuthenticationSpi implements Spi {
@Override
public String getName() {
return "authentication";
}
@Override
public Class<? extends Provider> getProviderClass() {
return AuthenticationProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return AuthenticationProviderFactory.class;
}
}
@@ -0,0 +1 @@
org.keycloak.authentication.AuthenticationSpi
+74
View File
@@ -0,0 +1,74 @@
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>keycloak-authentication-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-authentication-model</artifactId>
<name>Keycloak Authentication Model Based</name>
<description />
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authentication-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
<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.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<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>
</plugins>
</build>
</project>
@@ -0,0 +1,84 @@
package org.keycloak.authentication.model;
import java.util.Map;
import org.jboss.logging.Logger;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.authentication.AuthProviderStatus;
import org.keycloak.authentication.AuthUser;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderException;
/**
* Authentication provider, which delegates calling of all methods to specified realm
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public abstract class AbstractModelAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = Logger.getLogger(AbstractModelAuthenticationProvider.class);
@Override
public AuthUser getUser(RealmModel currentRealm, Map<String, String> config, String username) throws AuthenticationProviderException {
RealmModel realm = getRealm(currentRealm, config);
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username);
return user == null ? null : createAuthenticatedUserInstance(user);
}
@Override
public String registerUser(RealmModel currentRealm, Map<String, String> config, String username) throws AuthenticationProviderException {
RealmModel realm = getRealm(currentRealm, config);
UserModel user = currentRealm.addUser(username);
user.setEnabled(true);
return user.getId();
}
@Override
public AuthProviderStatus validatePassword(RealmModel currentRealm, Map<String, String> config, String username, String password) throws AuthenticationProviderException {
RealmModel realm = getRealm(currentRealm, config);
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(realm, username);
boolean result = realm.validatePassword(user, password);
return result ? AuthProviderStatus.SUCCESS : AuthProviderStatus.INVALID_CREDENTIALS;
}
@Override
public boolean updateCredential(RealmModel currentRealm, Map<String, String> config, String username, String password) throws AuthenticationProviderException {
RealmModel realm = getRealm(currentRealm, config);
// Validate password policy
String error = realm.getPasswordPolicy().validate(password);
if (error != null) {
throw new AuthenticationProviderException(error);
}
UserModel user = realm.getUser(username);
if (user == null) {
logger.warnf("User '%s' doesn't exists. Skip password update", username);
return false;
}
UserCredentialModel cred = new UserCredentialModel();
cred.setType(CredentialRepresentation.PASSWORD);
cred.setValue(password);
user.updateCredential(cred);
return true;
}
@Override
public void close() {
}
protected abstract RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) throws AuthenticationProviderException;
protected AuthUser createAuthenticatedUserInstance(UserModel user) {
return new AuthUser(user.getId(), user.getLoginName(), getName())
.setName(user.getFirstName(), user.getLastName())
.setEmail(user.getEmail());
}
}
@@ -0,0 +1,53 @@
package org.keycloak.authentication.model;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProviderException;
import org.keycloak.provider.ProviderSession;
/**
* AbstractModelAuthenticationProvider, which delegates authentication operations to different (external) realm
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExternalModelAuthenticationProvider extends AbstractModelAuthenticationProvider {
public ExternalModelAuthenticationProvider(ProviderSession providerSession) {
}
@Override
public String getName() {
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
}
@Override
public List<String> getAvailableOptions() {
return Arrays.asList(AuthProviderConstants.EXTERNAL_REALM_ID);
}
@Override
public RealmModel getRealm(RealmModel currentRealm, Map<String, String> configuration) throws AuthenticationProviderException {
String realmId = configuration.get(AuthProviderConstants.EXTERNAL_REALM_ID);
if (realmId == null) {
throw new AuthenticationProviderException("Option '" + AuthProviderConstants.EXTERNAL_REALM_ID + "' not specified in configuration");
}
// TODO: This won't be needed when KeycloakSession is available from ProviderSession
KeycloakSession session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
if (session == null) {
throw new AuthenticationProviderException("KeycloakSession not available");
}
RealmModel realm = session.getRealm(realmId);
if (realm == null) {
throw new AuthenticationProviderException("Realm with id '" + realmId + "' doesn't exists");
}
return realm;
}
}
@@ -0,0 +1,32 @@
package org.keycloak.authentication.model;
import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
import org.keycloak.provider.ProviderSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ExternalModelAuthenticationProviderFactory implements AuthenticationProviderFactory {
@Override
public AuthenticationProvider create(ProviderSession providerSession) {
return new ExternalModelAuthenticationProvider(providerSession);
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return AuthProviderConstants.PROVIDER_NAME_EXTERNAL_MODEL;
}
}
@@ -0,0 +1,31 @@
package org.keycloak.authentication.model;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.keycloak.models.RealmModel;
import org.keycloak.authentication.AuthProviderConstants;
/**
* AbstractModelAuthenticationProvider, which uses current realm to call operations on
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ModelAuthenticationProvider extends AbstractModelAuthenticationProvider {
@Override
public String getName() {
return AuthProviderConstants.PROVIDER_NAME_MODEL;
}
@Override
public List<String> getAvailableOptions() {
return Collections.EMPTY_LIST;
}
@Override
protected RealmModel getRealm(RealmModel currentRealm, Map<String, String> config) {
return currentRealm;
}
}
@@ -0,0 +1,32 @@
package org.keycloak.authentication.model;
import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
import org.keycloak.provider.ProviderSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ModelAuthenticationProviderFactory implements AuthenticationProviderFactory {
@Override
public AuthenticationProvider create(ProviderSession providerSession) {
return new ModelAuthenticationProvider();
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return AuthProviderConstants.PROVIDER_NAME_MODEL;
}
}
@@ -0,0 +1,2 @@
org.keycloak.authentication.model.ModelAuthenticationProviderFactory
org.keycloak.authentication.model.ExternalModelAuthenticationProviderFactory
+101
View File
@@ -0,0 +1,101 @@
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>keycloak-authentication-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>keycloak-authentication-picketlink</artifactId>
<name>Keycloak Authentication Picketlink Based</name>
<description />
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-model-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authentication-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-picketlink-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
<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.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-impl</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-simple-schema</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<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>
</plugins>
</build>
</project>
@@ -0,0 +1,134 @@
package org.keycloak.authentication.picketlink;
import org.jboss.logging.Logger;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthProviderStatus;
import org.keycloak.authentication.AuthUser;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderException;
import org.keycloak.models.RealmModel;
import org.keycloak.picketlink.IdentityManagerProvider;
import org.picketlink.idm.IdentityManagementException;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.Password;
import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.model.basic.BasicModel;
import org.picketlink.idm.model.basic.User;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* AuthenticationProvider, which delegates authentication to picketlink
*
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class PicketlinkAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = Logger.getLogger(PicketlinkAuthenticationProvider.class);
private final IdentityManagerProvider identityManagerProvider;
public PicketlinkAuthenticationProvider(IdentityManagerProvider identityManagerProvider) {
this.identityManagerProvider = identityManagerProvider;
}
@Override
public String getName() {
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
}
@Override
public List<String> getAvailableOptions() {
return Collections.EMPTY_LIST;
}
@Override
public AuthUser getUser(RealmModel realm, Map<String, String> configuration, String username) throws AuthenticationProviderException {
IdentityManager identityManager = getIdentityManager(realm);
try {
User picketlinkUser = BasicModel.getUser(identityManager, username);
return picketlinkUser == null ? null : new AuthUser(picketlinkUser.getId(), picketlinkUser.getLoginName(), getName())
.setName(picketlinkUser.getFirstName(), picketlinkUser.getLastName())
.setEmail(picketlinkUser.getEmail())
.setProviderName(getName());
} catch (IdentityManagementException ie) {
throw convertIDMException(ie);
}
}
@Override
public String registerUser(RealmModel realm, Map<String, String> configuration, String username) throws AuthenticationProviderException {
IdentityManager identityManager = getIdentityManager(realm);
try {
User picketlinkUser = new User(username);
identityManager.add(picketlinkUser);
// Hack needed due to ActiveDirectory bug in Picketlink TODO: Remove once https://issues.jboss.org/browse/PLINK-485 fixed and updated in keycloak master
picketlinkUser = BasicModel.getUser(identityManager, picketlinkUser.getLoginName());
return picketlinkUser.getId();
} catch (IdentityManagementException ie) {
throw convertIDMException(ie);
}
}
@Override
public AuthProviderStatus validatePassword(RealmModel realm, Map<String, String> configuration, String username, String password) throws AuthenticationProviderException {
IdentityManager identityManager = getIdentityManager(realm);
try {
UsernamePasswordCredentials credential = new UsernamePasswordCredentials();
credential.setUsername(username);
credential.setPassword(new Password(password.toCharArray()));
identityManager.validateCredentials(credential);
if (credential.getStatus() == Credentials.Status.VALID) {
return AuthProviderStatus.SUCCESS;
} else {
return AuthProviderStatus.INVALID_CREDENTIALS;
}
} catch (IdentityManagementException ie) {
throw convertIDMException(ie);
}
}
@Override
public boolean updateCredential(RealmModel realm, Map<String, String> configuration, String username, String password) throws AuthenticationProviderException {
IdentityManager identityManager = getIdentityManager(realm);
try {
User picketlinkUser = BasicModel.getUser(identityManager, username);
if (picketlinkUser == null) {
logger.debugf("User '%s' doesn't exists. Skip password update", username);
return false;
}
identityManager.updateCredential(picketlinkUser, new Password(password.toCharArray()));
return true;
} catch (IdentityManagementException ie) {
throw convertIDMException(ie);
}
}
@Override
public void close() {
}
public IdentityManager getIdentityManager(RealmModel realm) throws AuthenticationProviderException {
return identityManagerProvider.getIdentityManager(realm);
}
private AuthenticationProviderException convertIDMException(IdentityManagementException ie) {
Throwable realCause = ie;
while (realCause.getCause() != null) {
realCause = realCause.getCause();
}
// Use the message from the realCause
return new AuthenticationProviderException(realCause.getMessage(), ie);
}
}
@@ -0,0 +1,33 @@
package org.keycloak.authentication.picketlink;
import org.keycloak.Config;
import org.keycloak.authentication.AuthProviderConstants;
import org.keycloak.authentication.AuthenticationProvider;
import org.keycloak.authentication.AuthenticationProviderFactory;
import org.keycloak.picketlink.IdentityManagerProvider;
import org.keycloak.provider.ProviderSession;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class PicketlinkAuthenticationProviderFactory implements AuthenticationProviderFactory {
@Override
public AuthenticationProvider create(ProviderSession providerSession) {
return new PicketlinkAuthenticationProvider(providerSession.getProvider(IdentityManagerProvider.class));
}
@Override
public void init(Config.Scope config) {
}
@Override
public void close() {
}
@Override
public String getId() {
return AuthProviderConstants.PROVIDER_NAME_PICKETLINK;
}
}
@@ -0,0 +1 @@
org.keycloak.authentication.picketlink.PicketlinkAuthenticationProviderFactory
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>keycloak-authentication-parent</artifactId>
<name>Keycloak Authentication</name>
<description />
<modules>
<module>authentication-api</module>
<module>authentication-model</module>
<module>authentication-picketlink</module>
</modules>
</project>
+5 -9
View File
@@ -1,9 +1,10 @@
<?xml version="1.0"?>
<project>
<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.0-alpha-3</version>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -18,11 +19,6 @@
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
@@ -61,8 +57,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
+5 -4
View File
@@ -1,9 +1,10 @@
<?xml version="1.0"?>
<project>
<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.0-alpha-3</version>
<version>1.0-beta-3</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -45,8 +46,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
@@ -2,7 +2,6 @@ package org.keycloak;
import org.keycloak.util.KeycloakUriBuilder;
import java.security.KeyStore;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
@@ -12,7 +11,9 @@ import java.util.concurrent.atomic.AtomicLong;
* @version $Revision: 1 $
*/
public class AbstractOAuthClient {
public static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
private static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State";
private final AtomicLong counter = new AtomicLong();
protected String clientId;
protected Map<String, String> credentials;
protected String authUrl;
@@ -23,8 +24,6 @@ public class AbstractOAuthClient {
protected String stateCookiePath;
protected boolean isSecure;
protected boolean publicClient;
protected final AtomicLong counter = new AtomicLong();
protected String getStateCode() {
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
@@ -103,8 +102,8 @@ public class AbstractOAuthClient {
protected String stripOauthParametersFromRedirect(String uri) {
KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
.replaceQueryParam(OAuth2Constants.CODE, null)
.replaceQueryParam(OAuth2Constants.STATE, null);
return builder.build().toString();
}
+145
View File
@@ -0,0 +1,145 @@
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Config {
private static ConfigProvider configProvider = new SystemPropertiesConfigProvider();
public static void init(ConfigProvider configProvider) {
Config.configProvider = configProvider;
}
public static String getAdminRealm() {
return configProvider.scope("admin").get("realm", "master");
}
public static String getProvider(String spi) {
return configProvider.getProvider(spi);
}
public static Scope scope(String... scope) {
return configProvider.scope(scope);
}
public static interface ConfigProvider {
String getProvider(String spi);
Scope scope(String... scope);
}
public static class SystemPropertiesConfigProvider implements ConfigProvider {
@Override
public String getProvider(String spi) {
return System.getProperties().getProperty("keycloak." + spi + ".provider");
}
@Override
public Scope scope(String... scope) {
StringBuilder sb = new StringBuilder();
sb.append("keycloak.");
for (String s : scope) {
sb.append(s);
sb.append(".");
}
return new SystemPropertiesScope(sb.toString());
}
}
public static class SystemPropertiesScope implements Scope {
private String prefix;
public SystemPropertiesScope(String prefix) {
this.prefix = prefix;
}
@Override
public String get(String key) {
return get(key, null);
}
@Override
public String get(String key, String defaultValue) {
return System.getProperty(prefix + key, defaultValue);
}
@Override
public String[] getArray(String key) {
String value = get(key);
if (value != null) {
String[] a = value.split(",");
for (int i = 0; i < a.length; i++) {
a[i] = a[i].trim();
}
return a;
} else {
return null;
}
}
@Override
public Integer getInt(String key) {
return getInt(key, null);
}
@Override
public Integer getInt(String key, Integer defaultValue) {
String v = get(key, null);
return v != null ? Integer.parseInt(v) : defaultValue;
}
@Override
public Long getLong(String key) {
return getLong(key, null);
}
@Override
public Long getLong(String key, Long defaultValue) {
String v = get(key, null);
return v != null ? Long.parseLong(v) : defaultValue;
}
@Override
public Boolean getBoolean(String key) {
return getBoolean(key, null);
}
@Override
public Boolean getBoolean(String key, Boolean defaultValue) {
String v = get(key, null);
return v != null ? Boolean.parseBoolean(v) : defaultValue;
}
}
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public static interface Scope {
String get(String key);
String get(String key, String defaultValue);
String[] getArray(String key);
Integer getInt(String key);
Integer getInt(String key, Integer defaultValue);
Long getLong(String key);
Long getLong(String key, Long defaultValue);
Boolean getBoolean(String key);
Boolean getBoolean(String key, Boolean defaultValue);
}
}
@@ -8,12 +8,16 @@ import java.security.Principal;
* @version $Revision: 1 $
*/
public class KeycloakPrincipal implements Principal, Serializable {
protected String name;
protected String surrogate;
protected final String name;
protected final KeycloakSecurityContext context;
public KeycloakPrincipal(String name, String surrogate) {
public KeycloakPrincipal(String name, KeycloakSecurityContext context) {
this.name = name;
this.surrogate = surrogate;
this.context = context;
}
public KeycloakSecurityContext getKeycloakSecurityContext() {
return context;
}
@Override
@@ -21,10 +25,6 @@ public class KeycloakPrincipal implements Principal, Serializable {
return name;
}
public String getSurrogate() {
return surrogate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -33,16 +33,13 @@ public class KeycloakPrincipal implements Principal, Serializable {
KeycloakPrincipal that = (KeycloakPrincipal) o;
if (!name.equals(that.name)) return false;
if (surrogate != null ? !surrogate.equals(that.surrogate) : that.surrogate != null) return false;
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (surrogate != null ? surrogate.hashCode() : 0);
return result;
return name.hashCode();
}
@Override
@@ -0,0 +1,30 @@
package org.keycloak;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface OAuth2Constants {
String CODE = "code";
String CLIENT_ID = "client_id";
String ERROR = "error";
String ERROR_DESCRIPTION = "error_description";
String REDIRECT_URI = "redirect_uri";
String SCOPE = "scope";
String STATE = "state";
String GRANT_TYPE = "grant_type";
String RESPONSE_TYPE = "response_type";
String REFRESH_TOKEN = "refresh_token";
}
@@ -19,6 +19,8 @@ public class OAuthErrorException extends Exception {
}
public OAuthErrorException(String error, String description, String message) {
super(message);
this.error = error;
this.description = description;
}
public OAuthErrorException(String error, String description) {
super(description);
@@ -16,29 +16,27 @@ public class RSATokenVerifier {
return verifyToken(tokenString, realmKey, realm, true);
}
public static AccessToken verifyToken(String tokenString, PublicKey realmKey, String realm, boolean checkActive) throws VerificationException {
JWSInput input = new JWSInput(tokenString);
boolean verified = false;
JWSInput input = null;
try {
verified = RSAProvider.verify(input, realmKey);
} catch (Exception ignore) {
input = new JWSInput(tokenString);
} catch (Exception e) {
throw new VerificationException("Couldn't parse token", e);
}
if (!verified) throw new VerificationException("Token signature not validated");
if (!isPublicKeyValid(input, realmKey)) throw new VerificationException("Invalid token signature.");
AccessToken token = null;
AccessToken token;
try {
token = input.readJsonContent(AccessToken.class);
} catch (IOException e) {
throw new VerificationException(e);
throw new VerificationException("Couldn't parse token signature", e);
}
String user = token.getSubject();
if (user == null) {
throw new VerificationException("Token user was null");
throw new VerificationException("Token user was null.");
}
if (!realm.equals(token.getAudience())) {
throw new VerificationException("Token audience doesn't match domain");
throw new VerificationException("Token audience doesn't match domain.");
}
if (checkActive && !token.isActive()) {
@@ -47,4 +45,12 @@ public class RSATokenVerifier {
return token;
}
private static boolean isPublicKeyValid(JWSInput input, PublicKey realmKey) throws VerificationException {
try {
return RSAProvider.verify(input, realmKey);
} catch (Exception e) {
throw new VerificationException("Token signature not validated.", e);
}
}
}
@@ -6,7 +6,12 @@ package org.keycloak;
*/
public interface ServiceUrlConstants {
public static final String TOKEN_SERVICE_LOGIN_PATH = "/rest/realms/{realm-name}/tokens/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/rest/realms/{realm-name}/tokens/access/codes";
public static final String TOKEN_SERVICE_REFRESH_PATH = "/rest/realms/{realm-name}/tokens/refresh";
public static final String TOKEN_SERVICE_LOGIN_PATH = "/realms/{realm-name}/tokens/login";
public static final String TOKEN_SERVICE_ACCESS_CODE_PATH = "/realms/{realm-name}/tokens/access/codes";
public static final String TOKEN_SERVICE_REFRESH_PATH = "/realms/{realm-name}/tokens/refresh";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/realms/{realm-name}/tokens/logout";
public static final String TOKEN_SERVICE_DIRECT_GRANT_PATH = "/realms/{realm-name}/tokens/grants/access";
public static final String ACCOUNT_SERVICE_PATH = "/realms/{realm-name}/account";
public static final String REALM_INFO_PATH = "/realms/{realm-name}";
}
@@ -1,6 +1,5 @@
package org.keycloak.jose.jws;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
@@ -15,7 +15,7 @@ import java.security.NoSuchAlgorithmException;
* @version $Revision: 1 $
*/
public class HMACProvider {
public static String getJavaAlgorithm(Algorithm alg) {
private static String getJavaAlgorithm(Algorithm alg) {
switch (alg) {
case HS256:
return "HMACSHA256";
@@ -28,7 +28,7 @@ public class HMACProvider {
}
}
public static Mac getMAC(final Algorithm alg) {
private static Mac getMAC(final Algorithm alg) {
try {
return Mac.getInstance(getJavaAlgorithm(alg));
@@ -0,0 +1,10 @@
package org.keycloak.provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface Provider {
public void close();
}
@@ -0,0 +1,18 @@
package org.keycloak.provider;
import org.keycloak.Config;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ProviderFactory<T extends Provider> {
public T create(ProviderSession providerSession);
public void init(Config.Scope config);
public void close();
public String getId();
}
@@ -0,0 +1,20 @@
package org.keycloak.provider;
import java.util.Set;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ProviderSession {
<T extends Provider> T getProvider(Class<T> clazz);
<T extends Provider> T getProvider(Class<T> clazz, String id);
<T extends Provider> Set<String> listProviderIds(Class<T> clazz);
<T extends Provider> Set<T> getAllProviders(Class<T> clazz);
void close();
}
@@ -0,0 +1,14 @@
package org.keycloak.provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface ProviderSessionFactory {
ProviderSession createSession();
void close();
void init();
}
@@ -0,0 +1,12 @@
package org.keycloak.provider;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public interface Spi {
public String getName();
public Class<? extends Provider> getProviderClass();
public Class<? extends ProviderFactory> getProviderFactoryClass();
}
@@ -128,12 +128,12 @@ public class AccessToken extends IDToken {
}
@Override
public AccessToken expiration(long expiration) {
public AccessToken expiration(int expiration) {
return (AccessToken) super.expiration(expiration);
}
@Override
public AccessToken notBefore(long notBefore) {
public AccessToken notBefore(int notBefore) {
return (AccessToken) super.notBefore(notBefore);
}
@@ -27,6 +27,9 @@ public class AccessTokenResponse {
@JsonProperty("not-before-policy")
protected int notBeforePolicy;
@JsonProperty("session-state")
protected String sessionState;
public String getToken() {
return token;
}
@@ -74,4 +77,12 @@ public class AccessTokenResponse {
public void setNotBeforePolicy(int notBeforePolicy) {
this.notBeforePolicy = notBeforePolicy;
}
public String getSessionState() {
return sessionState;
}
public void setSessionState(String sessionState) {
this.sessionState = sessionState;
}
}
@@ -88,6 +88,9 @@ public class IDToken extends JsonWebToken {
@JsonProperty("claims_locales")
protected String claimsLocales;
@JsonProperty("session_state")
protected String sessionState;
public String getNonce() {
return nonce;
}
@@ -303,4 +306,12 @@ public class IDToken extends JsonWebToken {
public void setClaimsLocales(String claimsLocales) {
this.claimsLocales = claimsLocales;
}
public String getSessionState() {
return sessionState;
}
public void setSessionState(String sessionState) {
this.sessionState = sessionState;
}
}
@@ -2,6 +2,7 @@ package org.keycloak.representations;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.keycloak.util.Time;
import java.io.Serializable;
@@ -13,9 +14,9 @@ public class JsonWebToken implements Serializable {
@JsonProperty("jti")
protected String id;
@JsonProperty("exp")
protected long expiration;
protected int expiration;
@JsonProperty("nbf")
protected long notBefore;
protected int notBefore;
@JsonProperty("iat")
protected int issuedAt;
@JsonProperty("iss")
@@ -39,26 +40,25 @@ public class JsonWebToken implements Serializable {
}
public long getExpiration() {
public int getExpiration() {
return expiration;
}
public JsonWebToken expiration(long expiration) {
public JsonWebToken expiration(int expiration) {
this.expiration = expiration;
return this;
}
@JsonIgnore
public boolean isExpired() {
long time = System.currentTimeMillis() / 1000;
return time > expiration;
return Time.currentTime() > expiration;
}
public long getNotBefore() {
public int getNotBefore() {
return notBefore;
}
public JsonWebToken notBefore(long notBefore) {
public JsonWebToken notBefore(int notBefore) {
this.notBefore = notBefore;
return this;
}
@@ -66,7 +66,7 @@ public class JsonWebToken implements Serializable {
@JsonIgnore
public boolean isNotBefore() {
return (System.currentTimeMillis() / 1000) >= notBefore;
return Time.currentTime() >= notBefore;
}
@@ -89,7 +89,7 @@ public class JsonWebToken implements Serializable {
*/
@JsonIgnore
public JsonWebToken issuedNow() {
issuedAt = (int)(System.currentTimeMillis() / 1000);
issuedAt = Time.currentTime();
return this;
}
@@ -13,7 +13,7 @@ public class RefreshToken extends AccessToken {
}
/**
* Deep copies issuer, subject, issuedFor, realmAccess, and resourceAccess
* Deep copies issuer, subject, issuedFor, sessionState, realmAccess, and resourceAccess
* from AccessToken.
*
* @param token
@@ -23,6 +23,7 @@ public class RefreshToken extends AccessToken {
this.issuer = token.issuer;
this.subject = token.subject;
this.issuedFor = token.issuedFor;
this.sessionState = token.sessionState;
if (token.realmAccess != null) {
realmAccess = token.realmAccess.clone();
}
@@ -1,6 +1,7 @@
package org.keycloak.representations.adapters.action;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.keycloak.util.Time;
/**
* Posted to managed client from admin server.
@@ -34,8 +35,7 @@ public abstract class AdminAction {
@JsonIgnore
public boolean isExpired() {
long time = System.currentTimeMillis() / 1000;
return time > expiration;
return Time.currentTime() > expiration;
}
/**
@@ -7,14 +7,17 @@ package org.keycloak.representations.adapters.action;
public class LogoutAction extends AdminAction {
public static final String LOGOUT = "LOGOUT";
protected String user;
private String session;
protected int notBefore;
public LogoutAction() {
}
public LogoutAction(String id, int expiration, String resource, String user, int notBefore) {
public LogoutAction(String id, int expiration, String resource, String user, String session, int notBefore) {
super(id, expiration, resource, LOGOUT);
this.user = user;
this.session = session;
this.notBefore = notBefore;
}
public String getUser() {
@@ -25,6 +28,14 @@ public class LogoutAction extends AdminAction {
this.user = user;
}
public String getSession() {
return session;
}
public void setSession(String session) {
this.session = session;
}
public int getNotBefore() {
return notBefore;
}
@@ -1,8 +1,6 @@
package org.keycloak.representations.adapters.action;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -1,6 +1,5 @@
package org.keycloak.representations.idm;
import java.util.ArrayList;
import java.util.List;
/**
@@ -0,0 +1,26 @@
package org.keycloak.representations.idm;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class AuthenticationLinkRepresentation {
private String authProvider;
private String authUserId;
public String getAuthProvider() {
return authProvider;
}
public void setAuthProvider(String authProvider) {
this.authProvider = authProvider;
}
public String getAuthUserId() {
return authUserId;
}
public void setAuthUserId(String authUserId) {
this.authUserId = authUserId;
}
}
Loaded 100 of 1175 files, more files were not shown because too many files have changed in this diff. Show more