Compare commits

...

917 Commits

Author SHA1 Message Date
Justin Richer d074573de0
Merge pull request #1570 from shrexster42/master
Upgrade to Java 11 and Spring 5
2022-04-19 14:17:46 -04:00
shrexster42 5e87fa7650
Update .travis.yml to use oraclejdk11 2022-04-18 17:20:36 +01:00
shrexster42 7e85d2575e
Merge branch 'mitreid-connect:master' into master 2022-04-17 18:16:56 +01:00
Chen Zhang 05fd73e643 Improve Travis CI build Performance 2022-03-29 11:29:46 -04:00
faidh 2c41e6a267 Add SNAPSHOT back to pom files 2022-03-29 11:29:22 -04:00
faidh 8a58d12600 Merge latest MitreID with updated 3pps back to GitHub fork 2022-03-29 11:29:22 -04:00
Justin Richer f5df762153 [maven-release-plugin] prepare for next development iteration 2021-12-20 13:09:11 -05:00
Justin Richer a0bd2c70ac [maven-release-plugin] prepare release mitreid-connect-1.3.4 2021-12-20 13:09:08 -05:00
shrexster42 6906f616e2 Upgrade to Java 11 and Spring 5 2021-12-18 22:30:43 +00:00
Michael Stepankin 7eba3c12fe Fix Spring Autobinding vulnerability
1. Make authorizationRequest no longer affected by http request parameters due to @ModelAttribute. See http://agrrrdog.blogspot.com/2017/03/autobinding-vulns-and-spring-mvc.html
2021-02-18 16:13:36 -05:00
Justin Richer 0d4ef2cb4f
Update README.md 2019-08-01 16:41:55 -04:00
ruslan cc6bd4b590 upgrade eclipselink to v. 2.7.4 2019-04-29 16:13:21 -04:00
Justin Richer 621e86e62d [maven-release-plugin] prepare for next development iteration 2019-04-19 16:04:45 -04:00
Justin Richer 73459f0348 [maven-release-plugin] prepare release mitreid-connect-1.3.3 2019-04-19 16:04:40 -04:00
Justin Richer 5aa8b2a0a7 updated changelog for release 2019-04-19 16:00:06 -04:00
Martin Kuba ae7debba2f added refresh_token into grant_types_supported 2019-03-07 12:14:30 -05:00
Martin Kuba ad64aef0c5 updated dependencies patchlevels 2019-03-07 12:12:27 -05:00
Justin Richer 703c341308
Merge pull request #1436 from blm126/upgrade-guava
#1435: Update guava dependency to latest version.
2018-12-10 14:26:20 -05:00
Stephen Moore 8430b42ab3 Both approve pages were using pagecontext rather than the configured
issuer
2018-12-10 12:35:03 -05:00
Brady Mulhollem 4979f9f50e #1435: Update guava dependency to latest version. 2018-11-27 16:06:38 -05:00
Justin Richer a2e8cb1a67
Merge pull request #1410 from hausenism/master
fix bug #1397 Attempting to execute an operation on a closed EntityMa…
2018-06-21 15:50:12 -04:00
鄭脈龍 676451c73d fix bug #1397 Attempting to execute an operation on a closed EntityManager. 2018-06-21 10:05:49 +08:00
Justin Richer 04f439ec58
Merge pull request #1405 from angelok1/db_script_fixes
Corrected Oracle create script
2018-06-11 16:23:28 -04:00
Justin Richer aa2dc78148
Merge pull request #1406 from angelok1/db_script_schema_fixes
Fixed broken scripts from schema change on system_scope
2018-06-11 16:21:41 -04:00
Angelo Kastroulis f56918982a Fixed broken scripts from schema change on system_scope 2018-06-11 16:13:30 -04:00
Angelo Kastroulis 69afba59cc Corrected create script 2018-06-11 15:52:17 -04:00
Justin Richer 802e40ebc9 Updated changelog 2018-05-03 14:52:49 -04:00
Justin Richer ea6960e66a
Merge pull request #1259 from sbke/patch-1
Adjustment to generate longer codes
2018-05-03 14:48:52 -04:00
Justin Richer 9d6f42b141
Merge pull request #1320 from bverhoeven/rfc7662-sub
Client: Parse 'sub' key to identify resource owner in introspection response (RFC7662)
2018-05-03 14:46:49 -04:00
Justin Richer dd922b4cf7
Merge pull request #1378 from ketola/fetch-tokens-by-sub
Fetch tokens by user name
2018-05-03 14:44:51 -04:00
Justin Richer 938d7e00c2 Merge branch 'ondrejvelisek/verification-uri-complete'
Closes #1386
2018-05-03 14:39:23 -04:00
Justin Richer a596cc1fd4 Made full URLs for device flow switchable server-wide instead of per-client 2018-05-03 14:37:50 -04:00
Justin Richer 7ad29ae9c6 Revert "Add possibility to disable verification_uri_complete per client"
This reverts commit dae674af67.
2018-05-03 13:59:38 -04:00
Justin Richer e3cfb80c33
Merge pull request #1390 from mobilcom-debitel/master
Update admin.js
2018-05-03 11:40:26 -04:00
jansinger fd938e11e9
Update admin.js
Allow scope names longer than 30 characters to be checked in the client scope list.
2018-05-03 14:48:01 +02:00
ondrejvelisek dae674af67 Add possibility to disable verification_uri_complete per client 2018-05-01 13:46:23 +02:00
ondrejvelisek 67c87d56a6 Add support for verification_uri_complete 2018-05-01 10:45:49 +02:00
Justin Richer 4a818c7b4b
Merge pull request #1385 from elennick/master
"Unable to load locale" log should not be ERROR level
2018-04-23 15:38:46 -04:00
Evan Lennick fe000d91cb undid autoformatting again 2018-04-23 14:30:43 -04:00
Evan Lennick 011bf8adb8 addressed review feedback 2018-04-23 14:29:38 -04:00
Evan Lennick 0ee4ee2f58 undid some autoformatting changes 2018-04-21 13:22:17 -04:00
Evan Lennick 0b531a0fd3 fixed an issue where missing locales would generate a lot of ERROR level log messages 2018-04-21 13:19:44 -04:00
Sauli Ketola e6a8e0c17d Integration tests for new repository methods 2018-04-11 13:16:28 +03:00
Sauli Ketola a070f61edf Clean up code in modified classes, remove line breaks, add static imports 2018-04-06 09:12:47 +03:00
Sauli Ketola 51b580aa18 Use 'userName' instead of 'sub' in naming 2018-04-06 08:55:06 +03:00
Sauli Ketola 3f277047e3 Use query by user sub to get all tokens for user 2018-04-06 08:47:37 +03:00
Sauli Ketola 417a6b7c74 Removed some line breaks and auto generated comments for consistency 2018-04-05 19:29:54 +03:00
Sauli Ketola bf8149605a Create queries for getting access and refresh tokens by user sub 2018-04-05 19:25:23 +03:00
Justin Richer 64fbee7935
Merge pull request #1377 from ketola/master
Add an index for refresh_token.token_value
2018-04-04 10:12:53 -04:00
Sauli Ketola bca388d740 Add an index for refresh_token.token_value 2018-04-04 15:49:13 +03:00
Justin Richer e2d94f422a new year 2018 2018-02-12 10:39:04 -05:00
Justin Richer a5a16f27c7
Merge pull request #1353 from col-panic/master
Minor typo in en/messages.json (Registrered -> Registered)
2018-02-08 16:49:44 -05:00
Justin Richer 4dd907ea16
Merge pull request #1357 from praseodym/spring-security-4.2.4
Upgrade to Spring Security 4.2.4
2018-02-08 15:34:30 -05:00
Mark Janssen d119559d4d Upgrade to Spring Security 4.2.4
https://spring.io/blog/2018/01/30/cve-2018-1199-spring-security-5-0-1-4-2-4-4-1-5-released
2018-02-08 21:03:31 +01:00
Justin Richer b804f22bc8 [maven-release-plugin] prepare for next development iteration 2018-02-07 09:14:16 -05:00
Justin Richer f72e6b3e08 [maven-release-plugin] prepare release mitreid-connect-1.3.2 2018-02-07 09:14:10 -05:00
Justin Richer 1feb0958bd prepare for release 2018-02-07 09:09:07 -05:00
Justin Richer 6497af40e8 removed erroneous not yet implemented tag from client page 2018-02-07 09:05:43 -05:00
Justin Richer 7dc309c5af
Update CHANGELOG.md 2018-02-07 09:03:09 -05:00
Justin Richer 7f956a5854
Merge pull request #1355 from ocadotechnology/jwt_fix
Throwing exception on all other JWT types than SignedJWT
2018-02-07 08:52:59 -05:00
Tomasz Borowiec 37fba622b9 Throwing exception on all other JWT types than SignedJWT 2018-02-07 11:00:28 +01:00
Tomasz Borowiec c38b9d7a42 added PlainJWT and EncryptedJWT support + tests 2018-02-07 11:00:15 +01:00
Marco Descher 36ec1b82e6
Minor type (Registrered -> Registered) 2018-02-06 08:41:14 +01:00
Justin Richer fcb119ff6a
Merge pull request #1270 from bodewig/custom_claim_friendly_token_enhancer
add hook for custom JWT claims to ConnectTokenEnhancer
2018-02-05 16:01:09 -05:00
Justin Richer 8fb9adefc1
Merge pull request #1342 from bodewig/custom_claims_in_id_token
add hook for custom JWT claims to DefaultOIDCTokenService
2018-02-05 15:43:22 -05:00
Justin Richer 0ce55d079a
Merge pull request #1352 from blm126/upgrade-nimbus
Upgrade nimbus-jose-jwt to 5.4.
2018-02-05 15:26:50 -05:00
Brady Mulhollem f7da25fbe8 Upgrade nimbus-jose-jwt to 5.4. 2018-02-05 13:28:48 -05:00
Justin Richer 1c7b9d5b44
Merge pull request #1346 from praseodym/fix-admin-interface-without-trailing-slash
Fix interface for issuer URI without trailing slash
2018-01-22 05:54:25 -05:00
Mark Janssen a1a45aa36a Fix interface for issuer URI without trailing slash 2018-01-21 12:01:25 +01:00
Stefan Bodewig 01eb1401a3 add hook for custom JWT claims to DefaultOIDCTokenService 2018-01-12 15:22:37 +01:00
Justin Richer e6130872a9
Merge pull request #1324 from patfrat/master
Add French messages
2017-11-22 13:23:56 -05:00
Patrick Fratczak ca3642b6c3 Add French messages 2017-11-22 14:27:15 +01:00
Bas Verhoeven 85246d2d3e
Parse 'sub' to identify resource owner
As per https://tools.ietf.org/html/rfc7662#section-2.2 the `sub` key should
identify the resource owner in oauth2 introspection responses. 

This change adds support for the `sub` key and will allow the introspection 
response of RFC-compliant servers to be parsed.

Will still try `user_id` first as to not break backward compatibility.
2017-11-13 16:46:52 +01:00
Justin Richer ce9bf3507f
Merge pull request #1312 from kules/master
Correct minor typo error for confirmation message displayed when logging out from IDP
2017-11-01 13:56:24 -04:00
still fetalvero 9bff58085d Fix typo error for log out to IDP confirmation message 2017-10-30 22:56:07 +08:00
Stefan Bodewig 514dcc3851 add hook for custom JWT claims to ConnectTokenEnhancer 2017-07-18 16:10:58 +02:00
sbke 8b4e461748 Adjustment to generate longer codes
RandomValueStringGenerator default constructor creates a code of length six only. The RFC 6819 (OAuth 2.0 Threat Model and Security Considerations) suggests (5.1.4.2.2.  Use High Entropy for Secrets) that secrets that aren't used by humans (e.g. client secrets or token handles) have a reasonable level of enthropy. They propose a token lengths of at least 128 bits. Since the RandomValueStringGenerator only uses case sensitive alpha numeric symbols, 22 symbols are needed to achieve an enthropy >=128 bits.
2017-06-28 14:20:11 +02:00
Justin Richer ef01d3032e Merge pull request #1228 from leonard84/fix-psql-scripts
Fix psql_database script, replace SERIAL with BIGSERIAL and fix ...
2017-06-15 09:45:13 -04:00
Justin Richer bba18fd118 Merge pull request #1240 from Connz/patch-2
Corrected typo
2017-06-15 09:44:46 -04:00
Justin Richer 28ad78e9f3 Merge pull request #1233 from Connz/patch-1
Removed double 'sure'
2017-06-15 09:44:33 -04:00
Justin Richer 059e140164 removed old document PDFs from repo 2017-05-27 06:49:34 -04:00
Justin Richer 0b1f9000db check for missing refresh token value on refresh, closes #1242 2017-05-26 20:30:09 -04:00
Justin Richer 705ac9879c removed unused field from UI config bean 2017-05-26 20:20:11 -04:00
Justin Richer 4dc31cdfbd fixed client readme file 2017-05-26 20:17:29 -04:00
Justin Richer 661c242a9f Updated copyrights 2017-05-26 20:17:17 -04:00
Connz 0859a5d122 Corrected typo 2017-05-16 12:09:54 +02:00
Justin Richer c11e47a75b fixed unit test for new default redirect behavior 2017-05-11 11:27:41 -04:00
Justin Richer 2f31ceddf8 set redirect URI matching to strict by default 2017-05-10 17:39:59 -04:00
Justin Richer 7e6864ff38 escaped output values on approval page, closes #1111 2017-05-10 17:39:48 -04:00
Justin Richer a316306f33 added changelog file 2017-05-09 14:54:47 -04:00
Justin Richer 7b06d91700 [maven-release-plugin] prepare for next development iteration 2017-05-09 14:29:53 -04:00
Justin Richer 8301f35e17 [maven-release-plugin] prepare release mitreid-connect-1.3.1 2017-05-09 14:29:49 -04:00
Justin Richer f17a44e9b4 downgrade mysql dependency to GA version 2017-05-09 14:25:03 -04:00
Connz 90c3c396ee Removed double 'sure' 2017-05-04 15:35:34 +02:00
Justin Richer 713e872b8a fixed discovery endpoint, closes #1230 2017-04-29 15:01:15 -04:00
Justin Richer 9baacc0eaf Completed end session endpoint
Addresses #1129, addresses #972, addresses #891, addresses #1223
2017-04-29 14:58:37 -04:00
Justin Richer 2aa12fc0e3 end session endpoint 2017-04-28 19:05:30 -04:00
Justin Richer 0c46e7cb7a skeleton of end session endpoint, maybe need a change to user info lookup 2017-04-27 14:29:05 -04:00
Leonard Brünings e6679b6e4b Fix psql_database script, replace SERIAL with BIGSERIAL and fix ...
BIGINT AUTO_INCREMENT to BIGSERIAL

Change-Id: I19b4433d3bae29b0879be7d9dd9405eabe490482
2017-04-19 14:24:11 +02:00
Justin Richer 0efa77b580 [maven-release-plugin] prepare for next development iteration 2017-04-15 13:20:13 -04:00
Justin Richer b9b7bf53c3 [maven-release-plugin] prepare release mitreid-connect-1.3.0 2017-04-15 13:20:05 -04:00
Justin Richer 0aedfc8e22 minor cleanup 2017-04-14 17:21:50 -04:00
Justin Richer 0d564d9714 made token service transactional, closes #1222 2017-04-14 15:27:16 -04:00
Justin Richer 11f3cccab9 fix JWKS parsing in software statements, closes #1220 2017-04-14 14:42:49 -04:00
Justin Richer 702a775881 handle creation time stamp in clients, closes #1210 2017-04-13 11:50:57 -04:00
Justin Richer 45ea899de8 made user codes case insensitive 2017-04-12 16:00:23 -04:00
Justin Richer d317cf5024 added exception handling to device code creation step 2017-04-12 15:59:17 -04:00
Justin Richer cc0622edd0 internalized random string generation for device codes 2017-04-12 14:59:18 -04:00
Justin Richer 52829d4adb mapped user info and server config interceptors to only interactive portions of the site, closes #1206 2017-04-07 17:02:50 -04:00
Mark Janssen 903168a949 Decrease log level of trailing slash warning
Having an issuer without trailing slash configured is just fine, so
there is no reason to log a warning for this every time the discovery
endpoint is called.
2017-04-07 14:59:58 -04:00
Justin Richer 6216659cd6 manage reporting plugin versions, added jacoco coverage to reporting 2017-04-07 14:58:11 -04:00
Leonard Brünings 9d1a50d17e Add codecov badge
Change-Id: I04f56036af6bd2ac663843c2c10e8c0cebfb05d3
2017-04-07 13:38:25 -04:00
Leonard Brünings 2aecedfb3d Replace cobertura with jacoco to generate code-coverage for codecov.io
Change-Id: I031144c375d73aaa39d0a6111d37223ad6e4d655
2017-04-07 13:38:25 -04:00
Justin Richer f43ff53683 Extracted database indexes to separate files 2017-04-06 14:12:27 -04:00
Justin Richer bf49cd193d removed incompatible constraints on mysql files 2017-04-06 14:07:39 -04:00
Justin Richer 835a326627 allow polling of device codes, fixed UI for device code input 2017-03-27 14:39:40 -05:00
Justin Richer 1d7fba5d6e added cascade to address object, closes #1209 2017-03-24 12:44:49 -04:00
Justin Richer 2ea5f8fd28 sync’d databases with HSQL schema, closes #1212 2017-03-24 12:41:14 -04:00
Justin Richer 050662dd5c updated dependencies 2017-03-24 12:12:06 -04:00
Justin Richer 7767c7a831 add “if not exists” to all indexes in HSQL 2017-03-22 17:30:08 -04:00
Justin Richer 7a225e56c4 don’t pack wro4j into .war file
We use it only during compilation, not runtime
2017-03-22 17:29:37 -04:00
Justin Richer 78b9b6ced4 auto format and cleanup javascript 2017-03-21 15:04:18 -04:00
Justin Richer bd72b4138d added missing copyright declarations 2017-03-21 14:11:40 -04:00
Justin Richer 32ce21b5cd automated code formatting and cleanup 2017-03-21 14:07:20 -04:00
Justin Richer b6cf8fe22b cleanup 2017-03-20 13:45:55 -04:00
Justin Richer dd0f69ba6d [maven-release-plugin] prepare for next development iteration 2017-03-20 11:58:58 -04:00
Justin Richer 80358566a5 [maven-release-plugin] prepare release mitreid-connect-1.3.0-RC2 2017-03-20 11:58:52 -04:00
Justin Richer 4da1e619a0 plugin management, removed less files from .war 2017-03-18 11:38:28 -04:00
Justin Richer eb1ec0979d separated root bootstrap and responsive files into different WRO4J groups 2017-03-18 10:59:30 -04:00
Justin Richer 9b2177a422 switched to using wro4j, main file works but responsive file doesn’t 2017-03-17 17:52:33 -04:00
Justin Richer fd8f628a4f generate .css files and put them into the source directory 2017-03-17 16:33:48 -04:00
Justin Richer c377e411e3 removed packed-in bootstrap files (again) 2017-03-17 16:32:41 -04:00
Justin Richer 2a75535dce fix unit tests and downstream calls 2017-03-16 18:00:05 -04:00
Justin Richer a926a8f0ab cleaned up server-side stats service, UI now uses per-client calls 2017-03-16 17:31:26 -04:00
Justin Richer 256b79ae51 lazy load client stats in UI 2017-03-16 17:20:04 -04:00
Justin Richer 626b18d5ca added software id and version to UI search 2017-03-16 13:51:19 -04:00
Justin Richer 02928b048f added software ID and version to data API 2017-03-15 17:38:46 -04:00
Justin Richer e57ea488b3 fixed null handling on client admin pages, added software ID and version to UI 2017-03-15 17:30:26 -04:00
Justin Richer 22a4addfc0 added software ID and software version 2017-03-15 16:47:04 -04:00
Justin Richer 8406a89fd1 added device flow expiration 2017-03-14 17:40:30 -04:00
Justin Richer f0c8b1b235 fixed device code admin UI 2017-03-14 17:40:30 -04:00
Justin Richer f54d44cd9d added device code to discovery, moved device endpoints 2017-03-14 17:40:30 -04:00
Justin Richer f915196c2e fix approval display 2017-03-14 17:40:29 -04:00
Justin Richer cbf5bf742b added messages for display pages, better error handling in user-facing pages 2017-03-14 17:40:29 -04:00
Justin Richer 153776ecb5 Don’t catch OAuth2 errors, let the framework handle them here 2017-03-14 17:40:28 -04:00
Justin Richer d83fbc6c67 UI for managing device code flow 2017-03-14 17:40:28 -04:00
Justin Richer 44b24af466 database storage for device flow 2017-03-14 17:40:28 -04:00
Justin Richer 04dd67d073 added device codes to database 2017-03-14 17:40:27 -04:00
Justin Richer 548dad4e29 added expiration to device codes 2017-03-14 17:40:27 -04:00
Justin Richer 9cb5377ce8 added device code validity seconds to client model 2017-03-14 17:40:27 -04:00
Justin Richer a5b4115169 functioning device code flow 2017-03-14 17:40:26 -04:00
Justin Richer 3326eee934 shell for device flow 2017-03-14 17:40:26 -04:00
Justin Richer c42fe57367 changed task operations to print out name of operation on run 2017-03-14 17:40:26 -04:00
Justin Richer 72fd3c2b99 added ID Token Validity Seconds to data import/export API 2017-03-11 15:36:45 -05:00
Justin Richer 837cce786a moved special UI variable loading to inside dynamic footer block 2017-03-11 15:36:45 -05:00
Justin Richer 3e5e7a0f0b [maven-release-plugin] prepare for next development iteration 2017-03-03 18:03:26 -05:00
Justin Richer 0d84db49af [maven-release-plugin] prepare release mitreid-connect-1.3.0-RC1 2017-03-03 18:03:20 -05:00
Justin Richer 1cb5b6c6ff added toString to error for debug and display 2017-03-03 17:23:39 -05:00
Ryan Pickett e1ae8f3d8d Add parameters from error response to exception
Introduce a new exception class to hold the parameters from an
authentication error response, allowing simpler retrieval later in the
filter processing.
2017-03-03 17:22:13 -05:00
Justin Richer f056eb9387 compile bootstrap CSS from source 2017-03-03 17:20:37 -05:00
Justin Richer 98a4d56cdd made extraction function less side-effect-ful 2017-03-03 17:20:15 -05:00
Leonard Brünings 00ecd3dd22 Fix NPE if no claims are requested for the userinfo object
This happens if clients only requests id_token claims, or just send an empty claims parameter.

Change-Id: I8bd176ad271bda8a1e2f26b6221bd8e2d0a3ebfb
2017-03-03 16:09:51 -05:00
Justin Richer 141f4da7f1 added PKCE editing capabilities to UI 2017-02-20 15:40:16 -05:00
Justin Richer 650429a2de Updated MIT Internet Trust Consortium webpage links, closes #1184 2017-02-20 14:36:42 -05:00
Justin Richer 40b4dfa5fe extracted nav menu from topbar tag 2017-02-20 14:32:24 -05:00
Justin Richer 26c34c70de happy new year! again! 2017-02-20 14:07:10 -05:00
Justin Richer 9592c784d1 modularized UMA server UI 2017-02-20 14:07:01 -05:00
Justin Richer f2173907ac modularized app router initialization functions 2017-02-20 14:06:41 -05:00
Justin Richer 503d6f5725 load all templates from configured files 2017-02-20 13:20:21 -05:00
Justin Richer 5af98e1106 modularized javascript loading and UI components 2017-02-20 11:12:57 -05:00
Justin Richer 00c4ea9199 dynamically load client routes from sub page 2017-02-18 18:23:15 -05:00
Justin Richer c79b6da9d9 Javascript files for UI functionality loaded from configuration bean 2017-02-17 17:34:03 -05:00
Justin Richer 606dd2633b collapsed home page tags 2017-02-17 15:11:45 -05:00
Justin Richer 907f94e0ce collapsed tags into relevant pages 2017-02-17 15:11:10 -05:00
Justin Richer b176d4d77e cleaned up old endpoints 2017-02-16 18:24:21 -05:00
Justin Richer 8178af87f0 further modularized data import/export service 2017-02-16 18:24:05 -05:00
Justin Richer 3acb71763a cleaned up UMA server overlay 2017-02-16 18:23:32 -05:00
Justin Richer 52d2298f99 begin modularization of data import/export API 2017-02-15 11:51:32 -05:00
Justin Richer 777b7a2112 added new data package to logging defaults 2017-02-15 11:51:32 -05:00
Justin Richer 76c7bef0d6 restored previous filter order and set OAuth filter to stateless, addresses #1190, #1185, #1188 2017-02-15 11:48:56 -05:00
Justin Richer 01b798151d missed one... 2017-01-18 11:06:43 -05:00
Justin Richer db50a88fe5 Happy New Year 2017 2017-01-17 17:09:14 -05:00
Justin Richer d92cc4d488 fixed constants for spring 4.2 2017-01-17 17:06:18 -05:00
Justin Richer b17a7f43ae removed structured scopes 2017-01-17 17:06:04 -05:00
strangeweaver 524794fe2e Ignore timeout test as it's vulnerable to a race condition. 2017-01-17 15:36:57 -05:00
strangeweaver bdaf7cba23 Fixed race condition in test and added timeouts to prevent possibility of infinite loop. 2017-01-17 15:36:57 -05:00
strangeweaver 46046b574a Implemented paged operations and used for database cleanup tasks. 2017-01-17 15:36:57 -05:00
strangeweaver 099211593c Fix high load performance issue in token expiration task 2017-01-17 15:36:57 -05:00
juazugas ffc5782810 Fix field definition in the model object. 2017-01-17 15:27:26 -05:00
Sebastian Schuster 0c09a17f59 Adapted uma-server-webapp overlayed spring configuration files to changes in base webapp 2017-01-17 15:25:45 -05:00
Sebastian Schuster 93deef952f Adapted uma-webapp-server database initialization scripts to base changes 2017-01-17 15:25:45 -05:00
Sebastian Schuster 99d1b0cfec Adapted changes from base admin.js to overlayed admin.js in uma-server-webapp 2017-01-17 15:25:45 -05:00
Sebastian Schuster 0c821fcb51 Adapted overlayed application-context.xml in uma-server-webapp to base file 2017-01-17 15:25:45 -05:00
Sebastian Schuster 5993c879a6 Removed version from created war and added maven jetty plugin with context so URLs are prefixed correctly in uma-server-webapp 2017-01-17 15:25:45 -05:00
Justin Richer 0dd7eef428 Updated database examples, closes #1167 2017-01-17 14:38:51 -05:00
mialtamimi d862ba9fd8 add indexes on certain fields to shorten time taken to issue a new access token 2017-01-16 15:39:13 -05:00
Justin Richer 9b715f9632 put error logging inside the curried callback 2017-01-05 17:38:03 -05:00
Justin Richer 0d162b1423 disabled CSRF on API endpoints, changed auth manager to a bean ID instead of reference, changed filter order to keep SECOAUTH from clearing out security contexts. 2017-01-05 17:37:22 -05:00
Justin Richer 71bb8d6439 Spring 4.3 namespace 2016-12-27 21:04:38 -05:00
Justin Richer fc91043807 using defaults from spring 4 2016-12-22 15:17:18 -05:00
Justin Richer d5e8dd31a8 update to Spring Security 4 2016-12-22 14:30:59 -05:00
Justin Richer 0e703ef9f9 update a few dependency versions, closes #1145 2016-12-21 15:50:24 -05:00
Justin Richer 275c1b7e1c user info fetcher cache throws error instead of returning null (as per library contract), closes #1144 2016-12-21 14:48:37 -05:00
Justin Richer bea3af2470 database table sync 2016-12-21 13:44:49 -05:00
Justin Richer 63bd8d18fb cleaned ID token views from UI 2016-12-21 13:44:40 -05:00
Justin Richer 91da3935f5 Made ID tokens ephemeral, made access token’s “additional information” extensible 2016-12-21 13:01:15 -05:00
Justin Richer 91ed758ed1 removed “attributeName” from annotation as this breaks EclipseLink JPA 2016-12-09 16:58:43 -05:00
Mikko Tommila 4f4c8de1c8 Fix JPA issues to allow using Hibernate 2016-12-09 15:15:50 -05:00
Justin Richer 375a5f2e47 removed token count from grant admin page 2016-12-09 15:10:07 -05:00
Justin Richer 22fa3605ef Patched unit tests, still needs updates for checking approved site to token mapping on data import/export 2016-12-09 12:56:06 -05:00
Justin Richer 55b1b00b73 Updated relationship between approved sites and access tokens, closes #874 2016-12-09 12:55:42 -05:00
Justin Richer d875d52be7 updated data import/export services for 1.3 2016-12-08 17:01:55 -05:00
HeXetic 7725fcfa2b createAuthorizationCode should be @Transactional
An Authentication should not exist without its matching AuthorizationCode, but typically an AuthorizationCode will have a foreign key on an Authentication, meaning it can't be saved first. This block should be wrapped in a transaction so that other DB clients (say, for example, clearExpiredAuthorizationCodes) don't see an inconsistent snapshot and then misbehave.
2016-12-02 16:29:48 -05:00
Julian Schlichtholz c3d0c18af5 make HttpClient configurable, closes #1071 2016-12-02 16:23:55 -05:00
ngriesser f45a6ef56a use the same encoding as on client side
see OIDCAuthenticationFilter line 336
2016-12-02 16:20:09 -05:00
Oleksandr Shpota 476ec872ff Fixed NPE in case if algorithm is not specified 2016-12-02 16:13:26 -05:00
Sofia Ang bb6bb81dbc Add new tests which asserts that `user_id` should not be present in the introspection response if there's no user authentication available 2016-12-02 16:08:32 -05:00
Sofia Ang 52da5e769a Fix test by returning a new OAuth2Authentication instead of mocking it 2016-12-02 16:08:32 -05:00
Sofia Ang d361f01999 Fix such that the OAuth2Authentication returned would have a `null` userAuthentication if `user_id` is not found during introspection
`sub` cannot be used to create the user authentication because it may not necessarily refer to the user. Instead if may refer to the client
if the access token happens to be client-only.
2016-12-02 16:08:32 -05:00
Sofia Ang b2fab9642e Fix such that `user_id` is only added if user authentication is available
OAuth2Authentication#getPrincipal() used by OAuth2Authentication#getName() defaults to the client id if user authentication is not available.
Prior to this fix, an introspection of a client-only access token would result to the user_id also being the client_id. This causes problems when this
introspection result is converted into an OAuth2Authentication by a resource server's IntrospectingTokenService -- the user_id is populated with
the client_id and so OAuth2Authentication's userAuthentication is populated falsely.
2016-12-02 16:08:32 -05:00
Justin Richer 4ac3916db3 spaces to tabs 2016-12-02 15:50:22 -05:00
Justin Richer 8333d035b4 move database files to match new layouts 2016-12-02 15:50:15 -05:00
Tomasz Borowiec fa122e7ad6 ojdbc driver uncommented in dep mgmnt 2016-12-02 15:37:41 -05:00
Tomasz Borowiec 4b3284ffd2 ojdbc6 dependency moved to parent pom, added check constraints for boolean columns, fixed invalid column type 2016-12-02 15:37:41 -05:00
Tomasz Borowiec 83a9fef14d Oracle support added 2016-12-02 15:37:41 -05:00
Nicolas Liampotis dea6044e77 Set the encoding of the UserInfo response body to UTF-8
See http://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
2016-12-02 14:44:55 -05:00
Neths 1b7612a26d add db init script for mysql
add data-context example with mysql db initializer
2016-12-02 14:43:18 -05:00
Neths cbe6b9e1df add db init script for pgsql
add data-context example with pgsql db initializer
2016-12-02 14:43:18 -05:00
pwolf23 6f5ca3fd2f Fixed missing "final" modifier in constant 2016-12-02 14:31:25 -05:00
Justin Richer 337513a559 sync’d database tables from HSQL to MySQL and PGSQL
closes #1154
closes #1148
2016-12-02 14:28:56 -05:00
Justin Richer 74d34ab744 null-safe target link filter 2016-10-10 15:32:53 -04:00
Justin Richer d0056ae882 added target link URI capability to webfinger issuer service 2016-10-10 15:32:32 -04:00
Justin Richer 74f3e2d0c0 maven site generator working, closes #984 #941 2016-08-01 13:36:06 -04:00
Justin Richer af7c1f7d45 added PKCE support to discovery endpoint 2016-07-27 20:31:27 -04:00
Justin Richer 82c313f036 added PKCE support to client 2016-07-27 20:31:14 -04:00
Justin Richer ba0d0aab0b use parameter constants for extensions maps in token service 2016-07-24 17:46:04 -04:00
Justin Richer ac0cafe7b3 parse and process PKCE requests 2016-07-24 17:45:43 -04:00
Justin Richer 5dcda2812e added code challenge method to client model (properly this time) 2016-07-24 17:45:04 -04:00
Justin Richer 2cc90ba5f2 created PKCE algorithm class 2016-07-24 17:06:29 -04:00
Justin Richer 83d7627ed0 serialize phone_number and phone_number_verified, closes #1030 2016-07-24 16:49:46 -04:00
Justin Richer d1d05e506e added software statement to dynamic registration self-service 2016-07-24 16:28:08 -04:00
Justin Richer 57208ac35d added software statements to client API 2016-07-24 16:12:56 -04:00
Justin Richer d89257380f make client assertion auth work again 2016-07-24 15:28:51 -04:00
Justin Richer f9e4d75a4a use JWT bearer assertion token for assertion processing 2016-07-24 14:55:45 -04:00
Justin Richer 42ccb8b39e make software statement processing null-safe 2016-07-24 14:55:12 -04:00
Justin Richer bd9932d56f added assertion processor to token endpoint 2016-07-22 15:31:00 -04:00
Justin Richer 8c021ad403 added assertion validator that validates assertions signed by the local server only 2016-07-22 14:04:33 -04:00
Justin Richer 8e016a8d30 make the null assertion processor the default 2016-07-22 13:50:37 -04:00
Justin Richer a5a12b2f1f added assertion validation engine 2016-07-22 13:47:20 -04:00
Justin Richer fa63993896 added software statement to client model, added processor to dynamic registration parser 2016-07-21 16:55:46 -04:00
Justin Richer 17be89fe98 updated whitelist to use error function 2016-07-18 17:01:34 -04:00
Justin Richer 6e8a728c68 updated token management to use error handler 2016-07-18 16:59:54 -04:00
Justin Richer 1366db3b48 updated scopes to use error handler 2016-07-18 16:57:35 -04:00
Justin Richer 838fcb6789 changed resource set registration to use error handler 2016-07-18 16:54:36 -04:00
Justin Richer 241bc0f649 updated approved sites to use error handler 2016-07-18 16:49:58 -04:00
Justin Richer 055b5cc4da fixed title on saved client dialog 2016-07-18 16:48:17 -04:00
Justin Richer cdf5147706 ported dyn reg to new error handler 2016-07-18 16:48:07 -04:00
Justin Richer 40863f4696 converted list item to use error handler 2016-07-18 16:03:38 -04:00
Justin Richer bba0b2fcd2 converted blacklist to new error handler 2016-07-18 15:53:58 -04:00
Justin Richer ed7536837b fixed display errors for error dialog 2016-07-18 15:48:53 -04:00
Justin Richer e073df614f made the modal display sit on top for real this time 2016-07-18 15:47:57 -04:00
Justin Richer d79bbaf430 instrumented client error handling to use new framework 2016-07-18 14:47:57 -04:00
Justin Richer 8749e1124e added generic error message handler 2016-07-18 14:42:38 -04:00
Justin Richer 44313c4e10 reformatted error template 2016-07-18 11:58:02 -04:00
Justin Richer 93be6b59b8 switched to using templates instead of inline code 2016-07-15 15:49:10 -04:00
Justin Richer efc1c3c8bd added common API error handler function, closes #1066 2016-07-14 20:54:18 -04:00
Justin Richer ee537c404b externalize locale and message resolver configuration 2016-07-14 18:29:38 -04:00
Justin Richer a951a22bf8 explicitly use language and country codes for locale resolution 2016-07-14 18:29:37 -04:00
XIAO XI LIU b8cc0a82b3 fix issue #1061: auto-detect locale country code 2016-07-14 18:29:37 -04:00
XIAO XI LIU 805b6d1a7a add Chinese translation for README 2016-07-14 18:29:37 -04:00
XIAO XI LIU 928ed980fd add Chinese resources for UMA. 2016-07-14 18:29:37 -04:00
XIAO XI LIU 66667b95bc add blacklist i18n resource bundles. 2016-07-14 18:16:08 -04:00
XIAO XI LIU 0153ff9cb8 localize login page 2016-07-14 18:16:08 -04:00
XIAO XI LIU 55b54c53b3 add Chinese (both simplified and tranditional) messages. 2016-07-14 18:16:07 -04:00
XIAO XI LIU 4884b167f2 fix DBCS render issue #1056 2016-07-08 16:22:50 -04:00
Justin Richer 7177854416 inverted boolean for #1033 2016-07-08 13:00:26 -04:00
Justin Richer 39bae3a160 make the client auth URL matcher use an existing matcher instead of custom code 2016-07-08 11:42:35 -04:00
Justin Richer 01892b6f47 use a request matcher on authorization request filter, closes #1033 2016-07-08 11:00:01 -04:00
Justin Richer ca6e867df6 manage dependency versions in parent 2016-07-07 16:46:38 -04:00
Trung Nguyen ecb4a9ed53 Check that the underlying cause of the PersistenceException is caused by a duplicate entry. 2016-07-07 16:45:36 -04:00
Trung Nguyen 6fb26856a7 Make apiAddClient in the client api return a HttpStatus.Conflict if you try to create a client with a used client id.
This fixes a bug where if you try to create a client with a client id that is already in use, you get an empty error message. Instead, now you get a message that tells you that the client couldn't be created because the client id is already in use.
2016-07-07 16:45:36 -04:00
Leonard Brünings c96be134da Fix unqualified access to implicit request object ...
If the OpenId request object parameter is used it hides the implicit
request object, which in turn causes the expression to fail.
To circumvent this we need to access the request object through the
pageContext.
2016-07-07 16:40:23 -04:00
Leonard Brünings a8adcb1f6b Fix form action for approve.jsp for root contexts 2016-07-07 16:40:23 -04:00
Leonard Brünings 8e71107f9b Fix NPE when checking claim extension, Simplify always true expressions 2016-07-07 16:35:50 -04:00
Fredrik Jönsson 8f81278332 We really should specify an encoding here and not depend on the
servers default encoding, shouldn't we? It becomes ISO-8859-1
otherwise in Tomcat as per the Servlet specification.
2016-07-07 16:33:24 -04:00
jimmytheneutrino fa4722cdd8 shortTopbarTitle 2016-07-07 16:31:48 -04:00
Justin Richer e08b7f89fc fixed bouncy castle dependency range, closes #1084 2016-07-07 16:30:15 -04:00
Leonard Brünings f21c374e8a Add Editorconfig for minimal code style support 2016-07-05 15:09:09 -04:00
Justin Richer 832f5c0199 removed redundant profile for javadoc lint 2016-07-05 15:01:15 -04:00
Mark Janssen 2d495bd0bd Java 8 language level 2016-07-05 14:51:43 -04:00
Justin Richer c31f42c3f3 updated versions to 1.3 2016-07-05 14:39:22 -04:00
Justin Richer 326ce4cb6f trying out codecov.io for code coverage tests 2016-05-19 15:10:18 -05:00
Justin Richer 58724aa6dc [maven-release-plugin] prepare for next development iteration 2016-04-06 16:33:45 -04:00
Justin Richer 29c9ee2c46 [maven-release-plugin] prepare release mitreid-connect-1.2.6 2016-04-06 16:33:42 -04:00
Justin Richer 37bead1404 added configuration flag for HEART mode 2016-03-18 22:04:22 -04:00
Justin Richer 2d2cf57125 added 'green' display to http on 127.0.0.1 in addition to localhost 2016-03-18 22:03:00 -04:00
Justin Richer 37b9acda66 fixed erroneous error log 2016-03-18 22:02:40 -04:00
Justin Richer 89316cbab1 fixed default token lifetimes for heart mode 2016-03-18 22:02:28 -04:00
Justin Richer 9691f02772 added audience parameter to parser, fixed token generator to match HEART spec 2016-03-11 17:12:36 -05:00
Justin Richer 49a8848648 count really weird URIs as "custom scheme" 2016-03-10 12:50:47 -05:00
Justin Richer 60faf96e00 modified UI for HEART mode 2016-03-10 12:50:25 -05:00
Justin Richer 26d507d635 default new client in UI to HEART-compliant values 2016-03-10 12:34:10 -05:00
Justin Richer d75bba218d forbid password grant type in HEART mode 2016-03-10 12:30:48 -05:00
Justin Richer 52061ff05a pass heart mode variable to javascript 2016-03-09 10:47:48 -05:00
Justin Richer 3a0fd9141f added HEART Mode image to footer 2016-02-24 17:16:51 -05:00
Justin Richer 699e9bff39 testing for multiple classes of redirect URIs 2016-02-24 16:34:58 -05:00
Justin Richer 38710bd3d2 unit tests for HEART mode 2016-02-24 15:33:52 -05:00
Justin Richer 74ea42851b added check for HEART mode consistency 2016-02-24 13:09:58 -05:00
Justin Richer 028265faa6 pulled scope values to externalized strings 2016-02-24 13:09:39 -05:00
Justin Richer 5bccb602d8 always perform strict redirect URI matches in HEART mode 2016-02-24 13:09:00 -05:00
Justin Richer fa4ed7ea06 "dual-client" mode is mutually exclusive with HEART mode, HEART mode takes precedence 2016-02-24 13:08:40 -05:00
Justin Richer 51e3513307 disallow client secret JWT authentication in HEART mode 2016-02-24 13:07:14 -05:00
Justin Richer 84ff2f5fb9 disallow client secret authentication in HEART mode 2016-02-24 13:03:02 -05:00
Justin Richer fd452bf379 added heart-mode flag 2016-02-23 19:24:52 -05:00
Justin Richer d0d6ae2ad8 [maven-release-plugin] prepare for next development iteration 2016-02-23 19:02:05 -05:00
Justin Richer 7f5b70e9e1 [maven-release-plugin] prepare release mitreid-connect-1.2.5 2016-02-23 19:02:02 -05:00
Justin Richer 0781592357 added "clear all claims" function 2016-02-12 17:43:27 -05:00
Justin Richer cf70a20069 advanced claim addition function 2016-02-12 17:32:52 -05:00
Justin Richer cebf0fb8b2 added general javascript error catch 2016-02-12 17:32:35 -05:00
Justin Richer fc38a9f65d added loader to webfinger function 2016-02-12 17:31:05 -05:00
Justin Richer 65e5476c66 advanced claim addition tab 2016-02-09 17:53:57 -05:00
Justin Richer 659646ba9a sync overridden files from UMA server 2016-02-09 16:50:24 -05:00
Justin Richer 183a599126 fixed OIDC discovery relation URL 2016-01-29 17:17:35 -05:00
Justin Richer f27df01ccc encode empty arrays as nulls by default, leave old function as a backup
closes #1011
2016-01-29 16:42:40 -05:00
Justin Richer 61433cc23a deepen webfinger, endpoint is looser
closes #1008
2016-01-29 15:38:17 -05:00
Justin Richer 193d3f8ec6 fixed typo in messages file 2016-01-27 09:44:04 -05:00
Justin Richer 002767ec8a UI cleanup for dynamic registration and resource registration 2016-01-22 18:16:23 -05:00
Justin Richer 8168acf04b set off client registration information on dun reg page 2016-01-22 17:51:02 -05:00
Justin Richer 26483b22a9 added claims redirect URI editing to the UI for both admins and dynamic clients, closes #1005 2016-01-22 17:50:40 -05:00
Justin Richer c386f0d7c1 added claims redirect URIs to dynamic registration model 2016-01-22 15:19:47 -05:00
Justin Richer 82a1e49e79 [maven-release-plugin] prepare for next development iteration 2016-01-21 15:55:56 -05:00
Justin Richer e6684fb7a8 [maven-release-plugin] prepare release mitreid-connect-1.2.4 2016-01-21 15:55:53 -05:00
Misagh Moayyed 3d14b0d128 rename zone_info claim to zoneinfo 2016-01-21 15:52:59 -05:00
Justin Richer 7badfe1d17 Happy new year 2016! 2016-01-21 15:50:37 -05:00
Oscar Kurniawan b691cd198a Update client.html
In my instance, this typo cause an error to underscore.js when it is parsing
2015-12-29 18:50:32 +07:00
Justin Richer d74ba2cd04 handled errors better in JWK Set cache 2015-12-21 15:51:53 -05:00
Justin Richer d1033b693f added privacy-preserving client logo cache 2015-12-21 15:51:39 -05:00
Justin Richer 43509b7dfb removed a few straggling KIT references 2015-12-21 14:37:06 -05:00
Justin Richer 099ae41607 added client logo to admin table, closes #280 2015-12-21 14:33:49 -05:00
Justin Richer e828f3f18d [maven-release-plugin] prepare for next development iteration 2015-12-21 10:31:49 -05:00
Justin Richer 01ca5ef8e2 [maven-release-plugin] prepare release mitreid-connect-1.2.3 2015-12-21 10:31:47 -05:00
Justin Richer 8294dbedd5 handled HTTP and parsing errors, fixed guava cache contract, fixes #372 2015-12-18 17:42:15 -05:00
Justin Richer b3486c31a0 added cache to user info fetcher, closes #833 2015-12-18 16:30:03 -05:00
Justin Richer d338352cc8 scroll Ui to top of page on page loads, closes #977 2015-12-18 15:41:01 -05:00
Justin Richer aa878cc3cf pulled checks for expired tokens into utility functions 2015-12-18 11:22:50 -05:00
Mark Janssen 105d5d9e3d Update to Spring 4.1.9 and Spring Security 3.2.9
https://spring.io/blog/2015/12/17/spring-framework-4-2-4-4-1-9-released
https://spring.io/blog/2015/11/02/spring-security-3-2-9-released

Closes #987
2015-12-18 10:07:23 -05:00
Justin Richer 698feb49cd check access token expiration on read. closes #983 2015-12-16 22:46:42 -05:00
Justin Richer e1800b5fd6 fixed ITC URL 2015-12-16 14:54:51 -05:00
Justin Richer 616220e048 added praseodym to contributors list (thanks!) 2015-12-16 14:51:27 -05:00
Justin Richer 7f464c496b changed copyright to new consortium name 2015-12-16 14:51:12 -05:00
Justin Richer be9d8948ef added UMA classes to logger configuration 2015-12-10 16:35:25 -05:00
Justin Richer d120e8fb20 return ID of resource set in Location URL by calling the right object 2015-12-10 16:35:17 -05:00
Justin Richer 1596b6b9e7 Updated UMA server to use new multi-part messages structure 2015-12-10 16:35:05 -05:00
Justin Richer ea77bf2a19 quieted approved site cleanup 2015-12-02 16:51:55 -05:00
Justin Richer 9ffe877766 added getId to address interface, closes #958 2015-11-25 16:06:17 -05:00
Justin Richer 1ed3e2c47a quieted logging on database cleanup tasks when no expired elements are found 2015-11-25 15:55:16 -05:00
Justin Richer fcfc620d51 updated client API with more useful errors, removed unused service reference 2015-11-25 15:42:09 -05:00
Justin Richer c59f722cc2 enforce pairwise identifier consistency in UI, closes #969 2015-11-25 15:36:15 -05:00
Justin Richer 2496dc114c allow language system to be loaded from multiple files. closes #817 closes #876 2015-11-24 20:33:55 -05:00
Justin Richer e255fc1a10 change default behavior of message source, closes #964 2015-11-24 20:33:54 -05:00
Justin Richer 70751a3d4a updated configuration to comment out optional property value in example 2015-11-24 12:17:32 -05:00
Cosmin Cojocar 7b34a666d9 Make the dual client support configurable 2015-11-24 12:10:27 -05:00
Cosmin Cojocar a80953a2d4 Allow both flows authorization code and client credentials. This scenario might be found when the same client supports user authentication as well as service to service authentication. Such a client is trusted (whitelisted). 2015-11-24 12:10:27 -05:00
Mark Janssen dce80d488b Clean up ScopeClaimTranslationService
`getFieldNameForClaim` method is never used.
2015-11-23 21:35:16 -05:00
Mark Janssen f27673a5f5 Align user profile claims
Especially helps when `<dd>` collapses due to an empty claim value.
2015-11-23 21:34:54 -05:00
Mark Janssen 4f9ea0b474 Improve state handling in handleAuthorizationCodeResponse
Fail fast when there is no state in session, e.g. because the session
cookie was removed.

Resolves #949
2015-11-23 21:34:35 -05:00
Justin Richer 6d2b73a7ef added JSPs to filter 2015-11-23 21:25:02 -05:00
Mark Janssen 4c1e6866ce Filter only `*.tag` files
Instead of excluding all binary files, just filter `*.tag` files.
http://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html
2015-11-23 21:03:23 -05:00
Mark Janssen a3d01727f9 Make FILTER_PROCESSES_URL public
Currently hardcoded in the filter and the client's Spring Security config; would be nicer to reference the value instead.

c5e70ebd5c/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml (L54)
2015-11-23 21:03:08 -05:00
Mark Janssen abff7421c1 Upgrade to Spring Framework 4.1.8
http://spring.io/blog/2015/10/15/spring-framework-4-2-2-4-1-8-and-3-2-15-available-now
2015-11-23 21:02:46 -05:00
Justin Richer 5f24685f17 removed problematic (and not very useful) unit test, closes #742 2015-10-19 15:00:41 -04:00
Justin Richer f04face41e updated to nimbus 4.3, check JCE policy and algorithm availability before running unit tests, closes #938 2015-10-19 14:47:56 -04:00
Justin Richer 2deec98b58 [maven-release-plugin] prepare for next development iteration 2015-10-13 18:56:47 -04:00
Justin Richer d96b2dc130 [maven-release-plugin] prepare release mitreid-connect-1.2.2 2015-10-13 18:56:44 -04:00
Justin Richer 6129cfa61a added scope-based authorities granter for introspections services, closes #835 2015-10-13 18:51:21 -04:00
Justin Richer 96f4d5e8a8 fixed use of wrong constant, closes #940 2015-10-13 18:08:56 -04:00
Justin Richer a5701f4ea3 limit client pagination to 10 pages at a time, closes #886 2015-10-13 17:55:18 -04:00
Justin Richer 8cc89e4e85 made token fetching lazy-loaded 2015-10-13 17:04:36 -04:00
Justin Richer c9358f348a added transactional annotations, finally closes #926 addresses #862 2015-10-13 16:59:11 -04:00
Justin Richer e1e892377f added cleaner for duplicate refresh tokens 2015-10-13 15:38:07 -04:00
Justin Richer 542afca459 cleans duplicate access tokens from DB before other cleanup happens 2015-10-13 15:33:23 -04:00
Justin Richer 9599642f3a upgraded nimbus in uma module` 2015-10-13 12:13:07 -04:00
Justin Richer 149e93e970 Disabled broken crypto tests, pending #938 2015-10-13 11:57:41 -04:00
Justin Richer ebb4f2c3d4 Upgraded to nimbus 4.2, closes #934 2015-10-13 04:40:01 -04:00
Justin Richer c67611e975 added qualifier name to persistence unit and transaction manager, closes #883 2015-10-12 21:15:30 -04:00
Mark Janssen d337e14de3 Remove transitive commons-logging dependencies
We use slf4j instead; jcl-over-slf4j needs to be a compile-time dependency because we use it in several classes.

Unfortunately Maven does not have a way to exclude commons-logging globally, so we need to figure out which dependencies include it through `mvn dependency:tree` and specify an `<exclusion>` for each of them.

Finally, we upgrade to slf4j 1.7.12: http://www.slf4j.org/news.html.
2015-10-12 20:17:51 -04:00
Mark Janssen b89fa7028d Use Maven BOM dependency for Spring
The Maven "bill of materials" dependency ensures that all Spring dependencies use the same version, without having to specify them all.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#overview-maven-bom
2015-10-12 20:17:51 -04:00
Justin Richer d280ca40a4 login hints now handled in a slightly smarter (and more pluggable) manner, closes #851 2015-10-12 20:04:02 -04:00
Justin Richer 98e1d26134 limited when login_hint is sent to the server, closes #963 2015-10-12 17:56:31 -04:00
Mark Janssen 301802abd3 Speed up servlet start
- Set metadata-complete="true" attribute on the <web-app> element.
- Add an empty <absolute-ordering /> element.

See:
https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Configure_your_web_ap
plication

On my (old) machine, this reduces startup time with Jetty from 137580ms
to 20166ms.
2015-10-12 13:10:04 -04:00
Mark Janssen 90e4cb97ff Upgrade jetty-maven-plugin and configure war path
Configuring war path enables `mvn jetty:run-war`.
2015-10-12 13:10:04 -04:00
Mark Janssen 8b7fc5de68 Update HikariCP to 2.4.1
https://github.com/brettwooldridge/HikariCP/blob/dev/CHANGES
2015-10-12 13:08:32 -04:00
Mark Janssen 9117e7fe31 Add SQL indexes for PostgreSQL and HSQLDB 2015-10-12 13:08:16 -04:00
Mark Janssen 0269c24263 Travis build on JDK 7+8
Configures Travis to build on Oracle JDK 7+8 and OpenJDK 7.

Also enables migration to Travis' container-based infrastructure: http://docs.travis-ci.com/user/migrating-from-legacy/
2015-10-12 13:07:43 -04:00
Mark Janssen 7871ee0f26 Improve error message 2015-10-12 13:07:18 -04:00
Mark Janssen 58543ac9c4 Fix ID token icon description 2015-10-12 12:59:44 -04:00
Mark Janssen b5c298e0ca Remove legacy CSRF protection for approve page
Instead, we rely on the Spring Security CSRF protection, like we already do for the login page. Additionally, we remove the authentication check in`isApproved`, because this is already done by Spring Security (and if not, we have bigger problems to worry about).
2015-10-09 17:09:46 +02:00
Justin Richer 8b362f23f3 [maven-release-plugin] prepare for next development iteration 2015-10-02 18:53:48 -04:00
Justin Richer e384a6257b [maven-release-plugin] prepare release mitreid-connect-1.2.1 2015-10-02 18:53:45 -04:00
Justin Richer 4063f7f94f user info endpoint response uses correct client algorithms, addresses #921 2015-10-02 18:48:11 -04:00
Justin Richer 3c222b0d79 rewrote blacklist UI, fixed delete functions on rest of UI, closes #905 2015-10-02 18:37:57 -04:00
Justin Richer 43e9fbc29c fixed issuer on login page, added CSRF to login / logout, closes #870, closes #824, closes #875 2015-10-01 21:16:38 -04:00
Justin Richer ca23521c3b fixed entity relationship for address 2015-10-01 20:52:01 -04:00
Justin Richer e1af979995 don't load user info for anonymous authentications, closes #895 2015-10-01 19:12:50 -04:00
Justin Richer 74f5a248c7 Added indexes to MySQL file, closes #902 2015-10-01 18:59:28 -04:00
Justin Richer acb3d03052 added 'kid' to all signed tokens, closes #899 2015-10-01 18:54:38 -04:00
Justin Richer 48bc26901a added JTI to client auth 2015-10-01 18:54:15 -04:00
Justin Richer d3f8ff2855 added JTI to ID tokens, closes #900 2015-10-01 17:24:47 -04:00
Tony Fendall f43c94314c Change Address model to be an interface. Will allow consuming projects
to override this funcitonality more easily.
2015-10-01 15:57:34 -04:00
Mark Janssen c4726b09f0 Update to Spring Security 3.2.8
https://spring.io/blog/2015/07/23/spring-security-3-2-8-released
2015-10-01 15:55:31 -04:00
Justin Richer 9822748209 grabbed additional places that mention updated_time/updated_at 2015-10-01 15:53:21 -04:00
John Brooks 719a714735 Addresses issue 910 by replacing update_time with update_at for JSON
objects.
2015-10-01 15:43:31 -04:00
Sarah Squire 31ea96ce27 Update DefaultOIDCTokenService.java
fixed typo
2015-10-01 15:34:01 -04:00
Justin Richer 31374c0f7b added spring security to logger configuration, closes #917 2015-10-01 15:32:55 -04:00
Bernd Frey 9fe98e0132 OIDCAuthenticationFilter: Make authenticationSignerService optional so
it must not be provided in Spring config

OIDCAuthenticationProvider: Setter for UserInfoFetcher, so own
implementation can be wired

UserInfoFetcher: Call to DefaultUserInfo.fromJson moved to method, so it
can be overwritten by own implementation to use own UserInfo
implementation
2015-08-21 17:33:23 -04:00
Stephen Doxsee 8d0355a513 Fix commented-out datasource config for postgresql and mysql to user HikariDataSource instead of Apache's BasicDataSource (since the class isn't in the project by default) 2015-08-21 17:27:12 -04:00
Justin Richer 54d8d890e5 restricted access to /authorize to ROLE_USER accounts, closes #892 2015-08-21 10:20:26 -04:00
Justin Richer 22c05ec51b [maven-release-plugin] prepare for next development iteration 2015-08-05 12:07:47 -04:00
Justin Richer e6b64cd9cd [maven-release-plugin] prepare release mitreid-connect-1.2.0 2015-08-05 12:07:44 -04:00
Justin Richer cd46994fb3 removed old DB upgrade scripts (use the upgrade API instead) 2015-08-05 12:04:14 -04:00
Justin Richer 489450b1c2 automated code format cleanup 2015-08-05 12:04:14 -04:00
Justin Richer edda0218e1 added missing copyright statement. 2015-08-05 09:58:41 -04:00
Justin Richer 8a4fb5f839 cleaned up imports 2015-08-05 09:46:36 -04:00
Justin Richer 15c2b57730 [maven-release-plugin] prepare for next development iteration 2015-07-30 14:00:20 -04:00
Justin Richer 8317c759f1 [maven-release-plugin] prepare release mitreid-connect-1.2.0-RC2 2015-07-30 14:00:18 -04:00
Justin Richer 0740443768 added claims redirect uri set to client model for UMA usage 2015-07-30 13:56:14 -04:00
Justin Richer 658b5e1456 updated all available javascript libraries to latest versions 2015-07-10 16:04:36 -04:00
Justin Richer 99fbda3d13 fix scope icon overlay in scope editor for safari/chrome/IE, closes #867 2015-07-10 11:40:50 -04:00
Justin Richer 71c52d1a39 restored default scopes 2015-07-10 11:39:49 -04:00
Justin Richer a4e75ed733 [maven-release-plugin] prepare for next development iteration 2015-07-09 18:29:14 -04:00
Justin Richer 58a47d0e46 [maven-release-plugin] prepare release mitreid-connect-1.2.0-RC1 2015-07-09 18:29:12 -04:00
Justin Richer e18fa60054 database sync 2015-07-09 18:24:56 -04:00
Justin Richer 0714ed514e fixed errant unit test
why do they always get away like that??
2015-07-09 18:16:42 -04:00
Mark Janssen 62f6b7c45b Upgrade Spring versions 2015-07-09 18:12:32 -04:00
Justin Richer 064f36ef6c clean up resource sets when clients are deleted 2015-07-09 18:07:19 -04:00
Justin Richer f6c20ad314 changed to using merge() in JPA instead of persist() 2015-07-09 18:06:25 -04:00
Justin Richer d1c069ad1e clean up permissions and access tokens when a resource set is revoked 2015-07-09 16:40:07 -04:00
Justin Richer 7345a03aaa added UMA import, closes #811 even harder 2015-07-09 11:48:52 -04:00
Justin Richer bcd8a96b5d UMA data export, closes #811 2015-07-08 21:27:15 -04:00
Justin Richer a3360e9561 externalized strings in data API (1.2) 2015-07-08 18:05:17 -04:00
Justin Richer 4a382f2b1c updated unit tests to new structure 2015-07-08 17:32:15 -04:00
Justin Richer 8c822c0f54 detached whitelist from approved sites, closes #781 2015-07-08 17:22:55 -04:00
Justin Richer 2d6be48732 made error page responsive to HTTP status codes. 2015-07-08 14:36:03 -04:00
Justin Richer 3c297ba18f collapsed error clause 2015-07-08 14:35:45 -04:00
Justin Richer 6921ca9a42 fixed messages file format 2015-07-08 14:35:34 -04:00
Justin Richer e96eda0990 save dynamically registered clients to the server's database, closes #799 2015-07-08 14:35:20 -04:00
Justin Richer 662b0cd098 ported change to UMA server 2015-07-08 13:21:10 -04:00
Justin Richer 44dce71888 fixed database syntax, closes #860 2015-07-07 17:57:42 -04:00
Justin Richer 42b93be492 added uri-encoded client service, closes #857 2015-07-07 17:55:56 -04:00
Justin Richer a42920355c updated error page, closes #858 2015-07-07 14:48:46 -04:00
Justin Richer 0360d35c3b updated to servlet 3.0 2015-07-07 14:48:31 -04:00
Justin Richer de72311c95 updated key to 2048-bit version to set a good example 2015-07-07 13:50:57 -04:00
Justin Richer 2db607ec28 i18n for UMA policy management page 2015-07-03 20:45:00 -04:00
Justin Richer ee9413b882 database sync 2015-07-03 20:20:51 -04:00
Justin Richer aa96b1f1ed made things a little null safer
closes #813 (really)
2015-07-03 20:16:37 -04:00
Justin Richer 8086cc9153 removed test data 2015-07-03 20:16:37 -04:00
Justin Richer d4e3639236 added "add new policy" controls 2015-07-03 20:16:36 -04:00
Justin Richer 214097584a force refresh of resource set model after policies have been edited 2015-07-03 20:16:36 -04:00
Justin Richer c5a65e9cec webfigner claims replacement works 2015-07-03 20:16:36 -04:00
Justin Richer f3a777a2c8 enabled scope editing on existing policies 2015-07-03 20:16:36 -04:00
Justin Richer 3d760cad8b added edit policy button 2015-07-03 20:16:36 -04:00
Justin Richer 03b301b43b moved policy API around, fixed render/loading in UI 2015-07-03 20:16:35 -04:00
Justin Richer 53922374df problems loading the resource set 2015-07-03 20:16:35 -04:00
Justin Richer a9f531bffe removed extraneous save button 2015-07-03 20:16:35 -04:00
Justin Richer 8b8db24179 Policy delete works! 2015-07-03 20:16:35 -04:00
Justin Richer 72bb09550c basic display of Policy Table 2015-07-03 20:16:35 -04:00
Justin Richer 1259b8cd68 updated policy display 2015-07-03 20:16:34 -04:00
Justin Richer f0d628bf27 made Policy API fit the new data model (used to be Claims API) 2015-07-03 20:16:34 -04:00
Justin Richer d7af4b2cf9 added scope consistent check to resource set service 2015-07-03 20:16:34 -04:00
Justin Richer 6703db234d added equals/hashCode/toString on UMA model objects 2015-07-03 20:16:34 -04:00
Justin Richer bfd70efcc3 tweak demo claim values for testing 2015-07-03 20:16:34 -04:00
Justin Richer a8a6e7bf31 downscope resulting token based on policy 2015-07-03 20:16:33 -04:00
Justin Richer 7909e3e9ce made claim collection null safe 2015-07-03 20:16:33 -04:00
Justin Richer af798705b4 made claim values any JSON type, closes #853 2015-07-03 20:16:33 -04:00
Justin Richer b0935086c2 made claims processor take in policy set and ticket directly 2015-07-03 20:16:33 -04:00
Justin Richer de9f69e461 introduced a claims processor result data shuttle 2015-07-03 20:16:33 -04:00
Justin Richer 2cfaa1c1d7 renamed RequiredClaimSet to Policy 2015-07-03 20:16:32 -04:00
Justin Richer b8a5486995 made required claims sets stick in the database 2015-07-03 20:16:32 -04:00
Justin Richer 667c766273 reverted over-reaching check on webfinger fetcher 2015-07-03 20:16:32 -04:00
Justin Richer cd47d32e2d split required claim sets out as separate indirection structure, closes #813 2015-07-03 20:16:32 -04:00
Justin Richer 13239c1754 make eclipse happy with the warpath plugin 2015-06-26 15:24:45 -04:00
Justin Richer c4aaa29ffc updated unit tests for new refresh token mode 2015-06-25 12:44:52 -04:00
Justin Richer d9efeb3b67 added clear access tokens to export/import 2015-06-25 12:40:28 -04:00
Justin Richer 50cbeb3e4c DB table sync 2015-06-25 12:11:31 -04:00
Justin Richer 2f4d9ce54b clearing out refresh tokens is now configurable, closes #409 2015-06-25 12:07:38 -04:00
Justin Richer 8359ac2813 fixed refresh token lookup 2015-06-25 11:55:58 -04:00
Justin Richer d2a393f7f9 converted error handlers to a single @ControllerAdvice class, closes #788 2015-06-24 17:26:10 -04:00
Justin Richer b18bea6b9f switched connection pool to use HikariCP, closes #821 2015-06-24 16:21:31 -04:00
Justin Richer 7df3597757 split client's auth token into pending and authorized classes 2015-06-24 16:00:40 -04:00
Justin Richer b4520c170e ID Token carried through as parsed JWT instead of string, closes #832 2015-06-24 16:00:40 -04:00
Justin Richer f4a1b27e2e better handling of HTTP and JSON errors on network fetches, added http-forcing behavior for webfinger client and sector URL service 2015-06-23 22:21:18 -04:00
Justin Richer 9ae92b983a added http and json error handling to webfinger service 2015-06-23 21:50:16 -04:00
Justin Richer c166cbe49c added login hint capability to client library 2015-06-23 21:21:41 -04:00
Justin Richer f7a082d4b8 wrapped timestamp injection in a null-safe block, with warning; closes #849 2015-06-23 20:57:24 -04:00
Justin Richer fdf8c4d620 Updated UMA's ExternalAuthoritiesMapper to new OIDCAuthoritiesMapper class, closes #850 2015-06-23 20:49:03 -04:00
Justin Richer 445099fc74 Sync database changes across all three platforms 2015-06-23 20:31:28 -04:00
lomori 84b595ea6f Synch with HSQLDB version
Few fields were missing, e.g. user_info::src, causing an application crash with MySQL.
2015-06-23 20:24:29 -04:00
Mark Janssen bf295b4c67 Improve Spring Security dependency management 2015-06-23 20:21:35 -04:00
Mark Janssen a7c0a45e5d Add empty <relativePath> to avoid Maven warnings
Occurs when using a Git submodule in overlay project.

[WARNING] Some problems were encountered while building the effective model for org.mitre:openid-connect-common:jar:1.2.0-SNAPSHOT
[WARNING] 'parent.relativePath' of POM org.mitre:openid-connect-parent:1.2.0-SNAPSHOT (…/OpenID-Connect-Java-Spring-Server/pom.xml) points at …:…-overlay instead of org.sonatype.oss:oss-parent, please verify your project structure @ org.mitre:openid-connect-parent:1.2.0-SNAPSHOT, …/OpenID-Connect-Java-Spring-Server/pom.xml, line 26, column 10
2015-06-23 20:17:01 -04:00
Stephen Moore a259841eaf Added getters and setters to IntrospectingTokenService
Fixed TokenCacheObject constructor for setting TCO's expire time
2015-06-09 13:37:07 -04:00
Stephen Moore 698fe55b85 IntrospectingTokenService now takes parameters (cacheTokens, cacheNonExpiringTokens, defaultExpireTime, forceCacheExpireTime) to change the behavior or even disable the caching of responses from the IntrospectionEndpoint. 2015-06-04 16:33:37 -04:00
Justin Richer 286d433da6 save json object inside registered client if it's available, closes #800 2015-06-03 11:07:45 -04:00
Mark Janssen 9e74e40453 Use diamond syntax instead of explicit types 2015-06-03 10:24:48 -04:00
Mark Janssen 13f5e4f8a6 Collapse identical catch branches 2015-06-03 10:24:48 -04:00
Mark Janssen 6dc2b2cb5e Various small improvements/bugfixes 2015-06-03 10:24:41 -04:00
William Kim 54fbf0d0ac Added null check for expiration during introspection. Making assumption that null exp means tokens dont expire. 2015-06-03 09:57:22 -04:00
Yaser Alraddadi 2d5e53c0f2 Fix syntax error: , at the end of table creation
Fix syntax error: , at the end of table creation
2015-06-03 14:56:03 +03:00
Justin Richer d1e8529a7b expose ID Token and UserInfo to the AuthoritiesProvider and AuthoritiesMapper, both extensible
closes #699
closes #761
2015-06-01 21:11:19 -04:00
Justin Richer f7b5228109 UserInfo carries original JSON object along if available 2015-06-01 20:10:07 -04:00
Justin Richer 23e1e87368 dressed up error message a little 2015-06-01 19:39:09 -04:00
Justin Richer 0aabb7226d internationalized the error and login pages 2015-06-01 19:34:43 -04:00
Justin Richer 4655650a68 added OAuth error display page, closes #559 2015-06-01 19:21:32 -04:00
Justin Richer 118237ab05 moved user info interceptor to pre-handle 2015-06-01 19:15:54 -04:00
Justin Richer dfc8df42f5 moved server configuration injection to pre-request 2015-06-01 19:09:42 -04:00
Justin Richer 54e3b7e8d3 added new messages for JWK Set handling 2015-06-01 19:08:51 -04:00
Justin Richer 49c8804a1c JWK Set by value UI added to resource registration 2015-06-01 15:35:21 -04:00
Justin Richer d09b003bc3 JWK Set by value UI added to dynamic registration 2015-06-01 15:35:21 -04:00
Justin Richer 79317d5b70 JWK Set by value added to admin UI, addresses #826 2015-06-01 15:35:21 -04:00
Justin Richer 8b81b36e22 property editor to allow JWK Set to be represented as a string in the XML configuration 2015-06-01 15:35:20 -04:00
Justin Richer e43600494a minor automated code cleanup 2015-06-01 15:35:20 -04:00
Justin Richer 642942b5cf Generalized client key handling into a single cache service 2015-06-01 15:35:20 -04:00
Justin Richer 032d41e5ed added JWKs-by-value support to client data model and API, closes #826 2015-06-01 15:35:20 -04:00
Justin Richer 30162f6baa added direct JWK set to data model 2015-05-29 13:00:13 -04:00
Justin Richer 8d3a8471aa updated refresh token to use converter instead of dummy field 2015-05-29 12:58:00 -04:00
Justin Richer 9662f3e8b3 switched access token to using converter instead of dummy field 2015-05-29 12:40:50 -04:00
Justin Richer 285504cba1 sync database tables across different vendors 2015-05-28 17:26:30 -04:00
Mark Janssen 742ceea182 Support for PostgreSQL 2015-05-28 17:07:41 -04:00
Mark Janssen d583499a07 Add X-Frame-Options header 2015-05-28 17:07:06 -04:00
Mark Janssen effe955953 Fix blacklist/whitelist for DynamicRegistrationClientConfigurationService
ClientConfigurationService#getClientConfiguration has ServerConfiguration as parameter, not String
2015-05-28 17:05:55 -04:00
Justin Richer caf85b990d Revert "added option to send skip sending nonce if desired, closes #704, closes #683,"
This reverts commit bbeaeb06e3.

Conflicts:
	openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java
	openid-connect-common/src/main/java/org/mitre/openid/connect/config/ServerConfiguration.java
2015-05-28 16:44:26 -04:00
Justin Richer d32118d017 Revert "added unit tests for nonce-less url builders (exception cases)"
This reverts commit ada1b0d24e.

Conflicts:
	openid-connect-client/src/test/java/org/mitre/openid/connect/client/service/impl/TestPlainAuthRequestUrlBuilder.java
2015-05-28 16:41:24 -04:00
Justin Richer 9ba1a78d09 removed binary objects from data API importers, removed binary object JSON utility entirely 2015-05-27 19:33:05 -04:00
Justin Richer c974267cde return prompt=none error to client, closes #667 2015-05-27 12:11:41 -04:00
Justin Richer cbf6316050 cleaned up logic on user info interceptor to fix detection of redirects 2015-05-27 12:06:58 -04:00
Justin Richer fe6d2f8a6e updated and expanded unit tests to account for new data layer 2015-05-26 22:00:21 -04:00
Justin Richer d5a08d4996 cleaned up vestigial service component, to be fixed (maybe) in #825 2015-05-26 22:00:21 -04:00
Justin Richer d9e03b769b fixed auth holder reference handling, import/export works now 2015-05-26 22:00:21 -04:00
Justin Richer 3d1aee77b4 updated 1.2 import to reflect new objects 2015-05-26 22:00:21 -04:00
Justin Richer 441b19f0c5 fixed data export to comply with new auth holder 2015-05-26 22:00:21 -04:00
Justin Richer 84167396da made saved user auth remember original class if it gets re-used 2015-05-26 22:00:20 -04:00
Justin Richer a7905c9f82 only save strings in the Extensions map 2015-05-26 22:00:20 -04:00
Justin Richer 93a91c8f84 fixed oauth2request constructor 2015-05-26 22:00:20 -04:00
Justin Richer bedda2959d set table on entity class, added null-safe copies to all collection fields 2015-05-26 22:00:20 -04:00
Justin Richer 5e3d08ef4d temporarily commented out query by authentication in both token types 2015-05-26 22:00:20 -04:00
Justin Richer 98e414b6df broke out authentication holder class into parts, no more serializable pieces in the database, closes #696 2015-05-26 22:00:20 -04:00
Justin Richer 6533875dee certified! 2015-05-26 22:00:15 -04:00
Justin Richer 2f4956f3dd updated UMA project java version 2015-05-22 13:04:21 -04:00
Justin Richer cb8abca0f6 removed embedded JOSE classes in favor of converters 2015-05-22 13:04:21 -04:00
Justin Richer cf1cb34a5f cleaned up error reporting for multiple verifiers 2015-05-22 13:04:21 -04:00
Justin Richer e9aeb8318e added labels for new UI bits 2015-05-22 13:04:21 -04:00
Justin Richer 6be2b4f65e added ES* and PS* support for signed objects 2015-05-22 13:04:21 -04:00
Justin Richer 0d6775dfa8 made auth request url builder handle multiple keys 2015-05-22 13:04:21 -04:00
Mark Janssen eb1ea4c0b8 Update topbar.tag
Fixes #816
2015-05-22 18:21:07 +02:00
Justin Richer 04dc037f9e fixed unit tests to account for refresh token rotation 2015-05-14 11:17:10 -04:00
Justin Richer aeed2fa003 issue new refresh tokens for clients who are configured for it, closes #408 2015-05-13 18:01:49 -04:00
Justin Richer 5b02e18f7c added a simplified user menu and login button for collapsed navbars, closes #801 2015-05-13 17:16:03 -04:00
Justin Richer 31d5e3ad0e echo back requested scopes in error thrown by validator, closes #708 2015-05-13 16:55:28 -04:00
Justin Richer da72ce02ad added token endpoint options to client filter, closes #803 2015-05-13 16:53:35 -04:00
Justin Richer e52fff58f5 added hierarchical user info display, closes #787 2015-05-13 16:48:01 -04:00
Justin Richer 7f44132abc made address object serializable, closes #792 2015-05-13 15:29:38 -04:00
Justin Richer a44335198e made HTTPS warning stand out a little better in the logs 2015-05-13 14:22:50 -04:00
Justin Richer bf2449b693 Merge branch 'uma' 2015-05-13 12:22:30 -04:00
Justin Richer 80c172971a updated warpath plugin version, set minimum maven version to 3.1.0 to support it 2015-05-12 21:52:47 -04:00
Justin Richer 52b1bda8d8 version match and cleanup 2015-05-12 21:00:44 -04:00
Justin Richer 24a464e142 put in a dummy resource set service so that introspection can pass through 2015-05-12 20:30:05 -04:00
Justin Richer cdf6107b25 reverted changes related to UMA server 2015-05-12 20:09:31 -04:00
Justin Richer dece458c67 added warpath plugin to make overlay dependency injection work 2015-05-12 18:28:00 -04:00
Justin Richer f077579b29 moved UMA-specific files to the UMA webapp package 2015-05-12 17:39:17 -04:00
Justin Richer 1b4dba70f0 dependency shuffling and pom formatting 2015-05-12 16:27:37 -04:00
Justin Richer a2edb31753 moved UMA server to its own module 2015-05-12 15:59:03 -04:00
Justin Richer 582c52ebf5 display error on webfinger failure 2015-05-12 11:36:48 -04:00
Justin Richer 7188a06488 added deletion functionality to UI 2015-05-12 11:16:51 -04:00
Justin Richer c63651626f added simple display for required claims into resource set display 2015-05-12 10:57:34 -04:00
Justin Richer 43a432eb9a removed extraneous TODO 2015-05-12 10:31:22 -04:00
Justin Richer ed7799b54a make RPTs optionally expire, closes #794 2015-05-11 19:00:26 -04:00
Justin Richer e0cdeb3571 inject uma token service 2015-05-11 18:20:57 -04:00
Justin Richer fc64dcc9b9 discovery endpoint cleanup 2015-05-11 15:34:50 -04:00
Justin Richer f4f08d9449 RPT endpoint cleanup 2015-05-11 15:28:09 -04:00
Justin Richer 1f083c7acb extracted RPT generation component to new token service class, closes #797 2015-05-11 15:20:26 -04:00
Justin Richer 0ea06f01b8 moved claims processor to the right package 2015-05-11 15:07:56 -04:00
Justin Richer 53d4f15923 shuffle authz endpoint 2015-05-11 14:56:55 -04:00
Justin Richer 7951ff5086 separated claims processing out into its own service, closes #796 2015-05-11 14:44:21 -04:00
Justin Richer b811594ad4 project file cleanup 2015-05-11 14:44:02 -04:00
Justin Richer 8d5c7d6226 fixed some rogue documentation 2015-05-11 13:03:17 -04:00
Justin Richer afad3a720b Merge branch 'master' into uma
* master:
  added strict URI matching option to redirect resolver (off by default)
2015-05-11 12:33:05 -04:00
Justin Richer e155cdc282 added strict URI matching option to redirect resolver (off by default) 2015-05-09 16:37:11 -04:00
Justin Richer 396ed472a9 cleaned up external login page 2015-04-12 22:26:11 -05:00
Justin Richer 9c6f12087d fixed javascript bug on resource set save 2015-04-12 21:47:09 -05:00
Justin Richer 06f7dc984d switched to view constants 2015-04-12 21:20:10 -05:00
Justin Richer d6dfa89533 check client information on delete of resource set 2015-04-12 21:15:03 -05:00
Justin Richer 7273b0a5b7 fixed discovery endpoint information, closes #805 2015-04-12 17:00:46 -05:00
Justin Richer eb49d9624c inject claims from OIDC auth token into permission ticket 2015-03-31 18:21:34 -04:00
Justin Richer 98cd5ba27d added save to permission ticket system 2015-03-31 18:21:14 -04:00
Justin Richer b2912b944a tweaked configuration of login pages to allow parallel logins 2015-03-31 17:06:26 -04:00
Justin Richer 08413302eb configured OIDC client on claims collection endpoint 2015-03-31 15:35:20 -04:00
Justin Richer f48049be4d deny tickets with no claims required (closes a race condition) 2015-03-31 10:26:06 -04:00
Justin Richer dc10779abb removed extraneous issuer in discovery endpoint, closes #793 2015-03-31 10:10:14 -04:00
Justin Richer a38a0b6f75 removed extraneous bob 2015-03-30 18:19:13 -04:00
Justin Richer 2a4cceff5a object consistency across commits 2015-03-30 18:03:49 -04:00
Justin Richer 6e095e3266 can now add and remove email address claims from the UI 2015-03-30 17:54:16 -04:00
Justin Richer 1ad1813239 claim removal and policy saving 2015-03-30 14:47:58 -04:00
Justin Richer 687517d7f4 Merge branch 'master' into claims-editing-ui 2015-03-30 12:21:59 -04:00
Justin Richer d015d17fad search for local users first (by email), then check remote users 2015-03-30 12:20:19 -04:00
Justin Richer 348ff7ee17 made webfinger endpoint search by email address, then by username 2015-03-30 12:18:50 -04:00
Justin Richer 5aa5cc1a10 added search by email to user info data stack 2015-03-30 12:18:50 -04:00
Justin Richer e89d8cd985 added webfinger lookup helper service 2015-03-30 11:49:49 -04:00
Justin Richer 394785b9c4 don't give resource sets default client scopes 2015-03-30 09:57:10 -04:00
Justin Richer 7af19dbd61 added copyright text 2015-03-30 08:44:51 -04:00
Justin Richer 06ae8545ae Merge branch 'master' into uma 2015-03-20 18:15:27 -04:00
Justin Richer 332cb22a99 claim forms displayed 2015-03-20 18:15:05 -04:00
Justin Richer 3e931c68b4 added policy editing overview page 2015-03-20 17:27:10 -04:00
Justin Richer ba0c679e60 made "en" the default locale explicitly 2015-03-20 10:20:37 -04:00
Justin Richer 5698393d31 created claims API 2015-03-19 16:44:34 -04:00
Justin Richer bde03411f1 Merge branch 'master' into uma 2015-03-18 21:42:26 -04:00
Justin Richer 006a4d1ec6 fixed import function of 1.2 data service 2015-03-18 21:42:18 -04:00
Justin Richer 6f149cba69 Merge branch 'master' into uma 2015-03-18 20:10:19 -04:00
Justin Richer 30e894a64a put 'kid' into JWS header, closes #784 2015-03-18 20:09:06 -04:00
Justin Richer 866186f611 pointed data API at the correct service version 2015-03-18 19:54:42 -04:00
Justin Richer aee2544fbf updated tables for MySQL 2015-03-18 19:40:16 -04:00
Justin Richer 6daeeefb33 augmented introspection unit tests with one for new permissions mode 2015-03-18 08:45:05 -04:00
Justin Richer 9f913244a0 fixed unit tests for introspection results 2015-03-18 08:00:18 -04:00
Justin Richer 7df31f1e87 completed rudimentary UMA authorization API.
Working: resource set registration, permission ticket creation, RPT creation from ticket

Still missing: adding required claims to resource set, adding provided claims to permission ticket
2015-03-17 22:26:12 -04:00
Justin Richer e1769d1545 added (optional) permissions sets to access tokens 2015-03-17 21:42:36 -04:00
Justin Richer 1be9da52c6 separated ticket object from permission object to facilitate re-use of permission object with tokens 2015-03-17 21:16:29 -04:00
Justin Richer f123366069 added scope filtering to protection api 2015-03-17 19:43:02 -04:00
Justin Richer b635a2bc88 fixed DB mapping 2015-03-17 19:21:30 -04:00
Justin Richer ff958e20b6 basic authorization support 2015-03-17 19:21:20 -04:00
Justin Richer 098519da5e added OAuth2 error reporting to permission and resource set endpoints 2015-03-17 19:01:44 -04:00
Justin Richer 2993b76dad added auth request endpoint to context configuration 2015-03-17 18:59:43 -04:00
Justin Richer 1393251da9 added value to claim 2015-03-17 18:57:35 -04:00
Justin Richer 2aadb09f49 started claims service, added expiration to permissions 2015-03-16 22:52:21 -04:00
Justin Richer a57c336e11 added uma_authorization to default scope set 2015-03-16 12:29:17 -04:00
Justin Richer c234f78dbd Merge branch 'master' into authorization-api 2015-03-13 19:08:14 -04:00
Justin Richer 5873b336f2 fixed erroneous import 2015-03-13 19:07:27 -04:00
Justin Richer 8352145d82 Merge branch 'master' into authorization-api
Conflicts:
	openid-connect-common/src/main/java/org/mitre/oauth2/service/SystemScopeService.java
	openid-connect-server-webapp/src/main/webapp/WEB-INF/application-context.xml
	openid-connect-server/src/main/java/org/mitre/discovery/web/DiscoveryEndpoint.java
	openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java
	openid-connect-server/src/test/java/org/mitre/oauth2/service/impl/TestDefaultIntrospectionAuthorizer.java
2015-03-13 18:39:26 -04:00
Justin Richer ba51df0c37 consolidated client credential filter beans
(note: imports magic from secoauth)
2015-03-13 18:30:09 -04:00
Justin Richer 4f12fab56b made unused auth codes expired (they're still single-use), refactored auth code service layer 2015-03-13 13:45:49 -04:00
Justin Richer 7e9ee525a8 cleaned up old i18n files and references 2015-03-13 11:33:20 -04:00
Justin Richer f39e2e9412 ported the remainder of the swedish language file to the JSON format 2015-03-12 20:56:26 -04:00
Justin Richer 9b0e504cea transferred remainder of English text to new configuration 2015-03-12 18:03:05 -04:00
Justin Richer 2abcd96bbe set fallback locale to English, ultimate fall through is to return the code string itself 2015-03-12 17:28:27 -04:00
Justin Richer 285ad71874 made input reader use UTF8, imported the first set of Swedish text to the JSON format 2015-03-12 17:07:08 -04:00
Justin Richer 4d1b08f89d moved english homepage text to json format 2015-03-12 15:49:44 -04:00
Justin Richer 80605becf1 rudimentary json-based message source 2015-03-12 15:26:23 -04:00
Justin Richer ed8887864c added font and key files to non-filtered file sets 2015-03-12 13:35:11 -04:00
Justin Richer 75e0cdd550 fixed syntax error in messages file 2015-03-12 13:34:35 -04:00
Justin Richer e1fb8272cc redirect error on prompt=none, addresses #667 2015-03-12 09:26:38 -04:00
Justin Richer 54bec32b7e restored relative time display to a few pages where it was lost during i18n updates, closes #766 2015-03-11 21:24:11 -04:00
Justin Richer daee9266c5 default clients to SECRET_BASIC in UI, closes #772 2015-03-11 16:34:45 -04:00
Justin Richer ad9b49733f externalized queries for scopes, blacklists, user info, pairwise identifiers, and whitelists, closes #771 even harder 2015-03-11 16:13:28 -04:00
Justin Richer 15b97b1dcb Externalized strings for named queries on auth holders, auth codes, clients, and tokens, closes #771 2015-03-11 15:51:51 -04:00
Justin Richer 61a596dc15 externalized strings from user info views 2015-03-11 14:00:14 -04:00
Justin Richer 86e95d9e6e externalized json entity and error parameters, closes #770 2015-03-11 13:52:32 -04:00
Justin Richer e56161e223 extracted http "code" view parameter 2015-03-11 13:39:07 -04:00
Justin Richer 1735dbca11 extracted controller URLs to constants, closes #769 2015-03-11 13:20:59 -04:00
Justin Richer 617d485478 updated all references to media types to use constants instead of literals, closes #767 2015-03-11 12:06:38 -04:00
Justin Richer c777ebfac9 added universal OAuth exception handling 2015-03-11 11:41:28 -04:00
Justin Richer 1ba14f7682 added resource set and permission ticket tables to mysql datastore 2015-03-10 18:49:44 -04:00
Justin Richer 76b7324d88 fixed execution order of introspection endpoint 2015-03-10 18:29:48 -04:00
Justin Richer c3bf359629 turned resource server filter back on 2015-03-10 18:28:35 -04:00
Justin Richer 8c8f912880 fixed endpoint processing to account for client id 2015-03-10 15:37:07 -04:00
Justin Richer 99c57141cb fixed prepacked scope value 2015-03-10 15:36:43 -04:00
Justin Richer ee522100b9 Merge branch 'master' into uma-introspection
* master:
  fixed logger variable name
  made logger declarations consistent across project, closes #780
  Fixed logger
  null safe
  removed DateUtil
  added icons to scope editing panel
2015-03-10 15:03:26 -04:00
Justin Richer 5d35f2c1a6 toned down errors on introspection endpoint 2015-03-10 14:58:22 -04:00
Justin Richer 65d7b00f4d added uma-processing of scopes to introspection results 2015-03-10 12:38:37 -04:00
Justin Richer 627bcaee43 added client_id to resource sets 2015-03-10 12:38:13 -04:00
Justin Richer e5e4c15058 removed introspection authorizer hook 2015-03-10 11:12:37 -04:00
Justin Richer 2a6a17486a added initial uma discovery endpoint 2015-03-09 16:15:30 -04:00
Justin Richer 621399545e cleaned up introspection endpoint processing 2015-03-09 16:15:09 -04:00
Justin Richer 764df71758 refactored introspection to allow for UMA style token access 2015-03-09 12:43:05 -04:00
Justin Richer 1da5c2cd84 fixed imports 2015-03-09 11:51:41 -04:00
Justin Richer c7f6811961 refactored scope enforcement utilities to a separate authentication class 2015-03-09 11:51:24 -04:00
Justin Richer 48b857eb85 fixed logger variable name 2015-03-09 07:37:09 -04:00
Justin Richer c09b63c69f made logger declarations consistent across project, closes #780 2015-03-08 21:56:33 -04:00
Wolter Eldering 849a2b3271 Fixed logger 2015-03-08 16:02:53 +01:00
Wolter Eldering 020b410ffe null safe 2015-03-08 15:47:58 +01:00
Wolter Eldering db2574ab53 removed DateUtil 2015-03-08 15:41:47 +01:00
Justin Richer f266d3b151 added unit test for resource set service to make sure it catches error conditions 2015-03-06 16:56:30 -05:00
Justin Richer 35f2a03b4e added unit test for permission service 2015-03-06 15:50:24 -05:00
Justin Richer e59e988809 made permission service enforce scoping 2015-03-06 15:50:14 -05:00
Justin Richer 5ff9cd1bbb implemented permission registration API 2015-02-28 17:59:37 -05:00
Justin Richer eed8fb0b28 created skeleton of permission registration API 2015-02-28 08:33:09 -05:00
Justin Richer c41488b103 moved an uma package to common, extracted OAuth scope enforcement utility 2015-02-28 08:32:47 -05:00
Justin Richer 5be7d64c7d moved all uma files to their own package 2015-02-28 07:24:53 -05:00
Justin Richer 0d96b6a28a changed name of scope to match uma spec 2015-02-27 20:46:48 -05:00
Justin Richer 0dc7cb05e7 added icons to scope editing panel 2015-02-27 12:37:11 -05:00
Justin Richer 351ce3995a Merge branch 'master' into uma
pulled in deep link checking and checkbox handling
2015-02-27 10:16:25 -05:00
Justin Richer c8cf2abbd9 made scopes robust against deep links 2015-02-27 10:15:36 -05:00
Justin Richer 45754d3b75 made clients robust against deep links 2015-02-27 08:47:39 -05:00
Justin Richer d570497b16 fixed some bugs in whitelist rendering and saving 2015-02-26 21:17:40 -05:00
Justin Richer 692e8418d6 fixed whitelist deep linking, closes #718 2015-02-26 21:05:01 -05:00
Justin Richer 8caaf3ae20 whitelist editor now uses checkboxes, closes #773 2015-02-26 16:36:58 -05:00
Justin Richer a29f524186 Merge branch 'uma-backports' into uma 2015-02-26 16:21:01 -05:00
Justin Richer 7a1480bb07 moved and consolidated json utilities 2015-02-26 16:20:01 -05:00
Justin Richer 40fc70894e fixed oauth scope check 2015-02-24 18:01:03 -05:00
Justin Richer 4d88e04e59 added resource set registration scope to built in set 2015-02-24 17:45:34 -05:00
Justin Richer 4878e88d4f added list all by owner 2015-02-24 17:41:05 -05:00
Justin Richer 8d22ad03e2 implemented remove verb 2015-02-24 17:15:18 -05:00
Justin Richer 89114dcf74 implemented update 2015-02-24 16:05:18 -05:00
Justin Richer ad228e8953 send the _id as a string 2015-02-24 15:52:29 -05:00
Justin Richer 3b6412219b added abbreviated view, updated OAuth error handling, fixed URL mapping 2015-02-24 15:10:48 -05:00
Justin Richer 0b480bac10 implemented get 2015-02-24 15:09:52 -05:00
Justin Richer 3076da1ed8 functioning resource set repository layer 2015-02-24 12:10:54 -05:00
Justin Richer efeead52b6 fixed typos in data layer, added blank service layer to resource set 2015-02-24 12:00:58 -05:00
Justin Richer 99bf19e21b removed policy uri from data model 2015-02-23 13:51:52 -05:00
Justin Richer e7bf75e9a4 moved and consolidated json utilities 2015-02-23 13:43:08 -05:00
Justin Richer 90a7304b4e resource set registration endpoint and service shells 2015-02-23 11:43:05 -05:00
Justin Richer 8992841ffa added missing copyright 2015-02-23 11:33:20 -05:00
Justin Richer 071ea579a3 added resource set class 2015-02-23 11:28:21 -05:00
Justin Richer b670f44138 added UMA to version number 2015-02-19 17:55:25 -05:00
Justin Richer 19879c20c2 restored restricted grant type behavior on dynamic registration page (was lost in translation) 2015-02-18 22:01:50 -05:00
Justin Richer 6a41e98474 added display flag for default scopes 2015-02-18 17:39:00 -05:00
Justin Richer 5f116d522d fixed missing display message 2015-02-18 17:31:09 -05:00
Justin Richer 2d53f317b0 checkboxes now control list membership behavior, autocomplete is turned off 2015-02-18 17:30:56 -05:00
Justin Richer e963c3c1ec checkbox based list renderer 2015-02-18 16:44:44 -05:00
Justin Richer 9a19207f86 long list widgets now clickable 2015-02-18 15:49:25 -05:00
Justin Richer 720b73939f fixed token service logic, added verification to unit tests 2015-02-18 13:57:28 -05:00
Justin Richer 97ae456099 fixed unit tests affected by scope service changes 2015-02-18 13:48:16 -05:00
Justin Richer 9ccaa98e2a fixed default scope lists for dynamic clients and protected resources 2015-02-18 10:57:22 -05:00
Justin Richer cf07f75682 added UI for restricted scopes 2015-02-18 10:47:30 -05:00
Justin Richer 6885713eed added warning suppression for data layer -- non-templated generic types have to be used here 2015-02-18 10:19:36 -05:00
Justin Richer f4813fccee fixed log messages on data services 2015-02-18 09:33:13 -05:00
Justin Richer 4ae981f484 updated data layer and unit tests 2015-02-18 09:23:09 -05:00
Justin Richer 593fac83cf scopes can now be set as "restricted" instead of needing to be set "allowDynReg", closes #747 2015-02-17 18:25:52 -05:00
Justin Richer 1caf5ef8bc removed call to deprecated http components constructor 2015-02-17 17:06:34 -05:00
Justin Richer b376bc6059 removed some vestigial service/repository calls, closes #513 2015-02-17 16:22:40 -05:00
Justin Richer ecfb72bc50 additional JOSE class naming 2015-02-17 15:32:20 -05:00
Justin Richer 522edda074 additional JOSE class renaming 2015-02-17 14:57:29 -05:00
Justin Richer cef6cf17b6 externalized a number of strings, closes #385 2015-02-17 14:39:15 -05:00
Justin Richer 05f03f7c90 yet more year updates 2015-02-17 13:09:45 -05:00
Justin Richer f7998899cf missed a few copyright notices 2015-02-17 13:02:41 -05:00
Justin Richer 994ce6c743 consistently named JOSE-based classes, closes #529 2015-02-17 12:11:58 -05:00
Justin Richer 335d05bb5c renamed data service abstract class 2015-02-17 11:56:50 -05:00
Justin Richer 685960358c formatting cleanup 2015-02-17 11:08:46 -05:00
Justin Richer e2349984b8 happy new year 2015! 2015-02-17 10:24:08 -05:00
Justin Richer d56aec5652 removed extraneous version tag for managed dependency 2015-02-17 10:00:18 -05:00
Justin Richer d88cc2ec8e fixed pluralization of post logout URIs in data API services 2015-02-17 09:59:50 -05:00
Justin Richer d91da77a31 cleaned up resource reg view 2015-02-16 21:06:35 -05:00
Justin Richer cdd49d9d54 ported help-block text to other admin pages, cleaned up rsreg form processor 2015-02-16 20:51:16 -05:00
Justin Richer 40b390de6d pluralized post-logout redirect uris for dynamically registered clients 2015-02-16 16:56:20 -05:00
Justin Richer da9c8bdee5 added support for help blocks on list widget views 2015-02-16 16:43:58 -05:00
Justin Richer cc02f8fbe8 pluralized post-logout redirect URI on client, closes #654 2015-02-16 16:43:34 -05:00
Justin Richer b7612520c4 fixed swedish message 2015-02-16 15:16:03 -05:00
Justin Richer bedc101637 import cleanup 2015-02-16 15:02:34 -05:00
Justin Richer 95c7ba3cc2 updated library versions 2015-02-16 14:46:46 -05:00
Justin Richer 70779a69ea reorganized dependency management section, managed cross-module dependencies, updated Nimbus JWT library 2015-02-16 14:45:13 -05:00
Justin Richer 10f7612595 moved another version tag to dependency management list 2015-02-16 14:34:26 -05:00
Justin Richer 587d4b2db6 further pom file cleanup 2015-02-16 14:24:48 -05:00
Justin Richer 377d8cb884 moved dependency version management to parent pom, closes #666 2015-02-16 13:51:25 -05:00
Justin Richer a9544059cf flagged spurious serialization warnings from the libraries (we're not actually serializing things here) 2015-02-16 12:31:43 -05:00
Justin Richer 77c06e9557 replaced deprecated http components calls, closes #744 2015-02-16 12:31:16 -05:00
Justin Richer 3708b531df moved requirement to different component, closes #759
also cleaned up comments in filter
2015-02-16 11:16:24 -05:00
Justin Richer ef3a696972 removed getBySubject and getAll from user info repository and service layers, closes #760 2015-02-16 11:08:07 -05:00
Justin Richer 63dd7c0b25 removed deprecated DefaultUserInfoUserDetailsService and corresponding test, closes #413 2015-02-16 11:07:17 -05:00
Justin Richer d25602fbe7 created a locale resolved tied in with the existing server configuration bean, removed locale interceptor (it doesn't work with fixed resolvers), cleaned up comments and files 2015-02-16 10:12:27 -05:00
Fredrik Jönsson 7861300d72 Activate locale change interceptor and make it overrideable. 2015-02-15 21:44:48 +01:00
Fredrik Jönsson 10b7eb60c8 Fix typo. 2015-02-11 16:08:45 +01:00
Fredrik Jönsson a80bb19faf Translate dynreg, rsreg warning. 2015-02-11 15:26:08 +01:00
Fredrik Jönsson 3fbd17ffe3 Translate additional tooltip. 2015-02-11 14:03:28 +01:00
Fredrik Jönsson c5d1f4de9d Translated not implemented yet. 2015-02-11 13:54:40 +01:00
Fredrik Jönsson d774cfeb6d Fix explicit date format strings. 2015-02-11 13:36:09 +01:00
Fredrik Jönsson 0b4e584533 Translate dates. 2015-02-11 13:19:37 +01:00
Fredrik Jönsson 7dbfa37887 Switch language to English. 2015-02-11 12:53:59 +01:00
Fredrik Jönsson 22e9dd703b Fix typo. 2015-02-11 11:57:13 +01:00
Fredrik Jönsson 1801225528 Translate page titles. 2015-02-11 11:50:08 +01:00
Fredrik Jönsson bd38e43f5a Translated rsreg page and fixes. 2015-02-11 09:58:06 +01:00
Fredrik Jönsson c50392d77e Started working on rsreg page. 2015-02-11 07:40:35 +01:00
Fredrik Jönsson a602d4c231 Translate dialogs in dynreg.js. 2015-02-10 22:28:20 +01:00
Fredrik Jönsson 6f35c2273d Translated last tab of dynreg. 2015-02-10 22:15:37 +01:00
Fredrik Jönsson 19181446aa More reasonable max length for default max session. 2015-02-10 22:15:20 +01:00
Fredrik Jönsson 8b38d6a797 Translated dynreg cryptography tab. 2015-02-10 14:40:43 +01:00
Fredrik Jönsson 2982f8e199 Translated dynreg tokens tab. 2015-02-10 13:53:43 +01:00
Fredrik Jönsson 2cad53f5a5 Access tab translated. 2015-02-10 13:39:10 +01:00
Fredrik Jönsson dcf8e1988c Translate first tab of dynreg client. 2015-02-10 12:42:37 +01:00
Fredrik Jönsson 0e9214ccea Started working on dev pages. 2015-02-10 11:31:25 +01:00
Fredrik Jönsson c97cd1bd10 No pluras 's' in swedish. 2015-02-10 11:02:19 +01:00
Fredrik Jönsson d42ad7a9ab Translate popup dialogs. 2015-02-10 10:59:41 +01:00
Fredrik Jönsson 97cf6854ed Entire client form translated. 2015-02-10 10:14:31 +01:00
Fredrik Jönsson 76b10736ef Translated missing loading box. 2015-02-10 09:26:51 +01:00
Fredrik Jönsson eaf2ac3160 Add missing white space to loading box. 2015-02-10 09:23:13 +01:00
Fredrik Jönsson f6a26be722 Crypto tab in client form translated. 2015-02-10 09:21:14 +01:00
Fredrik Jönsson 89004b3b43 Fixes and started translating crypto tab. 2015-02-09 23:05:39 +01:00
Fredrik Jönsson 3c72097f3d Tokens tab translated. 2015-02-09 20:24:06 +01:00
Fredrik Jönsson a5ce2f66a2 Credentials tab translated. 2015-02-09 19:45:25 +01:00
Fredrik Jönsson 3f9f33f9a4 Started working on credentials tab. 2015-02-09 16:37:11 +01:00
Fredrik Jönsson d308f58e71 Translate searches in client table. 2015-02-09 12:37:08 +01:00
Fredrik Jönsson d082394bc8 Fix translation bug. 2015-02-09 11:22:24 +01:00
Fredrik Jönsson 91ac730129 Translate loading popyps in client page. 2015-02-09 11:03:47 +01:00
Fredrik Jönsson 7d24490f30 Translate missing peaces of client table. 2015-02-09 10:46:07 +01:00
Fredrik Jönsson 4626584b06 CSS tweak. 2015-02-09 10:33:53 +01:00
Fredrik Jönsson 62b6406581 Client access tab in client form translated. 2015-02-09 10:32:05 +01:00
Fredrik Jönsson 43b6472a7a First tab of client form translated. 2015-02-08 10:55:39 +01:00
Fredrik Jönsson ea1052388c Client list table translated. 2015-02-07 17:58:59 +01:00
Fredrik Jönsson 550b7d4e41 Translated last of scopes. 2015-02-07 15:41:00 +01:00
Fredrik Jönsson 73a4533906 Translate remains of scope form and some other fixes. 2015-02-07 09:04:00 +01:00
Fredrik Jönsson fdc9a65ec1 Most of scope pages translated. 2015-02-06 22:37:05 +01:00
Fredrik Jönsson 004c439711 Translated whitelist. 2015-02-06 15:56:19 +01:00
Fredrik Jönsson 44b8e565ae Admin template translated. 2015-02-06 14:12:35 +01:00
Fredrik Jönsson d0b3e19279 Most of token page translated. 2015-02-06 13:44:26 +01:00
Fredrik Jönsson b2d2a95a47 Most of grant page translated. 2015-02-06 09:59:32 +01:00
Fredrik Jönsson 5a7e70a18e First successful translation of template string. 2015-02-06 00:01:17 +01:00
Fredrik Jönsson 8f64e0c454 Initialize i18next library and load messages. 2015-02-05 18:21:48 +01:00
Fredrik Jönsson 5e2522491d Add i18next library. 2015-02-05 15:47:15 +01:00
Fredrik Jönsson ef3c13ef24 Minor tweaks. 2015-02-05 12:59:22 +01:00
Fredrik Jönsson 86e4f4afe1 Fix date printing in approval page. 2015-02-05 11:01:28 +01:00
Fredrik Jönsson 323a860210 Set correct language in header. 2015-02-05 10:58:13 +01:00
Fredrik Jönsson bed754dde6 Fix plural issues. 2015-02-05 09:31:37 +01:00
Fredrik Jönsson 4dde4fa054 Fixes in statistics. 2015-02-05 09:17:50 +01:00
Fredrik Jönsson 502150c196 Translate approval page. 2015-02-05 00:05:00 +01:00
Fredrik Jönsson 4f7e3ed4e3 Translate page titles for pages translated so far. 2015-02-04 21:58:47 +01:00
Fredrik Jönsson c36e0dbf9c Translate manage.jsp. 2015-02-04 21:26:39 +01:00
Fredrik Jönsson 3533dcdee9 Translate statistics, first version. 2015-02-04 21:09:01 +01:00
Fredrik Jönsson 55bc8713ef Fix issues in sidebar. 2015-02-04 18:40:39 +01:00
Fredrik Jönsson 644344a6e4 Refactorize, remove text attribute from messages so untranslated labels are easily identified. 2015-02-04 16:10:11 +01:00
Fredrik Jönsson f991ca0093 Translate sidebar. 2015-02-04 16:03:24 +01:00
Fredrik Jönsson a33a3c13c6 Fix the about page. 2015-02-04 15:48:57 +01:00
Fredrik Jönsson 6fccef3f69 Translate copyright notice. 2015-02-04 15:44:56 +01:00
Fredrik Jönsson 2dcedca7ac Translate home page, minus statistics string which currently is
non-translateable and needs to be refactorized.
2015-02-04 14:59:54 +01:00
Fredrik Jönsson a61759bf74 Translate contact page. 2015-02-04 14:32:13 +01:00
Fredrik Jönsson 222b7bae91 Initial i18n setup and translations. 2015-02-04 13:50:09 +01:00
Justin Richer 166c53cd6a fixed comparison of client IDs in refresh token, closes #752
Also addresses #735 (again)
2015-01-24 07:47:50 -05:00
Justin Richer 6c88d7c54b removed old owner_id field, closes #636 2015-01-17 08:18:36 -05:00
Charif Belhaffef e8015051d2 add @Transient to function getAuthorizedGrantTypes() so it does not persist 2015-01-14 07:09:34 -05:00
Justin Richer c6c09b9c6c made default user info parser more robust against null values 2015-01-07 18:23:20 -05:00
Justin Richer ada1b0d24e added unit tests for nonce-less url builders (exception cases) 2014-12-19 20:55:40 -05:00
Justin Richer ba97fcb88a changed name of clientAuthorization to authorizationRequest (which is more accurate), closes #697 2014-12-19 00:55:06 -05:00
John Brooks a1228d19b5 Changed lastWeek logic back to correct form, removed logic used for
testing.
2014-12-19 00:39:07 -05:00
Justin Richer bbeaeb06e3 added option to send skip sending nonce if desired, closes #704, closes #683, 2014-12-18 23:22:59 -05:00
William Kim 9aa45f8efb Made the constructor public for OIDCAuthentication filter. 2014-12-18 20:55:15 -05:00
Wolter Eldering 3a067f1875 modify foreign key column types 2014-12-18 20:39:37 -05:00
Wolter Eldering 0e50b2f250 Fix column foreign key data type
make client_id in access_token and approved_site_scope,
whitelisted_site_id in approved_site the same type at the key they
refer to.
2014-12-18 20:39:37 -05:00
Justin Richer e9d764e53e added support for login_hint, closes #250 2014-11-26 09:55:39 -05:00
Justin Richer 3e7ade9a67 fixed unit tests 2014-11-22 23:46:25 -05:00
Justin Richer 1a2ca25359 relaxed scope constraints on protected resources registered through self-service page 2014-11-22 23:46:25 -05:00
Justin Richer 55fb6667a0 removed unused variable in dynreg page 2014-11-22 23:46:25 -05:00
Justin Richer 76b25e13c1 made offline access non-default 2014-11-22 23:46:25 -05:00
Justin Richer e371ad345f fixed checking of refresh token permissions in client service, clients can now request either refresh_token grant type or offline_access scope and it will work. added checkbox to dynreg page for ease-of-use
closes #734
2014-11-22 23:46:25 -05:00
Justin Richer 56344fa12b make sure that client presenting refresh token is the same client the refresh token was issued to
closes #735
2014-11-22 23:46:25 -05:00
Justin Richer 0e776762c2 set up data API for 1.2 format (currently the same as 1.1 format) 2014-11-15 19:59:47 -10:00
Justin Richer 69c19d35fa moved test into test package 2014-11-13 22:17:45 -10:00
Justin Richer b4f3039c5a applied list widget catch to all objects 2014-11-13 14:16:00 -10:00
Justin Richer 51b10dbe96 more comprehensive list widget leftover object handling in client 2014-11-13 13:41:45 -10:00
Justin Richer 89f46fa872 client scopes now added appropriately 2014-11-13 13:15:11 -10:00
Justin Richer d9d9903c55 removed blur detection, started work on alternative 2014-11-13 11:42:50 -10:00
Justin Richer d7f8a846c3 made claim popover more friendly to mobile environments 2014-11-13 11:35:59 -10:00
Justin Richer b14dfa6458 approval page defaults to "ask again" when prompt=consent is passed, closes #669 2014-11-13 11:23:54 -10:00
Justin Richer 775b77b367 updated date format of token introspection response, closes #719 2014-11-13 11:08:20 -10:00
Justin Richer 4e4d9337b6 added assertion authentication to introspection and revocation endpoints, closes #724 2014-11-12 16:32:48 -10:00
Justin Richer c600787f1c added key id to id token, closes #725 2014-11-12 16:22:10 -10:00
Justin Richer d87bdb2120 added ROLE_CLIENT to assertion client authentication, cleaned up roles on client secret authentication, closes #728, closes #401 2014-11-12 16:03:06 -10:00
Justin Richer 34afe21e8a clean tabs, closes #727 2014-11-12 15:47:32 -10:00
Justin Richer b50facd4c2 explicitly added Jackson2 to support secoauth serialization, added string converter to work with our API 2014-11-11 00:17:03 -10:00
Justin Richer e6d10b67a4 update to Spring 4 and other related libraries 2014-11-10 18:29:54 -10:00
Justin Richer bc9942e929 relaxed issuer constraints in client, closes #638 2014-11-01 23:46:57 +00:00
Justin Richer 841e4b4d68 added click through sanity check to registration token rotation, closes #698 2014-10-23 23:30:34 -04:00
Justin Richer 9e1bd8d8c1 updated icons list, enhanced editor display
Addresses #679
2014-10-23 23:30:34 -04:00
Justin Richer f0e2fc6700 make user info classes serializable, closes #714 2014-10-23 23:30:34 -04:00
Justin Richer 3f5e2acfeb if no alg is explicitly set, use the default from the signer 2014-10-23 22:09:02 -04:00
Justin Richer a59fe0604e generate random fake password for private key clients and shared secret crypto clients to avoid accidentally using client secret authentication and bypassing authentication, closes #715 2014-10-23 21:53:32 -04:00
Alexander Imfeld 9dfac35912 Introduce introspection result assembler to allow for customized introspection results 2014-10-14 21:06:09 -04:00
Pascal Bruckert bf00c1f5e0 update spring-security-oauth2 2.0.3 , closes #663 2014-10-14 20:48:34 -04:00
David Steinkopff 659880b4dc fix broken dependency declaration, that follow up to org.springframework.beans.NotWritablePropertyException: Invalid property 'jwkKeyList' of bean class exception 2014-10-14 20:30:50 -04:00
arielak d557b1e2c2 RefreshToken to AuthHolder linkage test now using AuthHolder ID to verify 2014-10-14 20:30:50 -04:00
arielak ff436a6738 Added tests for ensuring the references between a refresh token and its authentication holder are preserved over import. Minor cleanup of other tests. 2014-10-14 20:30:50 -04:00
Ariel Abrams-Kudan aecd222c5a adding netbeans config to gitignore 2014-10-14 20:30:50 -04:00
arielak d18d325c0c Better method of creating test AuthenticationHolderEntity, added some more testing to testImport/ExportGrants
Conflicts:

	openid-connect-server/src/test/java/org/mitre/openid/connect/service/impl/TestMITREidDataService_1_1.java
2014-10-14 20:30:50 -04:00
arielak ff28e1a383 Added new data service tests, separated date parsing/formatting utilities into DateUtil class
Conflicts:

	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_X.java
	openid-connect-server/src/main/java/org/mitre/openid/connect/util/DateUtil.java
2014-10-14 20:30:50 -04:00
Justin Richer 188818dc0d added null check to confirmation controller, closes #684 2014-10-07 21:58:15 -04:00
Justin Richer e814c3abd4 changed color of "matched" element list in client search 2014-10-07 21:44:17 -04:00
Justin Richer 793740cf08 added warnings for empty scopes and empty redirect URI lists 2014-10-07 21:43:53 -04:00
Justin Richer db052f11ca Moved development branch to 1.2 2014-10-07 21:02:07 -04:00
John Brooks 55a906ae40 Change this.model.id to this.model.get('id') 2014-10-07 19:40:39 -04:00
John Brooks 2d6deeb6f3 Change whitelist references from .id to .get('id') 2014-10-07 19:40:38 -04:00
Justin Richer f12d37f84e added registration token rotation function to UI 2014-10-07 19:40:38 -04:00
Justin Richer 78ebcd030d fixed button sizes on dynreg and rsreg 2014-10-07 19:40:38 -04:00
Justin Richer 134909a82f import cleanup 2014-10-07 19:40:38 -04:00
Justin Richer 1e71749c23 added more generic rotation capability 2014-10-07 19:40:38 -04:00
Justin Richer 0b8dbc4f68 added registration token API 2014-10-07 19:40:38 -04:00
Justin Richer 13cee6bf06 Ported date format changes from 1.0.x 2014-10-06 23:41:33 -04:00
arielak 98ace5c9fb Separated date formatting and parsing functions to DateUtil class. Modified how timezone is printed to workaround Java date formatting issue.
Conflicts:
	openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/MITREidDataService_1_0.java
2014-10-06 23:28:20 -04:00
Justin Richer 1fbdd240f1 made binary encode/decode null safe 2014-10-06 23:25:48 -04:00
arielak a8377513a6 Fixed reading/writing of approved access tokens 2014-10-06 22:59:27 -04:00
arielak 0320bae15c Fixed netbeans copyright weirdness 2014-10-06 22:59:27 -04:00
arielak dcf66fadc4 Added support for 1.1 config import/export, and separated common functions into 1_X abstract class 2014-10-06 22:59:27 -04:00
arielak ad841a03df Added support for whitelisted and blacklisted site export 2014-10-06 22:59:27 -04:00
arielak 8495617aed Added support for whitelisted and blacklisted site import from a 1.0 config 2014-10-06 22:59:27 -04:00
arielak 16f15cc3c8 NPE fix 2014-10-06 22:59:27 -04:00
arielak 6333b1e4b1 Re-enabled reading of system scopes. Added 1.1 data export functionality 2014-10-06 22:59:27 -04:00
arielak d5551e9692 Added services for data import/export and modified JpaAuthenticationHolderEntity and Repository to allow getting all objects 2014-10-06 22:58:26 -04:00
arielak 03f2d8f8a0 Added service interface for data import/export service and modified AuthenticationHolderEntity and Repository to allow getting all objects 2014-10-06 22:58:26 -04:00
Justin Richer ec8f708472 swapped exception class for existing BeanCreationException, added example flag in config file (commented out)
closes #528
closes #689
2014-10-04 14:59:36 -04:00
John Brooks 3e3613f471 Corrected bean setup for checkForHttps case tests. 2014-10-04 11:21:01 -04:00
John Brooks acc4cf16bd Separated checkForHttps cases into separate test methods. 2014-10-04 11:21:01 -04:00
John Brooks cf2837f678 Initialized forceHttps to false. 2014-10-04 11:21:00 -04:00
John Brooks 0461e51ddc Changed parent class from Exception to RuntimeException; added copyright
language.
2014-10-04 11:21:00 -04:00
John Brooks e1015e1194 Create flag to force HTTPS of value of issuer on server startup, addresses #528 2014-10-04 11:21:00 -04:00
Justin Richer c683131f12 externalized view name strings and tied them to view beans 2014-09-28 22:25:39 -04:00
Justin Richer a704277652 Removed exceptions from @PostConstruct methods, closes #663 2014-09-28 21:12:46 -04:00
James Agnew fd472e3bb4 Use locally bundled html5shim 2014-09-28 20:43:23 -04:00
Justin Richer 9e88a62479 moved the API endpoints, made resource tokens accessible too 2014-09-22 23:38:12 -04:00
Justin Richer cf198cccc2 added view of registration token 2014-09-22 23:24:17 -04:00
Justin Richer 6d80a00d65 import cleanup 2014-09-22 23:04:23 -04:00
Justin Richer 81634e6165 added API for getting tokens by clientid 2014-09-22 22:55:13 -04:00
Justin Richer bf56fc34bb turned off ajax cache, switched to callback-based template loading
adresses #668
2014-09-22 21:57:48 -04:00
James Agnew e09c9af306 Update mitreid-connect.css 2014-09-15 21:34:59 -04:00
James Agnew d6cc626241 Fix IE8/9 issue where form elements don't display 2014-09-15 21:34:59 -04:00
Justin Richer 1a79949d51 made user info less transient 2014-09-14 22:03:19 -04:00
Justin Richer 54c95c39d2 redirect URI display within table 2014-09-14 22:02:59 -04:00
Justin Richer 094bb6108e cleaner introspection label 2014-09-14 21:41:09 -04:00
Justin Richer 7e35ed0100 renamed client table item template to something sensible 2014-09-14 21:13:46 -04:00
Justin Richer fc93f1b36c fixed whitelist edit button 2014-09-14 21:09:54 -04:00
Justin Richer 3cb76f1810 cleaned up extraneous console.log() debug calls 2014-09-14 21:06:30 -04:00
Justin Richer dee78c130c fixed missing null check in request object parser 2014-08-25 22:48:42 -04:00
Justin Richer ed0b476bb7 removed resource server filter from default <security:http> block 2014-08-24 21:46:40 -04:00
James Agnew c3c8df3dd1 Updating spring security versions 2014-08-06 13:57:35 -04:00
James Agnew e0b84069d4 Update to latest spring-security-oauth2 module 2014-08-06 11:12:40 -04:00
Justin Richer 6f2f807b0b [maven-release-plugin] prepare for next development iteration 2014-08-05 21:54:51 -04:00
519 changed files with 88516 additions and 33961 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 4 space - Tab indentation
[*.{java,xml,js,html}]
indent_style = tab
indent_size = 4

2
.gitignore vendored
View File

@ -1,4 +1,3 @@
local-values.conf
target
*~
bin
@ -10,3 +9,4 @@ bin
.classpath
/target
.springBeans
nb-configuration.xml

View File

@ -1 +1,11 @@
language: java
jdk:
- oraclejdk11
sudo: false
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:
directories:
- $HOME/.m2

43
CHANGELOG.md Normal file
View File

@ -0,0 +1,43 @@
Unreleased:
*1.3.3*:
- Authorization codes are now longer
- Client/RS can parse the "sub" and "user_id" claims in introspection response
- Database-direct queries for fetching tokens by user (optimization)
- Device flow supports verification_uri_complete (must be turned on)
- Long scopes display properly and are still checkable
- Language system remebers when it can't find a file and stops throwing so many errors
- Index added for refresh tokens
- Updated to Spring Security 4.2.11
- Updated Spring to 4.3.22
- Change approve pages to use issuer instead of page context
- Updated oracle database scripts
*1.3.2*:
- Added changelog
- Set default redirect URI resolver strict matching to true
- Fixed XSS vulnerability on redirect URI display on approval page
- Removed MITRE from copyright
- Disallow unsigned JWTs on client authentication
- Upgraded Nimbus revision
- Added French translation
- Added hooks for custom JWT claims
- Removed "Not Yet Implemented" tag from post-logout redirect URI
*1.3.1*:
- Added End Session endpoint
- Fixed discovery endpoint
- Downgrade MySQL connector dependency version from developer preview to GA release
*1.3.0*:
- Added device flow support
- Added PKCE support
- Modularized UI to allow better overlay and extensions
- Modularized data import/export API
- Added software statements to dynamic client registration
- Added assertion processing framework
- Removed ID tokens from storage
- Removed structured scopes
*1.2.6*:
- Added strict HEART compliance mode

View File

@ -1,8 +1,9 @@
Copyright 2014 The MITRE Corporation
and the MIT Kerberos and Internet Trust Consortium
Copyright 2018 The MIT Internet Trust Consortium
Portions copyright 2011-2013 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may not use this project except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0

View File

@ -1,9 +1,11 @@
# MITREid Connect
---
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent) [![Travis CI](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server.svg?branch=master)](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent) [![Travis CI](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server.svg?branch=master)](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server) [![Codecov](https://codecov.io/github/mitreid-connect/OpenID-Connect-Java-Spring-Server/coverage.svg?branch=master)](https://codecov.io/github/mitreid-connect/OpenID-Connect-Java-Spring-Server)
This project contains an OpenID Connect reference implementation in Java on the Spring platform, including a functioning [server library](openid-connect-server), [deployable server package](openid-connect-server-webapp), [client (RP) library](openid-connect-client), and general [utility libraries](openid-connect-common). The server can be used as an OpenID Connect Identity Provider as well as a general-purpose OAuth 2.0 Authorization Server.
This project contains a certified OpenID Connect reference implementation in Java on the Spring platform, including a functioning [server library](openid-connect-server), [deployable server package](openid-connect-server-webapp), [client (RP) library](openid-connect-client), and general [utility libraries](openid-connect-common). The server can be used as an OpenID Connect Identity Provider as well as a general-purpose OAuth 2.0 Authorization Server.
[![OpenID Certified](https://cloud.githubusercontent.com/assets/1454075/7611268/4d19de32-f97b-11e4-895b-31b2455a7ca6.png)](https://openid.net/certification/)
More information about the project can be found:
@ -23,9 +25,7 @@ The authors and key contributors of the project include:
* [Steve Moore](https://github.com/srmoore)
* [Mike Derryberry](https://github.com/mtderryberry)
* [William Kim](https://github.com/wikkim)
* [Mark Janssen](https://github.com/praseodym)
Copyright &copy;2014, [The MITRE Corporation](http://www.mitre.org/)
and the [MIT Kerberos and Internet Trust Consortium](http://kit.mit.edu/). Licensed under the Apache 2.0 license, for details see `LICENSE.txt`.
Licensed under the Apache 2.0 license, for details see `LICENSE.txt`.

38
README_zh_CN.md Normal file
View File

@ -0,0 +1,38 @@
# MITREid Connect
---
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.mitre/openid-connect-parent) [![Travis CI](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server.svg?branch=master)](https://travis-ci.org/mitreid-connect/OpenID-Connect-Java-Spring-Server)
此项目提供了一个业经认证的、用Java语言构筑于Spring平台之上的OpenID Connect参考实现包括 [服务器端的实现库](openid-connect-server), [可部署的服务器包](openid-connect-server-webapp), [客户端 (RP) 的库](openid-connect-client), 以及 [工具类库](openid-connect-common)。该服务器可以用做OpenID Connect身份提供者也可以用做一般意义上的OAuth 2.0授权服务器。
[![OpenID认证](https://cloud.githubusercontent.com/assets/1454075/7611268/4d19de32-f97b-11e4-895b-31b2455a7ca6.png)](https://openid.net/certification/)
有关项目的更多信息参见:
* [项目在GitHub上的主页 (及相关项目)](https://github.com/mitreid-connect/)
* [完整的文档](https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/wiki)
* [Maven文档及Java API](http://mitreid-connect.github.com/)
* [问题Issue追踪系统 (用于报告bug及提交支持请求)](https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/issues)
* 项目的邮件列表: `mitreid-connect@mit.edu`, 及其 [在线存档](https://mailman.mit.edu/mailman/listinfo/mitreid-connect).
项目的作者及主要贡献者有:
* [Justin Richer](https://github.com/jricher/)
* [Amanda Anganes](https://github.com/aanganes/)
* [Michael Jett](https://github.com/jumbojett/)
* [Michael Walsh](https://github.com/nemonik/)
* [Steve Moore](https://github.com/srmoore)
* [Mike Derryberry](https://github.com/mtderryberry)
* [William Kim](https://github.com/wikkim)
* [Mark Janssen](https://github.com/praseodym)
项目的中文译者:
* [刘晓曦](https://github.com/liouxiao/)
版权所有 &copy;2018 [MIT因特网信任联盟](http://www.mit-trust.org/). 采用Apache 2.0许可证, 详见 `LICENSE.txt`.

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2014 The MITRE Corporation
and the MIT Kerberos and Internet Trust Consortium
Copyright 2018 The MIT Internet Trust Consortium
Portions copyright 2011-2013 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@
## Overview ##
This project contains an OpenID Connect Client implemented as a Spring Security AuthenticationFilter. The client facilitates a user's authentication into the secured application to an OpenID Connect Java Spring Server following the OpenID Connect Standard protocol.
This project contains an OpenID Connect Client implemented as a Spring Security AuthenticationFilter. The client facilitates a user's authentication into the secured application to an OpenID Connect Server following the OpenID Connect standard protocol.
## Configuring ##

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2014 The MITRE Corporation
and the MIT Kerberos and Internet Trust Consortium
Copyright 2018 The MIT Internet Trust Consortium
Portions copyright 2011-2013 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -20,7 +22,7 @@
<parent>
<artifactId>openid-connect-parent</artifactId>
<groupId>org.mitre</groupId>
<version>1.1.9</version>
<version>1.3.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>openid-connect-client</artifactId>
@ -30,7 +32,6 @@
<dependency>
<groupId>org.mitre</groupId>
<artifactId>openid-connect-common</artifactId>
<version>1.1.9</version>
</dependency>
</dependencies>
<packaging>jar</packaging>

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,13 +14,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.oauth2.introspectingfilter;
import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_BASIC;
import java.io.IOException;
import java.net.URI;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@ -27,7 +29,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.oauth2.introspectingfilter.service.IntrospectionAuthorityGranter;
import org.mitre.oauth2.introspectingfilter.service.IntrospectionConfigurationService;
import org.mitre.oauth2.introspectingfilter.service.impl.SimpleIntrospectionAuthorityGranter;
@ -67,22 +69,49 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
private IntrospectionConfigurationService introspectionConfigurationService;
private IntrospectionAuthorityGranter introspectionAuthorityGranter = new SimpleIntrospectionAuthorityGranter();
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
private int defaultExpireTime = 300000; // 5 minutes in milliseconds
private boolean forceCacheExpireTime = false; // force removal of cached tokens based on default expire time
private boolean cacheNonExpiringTokens = false;
private boolean cacheTokens = true;
private HttpComponentsClientHttpRequestFactory factory;
public IntrospectingTokenService() {
this(HttpClientBuilder.create().useSystemProperties().build());
}
public IntrospectingTokenService(HttpClient httpClient) {
this.factory = new HttpComponentsClientHttpRequestFactory(httpClient);
}
// Inner class to store in the hash map
private class TokenCacheObject {
OAuth2AccessToken token;
OAuth2Authentication auth;
Date cacheExpire;
private TokenCacheObject(OAuth2AccessToken token, OAuth2Authentication auth) {
this.token = token;
this.auth = auth;
// we don't need to check the cacheTokens values, because this won't actually be added to the cache if cacheTokens is false
// if the token isn't null we use the token expire time
// if forceCacheExpireTime is also true, we also make sure that the token expire time is shorter than the default expire time
if ((this.token.getExpiration() != null) && (!forceCacheExpireTime || (forceCacheExpireTime && (this.token.getExpiration().getTime() - System.currentTimeMillis() <= defaultExpireTime)))) {
this.cacheExpire = this.token.getExpiration();
} else { // if the token doesn't have an expire time, or if the using forceCacheExpireTime the token expire time is longer than the default, then use the default expire time
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MILLISECOND, defaultExpireTime);
this.cacheExpire = cal.getTime();
}
}
}
private Map<String, TokenCacheObject> authCache = new HashMap<String, TokenCacheObject>();
private static Logger logger = LoggerFactory.getLogger(IntrospectingTokenService.class);
private Map<String, TokenCacheObject> authCache = new HashMap<>();
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(IntrospectingTokenService.class);
/**
* @return the introspectionConfigurationService
@ -112,12 +141,84 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
return introspectionAuthorityGranter;
}
// Check if there is a token and authentication in the cache
// and check if it is not expired.
/**
* get the default cache expire time in milliseconds
* @return
*/
public int getDefaultExpireTime() {
return defaultExpireTime;
}
/**
* set the default cache expire time in milliseconds
* @param defaultExpireTime
*/
public void setDefaultExpireTime(int defaultExpireTime) {
this.defaultExpireTime = defaultExpireTime;
}
/**
* check if forcing a cache expire time maximum value
* @return the forceCacheExpireTime setting
*/
public boolean isForceCacheExpireTime() {
return forceCacheExpireTime;
}
/**
* set forcing a cache expire time maximum value
* @param forceCacheExpireTime
*/
public void setForceCacheExpireTime(boolean forceCacheExpireTime) {
this.forceCacheExpireTime = forceCacheExpireTime;
}
/**
* Are non-expiring tokens cached using the default cache time
* @return state of cacheNonExpiringTokens
*/
public boolean isCacheNonExpiringTokens() {
return cacheNonExpiringTokens;
}
/**
* should non-expiring tokens be cached using the default cache timeout
* @param cacheNonExpiringTokens
*/
public void setCacheNonExpiringTokens(boolean cacheNonExpiringTokens) {
this.cacheNonExpiringTokens = cacheNonExpiringTokens;
}
/**
* Is the service caching tokens, or is it hitting the introspection end point every time
* @return true is caching tokens locally, false hits the introspection end point every time
*/
public boolean isCacheTokens() {
return cacheTokens;
}
/**
* Configure if the client should cache tokens locally or not
* @param cacheTokens
*/
public void setCacheTokens(boolean cacheTokens) {
this.cacheTokens = cacheTokens;
}
/**
* Check to see if the introspection end point response for a token has been cached locally
* This call will return the token if it has been cached and is still valid according to
* the cache expire time on the TokenCacheObject. If a cached value has been found but is
* expired, either by default expire times or the token's own expire time, then the token is
* removed from the cache and null is returned.
* @param key is the token to check
* @return the cached TokenCacheObject or null
*/
private TokenCacheObject checkCache(String key) {
if (authCache.containsKey(key)) {
if (cacheTokens && authCache.containsKey(key)) {
TokenCacheObject tco = authCache.get(key);
if (tco.token.getExpiration().after(new Date())) {
if (tco != null && tco.cacheExpire != null && tco.cacheExpire.after(new Date())) {
return tco;
} else {
// if the token is expired, don't keep things around.
@ -129,19 +230,27 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
private OAuth2Request createStoredRequest(final JsonObject token) {
String clientId = token.get("client_id").getAsString();
Set<String> scopes = new HashSet<String>();
Set<String> scopes = new HashSet<>();
if (token.has("scope")) {
scopes.addAll(OAuth2Utils.parseParameterList(token.get("scope").getAsString()));
}
Map<String, String> parameters = new HashMap<String, String>();
Map<String, String> parameters = new HashMap<>();
parameters.put("client_id", clientId);
parameters.put("scope", OAuth2Utils.formatParameterList(scopes));
OAuth2Request storedRequest = new OAuth2Request(parameters, clientId, null, true, scopes, null, null, null, null);
return storedRequest;
}
private Authentication createAuthentication(JsonObject token) {
return new PreAuthenticatedAuthenticationToken(token.get("sub").getAsString(), token, introspectionAuthorityGranter.getAuthorities(token));
private Authentication createUserAuthentication(JsonObject token) {
JsonElement userId = token.get("user_id");
if(userId == null) {
userId = token.get("sub");
if (userId == null) {
return null;
}
}
return new PreAuthenticatedAuthenticationToken(userId.getAsString(), token, introspectionAuthorityGranter.getAuthorities(token));
}
private OAuth2AccessToken createAccessToken(final JsonObject token, final String tokenString) {
@ -149,10 +258,14 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
return accessToken;
}
// Validate a token string against the introspection endpoint,
// then parse it and store it in the local cache. Return true on
// sucess, false otherwise.
private boolean parseToken(String accessToken) {
/**
* Validate a token string against the introspection endpoint,
* then parse it and store it in the local cache if caching is enabled.
*
* @param accessToken Token to pass to the introspection endpoint
* @return TokenCacheObject containing authentication and token if the token was valid, otherwise null
*/
private TokenCacheObject parseToken(String accessToken) {
// find out which URL to ask
String introspectionUrl;
@ -162,14 +275,14 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
client = introspectionConfigurationService.getClientConfiguration(accessToken);
} catch (IllegalArgumentException e) {
logger.error("Unable to load introspection URL or client configuration", e);
return false;
return null;
}
// Use the SpringFramework RestTemplate to send the request to the
// endpoint
String validatedToken = null;
RestTemplate restTemplate;
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
final String clientId = client.getClientId();
final String clientSecret = client.getClientSecret();
@ -199,12 +312,13 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
validatedToken = restTemplate.postForObject(introspectionUrl, form, String.class);
} catch (RestClientException rce) {
logger.error("validateToken", rce);
return null;
}
if (validatedToken != null) {
// parse the json
JsonElement jsonRoot = new JsonParser().parse(validatedToken);
if (!jsonRoot.isJsonObject()) {
return false; // didn't get a proper JSON object
return null; // didn't get a proper JSON object
}
JsonObject tokenResponse = jsonRoot.getAsJsonObject();
@ -212,29 +326,31 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
if (tokenResponse.get("error") != null) {
// report an error?
logger.error("Got an error back: " + tokenResponse.get("error") + ", " + tokenResponse.get("error_description"));
return false;
return null;
}
if (!tokenResponse.get("active").getAsBoolean()) {
// non-valid token
logger.info("Server returned non-active token");
return false;
return null;
}
// create an OAuth2Authentication
OAuth2Authentication auth = new OAuth2Authentication(createStoredRequest(tokenResponse), createAuthentication(tokenResponse));
OAuth2Authentication auth = new OAuth2Authentication(createStoredRequest(tokenResponse), createUserAuthentication(tokenResponse));
// create an OAuth2AccessToken
OAuth2AccessToken token = createAccessToken(tokenResponse, accessToken);
if (token.getExpiration().after(new Date())) {
if (token.getExpiration() == null || token.getExpiration().after(new Date())) {
// Store them in the cache
authCache.put(accessToken, new TokenCacheObject(token, auth));
return true;
TokenCacheObject tco = new TokenCacheObject(token, auth);
if (cacheTokens && (cacheNonExpiringTokens || token.getExpiration() != null)) {
authCache.put(accessToken, tco);
}
return tco;
}
}
// If we never put a token and an authentication in the cache...
return false;
// when the token is invalid for whatever reason
return null;
}
@Override
@ -246,16 +362,12 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
if (cacheAuth != null) {
return cacheAuth.auth;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
cacheAuth = parseToken(accessToken);
if (cacheAuth != null) {
return cacheAuth.auth;
} else {
return null;
}
} else {
return null;
}
}
}
@ -268,16 +380,12 @@ public class IntrospectingTokenService implements ResourceServerTokenServices {
if (cacheAuth != null) {
return cacheAuth.token;
} else {
if (parseToken(accessToken)) {
cacheAuth = authCache.get(accessToken);
if (cacheAuth != null && (cacheAuth.token.getExpiration().after(new Date()))) {
cacheAuth = parseToken(accessToken);
if (cacheAuth != null) {
return cacheAuth.token;
} else {
return null;
}
} else {
return null;
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,19 +14,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.oauth2.introspectingfilter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
@ -37,26 +33,21 @@ import com.google.gson.JsonObject;
public class OAuth2AccessTokenImpl implements OAuth2AccessToken {
private JsonObject token;
private JsonObject introspectionResponse;
private String tokenString;
private Set<String> scopes = new HashSet<String>();
private Set<String> scopes = new HashSet<>();
private Date expireDate;
public OAuth2AccessTokenImpl(JsonObject token, String tokenString) {
this.token = token;
public OAuth2AccessTokenImpl(JsonObject introspectionResponse, String tokenString) {
this.setIntrospectionResponse(introspectionResponse);
this.tokenString = tokenString;
if (token.get("scope") != null) {
scopes = Sets.newHashSet(Splitter.on(" ").split(token.get("scope").getAsString()));
if (introspectionResponse.get("scope") != null) {
scopes = Sets.newHashSet(Splitter.on(" ").split(introspectionResponse.get("scope").getAsString()));
}
DateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
if (token.get("exp") != null) {
try {
expireDate = dateFormater.parse(token.get("exp").getAsString());
} catch (ParseException ex) {
Logger.getLogger(IntrospectingTokenService.class.getName()).log(Level.SEVERE, null, ex);
}
if (introspectionResponse.get("exp") != null) {
expireDate = new Date(introspectionResponse.get("exp").getAsLong() * 1000L);
}
}
@ -107,4 +98,20 @@ public class OAuth2AccessTokenImpl implements OAuth2AccessToken {
return tokenString;
}
/**
* @return the token
*/
public JsonObject getIntrospectionResponse() {
return introspectionResponse;
}
/**
* @param token the token to set
*/
public void setIntrospectionResponse(JsonObject token) {
this.introspectionResponse = token;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.introspectingfilter.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.mitre.oauth2.introspectingfilter.service.IntrospectionAuthorityGranter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import com.google.gson.JsonObject;
/**
* @author jricher
*
*/
public class ScopeBasedIntrospectionAuthoritiesGranter implements IntrospectionAuthorityGranter {
private List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_API");
/* (non-Javadoc)
* @see org.mitre.oauth2.introspectingfilter.IntrospectionAuthorityGranter#getAuthorities(net.minidev.json.JSONObject)
*/
@Override
public List<GrantedAuthority> getAuthorities(JsonObject introspectionResponse) {
List<GrantedAuthority> auth = new ArrayList<>(getAuthorities());
if (introspectionResponse.has("scope") && introspectionResponse.get("scope").isJsonPrimitive()) {
String scopeString = introspectionResponse.get("scope").getAsString();
Set<String> scopes = OAuth2Utils.parseParameterList(scopeString);
for (String scope : scopes) {
auth.add(new SimpleGrantedAuthority("OAUTH_SCOPE_" + scope));
}
}
return auth;
}
/**
* @return the authorities
*/
public List<GrantedAuthority> getAuthorities() {
return authorities;
}
/**
* @param authorities the authorities to set
*/
public void setAuthorities(List<GrantedAuthority> authorities) {
this.authorities = authorities;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.openid.connect.client;
import org.springframework.security.authentication.AuthenticationServiceException;
public class AuthorizationEndpointException extends AuthenticationServiceException {
private static final long serialVersionUID = 6953119789654778380L;
private String error;
private String errorDescription;
private String errorURI;
public AuthorizationEndpointException(String error, String errorDescription, String errorURI) {
super("Error from Authorization Endpoint: " + error + " " + errorDescription + " " + errorURI);
this.error = error;
this.errorDescription = errorDescription;
this.errorURI = errorURI;
}
public String getError() {
return error;
}
public String getErrorDescription() {
return errorDescription;
}
public String getErrorURI() {
return errorURI;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "AuthorizationEndpointException [error=" + error + ", errorDescription=" + errorDescription + ", errorURI=" + errorURI + "]";
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,20 +14,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
package org.mitre.openid.connect.client;
import java.text.ParseException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.mitre.openid.connect.model.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
/**
*
@ -37,31 +43,36 @@ import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper
* @author jricher
*
*/
public class NamedAdminAuthoritiesMapper implements GrantedAuthoritiesMapper {
public class NamedAdminAuthoritiesMapper implements OIDCAuthoritiesMapper {
private static Logger logger = LoggerFactory.getLogger(NamedAdminAuthoritiesMapper.class);
private static final SimpleGrantedAuthority ROLE_ADMIN = new SimpleGrantedAuthority("ROLE_ADMIN");
private static final SimpleGrantedAuthority ROLE_USER = new SimpleGrantedAuthority("ROLE_USER");
private Set<SubjectIssuerGrantedAuthority> admins = new HashSet<SubjectIssuerGrantedAuthority>();
private GrantedAuthoritiesMapper chain = new NullAuthoritiesMapper();
private Set<SubjectIssuerGrantedAuthority> admins = new HashSet<>();
@Override
public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
public Collection<? extends GrantedAuthority> mapAuthorities(JWT idToken, UserInfo userInfo) {
Set<GrantedAuthority> out = new HashSet<GrantedAuthority>();
out.addAll(authorities);
Set<GrantedAuthority> out = new HashSet<>();
try {
JWTClaimsSet claims = idToken.getJWTClaimsSet();
SubjectIssuerGrantedAuthority authority = new SubjectIssuerGrantedAuthority(claims.getSubject(), claims.getIssuer());
out.add(authority);
for (GrantedAuthority authority : authorities) {
if (admins.contains(authority)) {
out.add(ROLE_ADMIN);
}
}
// everybody's a user by default
out.add(ROLE_USER);
return chain.mapAuthorities(out);
} catch (ParseException e) {
logger.error("Unable to parse ID Token inside of authorities mapper (huh?)");
}
return out;
}
/**
@ -78,18 +89,4 @@ public class NamedAdminAuthoritiesMapper implements GrantedAuthoritiesMapper {
this.admins = admins;
}
/**
* @return the chain
*/
public GrantedAuthoritiesMapper getChain() {
return chain;
}
/**
* @param chain the chain to set
*/
public void setChain(GrantedAuthoritiesMapper chain) {
this.chain = chain;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client;
import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.PRIVATE_KEY;
@ -23,10 +24,14 @@ import static org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod.SECRET_JWT;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -34,10 +39,12 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.jwt.signer.service.impl.SymmetricCacheService;
import org.mitre.jwt.signer.service.impl.SymmetricKeyJWTValidatorCacheService;
import org.mitre.oauth2.model.PKCEAlgorithm;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.AuthRequestOptionsService;
@ -47,7 +54,7 @@ import org.mitre.openid.connect.client.service.IssuerService;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
@ -59,10 +66,12 @@ import org.springframework.security.web.authentication.AbstractAuthenticationPro
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@ -71,11 +80,11 @@ import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.JWTParser;
import com.nimbusds.jwt.PlainJWT;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
/**
@ -87,31 +96,45 @@ import com.nimbusds.jwt.SignedJWT;
public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
protected final static String REDIRECT_URI_SESION_VARIABLE = "redirect_uri";
protected final static String CODE_VERIFIER_SESSION_VARIABLE = "code_verifier";
protected final static String STATE_SESSION_VARIABLE = "state";
protected final static String NONCE_SESSION_VARIABLE = "nonce";
protected final static String ISSUER_SESSION_VARIABLE = "issuer";
protected static final String TARGET_SESSION_VARIABLE = "target";
protected final static String TARGET_SESSION_VARIABLE = "target";
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
protected final static String FILTER_PROCESSES_URL = "/openid_connect_login";
public final static String FILTER_PROCESSES_URL = "/openid_connect_login";
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
@Autowired
// fetches and caches public keys for servers
@Autowired(required=false)
private JWKSetCacheService validationServices;
// creates JWT signer/validators for symmetric keys
@Autowired(required=false)
private SymmetricCacheService symmetricCacheService;
private SymmetricKeyJWTValidatorCacheService symmetricCacheService;
// signer based on keypair for this client (for outgoing auth requests)
@Autowired(required=false)
private JWTSigningAndValidationService authenticationSignerService;
@Autowired(required=false)
private JwtSigningAndValidationService authenticationSignerService;
private HttpClient httpClient;
// modular services to build out client filter
private ServerConfigurationService servers;
private ClientConfigurationService clients;
/*
* Modular services to build out client filter.
*/
// looks at the request and determines which issuer to use for lookup on the server
private IssuerService issuerService;
// holds server information (auth URI, token URI, etc.), indexed by issuer
private ServerConfigurationService servers;
// holds client information (client ID, redirect URI, etc.), indexed by issuer of the server
private ClientConfigurationService clients;
// provides extra options to inject into the outbound request
private AuthRequestOptionsService authOptions = new StaticAuthRequestOptionsService(); // initialize with an empty set of options
// builds the actual request URI based on input from all other services
private AuthRequestUrlBuilder authRequestBuilder;
// private helpers to handle target link URLs
@ -123,7 +146,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
/**
* OpenIdConnectAuthenticationFilter constructor
*/
protected OIDCAuthenticationFilter() {
public OIDCAuthenticationFilter() {
super(FILTER_PROCESSES_URL);
targetSuccessHandler.passthrough = super.getSuccessHandler();
super.setAuthenticationSuccessHandler(targetSuccessHandler);
@ -140,7 +163,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
}
if (symmetricCacheService == null) {
symmetricCacheService = new SymmetricCacheService();
symmetricCacheService = new SymmetricKeyJWTValidatorCacheService();
}
}
@ -216,8 +239,6 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
throw new AuthenticationServiceException("No issuer found: " + issuer);
}
session.setAttribute(ISSUER_SESSION_VARIABLE, issuer);
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
if (serverConfig == null) {
logger.error("No server configuration found for issuer: " + issuer);
@ -225,6 +246,8 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
}
session.setAttribute(ISSUER_SESSION_VARIABLE, serverConfig.getIssuer());
RegisteredClient clientConfig = clients.getClientConfiguration(serverConfig);
if (clientConfig == null) {
logger.error("No client configuration found for issuer: " + issuer);
@ -234,7 +257,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
String redirectUri = null;
if (clientConfig.getRegisteredRedirectUri() != null && clientConfig.getRegisteredRedirectUri().size() == 1) {
// if there's a redirect uri configured (and only one), use that
redirectUri = clientConfig.getRegisteredRedirectUri().toArray(new String[] {})[0];
redirectUri = Iterables.getOnlyElement(clientConfig.getRegisteredRedirectUri());
} else {
// otherwise our redirect URI is this current URL, with no query parameters
redirectUri = request.getRequestURL().toString();
@ -249,7 +272,27 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
Map<String, String> options = authOptions.getOptions(serverConfig, clientConfig, request);
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options);
// if we're using PKCE, handle the challenge here
if (clientConfig.getCodeChallengeMethod() != null) {
String codeVerifier = createCodeVerifier(session);
options.put("code_challenge_method", clientConfig.getCodeChallengeMethod().getName());
if (clientConfig.getCodeChallengeMethod().equals(PKCEAlgorithm.plain)) {
options.put("code_challenge", codeVerifier);
} else if (clientConfig.getCodeChallengeMethod().equals(PKCEAlgorithm.S256)) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String hash = Base64URL.encode(digest.digest(codeVerifier.getBytes(StandardCharsets.US_ASCII))).toString();
options.put("code_challenge", hash);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options, issResp.getLoginHint());
logger.debug("Auth Request: " + authRequest);
@ -272,11 +315,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// check for state, if it doesn't match we bail early
String storedState = getStoredState(session);
if (!Strings.isNullOrEmpty(storedState)) {
String state = request.getParameter("state");
if (!storedState.equals(state)) {
throw new AuthenticationServiceException("State parameter mismatch on return. Expected " + storedState + " got " + state);
}
String requestState = request.getParameter("state");
if (storedState == null || !storedState.equals(requestState)) {
throw new AuthenticationServiceException("State parameter mismatch on return. Expected " + storedState + " got " + requestState);
}
// look up the issuer that we set out to talk to
@ -286,9 +327,15 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
ServerConfiguration serverConfig = servers.getServerConfiguration(issuer);
final RegisteredClient clientConfig = clients.getClientConfiguration(serverConfig);
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("grant_type", "authorization_code");
form.add("code", authorizationCode);
form.setAll(authOptions.getTokenOptions(serverConfig, clientConfig, request));
String codeVerifier = getStoredCodeVerifier(session);
if (codeVerifier != null) {
form.add("code_verifier", codeVerifier);
}
String redirectUri = getStoredSessionString(session, REDIRECT_URI_SESION_VARIABLE);
if (redirectUri != null) {
@ -296,9 +343,15 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
}
// Handle Token Endpoint interaction
HttpClient httpClient = new SystemDefaultHttpClient();
httpClient.getParams().setParameter("http.socket.timeout", new Integer(httpSocketTimeout));
if(httpClient == null) {
httpClient = HttpClientBuilder.create()
.useSystemProperties()
.setDefaultRequestConfig(RequestConfig.custom()
.setSocketTimeout(httpSocketTimeout)
.build())
.build();
}
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
@ -312,9 +365,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest httpRequest = super.createRequest(url, method);
httpRequest.getHeaders().add("Authorization",
String.format("Basic %s", Base64.encode(String.format("%s:%s", clientConfig.getClientId(), clientConfig.getClientSecret())) ));
String.format("Basic %s", Base64.encode(String.format("%s:%s",
UriUtils.encodePathSegment(clientConfig.getClientId(), "UTF-8"),
UriUtils.encodePathSegment(clientConfig.getClientSecret(), "UTF-8")))));
return httpRequest;
}
@ -327,13 +380,13 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// do a symmetric secret signed JWT for auth
JwtSigningAndValidationService signer = null;
JWTSigningAndValidationService signer = null;
JWSAlgorithm alg = clientConfig.getTokenEndpointAuthSigningAlg();
if (SECRET_JWT.equals(clientConfig.getTokenEndpointAuthMethod()) &&
(alg.equals(JWSAlgorithm.HS256)
|| alg.equals(JWSAlgorithm.HS384)
|| alg.equals(JWSAlgorithm.HS512))) {
(JWSAlgorithm.HS256.equals(alg)
|| JWSAlgorithm.HS384.equals(alg)
|| JWSAlgorithm.HS512.equals(alg))) {
// generate one based on client secret
signer = symmetricCacheService.getSymmetricValidtor(clientConfig.getClient());
@ -342,27 +395,35 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
// needs to be wired in to the bean
signer = authenticationSignerService;
if (alg == null) {
alg = authenticationSignerService.getDefaultSigningAlgorithm();
}
}
if (signer == null) {
throw new AuthenticationServiceException("Couldn't find required signer service for use with private key auth.");
}
JWTClaimsSet claimsSet = new JWTClaimsSet();
JWTClaimsSet.Builder claimsSet = new JWTClaimsSet.Builder();
claimsSet.setIssuer(clientConfig.getClientId());
claimsSet.setSubject(clientConfig.getClientId());
claimsSet.setAudience(Lists.newArrayList(serverConfig.getTokenEndpointUri()));
claimsSet.issuer(clientConfig.getClientId());
claimsSet.subject(clientConfig.getClientId());
claimsSet.audience(Lists.newArrayList(serverConfig.getTokenEndpointUri()));
claimsSet.jwtID(UUID.randomUUID().toString());
// TODO: make this configurable
Date exp = new Date(System.currentTimeMillis() + (60 * 1000)); // auth good for 60 seconds
claimsSet.setExpirationTime(exp);
claimsSet.expirationTime(exp);
Date now = new Date(System.currentTimeMillis());
claimsSet.setIssueTime(now);
claimsSet.setNotBeforeTime(now);
claimsSet.issueTime(now);
claimsSet.notBeforeTime(now);
SignedJWT jwt = new SignedJWT(new JWSHeader(alg), claimsSet);
JWSHeader header = new JWSHeader(alg, null, null, null, null, null, null, null, null, null,
signer.getDefaultSignerKeyId(),
null, null);
SignedJWT jwt = new SignedJWT(header, claimsSet.build());
signer.signJwt(jwt, alg);
@ -383,15 +444,13 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
try {
jsonString = restTemplate.postForObject(serverConfig.getTokenEndpointUri(), form, String.class);
} catch (HttpClientErrorException httpClientErrorException) {
} catch (RestClientException e) {
// Handle error
logger.error("Token Endpoint error response: "
+ httpClientErrorException.getStatusText() + " : "
+ httpClientErrorException.getMessage());
logger.error("Token Endpoint error response: " + e.getMessage());
throw new AuthenticationServiceException("Unable to obtain Access Token: " + httpClientErrorException.getMessage());
throw new AuthenticationServiceException("Unable to obtain Access Token: " + e.getMessage());
}
logger.debug("from TokenEndpoint jsonString = " + jsonString);
@ -444,10 +503,10 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
JWT idToken = JWTParser.parse(idTokenValue);
// validate our ID Token over a number of tests
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
JWTClaimsSet idClaims = idToken.getJWTClaimsSet();
// check the signature
JwtSigningAndValidationService jwtValidator = null;
JWTSigningAndValidationService jwtValidator = null;
Algorithm tokenAlg = idToken.getHeader().getAlgorithm();
@ -465,7 +524,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
throw new AuthenticationServiceException("Unsigned ID tokens can only be used if explicitly configured in client.");
}
if (tokenAlg != null && !tokenAlg.equals(JWSAlgorithm.NONE)) {
if (tokenAlg != null && !tokenAlg.equals(Algorithm.NONE)) {
throw new AuthenticationServiceException("Unsigned token received, expected signature with " + tokenAlg);
}
} else if (idToken instanceof SignedJWT) {
@ -556,13 +615,11 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
}
// pull the subject (user id) out as a claim on the id_token
// construct an PendingOIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
String userId = idClaims.getSubject();
// construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue);
PendingOIDCAuthenticationToken token = new PendingOIDCAuthenticationToken(idClaims.getSubject(), idClaims.getIssuer(),
serverConfig,
idToken, accessTokenValue, refreshTokenValue);
Authentication authentication = this.getAuthenticationManager().authenticate(token);
@ -593,7 +650,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
String errorDescription = request.getParameter("error_description");
String errorURI = request.getParameter("error_uri");
throw new AuthenticationServiceException("Error from Authorization Endpoint: " + error + " " + errorDescription + " " + errorURI);
throw new AuthorizationEndpointException(error, errorDescription, errorURI);
}
/**
@ -653,6 +710,26 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
return getStoredSessionString(session, STATE_SESSION_VARIABLE);
}
/**
* Create a random code challenge and store it in the session
* @param session
* @return
*/
protected static String createCodeVerifier(HttpSession session) {
String challenge = new BigInteger(50, new SecureRandom()).toString(16);
session.setAttribute(CODE_VERIFIER_SESSION_VARIABLE, challenge);
return challenge;
}
/**
* Retrieve the stored challenge from our session
* @param session
* @return
*/
protected static String getStoredCodeVerifier(HttpSession session) {
return getStoredSessionString(session, CODE_VERIFIER_SESSION_VARIABLE);
}
@Override
public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler successHandler) {
@ -685,7 +762,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
if (!Strings.isNullOrEmpty(target)) {
session.removeAttribute(TARGET_SESSION_VARIABLE);
if (deepLinkFilter != null) {
target = deepLinkFilter.filter(target);
}
response.sendRedirect(target);
} else {
@ -795,11 +874,11 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
this.authOptions = authOptions;
}
public SymmetricCacheService getSymmetricCacheService() {
public SymmetricKeyJWTValidatorCacheService getSymmetricCacheService() {
return symmetricCacheService;
}
public void setSymmetricCacheService(SymmetricCacheService symmetricCacheService) {
public void setSymmetricCacheService(SymmetricKeyJWTValidatorCacheService symmetricCacheService) {
this.symmetricCacheService = symmetricCacheService;
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,31 +14,36 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client;
import java.util.Collection;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.nimbusds.jwt.JWT;
/**
* @author nemonik
* @author nemonik, Justin Richer
*
*/
public class OIDCAuthenticationProvider implements AuthenticationProvider {
private static Logger logger = LoggerFactory.getLogger(OIDCAuthenticationProvider.class);
private UserInfoFetcher userInfoFetcher = new UserInfoFetcher();
private GrantedAuthoritiesMapper authoritiesMapper = new NamedAdminAuthoritiesMapper();
private OIDCAuthoritiesMapper authoritiesMapper = new NamedAdminAuthoritiesMapper();
/*
* (non-Javadoc)
@ -46,43 +52,65 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
* authenticate(org.springframework.security.core.Authentication)
*/
@Override
public Authentication authenticate(final Authentication authentication)
throws AuthenticationException {
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
if (!supports(authentication.getClass())) {
return null;
}
if (authentication instanceof OIDCAuthenticationToken) {
if (authentication instanceof PendingOIDCAuthenticationToken) {
OIDCAuthenticationToken token = (OIDCAuthenticationToken) authentication;
PendingOIDCAuthenticationToken token = (PendingOIDCAuthenticationToken) authentication;
Collection<SubjectIssuerGrantedAuthority> authorities = Lists.newArrayList(new SubjectIssuerGrantedAuthority(token.getSub(), token.getIssuer()));
// get the ID Token value out
JWT idToken = token.getIdToken();
// load the user info if we can
UserInfo userInfo = userInfoFetcher.loadUserInfo(token);
if (userInfo == null) {
// TODO: user Info not found -- error?
// user info not found -- could be an error, could be fine
} else {
// if we found userinfo, double check it
if (!Strings.isNullOrEmpty(userInfo.getSub()) && !userInfo.getSub().equals(token.getSub())) {
// the userinfo came back and the user_id fields don't match what was in the id_token
throw new UsernameNotFoundException("user_id mismatch between id_token and user_info call: " + token.getSub() + " / " + userInfo.getSub());
}
}
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
userInfo, authoritiesMapper.mapAuthorities(authorities),
token.getIdTokenValue(), token.getAccessTokenValue(), token.getRefreshTokenValue());
return createAuthenticationToken(token, authoritiesMapper.mapAuthorities(idToken, userInfo), userInfo);
}
return null;
}
/**
* Override this function to return a different kind of Authentication, processes the authorities differently,
* or do post-processing based on the UserInfo object.
*
* @param token
* @param authorities
* @param userInfo
* @return
*/
protected Authentication createAuthenticationToken(PendingOIDCAuthenticationToken token, Collection<? extends GrantedAuthority> authorities, UserInfo userInfo) {
return new OIDCAuthenticationToken(token.getSub(),
token.getIssuer(),
userInfo, authorities,
token.getIdToken(), token.getAccessTokenValue(), token.getRefreshTokenValue());
}
/**
* @param userInfoFetcher
*/
public void setUserInfoFetcher(UserInfoFetcher userInfoFetcher) {
this.userInfoFetcher = userInfoFetcher;
}
/**
* @param authoritiesMapper
*/
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
public void setAuthoritiesMapper(OIDCAuthoritiesMapper authoritiesMapper) {
this.authoritiesMapper = authoritiesMapper;
}
@ -95,6 +123,6 @@ public class OIDCAuthenticationProvider implements AuthenticationProvider {
*/
@Override
public boolean supports(Class<?> authentication) {
return OIDCAuthenticationToken.class.isAssignableFrom(authentication);
return PendingOIDCAuthenticationToken.class.isAssignableFrom(authentication);
}
}

View File

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.openid.connect.client;
import java.util.Collection;
import org.mitre.openid.connect.model.UserInfo;
import org.springframework.security.core.GrantedAuthority;
import com.nimbusds.jwt.JWT;
/**
* @author jricher
*
*/
public interface OIDCAuthoritiesMapper {
/**
* @param idToken the ID Token (parsed as a JWT, cannot be @null)
* @param userInfo userInfo of the current user (could be @null)
* @return the set of authorities to map to this user
*/
Collection<? extends GrantedAuthority> mapAuthorities(JWT idToken, UserInfo userInfo);
}

View File

@ -1,6 +1,5 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,5 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +12,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,5 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,19 +14,22 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mitre.openid.connect.config.ServerConfiguration.UserInfoTokenMethod;
import org.mitre.openid.connect.model.DefaultUserInfo;
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
import org.mitre.openid.connect.model.PendingOIDCAuthenticationToken;
import org.mitre.openid.connect.model.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -37,19 +41,58 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Utility class to fetch userinfo from the userinfo endpoint, if available.
* Utility class to fetch userinfo from the userinfo endpoint, if available. Caches the results.
* @author jricher
*
*/
public class UserInfoFetcher {
private Logger logger = LoggerFactory.getLogger(UserInfoFetcher.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(UserInfoFetcher.class);
public UserInfo loadUserInfo(final OIDCAuthenticationToken token) {
private LoadingCache<PendingOIDCAuthenticationToken, UserInfo> cache;
public UserInfoFetcher() {
this(HttpClientBuilder.create().useSystemProperties().build());
}
public UserInfoFetcher(HttpClient httpClient) {
cache = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new UserInfoLoader(httpClient));
}
public UserInfo loadUserInfo(final PendingOIDCAuthenticationToken token) {
try {
return cache.get(token);
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Couldn't load User Info from token: " + e.getMessage());
return null;
}
}
private class UserInfoLoader extends CacheLoader<PendingOIDCAuthenticationToken, UserInfo> {
private HttpComponentsClientHttpRequestFactory factory;
UserInfoLoader(HttpClient httpClient) {
this.factory = new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Override
public UserInfo load(final PendingOIDCAuthenticationToken token) throws URISyntaxException {
ServerConfiguration serverConfiguration = token.getServerConfiguration();
@ -63,13 +106,6 @@ public class UserInfoFetcher {
return null;
}
try {
// if we got this far, try to actually get the userinfo
HttpClient httpClient = new SystemDefaultHttpClient();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
String userInfoString = null;
if (serverConfiguration.getUserInfoTokenMethod() == null || serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.HEADER)) {
@ -86,7 +122,7 @@ public class UserInfoFetcher {
userInfoString = restTemplate.getForObject(serverConfiguration.getUserInfoUri(), String.class);
} else if (serverConfiguration.getUserInfoTokenMethod().equals(UserInfoTokenMethod.FORM)) {
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("access_token", token.getAccessTokenValue());
RestTemplate restTemplate = new RestTemplate(factory);
@ -104,18 +140,18 @@ public class UserInfoFetcher {
JsonObject userInfoJson = new JsonParser().parse(userInfoString).getAsJsonObject();
UserInfo userInfo = DefaultUserInfo.fromJson(userInfoJson);
UserInfo userInfo = fromJson(userInfoJson);
return userInfo;
} else {
// didn't get anything, return null
return null;
}
} catch (Exception e) {
logger.warn("Error fetching userinfo", e);
return null;
// didn't get anything throw exception
throw new IllegalArgumentException("Unable to load user info");
}
}
}
protected UserInfo fromJson(JsonObject userInfoJson) {
return DefaultUserInfo.fromJson(userInfoJson);
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,14 +14,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.keypublisher;
import java.util.Map;
import java.util.UUID;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.openid.connect.view.JwkKeyListView;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.openid.connect.view.JWKSetView;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@ -37,13 +38,13 @@ import com.nimbusds.jose.jwk.JWK;
*/
public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
private JwtSigningAndValidationService signingAndValidationService;
private JWTSigningAndValidationService signingAndValidationService;
private String jwkPublishUrl;
private BeanDefinitionRegistry registry;
private String jwkViewName = "jwkKeyList";
private String jwkViewName = JWKSetView.VIEWNAME;
/**
* If the jwkPublishUrl field is set on this bean, set up a listener on that URL to publish keys.
@ -61,13 +62,13 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
clientKeyMapping.addPropertyValue("jwkPublishUrl", getJwkPublishUrl());
// randomize view name to make sure it doesn't conflict with local views
jwkViewName = "jwkKeyList-" + UUID.randomUUID().toString();
jwkViewName = JWKSetView.VIEWNAME + "-" + UUID.randomUUID().toString();
viewResolver.addPropertyValue("jwkViewName", jwkViewName);
// view bean
BeanDefinitionBuilder jwkView = BeanDefinitionBuilder.rootBeanDefinition(JwkKeyListView.class);
registry.registerBeanDefinition("jwkKeyList", jwkView.getBeanDefinition());
viewResolver.addPropertyReference("jwk", "jwkKeyList");
BeanDefinitionBuilder jwkView = BeanDefinitionBuilder.rootBeanDefinition(JWKSetView.class);
registry.registerBeanDefinition(JWKSetView.VIEWNAME, jwkView.getBeanDefinition());
viewResolver.addPropertyReference("jwk", JWKSetView.VIEWNAME);
}
registry.registerBeanDefinition("clientKeyMapping", clientKeyMapping.getBeanDefinition());
@ -114,14 +115,14 @@ public class ClientKeyPublisher implements BeanDefinitionRegistryPostProcessor {
/**
* @return the signingAndValidationService
*/
public JwtSigningAndValidationService getSigningAndValidationService() {
public JWTSigningAndValidationService getSigningAndValidationService() {
return signingAndValidationService;
}
/**
* @param signingAndValidationService the signingAndValidationService to set
*/
public void setSigningAndValidationService(JwtSigningAndValidationService signingAndValidationService) {
public void setSigningAndValidationService(JWTSigningAndValidationService signingAndValidationService) {
this.signingAndValidationService = signingAndValidationService;
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,7 +29,8 @@ import org.mitre.openid.connect.config.ServerConfiguration;
/**
*
* This service provides any extra options that need to be passed to the authentication request.
* This service provides any extra options that need to be passed to the authentication request,
* either through the authorization endpoint (getOptions) or the token endpoint (getTokenOptions).
* These options may depend on the server configuration, client configuration, or HTTP request.
*
* @author jricher
@ -36,6 +38,24 @@ import org.mitre.openid.connect.config.ServerConfiguration;
*/
public interface AuthRequestOptionsService {
/**
* The set of options needed at the authorization endpoint.
*
* @param server
* @param client
* @param request
* @return
*/
public Map<String, String> getOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request);
/**
* The set of options needed at the token endpoint.
*
* @param server
* @param client
* @param request
* @return
*/
public Map<String, String> getTokenOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request);
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -25,6 +26,8 @@ import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
/**
* Builds a URL string to the IdP's authorization endpoint.
*
* @author jricher
*
*/
@ -36,8 +39,9 @@ public interface AuthRequestUrlBuilder {
* @param redirectUri
* @param nonce
* @param state
* @param loginHint
* @return
*/
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options);
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options, String loginHint);
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -24,7 +25,7 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
import org.mitre.openid.connect.client.service.ClientConfigurationService;
@ -39,6 +40,8 @@ import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.CacheBuilder;
@ -55,7 +58,10 @@ import com.google.gson.JsonObject;
*/
public class DynamicRegistrationClientConfigurationService implements ClientConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(DynamicRegistrationClientConfigurationService.class);
private LoadingCache<ServerConfiguration, RegisteredClient> clients;
@ -63,29 +69,30 @@ public class DynamicRegistrationClientConfigurationService implements ClientConf
private RegisteredClient template;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
private Set<String> whitelist = new HashSet<>();
private Set<String> blacklist = new HashSet<>();
public DynamicRegistrationClientConfigurationService() {
clients = CacheBuilder.newBuilder().build(new DynamicClientRegistrationLoader());
this(HttpClientBuilder.create().useSystemProperties().build());
}
public DynamicRegistrationClientConfigurationService(HttpClient httpClient) {
clients = CacheBuilder.newBuilder().build(new DynamicClientRegistrationLoader(httpClient));
}
@Override
public RegisteredClient getClientConfiguration(ServerConfiguration issuer) {
try {
if (!whitelist.isEmpty() && !whitelist.contains(issuer)) {
if (!whitelist.isEmpty() && !whitelist.contains(issuer.getIssuer())) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + issuer);
}
if (blacklist.contains(issuer)) {
if (blacklist.contains(issuer.getIssuer())) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer);
}
return clients.get(issuer);
} catch (UncheckedExecutionException ue) {
logger.warn("Unable to get client configuration", ue);
return null;
} catch (ExecutionException e) {
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Unable to get client configuration", e);
return null;
}
@ -166,10 +173,17 @@ public class DynamicRegistrationClientConfigurationService implements ClientConf
*
*/
public class DynamicClientRegistrationLoader extends CacheLoader<ServerConfiguration, RegisteredClient> {
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private HttpComponentsClientHttpRequestFactory httpFactory;
private Gson gson = new Gson(); // note that this doesn't serialize nulls by default
public DynamicClientRegistrationLoader() {
this(HttpClientBuilder.create().useSystemProperties().build());
}
public DynamicClientRegistrationLoader(HttpClient httpClient) {
this.httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Override
public RegisteredClient load(ServerConfiguration serverConfig) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
@ -186,10 +200,10 @@ public class DynamicRegistrationClientConfigurationService implements ClientConf
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(serializedClient, headers);
HttpEntity<String> entity = new HttpEntity<>(serializedClient, headers);
try {
String registered = restTemplate.postForObject(serverConfig.getRegistrationEndpointUri(), entity, String.class);
// TODO: handle HTTP errors
RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered);
@ -197,6 +211,9 @@ public class DynamicRegistrationClientConfigurationService implements ClientConf
registeredClientService.save(serverConfig.getIssuer(), client);
return client;
} catch (RestClientException rce) {
throw new InvalidClientException("Error registering client with server");
}
} else {
if (knownClient.getClientId() == null) {
@ -206,14 +223,18 @@ public class DynamicRegistrationClientConfigurationService implements ClientConf
headers.set("Authorization", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, knownClient.getRegistrationAccessToken()));
headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>(headers);
HttpEntity<String> entity = new HttpEntity<>(headers);
try {
String registered = restTemplate.exchange(knownClient.getRegistrationClientUri(), HttpMethod.GET, entity, String.class).getBody();
// TODO: handle HTTP errors
RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(registered);
return client;
} catch (RestClientException rce) {
throw new InvalidClientException("Error loading previously registered client information from server");
}
} else {
// it's got a client ID from the store, don't bother trying to load it
return knownClient;

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,25 +14,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
package org.mitre.openid.connect.client.service.impl;
import static org.mitre.discovery.util.JsonUtils.getAsBoolean;
import static org.mitre.discovery.util.JsonUtils.getAsEncryptionMethodList;
import static org.mitre.discovery.util.JsonUtils.getAsJweAlgorithmList;
import static org.mitre.discovery.util.JsonUtils.getAsJwsAlgorithmList;
import static org.mitre.discovery.util.JsonUtils.getAsString;
import static org.mitre.discovery.util.JsonUtils.getAsStringList;
import static org.mitre.util.JsonUtils.getAsBoolean;
import static org.mitre.util.JsonUtils.getAsEncryptionMethodList;
import static org.mitre.util.JsonUtils.getAsJweAlgorithmList;
import static org.mitre.util.JsonUtils.getAsJwsAlgorithmList;
import static org.mitre.util.JsonUtils.getAsString;
import static org.mitre.util.JsonUtils.getAsStringList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.openid.connect.client.service.ServerConfigurationService;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.slf4j.Logger;
@ -57,17 +58,24 @@ import com.google.gson.JsonParser;
*/
public class DynamicServerConfigurationService implements ServerConfigurationService {
private static Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(DynamicServerConfigurationService.class);
// map of issuer -> server configuration, loaded dynamically from service discovery
private LoadingCache<String, ServerConfiguration> servers;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
private Set<String> whitelist = new HashSet<>();
private Set<String> blacklist = new HashSet<>();
public DynamicServerConfigurationService() {
this(HttpClientBuilder.create().useSystemProperties().build());
}
public DynamicServerConfigurationService(HttpClient httpClient) {
// initialize the cache
servers = CacheBuilder.newBuilder().build(new OpenIDConnectServiceConfigurationFetcher());
servers = CacheBuilder.newBuilder().build(new OpenIDConnectServiceConfigurationFetcher(httpClient));
}
/**
@ -111,11 +119,8 @@ public class DynamicServerConfigurationService implements ServerConfigurationSer
}
return servers.get(issuer);
} catch (UncheckedExecutionException ue) {
logger.warn("Couldn't load configuration for " + issuer, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Couldn't load configuration for " + issuer, e);
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Couldn't load configuration for " + issuer + ": " + e);
return null;
}
@ -126,10 +131,13 @@ public class DynamicServerConfigurationService implements ServerConfigurationSer
*
*/
private class OpenIDConnectServiceConfigurationFetcher extends CacheLoader<String, ServerConfiguration> {
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private HttpComponentsClientHttpRequestFactory httpFactory;
private JsonParser parser = new JsonParser();
OpenIDConnectServiceConfigurationFetcher(HttpClient httpClient) {
this.httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Override
public ServerConfiguration load(String issuer) throws Exception {
RestTemplate restTemplate = new RestTemplate(httpFactory);
@ -154,7 +162,7 @@ public class DynamicServerConfigurationService implements ServerConfigurationSer
}
if (!issuer.equals(o.get("issuer").getAsString())) {
throw new IllegalStateException("Discovered issuers didn't match, expected " + issuer + " got " + o.get("issuer").getAsString());
logger.info("Issuer used for discover was " + issuer + " but final issuer is " + o.get("issuer").getAsString());
}
conf.setIssuer(o.get("issuer").getAsString());

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,7 +25,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
@ -32,6 +33,7 @@ import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWEHeader;
@ -54,33 +56,38 @@ public class EncryptedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequestUrl(org.mitre.openid.connect.config.ServerConfiguration, org.mitre.oauth2.model.RegisteredClient, java.lang.String, java.lang.String, java.lang.String, java.util.Map)
*/
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options) {
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options, String loginHint) {
// create our signed JWT for the request object
JWTClaimsSet claims = new JWTClaimsSet();
JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder();
//set parameters to JwtClaims
claims.setClaim("response_type", "code");
claims.setClaim("client_id", clientConfig.getClientId());
claims.setClaim("scope", Joiner.on(" ").join(clientConfig.getScope()));
claims.claim("response_type", "code");
claims.claim("client_id", clientConfig.getClientId());
claims.claim("scope", Joiner.on(" ").join(clientConfig.getScope()));
// build our redirect URI
claims.setClaim("redirect_uri", redirectUri);
claims.claim("redirect_uri", redirectUri);
// this comes back in the id token
claims.setClaim("nonce", nonce);
claims.claim("nonce", nonce);
// this comes back in the auth request return
claims.setClaim("state", state);
claims.claim("state", state);
// Optional parameters
for (Entry<String, String> option : options.entrySet()) {
claims.setClaim(option.getKey(), option.getValue());
claims.claim(option.getKey(), option.getValue());
}
EncryptedJWT jwt = new EncryptedJWT(new JWEHeader(alg, enc), claims);
// if there's a login hint, send it
if (!Strings.isNullOrEmpty(loginHint)) {
claims.claim("login_hint", loginHint);
}
JwtEncryptionAndDecryptionService encryptor = encrypterService.getEncrypter(serverConfig.getJwksUri());
EncryptedJWT jwt = new EncryptedJWT(new JWEHeader(alg, enc), claims.build());
JWTEncryptionAndDecryptionService encryptor = encrypterService.getEncrypter(serverConfig.getJwksUri());
encryptor.encryptJwt(jwt);

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +37,38 @@ import com.google.common.collect.Sets;
*/
public class HybridIssuerService implements IssuerService {
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.ThirdPartyIssuerService#getAccountChooserUrl()
*/
public String getAccountChooserUrl() {
return thirdPartyIssuerService.getAccountChooserUrl();
}
/**
* @param accountChooserUrl
* @see org.mitre.openid.connect.client.service.impl.ThirdPartyIssuerService#setAccountChooserUrl(java.lang.String)
*/
public void setAccountChooserUrl(String accountChooserUrl) {
thirdPartyIssuerService.setAccountChooserUrl(accountChooserUrl);
}
/**
* @return
* @see org.mitre.openid.connect.client.service.impl.WebfingerIssuerService#isForceHttps()
*/
public boolean isForceHttps() {
return webfingerIssuerService.isForceHttps();
}
/**
* @param forceHttps
* @see org.mitre.openid.connect.client.service.impl.WebfingerIssuerService#setForceHttps(boolean)
*/
public void setForceHttps(boolean forceHttps) {
webfingerIssuerService.setForceHttps(forceHttps);
}
private ThirdPartyIssuerService thirdPartyIssuerService = new ThirdPartyIssuerService();
private WebfingerIssuerService webfingerIssuerService = new WebfingerIssuerService();

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -31,7 +32,7 @@ import org.mitre.openid.connect.client.service.RegisteredClientService;
*/
public class InMemoryRegisteredClientService implements RegisteredClientService {
private Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
private Map<String, RegisteredClient> clients = new HashMap<>();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.RegisteredClientService#getByIssuer(java.lang.String)

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,14 +14,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
package org.mitre.openid.connect.client.service.impl;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
@ -50,7 +50,10 @@ import com.google.gson.JsonSerializer;
*/
public class JsonFileRegisteredClientService implements RegisteredClientService {
private static Logger logger = LoggerFactory.getLogger(JsonFileRegisteredClientService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(JsonFileRegisteredClientService.class);
private Gson gson = new GsonBuilder()
.registerTypeAdapter(RegisteredClient.class, new JsonSerializer<RegisteredClient>() {
@ -70,7 +73,7 @@ public class JsonFileRegisteredClientService implements RegisteredClientService
private File file;
private Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
private Map<String, RegisteredClient> clients = new HashMap<>();
public JsonFileRegisteredClientService(String filename) {
this.file = new File(filename);
@ -97,6 +100,7 @@ public class JsonFileRegisteredClientService implements RegisteredClientService
/**
* Sync the map of clients out to disk.
*/
@SuppressWarnings("serial")
private void write() {
try {
if (!file.exists()) {
@ -110,8 +114,6 @@ public class JsonFileRegisteredClientService implements RegisteredClientService
out.close();
} catch (FileNotFoundException e) {
logger.error("Could not write to output file", e);
} catch (IOException e) {
logger.error("Could not write to output file", e);
}
@ -120,6 +122,7 @@ public class JsonFileRegisteredClientService implements RegisteredClientService
/**
* Load the map in from disk.
*/
@SuppressWarnings("serial")
private void load() {
try {
if (!file.exists()) {
@ -132,8 +135,6 @@ public class JsonFileRegisteredClientService implements RegisteredClientService
in.close();
} catch (FileNotFoundException e) {
logger.error("Could not read from input file", e);
} catch (IOException e) {
logger.error("Could not read from input file", e);
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -30,6 +31,7 @@ import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
/**
*
@ -44,7 +46,7 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequest(javax.servlet.http.HttpServletRequest, org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails)
*/
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options) {
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options, String loginHint) {
try {
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
@ -63,6 +65,11 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
uriBuilder.addParameter(option.getKey(), option.getValue());
}
// if there's a login hint, send it
if (!Strings.isNullOrEmpty(loginHint)) {
uriBuilder.addParameter("login_hint", loginHint);
}
return uriBuilder.build().toString();
} catch (URISyntaxException e) {

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -24,13 +25,15 @@ import java.util.Map;
import java.util.Map.Entry;
import org.apache.http.client.utils.URIBuilder;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.springframework.security.authentication.AuthenticationServiceException;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
@ -41,41 +44,49 @@ import com.nimbusds.jwt.SignedJWT;
*/
public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
private JwtSigningAndValidationService signingAndValidationService;
private JWTSigningAndValidationService signingAndValidationService;
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequestUrl(org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options) {
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options, String loginHint) {
// create our signed JWT for the request object
JWTClaimsSet claims = new JWTClaimsSet();
JWTClaimsSet.Builder claims = new JWTClaimsSet.Builder();
//set parameters to JwtClaims
claims.setClaim("response_type", "code");
claims.setClaim("client_id", clientConfig.getClientId());
claims.setClaim("scope", Joiner.on(" ").join(clientConfig.getScope()));
claims.claim("response_type", "code");
claims.claim("client_id", clientConfig.getClientId());
claims.claim("scope", Joiner.on(" ").join(clientConfig.getScope()));
// build our redirect URI
claims.setClaim("redirect_uri", redirectUri);
claims.claim("redirect_uri", redirectUri);
// this comes back in the id token
claims.setClaim("nonce", nonce);
claims.claim("nonce", nonce);
// this comes back in the auth request return
claims.setClaim("state", state);
claims.claim("state", state);
// Optional parameters
for (Entry<String, String> option : options.entrySet()) {
claims.setClaim(option.getKey(), option.getValue());
claims.claim(option.getKey(), option.getValue());
}
// if there's a login hint, send it
if (!Strings.isNullOrEmpty(loginHint)) {
claims.claim("login_hint", loginHint);
}
JWSAlgorithm alg = clientConfig.getRequestObjectSigningAlg();
if (alg == null) {
alg = signingAndValidationService.getDefaultSigningAlgorithm();
}
SignedJWT jwt = new SignedJWT(new JWSHeader(signingAndValidationService.getDefaultSigningAlgorithm()), claims);
SignedJWT jwt = new SignedJWT(new JWSHeader(alg), claims.build());
signingAndValidationService.signJwt(jwt);
signingAndValidationService.signJwt(jwt, alg);
try {
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
@ -91,14 +102,14 @@ public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
/**
* @return the signingAndValidationService
*/
public JwtSigningAndValidationService getSigningAndValidationService() {
public JWTSigningAndValidationService getSigningAndValidationService() {
return signingAndValidationService;
}
/**
* @param signingAndValidationService the signingAndValidationService to set
*/
public void setSigningAndValidationService(JwtSigningAndValidationService signingAndValidationService) {
public void setSigningAndValidationService(JWTSigningAndValidationService signingAndValidationService) {
this.signingAndValidationService = signingAndValidationService;
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -37,7 +38,8 @@ import org.mitre.openid.connect.config.ServerConfiguration;
*/
public class StaticAuthRequestOptionsService implements AuthRequestOptionsService {
private Map<String, String> options = new HashMap<String, String>();
private Map<String, String> options = new HashMap<>();
private Map<String, String> tokenOptions = new HashMap<>();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.AuthRequestOptionsService#getOptions(org.mitre.openid.connect.config.ServerConfiguration, org.mitre.oauth2.model.RegisteredClient, javax.servlet.http.HttpServletRequest)
@ -47,8 +49,16 @@ public class StaticAuthRequestOptionsService implements AuthRequestOptionsServic
return options;
}
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.AuthRequestOptionsService#getTokenOptions(org.mitre.openid.connect.config.ServerConfiguration, org.mitre.oauth2.model.RegisteredClient, javax.servlet.http.HttpServletRequest)
*/
@Override
public Map<String, String> getTokenOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request) {
return tokenOptions;
}
/**
* @return the options
* @return the options object directly
*/
public Map<String, String> getOptions() {
return options;
@ -61,6 +71,18 @@ public class StaticAuthRequestOptionsService implements AuthRequestOptionsServic
this.options = options;
}
/**
* @return the tokenOptions
*/
public Map<String, String> getTokenOptions() {
return tokenOptions;
}
/**
* @param tokenOptions the tokenOptions to set
*/
public void setTokenOptions(Map<String, String> tokenOptions) {
this.tokenOptions = tokenOptions;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -66,7 +67,7 @@ public class StaticClientConfigurationService implements ClientConfigurationServ
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
if (clients == null || clients.isEmpty()) {
throw new IllegalArgumentException("Clients map cannot be null or empty");
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -60,7 +61,7 @@ public class StaticServerConfigurationService implements ServerConfigurationServ
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
if (servers == null || servers.isEmpty()) {
throw new IllegalArgumentException("Servers map cannot be null or empty.");
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -60,7 +61,7 @@ public class StaticSingleIssuerService implements IssuerService {
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
if (Strings.isNullOrEmpty(issuer)) {
throw new IllegalArgumentException("Issuer must not be null or empty.");

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -44,8 +45,8 @@ public class ThirdPartyIssuerService implements IssuerService {
private String accountChooserUrl;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
private Set<String> whitelist = new HashSet<>();
private Set<String> blacklist = new HashSet<>();
/* (non-Javadoc)
* @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest)
@ -127,11 +128,8 @@ public class ThirdPartyIssuerService implements IssuerService {
this.blacklist = blacklist;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@PostConstruct
public void afterPropertiesSet() throws Exception {
public void afterPropertiesSet() {
if (Strings.isNullOrEmpty(this.accountChooserUrl)) {
throw new IllegalArgumentException("Account Chooser URL cannot be null or empty");
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -27,7 +28,7 @@ import javax.servlet.http.HttpServletRequest;
import org.apache.http.client.HttpClient;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.discovery.util.WebfingerURLNormalizer;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.IssuerService;
@ -35,6 +36,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
@ -46,6 +48,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
/**
@ -55,13 +58,26 @@ import com.google.gson.JsonParser;
*/
public class WebfingerIssuerService implements IssuerService {
private static Logger logger = LoggerFactory.getLogger(WebfingerIssuerService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(WebfingerIssuerService.class);
// map of user input -> issuer, loaded dynamically from webfinger discover
private LoadingCache<UriComponents, String> issuers;
private LoadingCache<String, LoadingResult> issuers;
private Set<String> whitelist = new HashSet<String>();
private Set<String> blacklist = new HashSet<String>();
// private data shuttle class to get back two bits of info from the cache loader
private class LoadingResult {
public String loginHint;
public String issuer;
public LoadingResult(String loginHint, String issuer) {
this.loginHint = loginHint;
this.issuer = issuer;
}
}
private Set<String> whitelist = new HashSet<>();
private Set<String> blacklist = new HashSet<>();
/**
* Name of the incoming parameter to check for discovery purposes.
@ -73,8 +89,17 @@ public class WebfingerIssuerService implements IssuerService {
*/
private String loginPageUrl;
/**
* Strict enfocement of "https"
*/
private boolean forceHttps = true;
public WebfingerIssuerService() {
issuers = CacheBuilder.newBuilder().build(new WebfingerIssuerFetcher());
this(HttpClientBuilder.create().useSystemProperties().build());
}
public WebfingerIssuerService(HttpClient httpClient) {
issuers = CacheBuilder.newBuilder().build(new WebfingerIssuerFetcher(httpClient));
}
/* (non-Javadoc)
@ -86,21 +111,18 @@ public class WebfingerIssuerService implements IssuerService {
String identifier = request.getParameter(parameterName);
if (!Strings.isNullOrEmpty(identifier)) {
try {
String issuer = issuers.get(WebfingerURLNormalizer.normalizeResource(identifier));
if (!whitelist.isEmpty() && !whitelist.contains(issuer)) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + issuer);
LoadingResult lr = issuers.get(identifier);
if (!whitelist.isEmpty() && !whitelist.contains(lr.issuer)) {
throw new AuthenticationServiceException("Whitelist was nonempty, issuer was not in whitelist: " + lr.issuer);
}
if (blacklist.contains(issuer)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + issuer);
if (blacklist.contains(lr.issuer)) {
throw new AuthenticationServiceException("Issuer was in blacklist: " + lr.issuer);
}
return new IssuerServiceResponse(issuer, null, null);
} catch (UncheckedExecutionException ue) {
logger.warn("Issue fetching issuer for user input: " + identifier, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Issue fetching issuer for user input: " + identifier, e);
return new IssuerServiceResponse(lr.issuer, lr.loginHint, request.getParameter("target_link_uri"));
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Issue fetching issuer for user input: " + identifier + ": " + e.getMessage());
return null;
}
@ -167,27 +189,52 @@ public class WebfingerIssuerService implements IssuerService {
this.blacklist = blacklist;
}
/**
* @return the forceHttps
*/
public boolean isForceHttps() {
return forceHttps;
}
/**
* @param forceHttps the forceHttps to set
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
}
/**
* @author jricher
*
*/
private class WebfingerIssuerFetcher extends CacheLoader<UriComponents, String> {
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private class WebfingerIssuerFetcher extends CacheLoader<String, LoadingResult> {
private HttpComponentsClientHttpRequestFactory httpFactory;
private JsonParser parser = new JsonParser();
WebfingerIssuerFetcher(HttpClient httpClient) {
this.httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Override
public String load(UriComponents key) throws Exception {
public LoadingResult load(String identifier) throws Exception {
UriComponents key = WebfingerURLNormalizer.normalizeResource(identifier);
RestTemplate restTemplate = new RestTemplate(httpFactory);
// construct the URL to go to
// preserving http scheme is strictly for demo system use only.
String scheme = key.getScheme();
// preserving http scheme is strictly for demo system use only.
if (!Strings.isNullOrEmpty(scheme) &&scheme.equals("http")) {
scheme = "http://"; // add on colon and slashes.
logger.warn("Webfinger endpoint MUST use the https URI scheme.");
if (forceHttps) {
throw new IllegalArgumentException("Scheme must not be 'http'");
} else {
logger.warn("Webfinger endpoint MUST use the https URI scheme, overriding by configuration");
scheme = "http://"; // add on colon and slashes.
}
} else {
// otherwise we don't know the scheme, assume HTTPS
scheme = "https://";
}
@ -199,19 +246,17 @@ public class WebfingerIssuerService implements IssuerService {
+ "/.well-known/webfinger"
+ (Strings.isNullOrEmpty(key.getQuery()) ? "" : "?" + key.getQuery())
);
builder.addParameter("resource", key.toString());
builder.addParameter("resource", identifier);
builder.addParameter("rel", "http://openid.net/specs/connect/1.0/issuer");
try {
// do the fetch
logger.info("Loading: " + builder.toString());
String webfingerResponse = restTemplate.getForObject(builder.build(), String.class);
// TODO: catch and handle HTTP errors
JsonElement json = parser.parse(webfingerResponse);
// TODO: catch and handle JSON errors
if (json != null && json.isJsonObject()) {
// find the issuer
JsonArray links = json.getAsJsonObject().get("links").getAsJsonArray();
@ -223,22 +268,34 @@ public class WebfingerIssuerService implements IssuerService {
&& linkObj.get("rel").getAsString().equals("http://openid.net/specs/connect/1.0/issuer")) {
// we found the issuer, return it
return linkObj.get("href").getAsString();
String href = linkObj.get("href").getAsString();
if (identifier.equals(href)
|| identifier.startsWith("http")) {
// try to avoid sending a URL as the login hint
return new LoadingResult(null, href);
} else {
// otherwise pass back whatever the user typed as a login hint
return new LoadingResult(identifier, href);
}
}
}
}
}
} catch (JsonParseException | RestClientException e) {
logger.warn("Failure in fetching webfinger input", e.getMessage());
}
// we couldn't find it
// we couldn't find it!
if (key.getScheme().equals("http") || key.getScheme().equals("https")) {
// if it looks like HTTP then punt and return the input
logger.warn("Returning normalized input string as issuer, hoping for the best: " + key.toString());
return key.toString();
// if it looks like HTTP then punt: return the input, hope for the best
logger.warn("Returning normalized input string as issuer, hoping for the best: " + identifier);
return new LoadingResult(null, identifier);
} else {
// if it's not HTTP, give up
logger.warn("Couldn't find issuer: " + key.toString());
return null;
logger.warn("Couldn't find issuer: " + identifier);
throw new IllegalArgumentException();
}
}

View File

@ -0,0 +1,106 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.introspectingfilter;
import java.util.Collections;
import java.util.Date;
import java.util.Set;
import org.junit.Test;
import com.google.common.collect.ImmutableSet;
import com.google.gson.JsonObject;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class TestOAuth2AccessTokenImpl {
private static String tokenString = "thisisatokenstring";
private static Set<String> scopes = ImmutableSet.of("bar", "foo");
private static String scopeString = "foo bar";
private static Date exp = new Date(123 * 1000L);
private static Long expVal = 123L;
@Test
public void testFullToken() {
JsonObject tokenObj = new JsonObject();
tokenObj.addProperty("active", true);
tokenObj.addProperty("scope", scopeString);
tokenObj.addProperty("exp", expVal);
tokenObj.addProperty("sub", "subject");
tokenObj.addProperty("client_id", "123-456-789");
OAuth2AccessTokenImpl tok = new OAuth2AccessTokenImpl(tokenObj, tokenString);
assertThat(tok.getScope(), is(equalTo(scopes)));
assertThat(tok.getExpiration(), is(equalTo(exp)));
}
@Test
public void testNullExp() {
JsonObject tokenObj = new JsonObject();
tokenObj.addProperty("active", true);
tokenObj.addProperty("scope", scopeString);
tokenObj.addProperty("sub", "subject");
tokenObj.addProperty("client_id", "123-456-789");
OAuth2AccessTokenImpl tok = new OAuth2AccessTokenImpl(tokenObj, tokenString);
assertThat(tok.getScope(), is(equalTo(scopes)));
assertThat(tok.getExpiration(), is(equalTo(null)));
}
@Test
public void testNullScopes() {
JsonObject tokenObj = new JsonObject();
tokenObj.addProperty("active", true);
tokenObj.addProperty("exp", expVal);
tokenObj.addProperty("sub", "subject");
tokenObj.addProperty("client_id", "123-456-789");
OAuth2AccessTokenImpl tok = new OAuth2AccessTokenImpl(tokenObj, tokenString);
assertThat(tok.getScope(), is(equalTo(Collections.EMPTY_SET)));
assertThat(tok.getExpiration(), is(equalTo(exp)));
}
@Test
public void testNullScopesNullExp() {
JsonObject tokenObj = new JsonObject();
tokenObj.addProperty("active", true);
tokenObj.addProperty("sub", "subject");
tokenObj.addProperty("client_id", "123-456-789");
OAuth2AccessTokenImpl tok = new OAuth2AccessTokenImpl(tokenObj, tokenString);
assertThat(tok.getScope(), is(equalTo(Collections.EMPTY_SET)));
assertThat(tok.getExpiration(), is(equalTo(null)));
}
}

View File

@ -0,0 +1,84 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.introspectingfilter.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import com.google.gson.JsonObject;
import static org.junit.Assert.assertTrue;
/**
* @author jricher
*
*/
public class TestScopeBasedIntrospectionAuthoritiesGranter {
private JsonObject introspectionResponse;
private ScopeBasedIntrospectionAuthoritiesGranter granter = new ScopeBasedIntrospectionAuthoritiesGranter();
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
introspectionResponse = new JsonObject();
}
/**
* Test method for {@link org.mitre.oauth2.introspectingfilter.service.impl.ScopeBasedIntrospectionAuthoritiesGranter#getAuthorities(com.google.gson.JsonObject)}.
*/
@Test
public void testGetAuthoritiesJsonObject_withScopes() {
introspectionResponse.addProperty("scope", "foo bar baz batman");
List<GrantedAuthority> expected = new ArrayList<>();
expected.add(new SimpleGrantedAuthority("ROLE_API"));
expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_foo"));
expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_bar"));
expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_baz"));
expected.add(new SimpleGrantedAuthority("OAUTH_SCOPE_batman"));
List<GrantedAuthority> authorities = granter.getAuthorities(introspectionResponse);
assertTrue(authorities.containsAll(expected));
assertTrue(expected.containsAll(authorities));
}
/**
* Test method for {@link org.mitre.oauth2.introspectingfilter.service.impl.ScopeBasedIntrospectionAuthoritiesGranter#getAuthorities(com.google.gson.JsonObject)}.
*/
@Test
public void testGetAuthoritiesJsonObject_withoutScopes() {
List<GrantedAuthority> expected = new ArrayList<>();
expected.add(new SimpleGrantedAuthority("ROLE_API"));
List<GrantedAuthority> authorities = granter.getAuthorities(introspectionResponse);
assertTrue(authorities.containsAll(expected));
assertTrue(expected.containsAll(authorities));
}
}

View File

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.openid.connect.client;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.security.authentication.AuthenticationServiceException;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.Mockito.mock;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class TestOIDCAuthenticationFilter {
private OIDCAuthenticationFilter filter = new OIDCAuthenticationFilter();
@Test
public void attemptAuthentication_error() throws Exception {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(request.getParameter("error")).thenReturn("Error");
Mockito.when(request.getParameter("error_description")).thenReturn("Description");
Mockito.when(request.getParameter("error_uri")).thenReturn("http://example.com");
try {
filter.attemptAuthentication(request, mock(HttpServletResponse.class));
fail("AuthorizationEndpointException expected.");
}
catch (AuthorizationEndpointException exception) {
assertThat(exception.getMessage(),
is("Error from Authorization Endpoint: Error Description http://example.com"));
assertThat(exception.getError(), is("Error"));
assertThat(exception.getErrorDescription(), is("Description"));
assertThat(exception.getErrorURI(), is("http://example.com"));
assertThat(exception, is(instanceOf(AuthenticationServiceException.class)));
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,14 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -32,6 +28,12 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,15 +14,10 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -32,6 +28,12 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,12 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import java.util.Map;
import org.junit.Before;
@ -31,6 +29,10 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
@ -68,7 +70,27 @@ public class TestPlainAuthRequestUrlBuilder {
Map<String, String> options = ImmutableMap.of("foo", "bar");
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj", options);
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj", options, null);
assertThat(actualUrl, equalTo(expectedUrl));
}
@Test
public void buildAuthRequestUrl_withLoginHint() {
String expectedUrl = "https://server.example.com/authorize?" +
"response_type=code" +
"&client_id=s6BhdRkqt3" +
"&scope=openid+profile" + // plus sign used for space per application/x-www-form-encoded standard
"&redirect_uri=https%3A%2F%2Fclient.example.org%2F" +
"&nonce=34fasf3ds" +
"&state=af0ifjsldkj" +
"&foo=bar" +
"&login_hint=bob";
Map<String, String> options = ImmutableMap.of("foo", "bar");
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj", options, "bob");
assertThat(actualUrl, equalTo(expectedUrl));
}
@ -80,7 +102,7 @@ public class TestPlainAuthRequestUrlBuilder {
Map<String, String> options = ImmutableMap.of("foo", "bar");
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options);
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options, null);
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,13 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
@ -31,7 +28,7 @@ import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.DefaultJWTSigningAndValidationService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mockito;
@ -44,12 +41,16 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author wkim
*
@ -82,19 +83,20 @@ public class TestSignedAuthRequestUrlBuilder {
"9Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFzme1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q";
private String alg = "RS256";
private String kid = "2011-04-29";
private String loginHint = "bob";
private DefaultJwtSigningAndValidationService signingAndValidationService;
private DefaultJWTSigningAndValidationService signingAndValidationService;
private SignedAuthRequestUrlBuilder urlBuilder = new SignedAuthRequestUrlBuilder();
@Before
public void prepare() throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAKey key = new RSAKey(new Base64URL(n), new Base64URL(e), new Base64URL(d), KeyUse.SIGNATURE, null, new Algorithm(alg), kid, null, null, null);
RSAKey key = new RSAKey(new Base64URL(n), new Base64URL(e), new Base64URL(d), KeyUse.SIGNATURE, null, new Algorithm(alg), kid, null, null, null, null, null);
Map<String, JWK> keys = Maps.newHashMap();
keys.put("client", key);
signingAndValidationService = new DefaultJwtSigningAndValidationService(keys);
signingAndValidationService = new DefaultJWTSigningAndValidationService(keys);
signingAndValidationService.setDefaultSignerKeyId("client");
signingAndValidationService.setDefaultSigningAlgorithmName(alg);
@ -116,7 +118,7 @@ public class TestSignedAuthRequestUrlBuilder {
@Test
public void buildAuthRequestUrl() {
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options);
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options, null);
// parsing the result
UriComponentsBuilder builder = null;
@ -129,7 +131,7 @@ public class TestSignedAuthRequestUrlBuilder {
UriComponents components = builder.build();
String jwtString = components.getQueryParams().get("request").get(0);
ReadOnlyJWTClaimsSet claims = null;
JWTClaimsSet claims = null;
try {
SignedJWT jwt = SignedJWT.parse(jwtString);
@ -152,11 +154,51 @@ public class TestSignedAuthRequestUrlBuilder {
}
}
@Test
public void buildAuthRequestUrl_withLoginHint() {
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options, loginHint);
// parsing the result
UriComponentsBuilder builder = null;
try {
builder = UriComponentsBuilder.fromUri(new URI(requestUri));
} catch (URISyntaxException e1) {
fail("URISyntaxException was thrown.");
}
UriComponents components = builder.build();
String jwtString = components.getQueryParams().get("request").get(0);
JWTClaimsSet claims = null;
try {
SignedJWT jwt = SignedJWT.parse(jwtString);
claims = jwt.getJWTClaimsSet();
} catch (ParseException e) {
fail("ParseException was thrown.");
}
assertEquals(responseType, claims.getClaim("response_type"));
assertEquals(clientConfig.getClientId(), claims.getClaim("client_id"));
List<String> scopeList = Arrays.asList(((String) claims.getClaim("scope")).split(" "));
assertTrue(scopeList.containsAll(clientConfig.getScope()));
assertEquals(redirectUri, claims.getClaim("redirect_uri"));
assertEquals(nonce, claims.getClaim("nonce"));
assertEquals(state, claims.getClaim("state"));
for (String claim : options.keySet()) {
assertEquals(options.get(claim), claims.getClaim(claim));
}
assertEquals(loginHint, claims.getClaim("login_hint"));
}
@Test(expected = AuthenticationServiceException.class)
public void buildAuthRequestUrl_badUri() {
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("e=mc^2");
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options);
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options, null);
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,15 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.HashMap;
import java.util.Map;
@ -34,6 +29,13 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
@ -56,7 +58,7 @@ public class TestStaticClientConfigurationService {
service = new StaticClientConfigurationService();
Map<String, RegisteredClient> clients = new HashMap<String, RegisteredClient>();
Map<String, RegisteredClient> clients = new HashMap<>();
clients.put(issuer, mockClient);
service.setClients(clients);

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,15 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.util.HashMap;
import java.util.Map;
@ -32,6 +27,13 @@ import org.mitre.openid.connect.config.ServerConfiguration;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*
@ -52,7 +54,7 @@ public class TestStaticServerConfigurationService {
service = new StaticServerConfigurationService();
Map<String, ServerConfiguration> servers = new HashMap<String, ServerConfiguration>();
Map<String, ServerConfiguration> servers = new HashMap<>();
servers.put(issuer, mockServerConfig);
service.setServers(servers);

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,13 +14,9 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.openid.connect.client.service.impl;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
@ -30,6 +27,11 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
import com.google.common.collect.Sets;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
/**
* @author wkim
*

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2014 The MITRE Corporation
and the MIT Kerberos and Internet Trust Consortium
Copyright 2018 The MIT Internet Trust Consortium
Portions copyright 2011-2013 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2014 The MITRE Corporation
and the MIT Kerberos and Internet Trust Consortium
Copyright 2018 The MIT Internet Trust Consortium
Portions copyright 2011-2013 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -20,7 +22,7 @@
<parent>
<artifactId>openid-connect-parent</artifactId>
<groupId>org.mitre</groupId>
<version>1.1.9</version>
<version>1.3.5-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>openid-connect-common</artifactId>
@ -30,65 +32,85 @@
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>*</artifactId>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>16.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<version>2.0.0.M2</version>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>2.26.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.0</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<!-- /Logging -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
</dependencies>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>

View File

@ -0,0 +1,206 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.data;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Abstract class for performing an operation on a potentially large
* number of items by paging through the items in discreet chunks.
*
* @param <T> the type parameter
* @author Colm Smyth.
*/
public abstract class AbstractPageOperationTemplate<T> {
private static final Logger logger = LoggerFactory.getLogger(AbstractPageOperationTemplate.class);
private static int DEFAULT_MAX_PAGES = 1000;
private static long DEFAULT_MAX_TIME_MILLIS = 600000L; //10 Minutes
/**
* int specifying the maximum number of
* pages which should be fetched before
* execution should terminate
*/
private int maxPages;
/**
* long specifying the maximum execution time
* in milliseconds
*/
private long maxTime;
/**
* boolean specifying whether or not Exceptions
* incurred performing the operation should be
* swallowed during execution default true.
*/
private boolean swallowExceptions = true;
/**
* String that is used for logging in final tallies.
*/
private String operationName = "";
/**
* default constructor which sets the value of
* maxPages and maxTime to DEFAULT_MAX_PAGES and
* DEFAULT_MAX_TIME_MILLIS respectively
*/
public AbstractPageOperationTemplate(String operationName){
this(DEFAULT_MAX_PAGES, DEFAULT_MAX_TIME_MILLIS, operationName);
}
/**
* Instantiates a new AbstractPageOperationTemplate with the
* given maxPages and maxTime
*
* @param maxPages the maximum number of pages to fetch.
* @param maxTime the maximum execution time.
*/
public AbstractPageOperationTemplate(int maxPages, long maxTime, String operationName){
this.maxPages = maxPages;
this.maxTime = maxTime;
this.operationName = operationName;
}
/**
* Execute the operation on each member of a page of results
* retrieved through the fetch method. the method will execute
* until either the maxPages or maxTime limit is reached or until
* the fetch method returns no more results. Exceptions thrown
* performing the operation on the item will be swallowed if the
* swallowException (default true) field is set true.
*/
public void execute(){
logger.debug("[" + getOperationName() + "] Starting execution of paged operation. maximum time: " + maxTime + ", maximum pages: " + maxPages);
long startTime = System.currentTimeMillis();
long executionTime = 0;
int i = 0;
int exceptionsSwallowedCount = 0;
int operationsCompleted = 0;
Set<String> exceptionsSwallowedClasses = new HashSet<String>();
while (i< maxPages && executionTime < maxTime){
Collection<T> page = fetchPage();
if(page == null || page.size() == 0){
break;
}
for (T item : page) {
try {
doOperation(item);
operationsCompleted++;
} catch (Exception e){
if(swallowExceptions){
exceptionsSwallowedCount++;
exceptionsSwallowedClasses.add(e.getClass().getName());
logger.debug("Swallowing exception " + e.getMessage(), e);
} else {
logger.debug("Rethrowing exception " + e.getMessage());
throw e;
}
}
}
i++;
executionTime = System.currentTimeMillis() - startTime;
}
finalReport(operationsCompleted, exceptionsSwallowedCount, exceptionsSwallowedClasses);
}
/**
* method responsible for fetching
* a page of items.
*
* @return the collection of items
*/
public abstract Collection<T> fetchPage();
/**
* method responsible for performing desired
* operation on a fetched page item.
*
* @param item the item
*/
protected abstract void doOperation(T item);
/**
* Method responsible for final report of progress.
* @return
*/
protected void finalReport(int operationsCompleted, int exceptionsSwallowedCount, Set<String> exceptionsSwallowedClasses) {
if (operationsCompleted > 0 || exceptionsSwallowedCount > 0) {
logger.info("[" + getOperationName() + "] Paged operation run: completed " + operationsCompleted + "; swallowed " + exceptionsSwallowedCount + " exceptions");
}
for(String className: exceptionsSwallowedClasses) {
logger.warn("[" + getOperationName() + "] Paged operation swallowed at least one exception of type " + className);
}
}
public int getMaxPages() {
return maxPages;
}
public void setMaxPages(int maxPages) {
this.maxPages = maxPages;
}
public long getMaxTime() {
return maxTime;
}
public void setMaxTime(long maxTime) {
this.maxTime = maxTime;
}
public boolean isSwallowExceptions() {
return swallowExceptions;
}
public void setSwallowExceptions(boolean swallowExceptions) {
this.swallowExceptions = swallowExceptions;
}
/**
* @return the operationName
*/
public String getOperationName() {
return operationName;
}
/**
* @param operationName the operationName to set
*/
public void setOperationName(String operationName) {
this.operationName = operationName;
}
}

View File

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.data;
/**
* Default implementation of PageCriteria which specifies
* both page to be retrieved and page size in the constructor.
*
* @author Colm Smyth
*/
public class DefaultPageCriteria implements PageCriteria {
private static final int DEFAULT_PAGE_NUMBER = 0;
private static final int DEFAULT_PAGE_SIZE = 100;
private int pageNumber;
private int pageSize;
public DefaultPageCriteria(){
this(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE);
}
public DefaultPageCriteria(int pageNumber, int pageSize) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
}
@Override
public int getPageNumber() {
return pageNumber;
}
@Override
public int getPageSize() {
return pageSize;
}
}

View File

@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.data;
/**
* Interface which defines page criteria for use in
* a repository operation.
*
* @author Colm Smyth
*/
public interface PageCriteria {
public int getPageNumber();
public int getPageSize();
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.discovery.util;
import java.util.regex.Matcher;
@ -35,7 +36,10 @@ import com.google.common.base.Strings;
*/
public class WebfingerURLNormalizer {
private static Logger logger = LoggerFactory.getLogger(WebfingerURLNormalizer.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(WebfingerURLNormalizer.class);
// pattern used to parse user input; we can't use the built-in java URI parser
private static final Pattern pattern = Pattern.compile("^" +

View File

@ -1,110 +0,0 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.mitre.jose;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
import com.google.common.base.Strings;
import com.nimbusds.jose.JWEAlgorithm;
/**
*
* Wrapper class for Nimbus JOSE objects to fit into JPA
*
* @author jricher
*
*/
@Embeddable
public class JWEAlgorithmEmbed {
public static final JWEAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWEAlgorithm algorithm;
public JWEAlgorithmEmbed() {
}
public JWEAlgorithmEmbed(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
public static JWEAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWEAlgorithmEmbed ent = new JWEAlgorithmEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
@Basic
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls JWEAlgorithm.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = JWEAlgorithm.parse(algorithmName);
} else {
algorithm = null;
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEAlgorithmEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
@Transient
public JWEAlgorithm getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(JWEAlgorithm algorithm) {
this.algorithm = algorithm;
}
}

View File

@ -1,108 +0,0 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.mitre.jose;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
import com.google.common.base.Strings;
import com.nimbusds.jose.EncryptionMethod;
/**
* @author jricher
*
*/
@Embeddable
public class JWEEncryptionMethodEmbed {
public static final JWEEncryptionMethodEmbed NONE = getForAlgorithmName("none");
private EncryptionMethod algorithm;
public JWEEncryptionMethodEmbed() {
}
public JWEEncryptionMethodEmbed(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
public static JWEEncryptionMethodEmbed getForAlgorithmName (String algorithmName) {
JWEEncryptionMethodEmbed ent = new JWEEncryptionMethodEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
@Basic
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls EncryptionMethod.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = EncryptionMethod.parse(algorithmName);
} else {
algorithm = null;
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWEEncryptionMethodEmbed [algorithm=" + algorithm + "]";
}
/**
* @return the algorithm
*/
@Transient
public EncryptionMethod getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(EncryptionMethod algorithm) {
this.algorithm = algorithm;
}
}

View File

@ -1,117 +0,0 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
/**
*
*/
package org.mitre.jose;
import javax.persistence.Basic;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
import com.google.common.base.Strings;
import com.nimbusds.jose.JWSAlgorithm;
/**
*
* Wrapper class for Nimbus JOSE objects to fit into JPA
*
* @author jricher
*
*/
@Embeddable
public class JWSAlgorithmEmbed {
public static final JWSAlgorithmEmbed NONE = getForAlgorithmName("none");
private JWSAlgorithm algorithm;
public JWSAlgorithmEmbed() {
}
public JWSAlgorithmEmbed(JWSAlgorithm algorithm) {
this.algorithm = algorithm;
}
/**
*
* @param algorithmName
* @return null if algorithmName is empty or null
*/
public static JWSAlgorithmEmbed getForAlgorithmName (String algorithmName) {
JWSAlgorithmEmbed ent = new JWSAlgorithmEmbed();
ent.setAlgorithmName(algorithmName);
if (ent.getAlgorithm() == null) {
return null;
} else {
return ent;
}
}
/**
* Get the name of this algorithm, return null if no algorithm set.
* @return
*/
@Basic
public String getAlgorithmName() {
if (algorithm != null) {
return algorithm.getName();
} else {
return null;
}
}
/**
* Set the name of this algorithm.
* Calls JWSAlgorithm.parse()
* @param algorithmName
*/
public void setAlgorithmName(String algorithmName) {
if (!Strings.isNullOrEmpty(algorithmName)) {
algorithm = JWSAlgorithm.parse(algorithmName);
} else {
algorithm = null;
}
}
/**
* @return the algorithm
*/
@Transient
public JWSAlgorithm getAlgorithm() {
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public void setAlgorithm(JWSAlgorithm algorithm) {
this.algorithm = algorithm;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "JWSAlgorithmEmbed [algorithm=" + algorithm + "]";
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/

View File

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.jwt.assertion;
import com.nimbusds.jwt.JWT;
/**
* @author jricher
*
*/
public interface AssertionValidator {
public boolean isValid(JWT assertion);
}

View File

@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.jwt.assertion.impl;
import org.mitre.jwt.assertion.AssertionValidator;
import com.nimbusds.jwt.JWT;
/**
* Reject all assertions passed in.
*
* @author jricher
*
*/
public class NullAssertionValidator implements AssertionValidator {
/**
* Reject all assertions passed in, always returns false.
*/
@Override
public boolean isValid(JWT assertion) {
return false;
}
}

View File

@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.jwt.assertion.impl;
import java.text.ParseException;
import org.mitre.jwt.assertion.AssertionValidator;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.common.base.Strings;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
/**
* Validates all assertions generated by this server
*
* @author jricher
*
*/
@Component("selfAssertionValidator")
public class SelfAssertionValidator implements AssertionValidator {
private static Logger logger = LoggerFactory.getLogger(SelfAssertionValidator.class);
@Autowired
private ConfigurationPropertiesBean config;
@Autowired
private JWTSigningAndValidationService jwtService;
@Override
public boolean isValid(JWT assertion) {
if (!(assertion instanceof SignedJWT)) {
// unsigned assertion
return false;
}
JWTClaimsSet claims;
try {
claims = assertion.getJWTClaimsSet();
} catch (ParseException e) {
logger.debug("Invalid assertion claims");
return false;
}
// make sure the issuer exists
if (Strings.isNullOrEmpty(claims.getIssuer())) {
logger.debug("No issuer for assertion, rejecting");
return false;
}
// make sure the issuer is us
if (!claims.getIssuer().equals(config.getIssuer())) {
logger.debug("Issuer is not the same as this server, rejecting");
return false;
}
// validate the signature based on our public key
if (jwtService.validateSignature((SignedJWT) assertion)) {
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,104 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.jwt.assertion.impl;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import org.mitre.jwt.assertion.AssertionValidator;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.base.Strings;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
/**
* Checks to see if the assertion was signed by a particular authority available from a whitelist
* @author jricher
*
*/
public class WhitelistedIssuerAssertionValidator implements AssertionValidator {
private static Logger logger = LoggerFactory.getLogger(WhitelistedIssuerAssertionValidator.class);
/**
* Map of issuer -> JWKSetUri
*/
private Map<String, String> whitelist = new HashMap<>();
/**
* @return the whitelist
*/
public Map<String, String> getWhitelist() {
return whitelist;
}
/**
* @param whitelist the whitelist to set
*/
public void setWhitelist(Map<String, String> whitelist) {
this.whitelist = whitelist;
}
@Autowired
private JWKSetCacheService jwkCache;
@Override
public boolean isValid(JWT assertion) {
if (!(assertion instanceof SignedJWT)) {
// unsigned assertion
return false;
}
JWTClaimsSet claims;
try {
claims = assertion.getJWTClaimsSet();
} catch (ParseException e) {
logger.debug("Invalid assertion claims");
return false;
}
if (Strings.isNullOrEmpty(claims.getIssuer())) {
logger.debug("No issuer for assertion, rejecting");
return false;
}
if (!whitelist.containsKey(claims.getIssuer())) {
logger.debug("Issuer is not in whitelist, rejecting");
return false;
}
String jwksUri = whitelist.get(claims.getIssuer());
JWTSigningAndValidationService validator = jwkCache.getValidator(jwksUri);
if (validator.validateSignature((SignedJWT) assertion)) {
return true;
} else {
return false;
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.jwt.encryption.service;
import java.util.Collection;
@ -28,7 +29,7 @@ import com.nimbusds.jose.jwk.JWK;
* @author wkim
*
*/
public interface JwtEncryptionAndDecryptionService {
public interface JWTEncryptionAndDecryptionService {
/**
* Encrypts the JWT in place with the default encrypter.

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.jwt.encryption.service.impl;
import java.security.NoSuchAlgorithmException;
@ -27,7 +28,7 @@ import java.util.Set;
import javax.annotation.PostConstruct;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -40,8 +41,12 @@ import com.nimbusds.jose.JWEEncrypter;
import com.nimbusds.jose.JWEObject;
import com.nimbusds.jose.crypto.DirectDecrypter;
import com.nimbusds.jose.crypto.DirectEncrypter;
import com.nimbusds.jose.crypto.ECDHDecrypter;
import com.nimbusds.jose.crypto.ECDHEncrypter;
import com.nimbusds.jose.crypto.RSADecrypter;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.crypto.bc.BouncyCastleProviderSingleton;
import com.nimbusds.jose.jwk.ECKey;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
@ -50,15 +55,18 @@ import com.nimbusds.jose.jwk.RSAKey;
* @author wkim
*
*/
public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAndDecryptionService {
public class DefaultJWTEncryptionAndDecryptionService implements JWTEncryptionAndDecryptionService {
private static Logger logger = LoggerFactory.getLogger(DefaultJwtEncryptionAndDecryptionService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(DefaultJWTEncryptionAndDecryptionService.class);
// map of identifier to encrypter
private Map<String, JWEEncrypter> encrypters = new HashMap<String, JWEEncrypter>();
private Map<String, JWEEncrypter> encrypters = new HashMap<>();
// map of identifier to decrypter
private Map<String, JWEDecrypter> decrypters = new HashMap<String, JWEDecrypter>();
private Map<String, JWEDecrypter> decrypters = new HashMap<>();
private String defaultEncryptionKeyId;
@ -67,7 +75,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
private JWEAlgorithm defaultAlgorithm;
// map of identifier to key
private Map<String, JWK> keys = new HashMap<String, JWK>();
private Map<String, JWK> keys = new HashMap<>();
/**
* Build this service based on the keys given. All public keys will be used to make encrypters,
@ -78,7 +86,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
* @throws InvalidKeySpecException
* @throws JOSEException
*/
public DefaultJwtEncryptionAndDecryptionService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
public DefaultJWTEncryptionAndDecryptionService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
this.keys = keys;
buildEncryptersAndDecrypters();
}
@ -92,7 +100,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
* @throws InvalidKeySpecException
* @throws JOSEException
*/
public DefaultJwtEncryptionAndDecryptionService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
public DefaultJWTEncryptionAndDecryptionService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
// convert all keys in the keystore to a map based on key id
for (JWK key : keyStore.getKeys()) {
@ -109,12 +117,20 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
@PostConstruct
public void afterPropertiesSet() throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException{
public void afterPropertiesSet() {
if (keys == null) {
throw new IllegalArgumentException("Encryption and decryption service must have at least one key configured.");
}
try {
buildEncryptersAndDecrypters();
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Encryption and decryption service could not find given algorithm.");
} catch (InvalidKeySpecException e) {
throw new IllegalArgumentException("Encryption and decryption service saw an invalid key specification.");
} catch (JOSEException e) {
throw new IllegalArgumentException("Encryption and decryption service was unable to process JOSE object.");
}
}
public String getDefaultEncryptionKeyId() {
@ -212,23 +228,40 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
if (jwk instanceof RSAKey) {
// build RSA encrypters and decrypters
RSAEncrypter encrypter = new RSAEncrypter(((RSAKey) jwk).toRSAPublicKey()); // there should always at least be the public key
RSAEncrypter encrypter = new RSAEncrypter((RSAKey) jwk); // there should always at least be the public key
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
encrypters.put(id, encrypter);
if (jwk.isPrivate()) { // we can decrypt!
RSADecrypter decrypter = new RSADecrypter(((RSAKey) jwk).toRSAPrivateKey());
RSADecrypter decrypter = new RSADecrypter((RSAKey) jwk);
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
decrypters.put(id, decrypter);
} else {
logger.warn("No private key for key #" + jwk.getKeyID());
}
} else if (jwk instanceof ECKey) {
// build EC Encrypters and decrypters
ECDHEncrypter encrypter = new ECDHEncrypter((ECKey) jwk);
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
encrypters.put(id, encrypter);
if (jwk.isPrivate()) { // we can decrypt too
ECDHDecrypter decrypter = new ECDHDecrypter((ECKey) jwk);
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
decrypters.put(id, decrypter);
} else {
logger.warn("No private key for key # " + jwk.getKeyID());
}
// TODO: add support for EC keys
} else if (jwk instanceof OctetSequenceKey) {
// build symmetric encrypters and decrypters
DirectEncrypter encrypter = new DirectEncrypter(((OctetSequenceKey) jwk).toByteArray());
DirectDecrypter decrypter = new DirectDecrypter(((OctetSequenceKey) jwk).toByteArray());
DirectEncrypter encrypter = new DirectEncrypter((OctetSequenceKey) jwk);
encrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
DirectDecrypter decrypter = new DirectDecrypter((OctetSequenceKey) jwk);
decrypter.getJCAContext().setProvider(BouncyCastleProviderSingleton.getInstance());
encrypters.put(id, encrypter);
decrypters.put(id, decrypter);
@ -242,7 +275,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
@Override
public Map<String, JWK> getAllPublicKeys() {
Map<String, JWK> pubKeys = new HashMap<String, JWK>();
Map<String, JWK> pubKeys = new HashMap<>();
// pull out all public keys
for (String keyId : keys.keySet()) {
@ -258,14 +291,14 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
@Override
public Collection<JWEAlgorithm> getAllEncryptionAlgsSupported() {
Set<JWEAlgorithm> algs = new HashSet<JWEAlgorithm>();
Set<JWEAlgorithm> algs = new HashSet<>();
for (JWEEncrypter encrypter : encrypters.values()) {
algs.addAll(encrypter.supportedAlgorithms());
algs.addAll(encrypter.supportedJWEAlgorithms());
}
for (JWEDecrypter decrypter : decrypters.values()) {
algs.addAll(decrypter.supportedAlgorithms());
algs.addAll(decrypter.supportedJWEAlgorithms());
}
return algs;
@ -276,7 +309,7 @@ public class DefaultJwtEncryptionAndDecryptionService implements JwtEncryptionAn
*/
@Override
public Collection<EncryptionMethod> getAllEncryptionEncsSupported() {
Set<EncryptionMethod> encs = new HashSet<EncryptionMethod>();
Set<EncryptionMethod> encs = new HashSet<>();
for (JWEEncrypter encrypter : encrypters.values()) {
encs.addAll(encrypter.supportedEncryptionMethods());

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.jwt.signer.service;
import java.security.NoSuchAlgorithmException;
@ -24,7 +25,7 @@ import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jwt.SignedJWT;
public interface JwtSigningAndValidationService {
public interface JWTSigningAndValidationService {
/**
* Get all public keys for this service, mapped by their Key ID
@ -74,6 +75,8 @@ public interface JwtSigningAndValidationService {
*/
public void signJwt(SignedJWT jwt, JWSAlgorithm alg);
public String getDefaultSignerKeyId();
/**
* TODO: method to sign a jwt using a specified algorithm and a key id
*/

View File

@ -0,0 +1,155 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.jwt.signer.service.impl;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.impl.DefaultJWTEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWKSet;
/**
*
* Takes in a client and returns the appropriate validator or encrypter for
* that client's registered key types.
*
* @author jricher
*
*/
@Service
public class ClientKeyCacheService {
private static Logger logger = LoggerFactory.getLogger(ClientKeyCacheService.class);
@Autowired
private JWKSetCacheService jwksUriCache = new JWKSetCacheService();
@Autowired
private SymmetricKeyJWTValidatorCacheService symmetricCache = new SymmetricKeyJWTValidatorCacheService();
// cache of validators for by-value JWKs
private LoadingCache<JWKSet, JWTSigningAndValidationService> jwksValidators;
// cache of encryptors for by-value JWKs
private LoadingCache<JWKSet, JWTEncryptionAndDecryptionService> jwksEncrypters;
public ClientKeyCacheService() {
this.jwksValidators = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetVerifierBuilder());
this.jwksEncrypters = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetEncryptorBuilder());
}
public JWTSigningAndValidationService getValidator(ClientDetailsEntity client, JWSAlgorithm alg) {
try {
if (alg.equals(JWSAlgorithm.RS256)
|| alg.equals(JWSAlgorithm.RS384)
|| alg.equals(JWSAlgorithm.RS512)
|| alg.equals(JWSAlgorithm.ES256)
|| alg.equals(JWSAlgorithm.ES384)
|| alg.equals(JWSAlgorithm.ES512)
|| alg.equals(JWSAlgorithm.PS256)
|| alg.equals(JWSAlgorithm.PS384)
|| alg.equals(JWSAlgorithm.PS512)) {
// asymmetric key
if (client.getJwks() != null) {
return jwksValidators.get(client.getJwks());
} else if (!Strings.isNullOrEmpty(client.getJwksUri())) {
return jwksUriCache.getValidator(client.getJwksUri());
} else {
return null;
}
} else if (alg.equals(JWSAlgorithm.HS256)
|| alg.equals(JWSAlgorithm.HS384)
|| alg.equals(JWSAlgorithm.HS512)) {
// symmetric key
return symmetricCache.getSymmetricValidtor(client);
} else {
return null;
}
} catch (UncheckedExecutionException | ExecutionException e) {
logger.error("Problem loading client validator", e);
return null;
}
}
public JWTEncryptionAndDecryptionService getEncrypter(ClientDetailsEntity client) {
try {
if (client.getJwks() != null) {
return jwksEncrypters.get(client.getJwks());
} else if (!Strings.isNullOrEmpty(client.getJwksUri())) {
return jwksUriCache.getEncrypter(client.getJwksUri());
} else {
return null;
}
} catch (UncheckedExecutionException | ExecutionException e) {
logger.error("Problem loading client encrypter", e);
return null;
}
}
private class JWKSetEncryptorBuilder extends CacheLoader<JWKSet, JWTEncryptionAndDecryptionService> {
@Override
public JWTEncryptionAndDecryptionService load(JWKSet key) throws Exception {
return new DefaultJWTEncryptionAndDecryptionService(new JWKSetKeyStore(key));
}
}
private class JWKSetVerifierBuilder extends CacheLoader<JWKSet, JWTSigningAndValidationService> {
@Override
public JWTSigningAndValidationService load(JWKSet key) throws Exception {
return new DefaultJWTSigningAndValidationService(new JWKSetKeyStore(key));
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.jwt.signer.service.impl;
import java.security.NoSuchAlgorithmException;
@ -26,7 +27,7 @@ import java.util.Set;
import java.util.UUID;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -35,6 +36,8 @@ import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSSigner;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.ECDSASigner;
import com.nimbusds.jose.crypto.ECDSAVerifier;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jose.crypto.RSASSASigner;
@ -45,22 +48,25 @@ import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.SignedJWT;
public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
public class DefaultJWTSigningAndValidationService implements JWTSigningAndValidationService {
// map of identifier to signer
private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();
private Map<String, JWSSigner> signers = new HashMap<>();
// map of identifier to verifier
private Map<String, JWSVerifier> verifiers = new HashMap<String, JWSVerifier>();
private Map<String, JWSVerifier> verifiers = new HashMap<>();
private static Logger logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(DefaultJWTSigningAndValidationService.class);
private String defaultSignerKeyId;
private JWSAlgorithm defaultAlgorithm;
// map of identifier to key
private Map<String, JWK> keys = new HashMap<String, JWK>();
private Map<String, JWK> keys = new HashMap<>();
/**
* Build this service based on the keys given. All public keys will be used
@ -74,7 +80,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
*/
public DefaultJwtSigningAndValidationService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException {
public DefaultJWTSigningAndValidationService(Map<String, JWK> keys) throws NoSuchAlgorithmException, InvalidKeySpecException {
this.keys = keys;
buildSignersAndVerifiers();
}
@ -91,13 +97,12 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
* @throws NoSuchAlgorithmException
* If there is no appropriate algorithm to tie the keys to.
*/
public DefaultJwtSigningAndValidationService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException {
public DefaultJWTSigningAndValidationService(JWKSetKeyStore keyStore) throws NoSuchAlgorithmException, InvalidKeySpecException {
// convert all keys in the keystore to a map based on key id
if (keyStore!= null && keyStore.getJwkSet() != null) {
for (JWK key : keyStore.getKeys()) {
if (!Strings.isNullOrEmpty(key.getKeyID())) {
// use the key ID that's built into the key itself
// TODO (#641): deal with JWK thumbprints
this.keys.put(key.getKeyID(), key);
} else {
// create a random key id
@ -113,6 +118,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
/**
* @return the defaultSignerKeyId
*/
@Override
public String getDefaultSignerKeyId() {
return defaultSignerKeyId;
}
@ -155,37 +161,46 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
String id = jwkEntry.getKey();
JWK jwk = jwkEntry.getValue();
try {
if (jwk instanceof RSAKey) {
// build RSA signers & verifiers
if (jwk.isPrivate()) { // only add the signer if there's a private key
RSASSASigner signer = new RSASSASigner(((RSAKey) jwk).toRSAPrivateKey());
RSASSASigner signer = new RSASSASigner((RSAKey) jwk);
signers.put(id, signer);
}
RSASSAVerifier verifier = new RSASSAVerifier(((RSAKey) jwk).toRSAPublicKey());
RSASSAVerifier verifier = new RSASSAVerifier((RSAKey) jwk);
verifiers.put(id, verifier);
} else if (jwk instanceof ECKey) {
// build EC signers & verifiers
// TODO: add support for EC keys
logger.warn("EC Keys are not yet supported.");
if (jwk.isPrivate()) {
ECDSASigner signer = new ECDSASigner((ECKey) jwk);
signers.put(id, signer);
}
ECDSAVerifier verifier = new ECDSAVerifier((ECKey) jwk);
verifiers.put(id, verifier);
} else if (jwk instanceof OctetSequenceKey) {
// build HMAC signers & verifiers
if (jwk.isPrivate()) { // technically redundant check because all HMAC keys are private
MACSigner signer = new MACSigner(((OctetSequenceKey) jwk).toByteArray());
MACSigner signer = new MACSigner((OctetSequenceKey) jwk);
signers.put(id, signer);
}
MACVerifier verifier = new MACVerifier(((OctetSequenceKey) jwk).toByteArray());
MACVerifier verifier = new MACVerifier((OctetSequenceKey) jwk);
verifiers.put(id, verifier);
} else {
logger.warn("Unknown key type: " + jwk);
}
} catch (JOSEException e) {
logger.warn("Exception loading signer/verifier", e);
}
}
if (defaultSignerKeyId == null && keys.size() == 1) {
@ -220,7 +235,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
JWSSigner signer = null;
for (JWSSigner s : signers.values()) {
if (s.supportedAlgorithms().contains(alg)) {
if (s.supportedJWSAlgorithms().contains(alg)) {
signer = s;
break;
}
@ -251,7 +266,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
}
} catch (JOSEException e) {
logger.error("Failed to validate signature, error was: ", e);
logger.error("Failed to validate signature with " + verifier + " error message: " + e.getMessage());
}
}
return false;
@ -259,7 +274,7 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
@Override
public Map<String, JWK> getAllPublicKeys() {
Map<String, JWK> pubKeys = new HashMap<String, JWK>();
Map<String, JWK> pubKeys = new HashMap<>();
// pull all keys out of the verifiers if we know how
for (String keyId : keys.keySet()) {
@ -279,14 +294,14 @@ public class DefaultJwtSigningAndValidationService implements JwtSigningAndValid
@Override
public Collection<JWSAlgorithm> getAllSigningAlgsSupported() {
Set<JWSAlgorithm> algs = new HashSet<JWSAlgorithm>();
Set<JWSAlgorithm> algs = new HashSet<>();
for (JWSSigner signer : signers.values()) {
algs.addAll(signer.supportedAlgorithms());
algs.addAll(signer.supportedJWSAlgorithms());
}
for (JWSVerifier verifier : verifiers.values()) {
algs.addAll(verifier.supportedAlgorithms());
algs.addAll(verifier.supportedJWSAlgorithms());
}
return algs;

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -23,21 +24,23 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.encryption.service.JWTEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.impl.DefaultJWTEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gson.JsonParseException;
import com.nimbusds.jose.jwk.JWKSet;
/**
@ -51,23 +54,26 @@ import com.nimbusds.jose.jwk.JWKSet;
@Service
public class JWKSetCacheService {
private static Logger logger = LoggerFactory.getLogger(JWKSetCacheService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(JWKSetCacheService.class);
// map of jwk set uri -> signing/validation service built on the keys found in that jwk set
private LoadingCache<String, JwtSigningAndValidationService> validators;
private LoadingCache<String, JWTSigningAndValidationService> validators;
// map of jwk set uri -> encryption/decryption service built on the keys found in that jwk set
private LoadingCache<String, JwtEncryptionAndDecryptionService> encrypters;
private LoadingCache<String, JWTEncryptionAndDecryptionService> encrypters;
public JWKSetCacheService() {
this.validators = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetVerifierFetcher());
.build(new JWKSetVerifierFetcher(HttpClientBuilder.create().useSystemProperties().build()));
this.encrypters = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetEncryptorFetcher());
.build(new JWKSetEncryptorFetcher(HttpClientBuilder.create().useSystemProperties().build()));
}
/**
@ -76,26 +82,20 @@ public class JWKSetCacheService {
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService getValidator(String jwksUri) {
public JWTSigningAndValidationService getValidator(String jwksUri) {
try {
return validators.get(jwksUri);
} catch (UncheckedExecutionException ue) {
logger.warn("Couldn't load JWK Set from " + jwksUri, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri + ": " + e.getMessage());
return null;
}
}
public JwtEncryptionAndDecryptionService getEncrypter(String jwksUri) {
public JWTEncryptionAndDecryptionService getEncrypter(String jwksUri) {
try {
return encrypters.get(jwksUri);
} catch (UncheckedExecutionException ue) {
logger.warn("Couldn't load JWK Set from " + jwksUri, ue);
return null;
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
} catch (UncheckedExecutionException | ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri + ": " + e.getMessage());
return null;
}
}
@ -104,26 +104,28 @@ public class JWKSetCacheService {
* @author jricher
*
*/
private class JWKSetVerifierFetcher extends CacheLoader<String, JwtSigningAndValidationService> {
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
private class JWKSetVerifierFetcher extends CacheLoader<String, JWTSigningAndValidationService> {
private HttpComponentsClientHttpRequestFactory httpFactory;
private RestTemplate restTemplate;
JWKSetVerifierFetcher(HttpClient httpClient) {
this.httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
this.restTemplate = new RestTemplate(httpFactory);
}
/**
* Load the JWK Set and build the appropriate signing service.
*/
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
public JWTSigningAndValidationService load(String key) throws Exception {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keyStore);
JWTSigningAndValidationService service = new DefaultJWTSigningAndValidationService(keyStore);
return service;
}
}
@ -132,23 +134,32 @@ public class JWKSetCacheService {
* @author jricher
*
*/
private class JWKSetEncryptorFetcher extends CacheLoader<String, JwtEncryptionAndDecryptionService> {
private HttpClient httpClient = new SystemDefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
private class JWKSetEncryptorFetcher extends CacheLoader<String, JWTEncryptionAndDecryptionService> {
private HttpComponentsClientHttpRequestFactory httpFactory;
private RestTemplate restTemplate;
public JWKSetEncryptorFetcher(HttpClient httpClient) {
this.httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
this.restTemplate = new RestTemplate(httpFactory);
}
/* (non-Javadoc)
* @see com.google.common.cache.CacheLoader#load(java.lang.Object)
*/
@Override
public JwtEncryptionAndDecryptionService load(String key) throws Exception {
public JWTEncryptionAndDecryptionService load(String key) throws Exception {
try {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtEncryptionAndDecryptionService service = new DefaultJwtEncryptionAndDecryptionService(keyStore);
JWTEncryptionAndDecryptionService service = new DefaultJWTEncryptionAndDecryptionService(keyStore);
return service;
} catch (JsonParseException | RestClientException e) {
throw new IllegalArgumentException("Unable to load JWK Set");
}
}
}

View File

@ -1,6 +1,5 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,8 +21,7 @@ import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.nimbusds.jose.Algorithm;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.JWTSigningAndValidationService;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,8 +34,8 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.jwk.KeyUse;
import com.nimbusds.jose.jwk.OctetSequenceKey;
import com.nimbusds.jose.util.Base64URL;
/**
@ -47,14 +45,17 @@ import com.nimbusds.jose.util.Base64URL;
*
*/
@Service
public class SymmetricCacheService {
public class SymmetricKeyJWTValidatorCacheService {
private static Logger logger = LoggerFactory.getLogger(SymmetricCacheService.class);
/**
* Logger for this class
*/
private static final Logger logger = LoggerFactory.getLogger(SymmetricKeyJWTValidatorCacheService.class);
private LoadingCache<String, JwtSigningAndValidationService> validators;
private LoadingCache<String, JWTSigningAndValidationService> validators;
public SymmetricCacheService() {
public SymmetricKeyJWTValidatorCacheService() {
validators = CacheBuilder.newBuilder()
.expireAfterAccess(24, TimeUnit.HOURS)
.maximumSize(100)
@ -68,7 +69,7 @@ public class SymmetricCacheService {
* @param client
* @return
*/
public JwtSigningAndValidationService getSymmetricValidtor(ClientDetailsEntity client) {
public JWTSigningAndValidationService getSymmetricValidtor(ClientDetailsEntity client) {
if (client == null) {
logger.error("Couldn't create symmetric validator for null client");
@ -92,22 +93,22 @@ public class SymmetricCacheService {
}
public class SymmetricValidatorBuilder extends CacheLoader<String, JwtSigningAndValidationService> {
public class SymmetricValidatorBuilder extends CacheLoader<String, JWTSigningAndValidationService> {
@Override
public JwtSigningAndValidationService load(String key) throws Exception {
public JWTSigningAndValidationService load(String key) throws Exception {
try {
String id = "SYMMETRIC-KEY";
JWK jwk = new OctetSequenceKey(Base64URL.encode(key), KeyUse.SIGNATURE, null, null, id, null, null, null);
JWK jwk = new OctetSequenceKey.Builder(Base64URL.encode(key))
.keyUse(KeyUse.SIGNATURE)
.keyID(id)
.build();
Map<String, JWK> keys = ImmutableMap.of(id, jwk);
JwtSigningAndValidationService service = new DefaultJwtSigningAndValidationService(keys);
JWTSigningAndValidationService service = new DefaultJWTSigningAndValidationService(keys);
return service;
} catch (NoSuchAlgorithmException e) {
logger.error("Couldn't create symmetric validator for client", e);
} catch (InvalidKeySpecException e) {
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
logger.error("Couldn't create symmetric validator for client", e);
}

View File

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.exception;
/**
* @author jricher
*
*/
public class DeviceCodeCreationException extends Exception {
private static final long serialVersionUID = 8078568710169208466L;
private String error;
public DeviceCodeCreationException(String error, String message) {
super(message);
this.error = error;
}
/**
* @return the error
*/
public String getError() {
return error;
}
/**
* @param error the error to set
*/
public void setError(String error) {
this.error = error;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,36 +14,76 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.oauth2.model;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.JoinColumn;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.mitre.oauth2.model.convert.SerializableStringConverter;
import org.mitre.oauth2.model.convert.SimpleGrantedAuthorityStringConverter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
@Entity
@Table(name = "authentication_holder")
@NamedQueries ({
@NamedQuery(name = "AuthenticationHolderEntity.getByAuthentication", query = "select a from AuthenticationHolderEntity a where a.authentication = :authentication"),
@NamedQuery(name = "AuthenticationHolderEntity.getUnusedAuthenticationHolders", query = "select a from AuthenticationHolderEntity a where a.id not in (select t.authenticationHolder.id from OAuth2AccessTokenEntity t) and a.id not in (select r.authenticationHolder.id from OAuth2RefreshTokenEntity r)")
@NamedQuery(name = AuthenticationHolderEntity.QUERY_ALL, query = "select a from AuthenticationHolderEntity a"),
@NamedQuery(name = AuthenticationHolderEntity.QUERY_GET_UNUSED, query = "select a from AuthenticationHolderEntity a where " +
"a.id not in (select t.authenticationHolder.id from OAuth2AccessTokenEntity t) and " +
"a.id not in (select r.authenticationHolder.id from OAuth2RefreshTokenEntity r) and " +
"a.id not in (select c.authenticationHolder.id from AuthorizationCodeEntity c)")
})
public class AuthenticationHolderEntity {
public static final String QUERY_GET_UNUSED = "AuthenticationHolderEntity.getUnusedAuthenticationHolders";
public static final String QUERY_ALL = "AuthenticationHolderEntity.getAll";
private Long id;
private Long ownerId;
private SavedUserAuthentication userAuth;
private OAuth2Authentication authentication;
private Collection<GrantedAuthority> authorities;
private Set<String> resourceIds;
private boolean approved;
private String redirectUri;
private Set<String> responseTypes;
private Map<String, Serializable> extensions;
private String clientId;
private Set<String> scope;
private Map<String, String> requestParameters;
public AuthenticationHolderEntity() {
@ -59,25 +100,226 @@ public class AuthenticationHolderEntity {
this.id = id;
}
@Basic
@Column(name = "owner_id")
public Long getOwnerId() {
return ownerId;
}
public void setOwnerId(Long owner_id) {
this.ownerId = owner_id;
}
@Lob
@Basic(fetch=FetchType.LAZY)
@Column(name = "authentication")
@Transient
public OAuth2Authentication getAuthentication() {
return authentication;
// TODO: memoize this
return new OAuth2Authentication(createOAuth2Request(), getUserAuth());
}
/**
* @return
*/
private OAuth2Request createOAuth2Request() {
return new OAuth2Request(requestParameters, clientId, authorities, approved, scope, resourceIds, redirectUri, responseTypes, extensions);
}
public void setAuthentication(OAuth2Authentication authentication) {
this.authentication = authentication;
// pull apart the request and save its bits
OAuth2Request o2Request = authentication.getOAuth2Request();
setAuthorities(o2Request.getAuthorities() == null ? null : new HashSet<>(o2Request.getAuthorities()));
setClientId(o2Request.getClientId());
setExtensions(o2Request.getExtensions() == null ? null : new HashMap<>(o2Request.getExtensions()));
setRedirectUri(o2Request.getRedirectUri());
setRequestParameters(o2Request.getRequestParameters() == null ? null : new HashMap<>(o2Request.getRequestParameters()));
setResourceIds(o2Request.getResourceIds() == null ? null : new HashSet<>(o2Request.getResourceIds()));
setResponseTypes(o2Request.getResponseTypes() == null ? null : new HashSet<>(o2Request.getResponseTypes()));
setScope(o2Request.getScope() == null ? null : new HashSet<>(o2Request.getScope()));
setApproved(o2Request.isApproved());
if (authentication.getUserAuthentication() != null) {
this.userAuth = new SavedUserAuthentication(authentication.getUserAuthentication());
} else {
this.userAuth = null;
}
}
/**
* @return the userAuth
*/
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "user_auth_id")
public SavedUserAuthentication getUserAuth() {
return userAuth;
}
/**
* @param userAuth the userAuth to set
*/
public void setUserAuth(SavedUserAuthentication userAuth) {
this.userAuth = userAuth;
}
/**
* @return the authorities
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_authority",
joinColumns=@JoinColumn(name="owner_id")
)
@Convert(converter = SimpleGrantedAuthorityStringConverter.class)
@Column(name="authority")
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
/**
* @param authorities the authorities to set
*/
public void setAuthorities(Collection<GrantedAuthority> authorities) {
this.authorities = authorities;
}
/**
* @return the resourceIds
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_resource_id",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="resource_id")
public Set<String> getResourceIds() {
return resourceIds;
}
/**
* @param resourceIds the resourceIds to set
*/
public void setResourceIds(Set<String> resourceIds) {
this.resourceIds = resourceIds;
}
/**
* @return the approved
*/
@Basic
@Column(name="approved")
public boolean isApproved() {
return approved;
}
/**
* @param approved the approved to set
*/
public void setApproved(boolean approved) {
this.approved = approved;
}
/**
* @return the redirectUri
*/
@Basic
@Column(name="redirect_uri")
public String getRedirectUri() {
return redirectUri;
}
/**
* @param redirectUri the redirectUri to set
*/
public void setRedirectUri(String redirectUri) {
this.redirectUri = redirectUri;
}
/**
* @return the responseTypes
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_response_type",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="response_type")
public Set<String> getResponseTypes() {
return responseTypes;
}
/**
* @param responseTypes the responseTypes to set
*/
public void setResponseTypes(Set<String> responseTypes) {
this.responseTypes = responseTypes;
}
/**
* @return the extensions
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_extension",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="val")
@MapKeyColumn(name="extension")
@Convert(converter=SerializableStringConverter.class)
public Map<String, Serializable> getExtensions() {
return extensions;
}
/**
* @param extensions the extensions to set
*/
public void setExtensions(Map<String, Serializable> extensions) {
this.extensions = extensions;
}
/**
* @return the clientId
*/
@Basic
@Column(name="client_id")
public String getClientId() {
return clientId;
}
/**
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the scope
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_scope",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="scope")
public Set<String> getScope() {
return scope;
}
/**
* @param scope the scope to set
*/
public void setScope(Set<String> scope) {
this.scope = scope;
}
/**
* @return the requestParameters
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="authentication_holder_request_parameter",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="val")
@MapKeyColumn(name="param")
public Map<String, String> getRequestParameters() {
return requestParameters;
}
/**
* @param requestParameters the requestParameters to set
*/
public void setRequestParameters(Map<String, String> requestParameters) {
this.requestParameters = requestParameters;
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,22 +14,23 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
package org.mitre.oauth2.model;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import javax.persistence.Temporal;
/**
* Entity class for authorization codes
@ -39,15 +41,23 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication;
@Entity
@Table(name = "authorization_code")
@NamedQueries({
@NamedQuery(name = "AuthorizationCodeEntity.getByValue", query = "select a from AuthorizationCodeEntity a where a.code = :code")
@NamedQuery(name = AuthorizationCodeEntity.QUERY_BY_VALUE, query = "select a from AuthorizationCodeEntity a where a.code = :code"),
@NamedQuery(name = AuthorizationCodeEntity.QUERY_EXPIRATION_BY_DATE, query = "select a from AuthorizationCodeEntity a where a.expiration <= :" + AuthorizationCodeEntity.PARAM_DATE)
})
public class AuthorizationCodeEntity {
public static final String QUERY_BY_VALUE = "AuthorizationCodeEntity.getByValue";
public static final String QUERY_EXPIRATION_BY_DATE = "AuthorizationCodeEntity.expirationByDate";
public static final String PARAM_DATE = "date";
private Long id;
private String code;
private OAuth2Authentication authentication;
private AuthenticationHolderEntity authenticationHolder;
private Date expiration;
/**
* Default constructor.
@ -62,9 +72,10 @@ public class AuthorizationCodeEntity {
* @param code the authorization code
* @param authRequest the AuthoriztionRequestHolder associated with the original code request
*/
public AuthorizationCodeEntity(String code, OAuth2Authentication authRequest) {
public AuthorizationCodeEntity(String code, AuthenticationHolderEntity authenticationHolder, Date expiration) {
this.code = code;
this.authentication = authRequest;
this.authenticationHolder = authenticationHolder;
this.expiration = expiration;
}
/**
@ -101,20 +112,30 @@ public class AuthorizationCodeEntity {
}
/**
* The authentication in place when this token was created.
* @return the authentication
*/
@Lob
@Basic(fetch=FetchType.EAGER)
@Column(name="authentication")
public OAuth2Authentication getAuthentication() {
return authentication;
@ManyToOne
@JoinColumn(name = "auth_holder_id")
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
/**
* @param authentication the authentication to set
*/
public void setAuthentication(OAuth2Authentication authentication) {
this.authentication = authentication;
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -25,13 +26,11 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
@ -49,15 +48,21 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import org.mitre.jose.JWEAlgorithmEmbed;
import org.mitre.jose.JWEEncryptionMethodEmbed;
import org.mitre.jose.JWSAlgorithmEmbed;
import org.mitre.oauth2.model.convert.JWEAlgorithmStringConverter;
import org.mitre.oauth2.model.convert.JWEEncryptionMethodStringConverter;
import org.mitre.oauth2.model.convert.JWKSetStringConverter;
import org.mitre.oauth2.model.convert.JWSAlgorithmStringConverter;
import org.mitre.oauth2.model.convert.JWTStringConverter;
import org.mitre.oauth2.model.convert.PKCEAlgorithmStringConverter;
import org.mitre.oauth2.model.convert.SimpleGrantedAuthorityStringConverter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jwt.JWT;
/**
* @author jricher
@ -66,14 +71,16 @@ import com.nimbusds.jose.JWSAlgorithm;
@Entity
@Table(name = "client_details")
@NamedQueries({
@NamedQuery(name = "ClientDetailsEntity.findAll", query = "SELECT c FROM ClientDetailsEntity c"),
@NamedQuery(name = "ClientDetailsEntity.getByClientId", query = "select c from ClientDetailsEntity c where c.clientId = :clientId")
@NamedQuery(name = ClientDetailsEntity.QUERY_ALL, query = "SELECT c FROM ClientDetailsEntity c"),
@NamedQuery(name = ClientDetailsEntity.QUERY_BY_CLIENT_ID, query = "select c from ClientDetailsEntity c where c.clientId = :" + ClientDetailsEntity.PARAM_CLIENT_ID)
})
public class ClientDetailsEntity implements ClientDetails {
/**
*
*/
public static final String QUERY_BY_CLIENT_ID = "ClientDetailsEntity.getByClientId";
public static final String QUERY_ALL = "ClientDetailsEntity.findAll";
public static final String PARAM_CLIENT_ID = "clientId";
private static final int DEFAULT_ID_TOKEN_VALIDITY_SECONDS = 600;
private static final long serialVersionUID = -1617727085733786296L;
@ -83,51 +90,54 @@ public class ClientDetailsEntity implements ClientDetails {
/** Fields from the OAuth2 Dynamic Registration Specification */
private String clientId = null; // client_id
private String clientSecret = null; // client_secret
private Set<String> redirectUris = new HashSet<String>(); // redirect_uris
private Set<String> redirectUris = new HashSet<>(); // redirect_uris
private String clientName; // client_name
private String clientUri; // client_uri
private String logoUri; // logo_uri
private Set<String> contacts; // contacts
private String tosUri; // tos_uri
private AuthMethod tokenEndpointAuthMethod = AuthMethod.SECRET_BASIC; // token_endpoint_auth_method
private Set<String> scope = new HashSet<String>(); // scope
private Set<String> grantTypes = new HashSet<String>(); // grant_types
private Set<String> responseTypes = new HashSet<String>(); // response_types
private Set<String> scope = new HashSet<>(); // scope
private Set<String> grantTypes = new HashSet<>(); // grant_types
private Set<String> responseTypes = new HashSet<>(); // response_types
private String policyUri;
private String jwksUri;
private String jwksUri; // URI pointer to keys
private JWKSet jwks; // public key stored by value
private String softwareId;
private String softwareVersion;
/** Fields from OIDC Client Registration Specification **/
private AppType applicationType; // application_type
private String sectorIdentifierUri; // sector_identifier_uri
private SubjectType subjectType; // subject_type
private JWSAlgorithmEmbed requestObjectSigningAlg = null; // request_object_signing_alg
private JWSAlgorithm requestObjectSigningAlg = null; // request_object_signing_alg
private JWSAlgorithmEmbed userInfoSignedResponseAlg = null; // user_info_signed_response_alg
private JWEAlgorithmEmbed userInfoEncryptedResponseAlg = null; // user_info_encrypted_response_alg
private JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc = null; // user_info_encrypted_response_enc
private JWSAlgorithm userInfoSignedResponseAlg = null; // user_info_signed_response_alg
private JWEAlgorithm userInfoEncryptedResponseAlg = null; // user_info_encrypted_response_alg
private EncryptionMethod userInfoEncryptedResponseEnc = null; // user_info_encrypted_response_enc
private JWSAlgorithmEmbed idTokenSignedResponseAlg = null; // id_token_signed_response_alg
private JWEAlgorithmEmbed idTokenEncryptedResponseAlg = null; // id_token_encrypted_response_alg
private JWEEncryptionMethodEmbed idTokenEncryptedResponseEnc = null; // id_token_encrypted_response_enc
private JWSAlgorithm idTokenSignedResponseAlg = null; // id_token_signed_response_alg
private JWEAlgorithm idTokenEncryptedResponseAlg = null; // id_token_encrypted_response_alg
private EncryptionMethod idTokenEncryptedResponseEnc = null; // id_token_encrypted_response_enc
private JWSAlgorithmEmbed tokenEndpointAuthSigningAlg = null; // token_endpoint_auth_signing_alg
private JWSAlgorithm tokenEndpointAuthSigningAlg = null; // token_endpoint_auth_signing_alg
private Integer defaultMaxAge; // default_max_age
private Boolean requireAuthTime; // require_auth_time
private Set<String> defaultACRvalues; // default_acr_values
private String initiateLoginUri; // initiate_login_uri
private String postLogoutRedirectUri; // post_logout_redirect_uri
private Set<String> postLogoutRedirectUris; // post_logout_redirect_uris
private Set<String> requestUris; // request_uris
/** Fields to support the ClientDetails interface **/
private Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
private Set<GrantedAuthority> authorities = new HashSet<>();
private Integer accessTokenValiditySeconds = 0; // in seconds
private Integer refreshTokenValiditySeconds = 0; // in seconds
private Set<String> resourceIds = new HashSet<String>();
private Map<String, Object> additionalInformation = new HashMap<String, Object>();
private Set<String> resourceIds = new HashSet<>();
private Map<String, Object> additionalInformation = new HashMap<>();
/** Our own fields **/
private String clientDescription = ""; // human-readable description
@ -136,6 +146,17 @@ public class ClientDetailsEntity implements ClientDetails {
private boolean allowIntrospection = false; // do we let this client call the introspection endpoint?
private Integer idTokenValiditySeconds; //timeout for id tokens
private Date createdAt; // time the client was created
private boolean clearAccessTokensOnRefresh = true; // do we clear access tokens on refresh?
private Integer deviceCodeValiditySeconds; // timeout for device codes
/** fields for UMA */
private Set<String> claimsRedirectUris;
/** Software statement **/
private JWT softwareStatement;
/** PKCE **/
private PKCEAlgorithm codeChallengeMethod;
public enum AuthMethod {
SECRET_POST("client_secret_post"),
@ -147,7 +168,7 @@ public class ClientDetailsEntity implements ClientDetails {
private final String value;
// map to aid reverse lookup
private static final Map<String, AuthMethod> lookup = new HashMap<String, AuthMethod>();
private static final Map<String, AuthMethod> lookup = new HashMap<>();
static {
for (AuthMethod a : AuthMethod.values()) {
lookup.put(a.getValue(), a);
@ -173,7 +194,7 @@ public class ClientDetailsEntity implements ClientDetails {
private final String value;
// map to aid reverse lookup
private static final Map<String, AppType> lookup = new HashMap<String, AppType>();
private static final Map<String, AppType> lookup = new HashMap<>();
static {
for (AppType a : AppType.values()) {
lookup.put(a.getValue(), a);
@ -199,7 +220,7 @@ public class ClientDetailsEntity implements ClientDetails {
private final String value;
// map to aid reverse lookup
private static final Map<String, SubjectType> lookup = new HashMap<String, SubjectType>();
private static final Map<String, SubjectType> lookup = new HashMap<>();
static {
for (SubjectType u : SubjectType.values()) {
lookup.put(u.getValue(), u);
@ -450,6 +471,7 @@ public class ClientDetailsEntity implements ClientDetails {
* passthrough for SECOAUTH api
*/
@Override
@Transient
public Set<String> getAuthorizedGrantTypes() {
return getGrantTypes();
}
@ -463,6 +485,7 @@ public class ClientDetailsEntity implements ClientDetails {
joinColumns=@JoinColumn(name="owner_id")
)
@Override
@Convert(converter = SimpleGrantedAuthorityStringConverter.class)
@Column(name="authority")
public Set<GrantedAuthority> getAuthorities() {
return authorities;
@ -687,6 +710,23 @@ public class ClientDetailsEntity implements ClientDetails {
this.jwksUri = jwksUri;
}
/**
* @return the jwks
*/
@Basic
@Column(name="jwks")
@Convert(converter = JWKSetStringConverter.class)
public JWKSet getJwks() {
return jwks;
}
/**
* @param jwks the jwks to set
*/
public void setJwks(JWKSet jwks) {
this.jwks = jwks;
}
@Basic
@Column(name="sector_identifier_uri")
public String getSectorIdentifierUri() {
@ -697,212 +737,94 @@ public class ClientDetailsEntity implements ClientDetails {
this.sectorIdentifierUri = sectorIdentifierUri;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="request_object_signing_alg"))
})
public JWSAlgorithmEmbed getRequestObjectSigningAlgEmbed() {
@Basic
@Column(name = "request_object_signing_alg")
@Convert(converter = JWSAlgorithmStringConverter.class)
public JWSAlgorithm getRequestObjectSigningAlg() {
return requestObjectSigningAlg;
}
public void setRequestObjectSigningAlgEmbed(JWSAlgorithmEmbed requestObjectSigningAlg) {
public void setRequestObjectSigningAlg(JWSAlgorithm requestObjectSigningAlg) {
this.requestObjectSigningAlg = requestObjectSigningAlg;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="user_info_signed_response_alg"))
})
public JWSAlgorithmEmbed getUserInfoSignedResponseAlgEmbed() {
@Basic
@Column(name = "user_info_signed_response_alg")
@Convert(converter = JWSAlgorithmStringConverter.class)
public JWSAlgorithm getUserInfoSignedResponseAlg() {
return userInfoSignedResponseAlg;
}
public void setUserInfoSignedResponseAlgEmbed(JWSAlgorithmEmbed userInfoSignedResponseAlg) {
public void setUserInfoSignedResponseAlg(JWSAlgorithm userInfoSignedResponseAlg) {
this.userInfoSignedResponseAlg = userInfoSignedResponseAlg;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="user_info_encrypted_response_alg"))
})
public JWEAlgorithmEmbed getUserInfoEncryptedResponseAlgEmbed() {
@Basic
@Column(name = "user_info_encrypted_response_alg")
@Convert(converter = JWEAlgorithmStringConverter.class)
public JWEAlgorithm getUserInfoEncryptedResponseAlg() {
return userInfoEncryptedResponseAlg;
}
public void setUserInfoEncryptedResponseAlgEmbed(JWEAlgorithmEmbed userInfoEncryptedResponseAlg) {
public void setUserInfoEncryptedResponseAlg(JWEAlgorithm userInfoEncryptedResponseAlg) {
this.userInfoEncryptedResponseAlg = userInfoEncryptedResponseAlg;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="user_info_encrypted_response_enc"))
})
public JWEEncryptionMethodEmbed getUserInfoEncryptedResponseEncEmbed() {
@Basic
@Column(name = "user_info_encrypted_response_enc")
@Convert(converter = JWEEncryptionMethodStringConverter.class)
public EncryptionMethod getUserInfoEncryptedResponseEnc() {
return userInfoEncryptedResponseEnc;
}
public void setUserInfoEncryptedResponseEncEmbed(JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc) {
public void setUserInfoEncryptedResponseEnc(EncryptionMethod userInfoEncryptedResponseEnc) {
this.userInfoEncryptedResponseEnc = userInfoEncryptedResponseEnc;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="id_token_signed_response_alg"))
})
public JWSAlgorithmEmbed getIdTokenSignedResponseAlgEmbed() {
@Basic
@Column(name="id_token_signed_response_alg")
@Convert(converter = JWSAlgorithmStringConverter.class)
public JWSAlgorithm getIdTokenSignedResponseAlg() {
return idTokenSignedResponseAlg;
}
public void setIdTokenSignedResponseAlgEmbed(JWSAlgorithmEmbed idTokenSignedResponseAlg) {
public void setIdTokenSignedResponseAlg(JWSAlgorithm idTokenSignedResponseAlg) {
this.idTokenSignedResponseAlg = idTokenSignedResponseAlg;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="id_token_encrypted_response_alg"))
})
public JWEAlgorithmEmbed getIdTokenEncryptedResponseAlgEmbed() {
@Basic
@Column(name = "id_token_encrypted_response_alg")
@Convert(converter = JWEAlgorithmStringConverter.class)
public JWEAlgorithm getIdTokenEncryptedResponseAlg() {
return idTokenEncryptedResponseAlg;
}
public void setIdTokenEncryptedResponseAlgEmbed(JWEAlgorithmEmbed idTokenEncryptedResponseAlg) {
public void setIdTokenEncryptedResponseAlg(JWEAlgorithm idTokenEncryptedResponseAlg) {
this.idTokenEncryptedResponseAlg = idTokenEncryptedResponseAlg;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="id_token_encrypted_response_enc"))
})
public JWEEncryptionMethodEmbed getIdTokenEncryptedResponseEncEmbed() {
@Basic
@Column(name = "id_token_encrypted_response_enc")
@Convert(converter = JWEEncryptionMethodStringConverter.class)
public EncryptionMethod getIdTokenEncryptedResponseEnc() {
return idTokenEncryptedResponseEnc;
}
public void setIdTokenEncryptedResponseEncEmbed(JWEEncryptionMethodEmbed idTokenEncryptedResponseEnc) {
public void setIdTokenEncryptedResponseEnc(EncryptionMethod idTokenEncryptedResponseEnc) {
this.idTokenEncryptedResponseEnc = idTokenEncryptedResponseEnc;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "algorithmName", column=@Column(name="token_endpoint_auth_signing_alg"))
})
public JWSAlgorithmEmbed getTokenEndpointAuthSigningAlgEmbed() {
@Basic
@Column(name="token_endpoint_auth_signing_alg")
@Convert(converter = JWSAlgorithmStringConverter.class)
public JWSAlgorithm getTokenEndpointAuthSigningAlg() {
return tokenEndpointAuthSigningAlg;
}
public void setTokenEndpointAuthSigningAlgEmbed(JWSAlgorithmEmbed tokenEndpointAuthSigningAlgEmbed) {
this.tokenEndpointAuthSigningAlg = tokenEndpointAuthSigningAlgEmbed;
}
//
// Transient passthrough methods for JOSE elements
//
@Transient
public JWSAlgorithm getRequestObjectSigningAlg() {
if (requestObjectSigningAlg != null) {
return requestObjectSigningAlg.getAlgorithm();
} else {
return null;
}
}
public void setRequestObjectSigningAlg(JWSAlgorithm requestObjectSigningAlg) {
this.requestObjectSigningAlg = new JWSAlgorithmEmbed(requestObjectSigningAlg);
}
@Transient
public JWSAlgorithm getUserInfoSignedResponseAlg() {
if (userInfoSignedResponseAlg != null) {
return userInfoSignedResponseAlg.getAlgorithm();
} else {
return null;
}
}
public void setUserInfoSignedResponseAlg(JWSAlgorithm userInfoSignedResponseAlg) {
this.userInfoSignedResponseAlg = new JWSAlgorithmEmbed(userInfoSignedResponseAlg);
}
@Transient
public JWEAlgorithm getUserInfoEncryptedResponseAlg() {
if (userInfoEncryptedResponseAlg != null) {
return userInfoEncryptedResponseAlg.getAlgorithm();
} else {
return null;
}
}
public void setUserInfoEncryptedResponseAlg(JWEAlgorithm userInfoEncryptedResponseAlg) {
this.userInfoEncryptedResponseAlg = new JWEAlgorithmEmbed(userInfoEncryptedResponseAlg);
}
@Transient
public EncryptionMethod getUserInfoEncryptedResponseEnc() {
if (userInfoEncryptedResponseEnc != null) {
return userInfoEncryptedResponseEnc.getAlgorithm();
} else {
return null;
}
}
public void setUserInfoEncryptedResponseEnc(EncryptionMethod userInfoEncryptedResponseEnc) {
this.userInfoEncryptedResponseEnc = new JWEEncryptionMethodEmbed(userInfoEncryptedResponseEnc);
}
@Transient
public JWSAlgorithm getIdTokenSignedResponseAlg() {
if (idTokenSignedResponseAlg != null) {
return idTokenSignedResponseAlg.getAlgorithm();
} else {
return null;
}
}
public void setIdTokenSignedResponseAlg(JWSAlgorithm idTokenSignedResponseAlg) {
this.idTokenSignedResponseAlg = new JWSAlgorithmEmbed(idTokenSignedResponseAlg);
}
@Transient
public JWEAlgorithm getIdTokenEncryptedResponseAlg() {
if (idTokenEncryptedResponseAlg != null) {
return idTokenEncryptedResponseAlg.getAlgorithm();
} else {
return null;
}
}
public void setIdTokenEncryptedResponseAlg(JWEAlgorithm idTokenEncryptedResponseAlg) {
this.idTokenEncryptedResponseAlg = new JWEAlgorithmEmbed(idTokenEncryptedResponseAlg);
}
@Transient
public EncryptionMethod getIdTokenEncryptedResponseEnc() {
if (idTokenEncryptedResponseEnc != null) {
return idTokenEncryptedResponseEnc.getAlgorithm();
} else {
return null;
}
}
public void setIdTokenEncryptedResponseEnc(EncryptionMethod idTokenEncryptedResponseEnc) {
this.idTokenEncryptedResponseEnc = new JWEEncryptionMethodEmbed(idTokenEncryptedResponseEnc);
}
@Transient
public JWSAlgorithm getTokenEndpointAuthSigningAlg() {
if (tokenEndpointAuthSigningAlg != null) {
return tokenEndpointAuthSigningAlg.getAlgorithm();
} else {
return null;
}
}
public void setTokenEndpointAuthSigningAlg(JWSAlgorithm tokenEndpointAuthSigningAlg) {
this.tokenEndpointAuthSigningAlg = new JWSAlgorithmEmbed(tokenEndpointAuthSigningAlg);
this.tokenEndpointAuthSigningAlg = tokenEndpointAuthSigningAlg;
}
// END Transient JOSE methods
@Basic
@Column(name="default_max_age")
public Integer getDefaultMaxAge() {
@ -982,17 +904,21 @@ public class ClientDetailsEntity implements ClientDetails {
/**
* @return the postLogoutRedirectUri
*/
@Basic
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_post_logout_redirect_uri",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="post_logout_redirect_uri")
public String getPostLogoutRedirectUri() {
return postLogoutRedirectUri;
public Set<String> getPostLogoutRedirectUris() {
return postLogoutRedirectUris;
}
/**
* @param postLogoutRedirectUri the postLogoutRedirectUri to set
*/
public void setPostLogoutRedirectUri(String postLogoutRedirectUri) {
this.postLogoutRedirectUri = postLogoutRedirectUri;
public void setPostLogoutRedirectUris(Set<String> postLogoutRedirectUri) {
this.postLogoutRedirectUris = postLogoutRedirectUri;
}
/**
@ -1039,4 +965,122 @@ public class ClientDetailsEntity implements ClientDetails {
return false;
}
/**
* @return the clearAccessTokensOnRefresh
*/
@Basic
@Column(name = "clear_access_tokens_on_refresh")
public boolean isClearAccessTokensOnRefresh() {
return clearAccessTokensOnRefresh;
}
/**
* @param clearAccessTokensOnRefresh the clearAccessTokensOnRefresh to set
*/
public void setClearAccessTokensOnRefresh(boolean clearAccessTokensOnRefresh) {
this.clearAccessTokensOnRefresh = clearAccessTokensOnRefresh;
}
/**
* @return the claimsRedirectUris
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="client_claims_redirect_uri",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="redirect_uri")
public Set<String> getClaimsRedirectUris() {
return claimsRedirectUris;
}
/**
* @param claimsRedirectUris the claimsRedirectUris to set
*/
public void setClaimsRedirectUris(Set<String> claimsRedirectUris) {
this.claimsRedirectUris = claimsRedirectUris;
}
/**
* @return the softwareStatement
*/
@Basic
@Column(name = "software_statement")
@Convert(converter = JWTStringConverter.class)
public JWT getSoftwareStatement() {
return softwareStatement;
}
/**
* @param softwareStatement the softwareStatement to set
*/
public void setSoftwareStatement(JWT softwareStatement) {
this.softwareStatement = softwareStatement;
}
/**
* @return the codeChallengeMethod
*/
@Basic
@Column(name = "code_challenge_method")
@Convert(converter = PKCEAlgorithmStringConverter.class)
public PKCEAlgorithm getCodeChallengeMethod() {
return codeChallengeMethod;
}
/**
* @param codeChallengeMethod the codeChallengeMethod to set
*/
public void setCodeChallengeMethod(PKCEAlgorithm codeChallengeMethod) {
this.codeChallengeMethod = codeChallengeMethod;
}
/**
* @return the deviceCodeValiditySeconds
*/
@Basic
@Column(name="device_code_validity_seconds")
public Integer getDeviceCodeValiditySeconds() {
return deviceCodeValiditySeconds;
}
/**
* @param deviceCodeValiditySeconds the deviceCodeValiditySeconds to set
*/
public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) {
this.deviceCodeValiditySeconds = deviceCodeValiditySeconds;
}
/**
* @return the softwareId
*/
@Basic
@Column(name="software_id")
public String getSoftwareId() {
return softwareId;
}
/**
* @param softwareId the softwareId to set
*/
public void setSoftwareId(String softwareId) {
this.softwareId = softwareId;
}
/**
* @return the softwareVersion
*/
@Basic
@Column(name="software_version")
public String getSoftwareVersion() {
return softwareVersion;
}
/**
* @param softwareVersion the softwareVersion to set
*/
public void setSoftwareVersion(String softwareVersion) {
this.softwareVersion = softwareVersion;
}
}

View File

@ -0,0 +1,234 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
/**
* @author jricher
*
*/
@Entity
@Table(name = "device_code")
@NamedQueries({
@NamedQuery(name = DeviceCode.QUERY_BY_USER_CODE, query = "select d from DeviceCode d where d.userCode = :" + DeviceCode.PARAM_USER_CODE),
@NamedQuery(name = DeviceCode.QUERY_BY_DEVICE_CODE, query = "select d from DeviceCode d where d.deviceCode = :" + DeviceCode.PARAM_DEVICE_CODE),
@NamedQuery(name = DeviceCode.QUERY_EXPIRED_BY_DATE, query = "select d from DeviceCode d where d.expiration <= :" + DeviceCode.PARAM_DATE)
})
public class DeviceCode {
public static final String QUERY_BY_USER_CODE = "DeviceCode.queryByUserCode";
public static final String QUERY_BY_DEVICE_CODE = "DeviceCode.queryByDeviceCode";
public static final String QUERY_EXPIRED_BY_DATE = "DeviceCode.queryExpiredByDate";
public static final String PARAM_USER_CODE = "userCode";
public static final String PARAM_DEVICE_CODE = "deviceCode";
public static final String PARAM_DATE = "date";
private Long id;
private String deviceCode;
private String userCode;
private Set<String> scope;
private Date expiration;
private String clientId;
private Map<String, String> requestParameters;
private boolean approved;
private AuthenticationHolderEntity authenticationHolder;
public DeviceCode() {
}
public DeviceCode(String deviceCode, String userCode, Set<String> scope, String clientId, Map<String, String> params) {
this.deviceCode = deviceCode;
this.userCode = userCode;
this.scope = scope;
this.clientId = clientId;
this.requestParameters = params;
}
/**
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* @return the deviceCode
*/
@Basic
@Column(name = "device_code")
public String getDeviceCode() {
return deviceCode;
}
/**
* @param deviceCode the deviceCode to set
*/
public void setDeviceCode(String deviceCode) {
this.deviceCode = deviceCode;
}
/**
* @return the userCode
*/
@Basic
@Column(name = "user_code")
public String getUserCode() {
return userCode;
}
/**
* @param userCode the userCode to set
*/
public void setUserCode(String userCode) {
this.userCode = userCode;
}
/**
* @return the scope
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="device_code_scope",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="scope")
public Set<String> getScope() {
return scope;
}
/**
* @param scope the scope to set
*/
public void setScope(Set<String> scope) {
this.scope = scope;
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "expiration")
public Date getExpiration() {
return expiration;
}
public void setExpiration(Date expiration) {
this.expiration = expiration;
}
/**
* @return the clientId
*/
@Basic
@Column(name = "client_id")
public String getClientId() {
return clientId;
}
/**
* @param clientId the clientId to set
*/
public void setClientId(String clientId) {
this.clientId = clientId;
}
/**
* @return the params
*/
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="device_code_request_parameter",
joinColumns=@JoinColumn(name="owner_id")
)
@Column(name="val")
@MapKeyColumn(name="param")
public Map<String, String> getRequestParameters() {
return requestParameters;
}
/**
* @param params the params to set
*/
public void setRequestParameters(Map<String, String> params) {
this.requestParameters = params;
}
/**
* @return the approved
*/
@Basic
@Column(name = "approved")
public boolean isApproved() {
return approved;
}
/**
* @param approved the approved to set
*/
public void setApproved(boolean approved) {
this.approved = approved;
}
/**
* The authentication in place when this token was created.
* @return the authentication
*/
@ManyToOne
@JoinColumn(name = "auth_holder_id")
public AuthenticationHolderEntity getAuthenticationHolder() {
return authenticationHolder;
}
/**
* @param authentication the authentication to set
*/
public void setAuthenticationHolder(AuthenticationHolderEntity authenticationHolder) {
this.authenticationHolder = authenticationHolder;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,13 +14,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
package org.mitre.oauth2.model;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -29,6 +29,7 @@ import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@ -36,19 +37,26 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.Transient;
import org.mitre.oauth2.model.convert.JWTStringConverter;
import org.mitre.openid.connect.model.ApprovedSite;
import org.mitre.uma.model.Permission;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Deserializer;
import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson1Serializer;
import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Deserializer;
import org.springframework.security.oauth2.common.OAuth2AccessTokenJackson2Serializer;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
/**
* @author jricher
@ -57,19 +65,39 @@ import com.nimbusds.jwt.JWTParser;
@Entity
@Table(name = "access_token")
@NamedQueries({
@NamedQuery(name = "OAuth2AccessTokenEntity.getAll", query = "select a from OAuth2AccessTokenEntity a"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getAllExpiredByDate", query = "select a from OAuth2AccessTokenEntity a where a.expiration <= :date"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByRefreshToken", query = "select a from OAuth2AccessTokenEntity a where a.refreshToken = :refreshToken"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByClient", query = "select a from OAuth2AccessTokenEntity a where a.client = :client"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByAuthentication", query = "select a from OAuth2AccessTokenEntity a where a.authenticationHolder.authentication = :authentication"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByIdToken", query = "select a from OAuth2AccessTokenEntity a where a.idToken = :idToken"),
@NamedQuery(name = "OAuth2AccessTokenEntity.getByTokenValue", query = "select a from OAuth2AccessTokenEntity a where a.value = :tokenValue")
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_ALL, query = "select a from OAuth2AccessTokenEntity a"),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_EXPIRED_BY_DATE, query = "select a from OAuth2AccessTokenEntity a where a.expiration <= :" + OAuth2AccessTokenEntity.PARAM_DATE),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_REFRESH_TOKEN, query = "select a from OAuth2AccessTokenEntity a where a.refreshToken = :" + OAuth2AccessTokenEntity.PARAM_REFERSH_TOKEN),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_CLIENT, query = "select a from OAuth2AccessTokenEntity a where a.client = :" + OAuth2AccessTokenEntity.PARAM_CLIENT),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_TOKEN_VALUE, query = "select a from OAuth2AccessTokenEntity a where a.jwt = :" + OAuth2AccessTokenEntity.PARAM_TOKEN_VALUE),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_APPROVED_SITE, query = "select a from OAuth2AccessTokenEntity a where a.approvedSite = :" + OAuth2AccessTokenEntity.PARAM_APPROVED_SITE),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_RESOURCE_SET, query = "select a from OAuth2AccessTokenEntity a join a.permissions p where p.resourceSet.id = :" + OAuth2AccessTokenEntity.PARAM_RESOURCE_SET_ID),
@NamedQuery(name = OAuth2AccessTokenEntity.QUERY_BY_NAME, query = "select r from OAuth2AccessTokenEntity r where r.authenticationHolder.userAuth.name = :" + OAuth2AccessTokenEntity.PARAM_NAME)
})
//@JsonSerialize(using = OAuth2AccessTokenSerializer.class)
//@JsonDeserialize(using = OAuth2AccessTokenDeserializer.class)
@org.codehaus.jackson.map.annotate.JsonSerialize(using = OAuth2AccessTokenJackson1Serializer.class)
@org.codehaus.jackson.map.annotate.JsonDeserialize(using = OAuth2AccessTokenJackson1Deserializer.class)
@com.fasterxml.jackson.databind.annotation.JsonSerialize(using = OAuth2AccessTokenJackson2Serializer.class)
@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = OAuth2AccessTokenJackson2Deserializer.class)
public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
public static String ID_TOKEN_FIELD_NAME = "id_token";
public static final String QUERY_BY_APPROVED_SITE = "OAuth2AccessTokenEntity.getByApprovedSite";
public static final String QUERY_BY_TOKEN_VALUE = "OAuth2AccessTokenEntity.getByTokenValue";
public static final String QUERY_BY_CLIENT = "OAuth2AccessTokenEntity.getByClient";
public static final String QUERY_BY_REFRESH_TOKEN = "OAuth2AccessTokenEntity.getByRefreshToken";
public static final String QUERY_EXPIRED_BY_DATE = "OAuth2AccessTokenEntity.getAllExpiredByDate";
public static final String QUERY_ALL = "OAuth2AccessTokenEntity.getAll";
public static final String QUERY_BY_RESOURCE_SET = "OAuth2AccessTokenEntity.getByResourceSet";
public static final String QUERY_BY_NAME = "OAuth2AccessTokenEntity.getByName";
public static final String PARAM_TOKEN_VALUE = "tokenValue";
public static final String PARAM_CLIENT = "client";
public static final String PARAM_REFERSH_TOKEN = "refreshToken";
public static final String PARAM_DATE = "date";
public static final String PARAM_RESOURCE_SET_ID = "rsid";
public static final String PARAM_APPROVED_SITE = "approvedSite";
public static final String PARAM_NAME = "name";
public static final String ID_TOKEN_FIELD_NAME = "id_token";
private Long id;
@ -79,8 +107,6 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
private JWT jwtValue; // JWT-encoded access token value
private OAuth2AccessTokenEntity idToken; // JWT-encoded OpenID Connect IdToken
private Date expiration;
private String tokenType = OAuth2AccessToken.BEARER_TYPE;
@ -89,6 +115,12 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
private Set<String> scope;
private Set<Permission> permissions;
private ApprovedSite approvedSite;
private Map<String, Object> additionalInformation = new HashMap<>(); // ephemeral map of items to be added to the OAuth token response
/**
* Create a new, blank access token
*/
@ -114,16 +146,13 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
}
/**
* Get all additional information to be sent to the serializer. Inserts a copy of the IdToken (in JWT String form).
* Get all additional information to be sent to the serializer as part of the token response.
* This map is not persisted to the database.
*/
@Override
@Transient
public Map<String, Object> getAdditionalInformation() {
Map<String, Object> map = new HashMap<String, Object>(); //super.getAdditionalInformation();
if (getIdToken() != null) {
map.put(ID_TOKEN_FIELD_NAME, getIdTokenString());
}
return map;
return additionalInformation;
}
/**
@ -163,22 +192,11 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
* Get the string-encoded value of this access token.
*/
@Override
@Basic
@Column(name="token_value")
@Transient
public String getValue() {
return jwtValue.serialize();
}
/**
* Set the "value" of this Access Token
*
* @param value the JWT string
* @throws ParseException if "value" is not a properly formatted JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
@Override
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@ -241,38 +259,12 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
return getExpiration() == null ? false : System.currentTimeMillis() > getExpiration().getTime();
}
/**
* @return the idToken
*/
@OneToOne(cascade=CascadeType.ALL) // one-to-one mapping for now
@JoinColumn(name = "id_token_id")
public OAuth2AccessTokenEntity getIdToken() {
return idToken;
}
/**
* @param idToken the idToken to set
*/
public void setIdToken(OAuth2AccessTokenEntity idToken) {
this.idToken = idToken;
}
/**
* @return the idTokenString
*/
@Transient
public String getIdTokenString() {
if (idToken != null) {
return idToken.getValue(); // get the JWT string value of the id token entity
} else {
return null;
}
}
/**
* @return the jwtValue
*/
@Transient
@Basic
@Column(name="token_value")
@Convert(converter = JWTStringConverter.class)
public JWT getJwt() {
return jwtValue;
}
@ -300,4 +292,44 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
}
}
/**
* @return the permissions
*/
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(
name = "access_token_permissions",
joinColumns = @JoinColumn(name = "access_token_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id")
)
public Set<Permission> getPermissions() {
return permissions;
}
/**
* @param permissions the permissions to set
*/
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
@ManyToOne
@JoinColumn(name="approved_site_id")
public ApprovedSite getApprovedSite() {
return approvedSite;
}
public void setApprovedSite(ApprovedSite approvedSite) {
this.approvedSite = approvedSite;
}
/**
* Add the ID Token to the additionalInformation map for a token response.
* @param idToken
*/
@Transient
public void setIdToken(JWT idToken) {
if (idToken != null) {
additionalInformation.put(ID_TOKEN_FIELD_NAME, idToken.serialize());
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,17 +14,17 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
package org.mitre.oauth2.model;
import java.text.ParseException;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
@ -37,10 +38,10 @@ import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.Transient;
import org.mitre.oauth2.model.convert.JWTStringConverter;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTParser;
/**
* @author jricher
@ -49,14 +50,25 @@ import com.nimbusds.jwt.JWTParser;
@Entity
@Table(name = "refresh_token")
@NamedQueries({
@NamedQuery(name = "OAuth2RefreshTokenEntity.getAll", query = "select r from OAuth2RefreshTokenEntity r"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getAllExpiredByDate", query = "select r from OAuth2RefreshTokenEntity r where r.expiration <= :date"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByClient", query = "select r from OAuth2RefreshTokenEntity r where r.client = :client"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByTokenValue", query = "select r from OAuth2RefreshTokenEntity r where r.value = :tokenValue"),
@NamedQuery(name = "OAuth2RefreshTokenEntity.getByAuthentication", query = "select r from OAuth2RefreshTokenEntity r where r.authenticationHolder.authentication = :authentication")
@NamedQuery(name = OAuth2RefreshTokenEntity.QUERY_ALL, query = "select r from OAuth2RefreshTokenEntity r"),
@NamedQuery(name = OAuth2RefreshTokenEntity.QUERY_EXPIRED_BY_DATE, query = "select r from OAuth2RefreshTokenEntity r where r.expiration <= :" + OAuth2RefreshTokenEntity.PARAM_DATE),
@NamedQuery(name = OAuth2RefreshTokenEntity.QUERY_BY_CLIENT, query = "select r from OAuth2RefreshTokenEntity r where r.client = :" + OAuth2RefreshTokenEntity.PARAM_CLIENT),
@NamedQuery(name = OAuth2RefreshTokenEntity.QUERY_BY_TOKEN_VALUE, query = "select r from OAuth2RefreshTokenEntity r where r.jwt = :" + OAuth2RefreshTokenEntity.PARAM_TOKEN_VALUE),
@NamedQuery(name = OAuth2RefreshTokenEntity.QUERY_BY_NAME, query = "select r from OAuth2RefreshTokenEntity r where r.authenticationHolder.userAuth.name = :" + OAuth2RefreshTokenEntity.PARAM_NAME)
})
public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
public static final String QUERY_BY_TOKEN_VALUE = "OAuth2RefreshTokenEntity.getByTokenValue";
public static final String QUERY_BY_CLIENT = "OAuth2RefreshTokenEntity.getByClient";
public static final String QUERY_EXPIRED_BY_DATE = "OAuth2RefreshTokenEntity.getAllExpiredByDate";
public static final String QUERY_ALL = "OAuth2RefreshTokenEntity.getAll";
public static final String QUERY_BY_NAME = "OAuth2RefreshTokenEntity.getByName";
public static final String PARAM_TOKEN_VALUE = "tokenValue";
public static final String PARAM_CLIENT = "client";
public static final String PARAM_DATE = "date";
public static final String PARAM_NAME = "name";
private Long id;
private AuthenticationHolderEntity authenticationHolder;
@ -116,21 +128,11 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
* Get the JWT-encoded value of this token
*/
@Override
@Basic
@Column(name="token_value")
@Transient
public String getValue() {
return jwt.serialize();
}
/**
* Set the value of this token as a string. Parses the string into a JWT.
* @param value
* @throws ParseException if the value is not a valid JWT string
*/
public void setValue(String value) throws ParseException {
setJwt(JWTParser.parse(value));
}
@Basic
@Temporal(javax.persistence.TemporalType.TIMESTAMP)
@Column(name = "expiration")
@ -175,7 +177,9 @@ public class OAuth2RefreshTokenEntity implements OAuth2RefreshToken {
* Get the JWT object directly
* @return the jwt
*/
@Transient
@Basic
@Column(name="token_value")
@Convert(converter = JWTStringConverter.class)
public JWT getJwt() {
return jwt;
}

View File

@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model;
import com.nimbusds.jose.Algorithm;
import com.nimbusds.jose.Requirement;
/**
* @author jricher
*
*/
public final class PKCEAlgorithm extends Algorithm {
/**
*
*/
private static final long serialVersionUID = 7752852583210088925L;
public static final PKCEAlgorithm plain = new PKCEAlgorithm("plain", Requirement.REQUIRED);
public static final PKCEAlgorithm S256 = new PKCEAlgorithm("S256", Requirement.OPTIONAL);
public PKCEAlgorithm(String name, Requirement req) {
super(name, req);
}
public PKCEAlgorithm(String name) {
super(name, null);
}
public static PKCEAlgorithm parse(final String s) {
if (s.equals(plain.getName())) {
return plain;
} else if (s.equals(S256.getName())) {
return S256;
} else {
return new PKCEAlgorithm(s);
}
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -23,17 +24,17 @@ import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.mitre.jose.JWEAlgorithmEmbed;
import org.mitre.jose.JWEEncryptionMethodEmbed;
import org.mitre.jose.JWSAlgorithmEmbed;
import org.mitre.oauth2.model.ClientDetailsEntity.AppType;
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
import org.mitre.oauth2.model.ClientDetailsEntity.SubjectType;
import org.springframework.security.core.GrantedAuthority;
import com.google.gson.JsonObject;
import com.nimbusds.jose.EncryptionMethod;
import com.nimbusds.jose.JWEAlgorithm;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jwt.JWT;
/**
* @author jricher
@ -47,6 +48,7 @@ public class RegisteredClient {
private Date clientSecretExpiresAt;
private Date clientIdIssuedAt;
private ClientDetailsEntity client;
private JsonObject src;
/**
*
@ -463,6 +465,22 @@ public class RegisteredClient {
public void setJwksUri(String jwksUri) {
client.setJwksUri(jwksUri);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getJwks()
*/
public JWKSet getJwks() {
return client.getJwks();
}
/**
* @param jwks
* @see org.mitre.oauth2.model.ClientDetailsEntity#setJwks(com.nimbusds.jose.jwk.JWKSet)
*/
public void setJwks(JWKSet jwks) {
client.setJwks(jwks);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSectorIdentifierUri()
@ -549,17 +567,17 @@ public class RegisteredClient {
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getPostLogoutRedirectUri()
* @see org.mitre.oauth2.model.ClientDetailsEntity#getPostLogoutRedirectUris()
*/
public String getPostLogoutRedirectUri() {
return client.getPostLogoutRedirectUri();
public Set<String> getPostLogoutRedirectUris() {
return client.getPostLogoutRedirectUris();
}
/**
* @param postLogoutRedirectUri
* @see org.mitre.oauth2.model.ClientDetailsEntity#setPostLogoutRedirectUri(java.lang.String)
* @see org.mitre.oauth2.model.ClientDetailsEntity#setPostLogoutRedirectUris(java.lang.String)
*/
public void setPostLogoutRedirectUri(String postLogoutRedirectUri) {
client.setPostLogoutRedirectUri(postLogoutRedirectUri);
public void setPostLogoutRedirectUris(Set<String> postLogoutRedirectUri) {
client.setPostLogoutRedirectUris(postLogoutRedirectUri);
}
/**
* @return
@ -575,117 +593,6 @@ public class RegisteredClient {
public void setRequestUris(Set<String> requestUris) {
client.setRequestUris(requestUris);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getRequestObjectSigningAlgEmbed()
*/
public JWSAlgorithmEmbed getRequestObjectSigningAlgEmbed() {
return client.getRequestObjectSigningAlgEmbed();
}
/**
* @param requestObjectSigningAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setRequestObjectSigningAlgEmbed(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setRequestObjectSigningAlgEmbed(JWSAlgorithmEmbed requestObjectSigningAlg) {
client.setRequestObjectSigningAlgEmbed(requestObjectSigningAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoSignedResponseAlgEmbed()
*/
public JWSAlgorithmEmbed getUserInfoSignedResponseAlgEmbed() {
return client.getUserInfoSignedResponseAlgEmbed();
}
/**
* @param userInfoSignedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoSignedResponseAlgEmbed(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setUserInfoSignedResponseAlgEmbed(JWSAlgorithmEmbed userInfoSignedResponseAlg) {
client.setUserInfoSignedResponseAlgEmbed(userInfoSignedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoEncryptedResponseAlgEmbed()
*/
public JWEAlgorithmEmbed getUserInfoEncryptedResponseAlgEmbed() {
return client.getUserInfoEncryptedResponseAlgEmbed();
}
/**
* @param userInfoEncryptedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoEncryptedResponseAlgEmbed(org.mitre.jose.JWEAlgorithmEmbed)
*/
public void setUserInfoEncryptedResponseAlgEmbed(JWEAlgorithmEmbed userInfoEncryptedResponseAlg) {
client.setUserInfoEncryptedResponseAlgEmbed(userInfoEncryptedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getUserInfoEncryptedResponseEncEmbed()
*/
public JWEEncryptionMethodEmbed getUserInfoEncryptedResponseEncEmbed() {
return client.getUserInfoEncryptedResponseEncEmbed();
}
/**
* @param userInfoEncryptedResponseEnc
* @see org.mitre.oauth2.model.ClientDetailsEntity#setUserInfoEncryptedResponseEncEmbed(org.mitre.jose.JWEEncryptionMethodEmbed)
*/
public void setUserInfoEncryptedResponseEncEmbed(JWEEncryptionMethodEmbed userInfoEncryptedResponseEnc) {
client.setUserInfoEncryptedResponseEncEmbed(userInfoEncryptedResponseEnc);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenSignedResponseAlgEmbed()
*/
public JWSAlgorithmEmbed getIdTokenSignedResponseAlgEmbed() {
return client.getIdTokenSignedResponseAlgEmbed();
}
/**
* @param idTokenSignedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenSignedResponseAlgEmbed(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setIdTokenSignedResponseAlgEmbed(JWSAlgorithmEmbed idTokenSignedResponseAlg) {
client.setIdTokenSignedResponseAlgEmbed(idTokenSignedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenEncryptedResponseAlgEmbed()
*/
public JWEAlgorithmEmbed getIdTokenEncryptedResponseAlgEmbed() {
return client.getIdTokenEncryptedResponseAlgEmbed();
}
/**
* @param idTokenEncryptedResponseAlg
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenEncryptedResponseAlgEmbed(org.mitre.jose.JWEAlgorithmEmbed)
*/
public void setIdTokenEncryptedResponseAlgEmbed(JWEAlgorithmEmbed idTokenEncryptedResponseAlg) {
client.setIdTokenEncryptedResponseAlgEmbed(idTokenEncryptedResponseAlg);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getIdTokenEncryptedResponseEncEmbed()
*/
public JWEEncryptionMethodEmbed getIdTokenEncryptedResponseEncEmbed() {
return client.getIdTokenEncryptedResponseEncEmbed();
}
/**
* @param idTokenEncryptedResponseEnc
* @see org.mitre.oauth2.model.ClientDetailsEntity#setIdTokenEncryptedResponseEncEmbed(org.mitre.jose.JWEEncryptionMethodEmbed)
*/
public void setIdTokenEncryptedResponseEncEmbed(JWEEncryptionMethodEmbed idTokenEncryptedResponseEnc) {
client.setIdTokenEncryptedResponseEncEmbed(idTokenEncryptedResponseEnc);
}
/**
* @return
@ -799,22 +706,6 @@ public class RegisteredClient {
client.setIdTokenEncryptedResponseEnc(idTokenEncryptedResponseEnc);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getTokenEndpointAuthSigningAlgEmbed()
*/
public JWSAlgorithmEmbed getTokenEndpointAuthSigningAlgEmbed() {
return client.getTokenEndpointAuthSigningAlgEmbed();
}
/**
* @param tokenEndpointAuthSigningAlgEmbed
* @see org.mitre.oauth2.model.ClientDetailsEntity#setTokenEndpointAuthSigningAlgEmbed(org.mitre.jose.JWSAlgorithmEmbed)
*/
public void setTokenEndpointAuthSigningAlgEmbed(JWSAlgorithmEmbed tokenEndpointAuthSigningAlgEmbed) {
client.setTokenEndpointAuthSigningAlgEmbed(tokenEndpointAuthSigningAlgEmbed);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getTokenEndpointAuthSigningAlg()
@ -894,6 +785,116 @@ public class RegisteredClient {
this.clientIdIssuedAt = issuedAt;
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getClaimsRedirectUris()
*/
public Set<String> getClaimsRedirectUris() {
return client.getClaimsRedirectUris();
}
/**
* @param claimsRedirectUris
* @see org.mitre.oauth2.model.ClientDetailsEntity#setClaimsRedirectUris(java.util.Set)
*/
public void setClaimsRedirectUris(Set<String> claimsRedirectUris) {
client.setClaimsRedirectUris(claimsRedirectUris);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSoftwareStatement()
*/
public JWT getSoftwareStatement() {
return client.getSoftwareStatement();
}
/**
* @param softwareStatement
* @see org.mitre.oauth2.model.ClientDetailsEntity#setSoftwareStatement(com.nimbusds.jwt.JWT)
*/
public void setSoftwareStatement(JWT softwareStatement) {
client.setSoftwareStatement(softwareStatement);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getCodeChallengeMethod()
*/
public PKCEAlgorithm getCodeChallengeMethod() {
return client.getCodeChallengeMethod();
}
/**
* @param codeChallengeMethod
* @see org.mitre.oauth2.model.ClientDetailsEntity#setCodeChallengeMethod(org.mitre.oauth2.model.PKCEAlgorithm)
*/
public void setCodeChallengeMethod(PKCEAlgorithm codeChallengeMethod) {
client.setCodeChallengeMethod(codeChallengeMethod);
}
/**
* @return the src
*/
public JsonObject getSource() {
return src;
}
/**
* @param src the src to set
*/
public void setSource(JsonObject src) {
this.src = src;
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getDeviceCodeValiditySeconds()
*/
public Integer getDeviceCodeValiditySeconds() {
return client.getDeviceCodeValiditySeconds();
}
/**
* @param deviceCodeValiditySeconds
* @see org.mitre.oauth2.model.ClientDetailsEntity#setDeviceCodeValiditySeconds(java.lang.Integer)
*/
public void setDeviceCodeValiditySeconds(Integer deviceCodeValiditySeconds) {
client.setDeviceCodeValiditySeconds(deviceCodeValiditySeconds);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSoftwareId()
*/
public String getSoftwareId() {
return client.getSoftwareId();
}
/**
* @param softwareId
* @see org.mitre.oauth2.model.ClientDetailsEntity#setSoftwareId(java.lang.String)
*/
public void setSoftwareId(String softwareId) {
client.setSoftwareId(softwareId);
}
/**
* @return
* @see org.mitre.oauth2.model.ClientDetailsEntity#getSoftwareVersion()
*/
public String getSoftwareVersion() {
return client.getSoftwareVersion();
}
/**
* @param softwareVersion
* @see org.mitre.oauth2.model.ClientDetailsEntity#setSoftwareVersion(java.lang.String)
*/
public void setSoftwareVersion(String softwareVersion) {
client.setSoftwareVersion(softwareVersion);
}
}

View File

@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model;
public interface RegisteredClientFields {
public String SOFTWARE_ID = "software_id";
public String SOFTWARE_VERSION = "software_version";
public String SOFTWARE_STATEMENT = "software_statement";
public String CLAIMS_REDIRECT_URIS = "claims_redirect_uris";
public String CLIENT_SECRET_EXPIRES_AT = "client_secret_expires_at";
public String CLIENT_ID_ISSUED_AT = "client_id_issued_at";
public String REGISTRATION_CLIENT_URI = "registration_client_uri";
public String REGISTRATION_ACCESS_TOKEN = "registration_access_token";
public String REQUEST_URIS = "request_uris";
public String POST_LOGOUT_REDIRECT_URIS = "post_logout_redirect_uris";
public String INITIATE_LOGIN_URI = "initiate_login_uri";
public String DEFAULT_ACR_VALUES = "default_acr_values";
public String REQUIRE_AUTH_TIME = "require_auth_time";
public String DEFAULT_MAX_AGE = "default_max_age";
public String TOKEN_ENDPOINT_AUTH_SIGNING_ALG = "token_endpoint_auth_signing_alg";
public String ID_TOKEN_ENCRYPTED_RESPONSE_ENC = "id_token_encrypted_response_enc";
public String ID_TOKEN_ENCRYPTED_RESPONSE_ALG = "id_token_encrypted_response_alg";
public String ID_TOKEN_SIGNED_RESPONSE_ALG = "id_token_signed_response_alg";
public String USERINFO_ENCRYPTED_RESPONSE_ENC = "userinfo_encrypted_response_enc";
public String USERINFO_ENCRYPTED_RESPONSE_ALG = "userinfo_encrypted_response_alg";
public String USERINFO_SIGNED_RESPONSE_ALG = "userinfo_signed_response_alg";
public String REQUEST_OBJECT_SIGNING_ALG = "request_object_signing_alg";
public String SUBJECT_TYPE = "subject_type";
public String SECTOR_IDENTIFIER_URI = "sector_identifier_uri";
public String APPLICATION_TYPE = "application_type";
public String JWKS_URI = "jwks_uri";
public String JWKS = "jwks";
public String SCOPE_SEPARATOR = " ";
public String POLICY_URI = "policy_uri";
public String RESPONSE_TYPES = "response_types";
public String GRANT_TYPES = "grant_types";
public String SCOPE = "scope";
public String TOKEN_ENDPOINT_AUTH_METHOD = "token_endpoint_auth_method";
public String TOS_URI = "tos_uri";
public String CONTACTS = "contacts";
public String LOGO_URI = "logo_uri";
public String CLIENT_URI = "client_uri";
public String CLIENT_NAME = "client_name";
public String REDIRECT_URIS = "redirect_uris";
public String CLIENT_SECRET = "client_secret";
public String CLIENT_ID = "client_id";
public String CODE_CHALLENGE_METHOD = "code_challenge_method";
}

View File

@ -0,0 +1,182 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model;
import java.util.Collection;
import java.util.HashSet;
import javax.persistence.Basic;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.persistence.Transient;
import org.mitre.oauth2.model.convert.SimpleGrantedAuthorityStringConverter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
/**
* This class stands in for an original Authentication object.
*
* @author jricher
*
*/
@Entity
@Table(name="saved_user_auth")
public class SavedUserAuthentication implements Authentication {
private static final long serialVersionUID = -1804249963940323488L;
private Long id;
private String name;
private Collection<GrantedAuthority> authorities;
private boolean authenticated;
private String sourceClass;
/**
* Create a Saved Auth from an existing Auth token
*/
public SavedUserAuthentication(Authentication src) {
setName(src.getName());
setAuthorities(new HashSet<>(src.getAuthorities()));
setAuthenticated(src.isAuthenticated());
if (src instanceof SavedUserAuthentication) {
// if we're copying in a saved auth, carry over the original class name
setSourceClass(((SavedUserAuthentication) src).getSourceClass());
} else {
setSourceClass(src.getClass().getName());
}
}
/**
* Create an empty saved auth
*/
public SavedUserAuthentication() {
}
/**
* @return the id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
@Override
@Basic
@Column(name="name")
public String getName() {
return name;
}
@Override
@ElementCollection(fetch = FetchType.EAGER)
@CollectionTable(
name="saved_user_auth_authority",
joinColumns=@JoinColumn(name="owner_id")
)
@Convert(converter = SimpleGrantedAuthorityStringConverter.class)
@Column(name="authority")
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
@Transient
public Object getCredentials() {
return "";
}
@Override
@Transient
public Object getDetails() {
return null;
}
@Override
@Transient
public Object getPrincipal() {
return getName();
}
@Override
@Basic
@Column(name="authenticated")
public boolean isAuthenticated() {
return authenticated;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
this.authenticated = isAuthenticated;
}
/**
* @return the sourceClass
*/
@Basic
@Column(name="source_class")
public String getSourceClass() {
return sourceClass;
}
/**
* @param sourceClass the sourceClass to set
*/
public void setSourceClass(String sourceClass) {
this.sourceClass = sourceClass;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @param authorities the authorities to set
*/
public void setAuthorities(Collection<GrantedAuthority> authorities) {
this.authorities = authorities;
}
}

View File

@ -1,6 +1,7 @@
/*******************************************************************************
* Copyright 2014 The MITRE Corporation
* and the MIT Kerberos and Internet Trust Consortium
* Copyright 2018 The MIT Internet Trust Consortium
*
* Portions copyright 2011-2013 The MITRE Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -13,7 +14,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
*******************************************************************************/
/**
*
*/
@ -28,7 +29,6 @@ import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Transient;
/**
* @author jricher
@ -37,20 +37,22 @@ import javax.persistence.Transient;
@Entity
@Table(name = "system_scope")
@NamedQueries({
@NamedQuery(name = "SystemScope.findAll", query = "select s from SystemScope s ORDER BY s.id"),
@NamedQuery(name = "SystemScope.getByValue", query = "select s from SystemScope s WHERE s.value = :value")
@NamedQuery(name = SystemScope.QUERY_ALL, query = "select s from SystemScope s ORDER BY s.id"),
@NamedQuery(name = SystemScope.QUERY_BY_VALUE, query = "select s from SystemScope s WHERE s.value = :" + SystemScope.PARAM_VALUE)
})
public class SystemScope {
public static final String QUERY_BY_VALUE = "SystemScope.getByValue";
public static final String QUERY_ALL = "SystemScope.findAll";
public static final String PARAM_VALUE = "value";
private Long id;
private String value; // scope value
private String description; // human-readable description
private String icon; // class of the icon to display on the auth page
private boolean allowDynReg = false; // can a dynamically registered client ask for this scope?
private boolean defaultScope = false; // is this a default scope for newly-registered clients?
private boolean structured = false; // is this a default scope for newly-registered clients?
private String structuredParamDescription;
private String structuredValue;
private boolean restricted = false; // is this scope restricted to admin-only registration access?
/**
* Make a blank system scope with no value
@ -124,20 +126,6 @@ public class SystemScope {
public void setIcon(String icon) {
this.icon = icon;
}
/**
* @return the allowDynReg
*/
@Basic
@Column(name = "allow_dyn_reg")
public boolean isAllowDynReg() {
return allowDynReg;
}
/**
* @param allowDynReg the allowDynReg to set
*/
public void setAllowDynReg(boolean allowDynReg) {
this.allowDynReg = allowDynReg;
}
/**
* @return the defaultScope
@ -156,51 +144,21 @@ public class SystemScope {
}
/**
* @return the isStructured status
* @return the restricted
*/
@Basic
@Column(name = "structured")
public boolean isStructured() {
return structured;
@Column(name = "restricted")
public boolean isRestricted() {
return restricted;
}
/**
* @param structured the structured to set
* @param restricted the restricted to set
*/
public void setStructured(boolean structured) {
this.structured = structured;
public void setRestricted(boolean restricted) {
this.restricted = restricted;
}
@Basic
@Column(name = "structured_param_description")
public String getStructuredParamDescription() {
return structuredParamDescription;
}
/**
* @param isStructured the isStructured to set
*/
public void setStructuredParamDescription(String d) {
this.structuredParamDescription = d;
}
/**
* @return the structuredValue
*/
@Transient // we don't save the value of a system scope separately
public String getStructuredValue() {
return structuredValue;
}
/**
* @param structuredValue the structuredValue to set
*/
public void setStructuredValue(String structuredValue) {
this.structuredValue = structuredValue;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@ -208,14 +166,12 @@ public class SystemScope {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (allowDynReg ? 1231 : 1237);
result = prime * result + (defaultScope ? 1231 : 1237);
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result
+ ((description == null) ? 0 : description.hashCode());
result = prime * result + ((icon == null) ? 0 : icon.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + (structured ? 1231 : 1237);
result = prime * result + ((structuredParamDescription == null) ? 0 : structuredParamDescription.hashCode());
result = prime * result + ((structuredValue == null) ? 0 : structuredValue.hashCode());
result = prime * result + (restricted ? 1231 : 1237);
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@ -231,13 +187,10 @@ public class SystemScope {
if (obj == null) {
return false;
}
if (!(obj instanceof SystemScope)) {
if (getClass() != obj.getClass()) {
return false;
}
SystemScope other = (SystemScope) obj;
if (allowDynReg != other.allowDynReg) {
return false;
}
if (defaultScope != other.defaultScope) {
return false;
}
@ -262,21 +215,7 @@ public class SystemScope {
} else if (!id.equals(other.id)) {
return false;
}
if (structured != other.structured) {
return false;
}
if (structuredParamDescription == null) {
if (other.structuredParamDescription != null) {
return false;
}
} else if (!structuredParamDescription.equals(other.structuredParamDescription)) {
return false;
}
if (structuredValue == null) {
if (other.structuredValue != null) {
return false;
}
} else if (!structuredValue.equals(other.structuredValue)) {
if (restricted != other.restricted) {
return false;
}
if (value == null) {
@ -294,8 +233,9 @@ public class SystemScope {
*/
@Override
public String toString() {
return "SystemScope [id=" + id + ", value=" + value + ", description=" + description + ", icon=" + icon + ", allowDynReg=" + allowDynReg + ", defaultScope=" + defaultScope + ", structured=" + structured + ", structuredParamDescription=" + structuredParamDescription + ", structuredValue="
+ structuredValue + "]";
return "SystemScope [id=" + id + ", value=" + value + ", description="
+ description + ", icon=" + icon + ", defaultScope="
+ defaultScope + ", restricted=" + restricted + "]";
}
}

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model.convert;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import com.nimbusds.jose.JWEAlgorithm;
@Converter
public class JWEAlgorithmStringConverter implements AttributeConverter<JWEAlgorithm, String> {
@Override
public String convertToDatabaseColumn(JWEAlgorithm attribute) {
if (attribute != null) {
return attribute.getName();
} else {
return null;
}
}
/* (non-Javadoc)
* @see javax.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object)
*/
@Override
public JWEAlgorithm convertToEntityAttribute(String dbData) {
if (dbData != null) {
return JWEAlgorithm.parse(dbData);
} else {
return null;
}
}
}

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright 2018 The MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.model.convert;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import com.nimbusds.jose.EncryptionMethod;
@Converter
public class JWEEncryptionMethodStringConverter implements AttributeConverter<EncryptionMethod, String> {
@Override
public String convertToDatabaseColumn(EncryptionMethod attribute) {
if (attribute != null) {
return attribute.getName();
} else {
return null;
}
}
/* (non-Javadoc)
* @see javax.persistence.AttributeConverter#convertToEntityAttribute(java.lang.Object)
*/
@Override
public EncryptionMethod convertToEntityAttribute(String dbData) {
if (dbData != null) {
return EncryptionMethod.parse(dbData);
} else {
return null;
}
}
}

Some files were not shown because too many files have changed in this diff Show More