Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'releases/2.3.1'

  • Loading branch information...
commit 091c5e5961dd33c8c7ca5a15f4020e47d266a1c3 2 parents d5bcbdc + 4de071f
@fhanik fhanik authored
Showing with 2,968 additions and 5,007 deletions.
  1. +17 −11 .travis.yml
  2. +1 −1  build.gradle
  3. +2 −2 common/build.gradle
  4. +0 −1  common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.java
  5. +10 −2 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java
  6. +3 −3 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ChainedAuthenticationManager.java
  7. +4 −3 .../src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java
  8. +2 −1  common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java
  9. +3 −2 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LoginAuthenticationManager.java
  10. +1 −0  common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java
  11. +2 −1  common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/LoginSamlAuthenticationProvider.java
  12. +4 −3 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/Claims.java
  13. +80 −10 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/SignerProvider.java
  14. +27 −0 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/TokenRevokedException.java
  15. +90 −39 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java
  16. +17 −3 common/src/main/java/org/cloudfoundry/identity/uaa/rest/jdbc/SimpleSearchQueryConverter.java
  17. +6 −8 common/src/main/java/org/cloudfoundry/identity/uaa/security/web/SecurityFilterChainPostProcessor.java
  18. +4 −4 common/src/main/java/org/cloudfoundry/identity/uaa/user/JdbcUaaUserDatabase.java
  19. +14 −9 common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaUser.java
  20. +13 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/hsqldb/V2_3_0__Add_SaltFieldsToUsers.sql
  21. +15 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/hsqldb/V2_3_1__Add_Index_To_Users_Email.sql
  22. +13 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/mysql/V2_3_0__Add_SaltFieldsToUsers.sql
  23. +16 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/mysql/V2_3_1__Add_Index_To_Users_Email.sql
  24. +13 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/postgresql/V2_3_0__Add_SaltFieldsToUsers.sql
  25. +16 −0 common/src/main/resources/org/cloudfoundry/identity/uaa/db/postgresql/V2_3_1__Add_Index_To_Users_Email.sql
  26. +9 −1 common/src/test/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpointTest.java
  27. +5 −3 common/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/AuthzAuthenticationManagerTests.java
  28. +2 −1  ...src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java
  29. +39 −25 common/src/test/java/org/cloudfoundry/identity/uaa/login/SamlLoginServerKeyManagerTests.java
  30. +164 −31 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpointTests.java
  31. +1 −1  common/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaAuthorizationRequestManagerTests.java
  32. +24 −3 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/SignerProviderTests.java
  33. +41 −22 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java
  34. +6 −0 common/src/test/java/org/cloudfoundry/identity/uaa/test/JdbcTestBase.java
  35. +1 −1  common/src/test/java/org/cloudfoundry/identity/uaa/test/TestAccountSetup.java
  36. +6 −5 common/src/test/java/org/cloudfoundry/identity/uaa/test/UaaTestAccounts.java
  37. +3 −2 common/src/test/java/org/cloudfoundry/identity/uaa/user/InMemoryUaaUserDatabaseTests.java
  38. +26 −12 common/src/test/java/org/cloudfoundry/identity/uaa/user/JdbcUaaUserDatabaseTests.java
  39. +3 −3 common/src/test/java/org/cloudfoundry/identity/uaa/user/MockUaaUserDatabase.java
  40. +4 −4 common/src/test/java/org/cloudfoundry/identity/uaa/user/UaaUserTestFactory.java
  41. +32 −0 common/src/test/java/org/cloudfoundry/identity/uaa/util/EnsureOldJacksonIsGone.java
  42. +26 −6 common/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsServiceTests.java
  43. +1 −1  gradle.properties
  44. +51 −15 ...c/main/java/org/cloudfoundry/identity/uaa/authentication/manager/DynamicZoneAwareAuthenticationManager.java
  45. +0 −106 login/src/main/java/org/cloudfoundry/identity/uaa/login/ChainedAuthenticationManager.java
  46. +9 −1 login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailService.java
  47. +79 −0 login/src/main/java/org/cloudfoundry/identity/uaa/oauth/TokenRevocationEndpoint.java
  48. +12 −1 login/src/main/resources/login-ui.xml
  49. +1 −2  login/src/main/resources/templates/web/invalid_request.html
  50. +2 −0  login/src/main/resources/templates/web/login.html
  51. +2 −2 login/src/test/java/org/cloudfoundry/identity/uaa/login/ChangeEmailControllerTest.java
  52. +0 −1  samples/authcode/.gitignore
  53. +0 −38 samples/authcode/README.md
  54. +0 −17 samples/authcode/application.yml
  55. +0 −27 samples/authcode/build.gradle
  56. +0 −1  samples/authcode/gradle.properties
  57. BIN  samples/authcode/gradle/wrapper/gradle-wrapper.jar
  58. +0 −6 samples/authcode/gradle/wrapper/gradle-wrapper.properties
  59. +0 −164 samples/authcode/gradlew
  60. +0 −90 samples/authcode/gradlew.bat
  61. +0 −11 samples/authcode/manifest.yml
  62. +0 −40 samples/authcode/pom.xml
  63. +0 −76 samples/authcode/src/main/java/org/cloudfoundry/identity/samples/authcode/Application.java
  64. +0 −43 samples/authcode/src/main/java/org/cloudfoundry/identity/samples/authcode/SSLValidationDisabler.java
  65. +0 −13 samples/authcode/src/main/resources/application.yml
  66. +0 −23 samples/authcode/src/main/resources/log4j.xml
  67. +0 −30 samples/authcode/src/main/resources/templates/authorization_code.html
  68. +0 −17 samples/authcode/src/main/resources/templates/index.html
  69. +0 −1  samples/client_credentials/.gitignore
  70. +0 −36 samples/client_credentials/README.md
  71. +0 −14 samples/client_credentials/application.yml
  72. +0 −27 samples/client_credentials/build.gradle
  73. +0 −1  samples/client_credentials/gradle.properties
  74. BIN  samples/client_credentials/gradle/wrapper/gradle-wrapper.jar
  75. +0 −6 samples/client_credentials/gradle/wrapper/gradle-wrapper.properties
  76. +0 −164 samples/client_credentials/gradlew
  77. +0 −90 samples/client_credentials/gradlew.bat
  78. +0 −11 samples/client_credentials/manifest.yml
  79. +0 −40 samples/client_credentials/pom.xml
  80. +0 −91 samples/client_credentials/src/main/java/org/cloudfoundry/identity/samples/clientcredentials/Application.java
  81. +0 −43 ...nt_credentials/src/main/java/org/cloudfoundry/identity/samples/clientcredentials/SSLValidationDisabler.java
  82. +0 −13 samples/client_credentials/src/main/resources/application.yml
  83. +0 −23 samples/client_credentials/src/main/resources/log4j.xml
  84. +0 −42 samples/client_credentials/src/main/resources/templates/client_credentials.html
  85. +0 −17 samples/client_credentials/src/main/resources/templates/index.html
  86. +0 −1  samples/implicit/.gitignore
  87. +0 −38 samples/implicit/README.md
  88. +0 −16 samples/implicit/application.yml
  89. +0 −27 samples/implicit/build.gradle
  90. +0 −1  samples/implicit/gradle.properties
  91. BIN  samples/implicit/gradle/wrapper/gradle-wrapper.jar
  92. +0 −6 samples/implicit/gradle/wrapper/gradle-wrapper.properties
  93. +0 −164 samples/implicit/gradlew
  94. +0 −90 samples/implicit/gradlew.bat
  95. +0 −11 samples/implicit/manifest.yml
  96. +0 −40 samples/implicit/pom.xml
  97. +0 −38 samples/implicit/src/main/java/org/cloudfoundry/identity/samples/implicit/Application.java
  98. +0 −43 samples/implicit/src/main/java/org/cloudfoundry/identity/samples/implicit/SSLValidationDisabler.java
  99. +0 −12 samples/implicit/src/main/resources/application.yml
  100. +0 −23 samples/implicit/src/main/resources/log4j.xml
  101. +0 −55 samples/implicit/src/main/resources/public/implicit.html
  102. +0 −18 samples/implicit/src/main/resources/templates/index.html
  103. +0 −69 samples/oauth-showcase/build.gradle
  104. +0 −5 samples/oauth-showcase/manifest.yml
  105. +0 −30 samples/oauth-showcase/src/main/java/org/cloudfoundry/identity/oauth2showcase/Application.java
  106. +0 −54 samples/oauth-showcase/src/main/java/org/cloudfoundry/identity/oauth2showcase/AuthorizationCode.java
  107. +0 −54 samples/oauth-showcase/src/main/java/org/cloudfoundry/identity/oauth2showcase/ClientCredentials.java
  108. +0 −76 samples/oauth-showcase/src/main/java/org/cloudfoundry/identity/oauth2showcase/PasswordGrant.java
  109. +0 −37 samples/oauth-showcase/src/main/java/org/cloudfoundry/identity/oauth2showcase/Utils.java
  110. +0 −46 samples/oauth-showcase/src/main/resources/application.yml
  111. +0 −23 samples/oauth-showcase/src/main/resources/log4j.xml
  112. +0 −58 samples/oauth-showcase/src/main/resources/public/implicit.html
  113. +0 −36 samples/oauth-showcase/src/main/resources/templates/authorization_code.html
  114. +0 −43 samples/oauth-showcase/src/main/resources/templates/client_credentials.html
  115. +0 −35 samples/oauth-showcase/src/main/resources/templates/index.html
  116. +0 −23 samples/oauth-showcase/src/main/resources/templates/password_form.html
  117. +0 −30 samples/oauth-showcase/src/main/resources/templates/password_result.html
  118. +0 −1  samples/password/.gitignore
  119. +0 −38 samples/password/README.md
  120. +0 −14 samples/password/application.yml
  121. +0 −27 samples/password/build.gradle
  122. +0 −1  samples/password/gradle.properties
  123. BIN  samples/password/gradle/wrapper/gradle-wrapper.jar
  124. +0 −6 samples/password/gradle/wrapper/gradle-wrapper.properties
  125. +0 −164 samples/password/gradlew
  126. +0 −90 samples/password/gradlew.bat
  127. +0 −11 samples/password/manifest.yml
  128. +0 −40 samples/password/pom.xml
  129. +0 −120 samples/password/src/main/java/org/cloudfoundry/identity/samples/password/Application.java
  130. +0 −43 samples/password/src/main/java/org/cloudfoundry/identity/samples/password/SSLValidationDisabler.java
  131. +0 −11 samples/password/src/main/resources/application.yml
  132. +0 −23 samples/password/src/main/resources/log4j.xml
  133. +0 −17 samples/password/src/main/resources/templates/index.html
  134. +0 −23 samples/password/src/main/resources/templates/password_form.html
  135. +0 −22 samples/password/src/main/resources/templates/password_result.html
  136. +18 −6 scim/src/main/java/org/cloudfoundry/identity/uaa/password/event/PasswordChangeEventPublisher.java
  137. +14 −4 scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUser.java
  138. +1 −1  scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpoints.java
  139. +6 −2 scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/UserIdConversionEndpoints.java
  140. +11 −7 scim/src/main/java/org/cloudfoundry/identity/uaa/scim/jdbc/JdbcScimUserProvisioning.java
  141. +245 −0 scim/src/test/java/org/cloudfoundry/identity/uaa/performance/TestMySQLEmailSearch.java
  142. +6 −5 scim/src/test/java/org/cloudfoundry/identity/uaa/scim/bootstrap/ScimUserBootstrapTests.java
  143. +25 −4 scim/src/test/java/org/cloudfoundry/identity/uaa/scim/jdbc/JdbcScimUserProvisioningTests.java
  144. +29 −2 scim/src/test/java/org/cloudfoundry/identity/uaa/scim/jdbc/ScimSearchQueryConverterTests.java
  145. +0 −2  settings.gradle
  146. +1 −1  shared_versions.gradle
  147. +1 −0  uaa/build.gradle
  148. +7 −0 uaa/src/main/resources/uaa.yml
  149. +16 −2 uaa/src/main/webapp/WEB-INF/spring-servlet.xml
  150. +1 −3 uaa/src/main/webapp/WEB-INF/spring/approvals-endpoints.xml
  151. +1 −3 uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml
  152. +0 −14 uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml
  153. +117 −26 ...st/java/org/cloudfoundry/identity/uaa/authentication/manager/DynamicZoneAwareAuthenticationManagerTest.java
  154. +6 −1 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/AppApprovalIT.java
  155. +5 −5 uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/DefaultIntegrationTestConfig.java
  156. +83 −97 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java
  157. +37 −2 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/BootstrapTests.java
  158. +255 −130 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java
  159. +26 −51 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java
  160. +18 −46 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerMockMvcTests.java
  161. +11 −41 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/XFrameOptionsTheories.java
  162. +69 −98 uaa/src/test/java/org/cloudfoundry/identity/uaa/login/saml/SamlIDPRefreshMockMvcTests.java
  163. +22 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/Contextable.java
  164. +105 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/DefaultConfigurationTestSuite.java
  165. +83 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/InjectedMockContextTest.java
  166. +48 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/UaaBaseSuite.java
  167. +93 −0 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/UaaJunitSuiteRunner.java
  168. +52 −79 ...a/org/cloudfoundry/identity/uaa/mock/audit/{AuditCheckMvcMockTests.java → AuditCheckMockMvcTests.java}
  169. +66 −91 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/clients/ClientAdminEndpointsMockMvcTests.java
  170. +21 −47 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/codestore/ExpiringCodeStoreMockMvcTests.java
  171. +0 −91 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/config/CheckSmtpBeansMvcMockTests.java
  172. +73 −30 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/config/HealthzShouldNotBeProtectedMockMvcTests.java
  173. +4 −27 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/oauth/CheckDefaultAuthoritiesMvcMockTests.java
  174. +25 −35 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java
  175. +173 −187 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java
  176. +7 −2 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java
  177. +42 −73 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityProviderEndpointsMockMvcTests.java
  178. +67 −100 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java
  179. +25 −49 uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneSwitchingFilterMockMvcTest.java
  180. +20 −40 uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsMockMvcTests.java
  181. +48 −83 uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java
  182. +17 −40 uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserEndpointsMockMvcTests.java
  183. +46 −59 uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java
  184. +0 −1  uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java
View
28 .travis.yml
@@ -40,19 +40,25 @@ script:
- ./gradlew -Dspring.profiles.active=$TESTENV cobertura
after_success:
- ./gradlew coveralls
-- python scripts/travis/travis_after_all.py
-- export $(cat .to_export_back)
-- ! "if [ \"$BUILD_LEADER\" = \"YES\" ]; then\n if [ \"$BUILD_AGGREGATE_STATUS\"
- = \"others_succeeded\" ]; then\n echo \"All Succeeded!\"\n else\n echo \"Some Failed\"\n fi\nfi\n"
- for i in $(find $HOME/build/cloudfoundry/uaa/ -name reports -type d); do rm -rf $i; done
+- /bin/df -h
+- /usr/bin/du -sh *
+#- python scripts/travis/travis_after_all.py
+#- export $(cat .to_export_back)
+#- ! "if [ \"$BUILD_LEADER\" = \"YES\" ]; then\n if [ \"$BUILD_AGGREGATE_STATUS\"
+# = \"others_succeeded\" ]; then\n echo \"All Succeeded!\"\n else\n echo \"Some Failed\"\n fi\nfi\n"
+#after_failure:
+#- python scripts/travis/travis_after_all.py
+#- export $(cat .to_export_back)
+#- ! "if [ \"$BUILD_LEADER\" = \"YES\" ]; then\n if [ \"$BUILD_AGGREGATE_STATUS\"
+# = \"others_failed\" ]; then\n echo \"All Failed\"\n else\n echo \"Some Failed\"\n
+# \ fi\nfi\n"
+#after_script:
+#- echo leader=$BUILD_LEADER status=$BUILD_AGGREGATE_STATUS
+
after_failure:
-- python scripts/travis/travis_after_all.py
-- export $(cat .to_export_back)
-- ! "if [ \"$BUILD_LEADER\" = \"YES\" ]; then\n if [ \"$BUILD_AGGREGATE_STATUS\"
- = \"others_failed\" ]; then\n echo \"All Failed\"\n else\n echo \"Some Failed\"\n
- \ fi\nfi\n"
-after_script:
-- echo leader=$BUILD_LEADER status=$BUILD_AGGREGATE_STATUS
+- /bin/df -h
+- /usr/bin/du -sh *
addons:
hosts:
- testzone1.localhost
View
2  build.gradle
@@ -12,7 +12,7 @@ buildscript {
classpath group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '2.2.4'
classpath group: 'net.saliman', name: 'gradle-cobertura-plugin', version: '2.2.2'
classpath group: 'org.kt3k.gradle.plugin', name: 'coveralls-gradle-plugin', version: '0.4.1'
- classpath group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version:'1.1.7'
+ classpath group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version:'1.1.8'
classpath group: 'postgresql', name: 'postgresql', version:'9.1-901.jdbc3'
classpath group: 'org.flywaydb', name: 'flyway-gradle-plugin', version: '3.0'
classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.7'
View
4 common/build.gradle
@@ -12,6 +12,7 @@ dependencies {
compile group: 'org.springframework.security', name: 'spring-security-jwt', version:parent.springSecurityJwtVersion
compile(group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version:parent.springSecurityOAuthVersion) {
exclude(module: 'commons-codec')
+ exclude(module: 'jackson-mapper-asl')
}
compile group: 'org.springframework.security', name: 'spring-security-config', version:parent.springSecurityVersion
compile (group: 'org.springframework.security.oauth', name: 'spring-security-oauth', version:parent.springSecurityOAuthVersion) {
@@ -42,11 +43,10 @@ dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version:'1.7.7'
compile group: 'org.hibernate', name: 'hibernate-validator', version:'4.3.1.Final'
compile group: 'org.aspectj', name: 'aspectjrt', version:'1.6.9'
- //compile group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version:'1.9.2'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-core', version:parent.jacksonVersion
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version:parent.jacksonVersion
compile group: 'org.yaml', name: 'snakeyaml', version:'1.12'
- compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version:'1.1.7'
+ compile group: 'org.mariadb.jdbc', name: 'mariadb-java-client', version:'1.1.8'
compile group: 'com.googlecode.flyway', name: 'flyway-core', version:'2.3.1'
compile group: 'org.hsqldb', name: 'hsqldb', version:'2.3.1'
View
1  common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.java
@@ -21,7 +21,6 @@
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import java.io.IOException;
import java.util.Map;
public class TokenIssuedEvent extends AbstractUaaEvent {
View
12 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java
@@ -208,11 +208,13 @@ private String login(Model model, Principal principal, List<String> excludedProm
List<IdentityProviderDefinition> idps = getIdentityProviderDefinitions(allowedIdps);
+ boolean fieldUsernameShow = true;
+
if (allowedIdps==null ||
allowedIdps.contains(Origin.LDAP) ||
allowedIdps.contains(Origin.UAA) ||
allowedIdps.contains(Origin.KEYSTONE)) {
- model.addAttribute("fieldUsernameShow", true);
+ fieldUsernameShow = true;
} else if (idps!=null && idps.size()==1) {
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("saml/discovery");
builder.queryParam("returnIDParam", "idp");
@@ -221,8 +223,14 @@ private String login(Model model, Principal principal, List<String> excludedProm
builder.queryParam("isPassive", "true");
return "redirect:" + builder.build().toUriString();
} else {
- model.addAttribute("fieldUsernameShow", false);
+ fieldUsernameShow = false;
+ }
+ boolean linkCreateAccountShow = fieldUsernameShow;
+ if (fieldUsernameShow && (allowedIdps!=null && !allowedIdps.contains(Origin.UAA))) {
+ linkCreateAccountShow = false;
}
+ model.addAttribute("linkCreateAccountShow", linkCreateAccountShow);
+ model.addAttribute("fieldUsernameShow",fieldUsernameShow);
populatePrompts(model, excludedPrompts, nonHtml);
setCommitInfo(model);
model.addAttribute("zone_name", IdentityZoneHolder.get().getName());
View
6 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ChainedAuthenticationManager.java
@@ -53,9 +53,9 @@ public Authentication authenticate(Authentication authentication) throws Authent
if (authentication instanceof UsernamePasswordAuthenticationToken) {
output = (UsernamePasswordAuthenticationToken) authentication;
} else {
- output = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),
- authentication.getAuthorities());
- output.setAuthenticated(authentication.isAuthenticated());
+ output = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(),
+ authentication.getCredentials(),
+ authentication.getAuthorities());
output.setDetails(authentication.getDetails());
}
boolean authenticated = false;
View
7 ...c/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java
@@ -178,9 +178,9 @@ protected UaaUser getUser(UserDetails details, Map<String, String> info) {
familyName = email.split("@")[1];
}
return new UaaUser(
- "NaN",
+ "NaN",
name,
- "" /*zero length password for login server */,
+ "" /*zero length password for login server */,
email,
UaaAuthority.USER_AUTHORITIES,
givenName,
@@ -190,7 +190,8 @@ protected UaaUser getUser(UserDetails details, Map<String, String> info) {
origin,
details.getUsername(),
false,
- IdentityZoneHolder.get().getId());
+ IdentityZoneHolder.get().getId(),
+ null);
}
@Override
View
3  ...n/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java
@@ -48,7 +48,8 @@ protected UaaUser getUser(UserDetails details, Map<String, String> info) {
origin,
externalId,
false,
- IdentityZoneHolder.get().getId());
+ IdentityZoneHolder.get().getId(),
+ null);
} else {
logger.warn("Unable to get DN from user. Not an LDAP user:"+details+" of class:"+details.getClass());
return user.modifySource(getOrigin(), user.getExternalId());
View
5 common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LoginAuthenticationManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -176,7 +176,8 @@ protected UaaUser getUser(AuthzAuthenticationRequest req, Map<String, String> in
origin,
name,
false,
- IdentityZoneHolder.get().getId());
+ IdentityZoneHolder.get().getId(),
+ null);
}
}
View
1  common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java
@@ -18,4 +18,5 @@
public static final String CREATED_WITH = "createdwith";
public static final String CLIENT_NAME = "name";
public static final String APPROVALS_DELETED = "approvals_deleted";
+ public static final String TOKEN_SALT = "token_salt";
}
View
3  common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/LoginSamlAuthenticationProvider.java
@@ -157,7 +157,8 @@ protected UaaUser getUser(UaaPrincipal principal) {
origin,
name,
false,
- zoneId);
+ zoneId,
+ null);
}
}
View
7 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/Claims.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -17,10 +17,10 @@
* Constants that can be used to work with claims from OAuth2 Bearer and OpenID
* Connect tokens
* </p>
- *
+ *
* @author Joel D'sa
* @author Dave Syer
- *
+ *
*/
public class Claims {
public static final String USER_ID = "user_id";
@@ -44,4 +44,5 @@
public static final String AZP = "azp";
public static final String AUTH_TIME = "auth_time";
public static final String ZONE_ID = "zid";
+ public static final String REVOCATION_SIGNATURE = "rev_sig";
}
View
90 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/SignerProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -12,11 +12,7 @@
*******************************************************************************/
package org.cloudfoundry.identity.uaa.oauth.token;
-import java.lang.reflect.Field;
-import java.math.BigInteger;
-import java.security.interfaces.RSAPublicKey;
-
-import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
@@ -29,9 +25,11 @@
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.util.Assert;
+import java.util.List;
+
/**
* A class that knows how to provide the signing and verification keys
- *
+ *
*
*/
public class SignerProvider implements InitializingBean {
@@ -78,6 +76,10 @@ public String getVerifierKey() {
return verifierKey;
}
+ public String getSigningKey() {
+ return signingKey;
+ }
+
public String getType() {
return type;
}
@@ -98,11 +100,20 @@ public SignatureVerifier getVerifier() {
}
}
+ public String getRevocationHash(List<String> salts) {
+ String result = "";
+ for (String s : salts) {
+ byte[] hashable = (result+ "###" + s).getBytes();
+ result = Integer.toHexString(murmurhash3x8632(hashable, 0, hashable.length, 0xF0F0));
+ }
+ return result;
+ }
+
/**
* Sets the JWT signing key. It can be either a simple MAC key or an RSA
* key. RSA keys should be in OpenSSH format,
* as produced by <tt>ssh-keygen</tt>.
- *
+ *
* @param key the key to be used for signing JWTs.
*/
public void setSigningKey(String key) {
@@ -133,12 +144,12 @@ private boolean isAssymetricKey(String key) {
* The key used for verifying signatures produced by this class. This is not
* used but is returned from the endpoint
* to allow resource servers to obtain the key.
- *
+ *
* For an HMAC key it will be the same value as the signing key and does not
* need to be set. For and RSA key, it
* should be set to the String representation of the public key, in a
* standard format (e.g. OpenSSH keys)
- *
+ *
* @param verifierKey the signature verification key (typically an RSA
* public key)
*/
@@ -156,6 +167,65 @@ public void setVerifierKey(String verifierKey) {
this.verifierKey = verifierKey;
}
+ /**
+ * This code is public domain.
+ *
+ * The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain.
+ * @see - http://code.google.com/p/smhasher/
+ * @see - https://github.com/yonik/java_util/blob/master/src/util/hash/MurmurHash3.java
+ */
+ public static int murmurhash3x8632(byte[] data, int offset, int len, int seed) {
+
+ int c1 = 0xcc9e2d51;
+ int c2 = 0x1b873593;
+
+ int h1 = seed;
+ int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block
+
+ for (int i = offset; i < roundedEnd; i += 4) {
+ // little endian load order
+ int k1 = (data[i] & 0xff) | ((data[i + 1] & 0xff) << 8) | ((data[i + 2] & 0xff) << 16) | (data[i + 3] << 24);
+ k1 *= c1;
+ k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
+ k1 *= c2;
+
+ h1 ^= k1;
+ h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13);
+ h1 = h1 * 5 + 0xe6546b64;
+ }
+
+ // tail
+ int k1 = 0;
+
+ switch(len & 0x03) {
+ case 3:
+ k1 = (data[roundedEnd + 2] & 0xff) << 16;
+ // fallthrough
+ case 2:
+ k1 |= (data[roundedEnd + 1] & 0xff) << 8;
+ // fallthrough
+ case 1:
+ k1 |= data[roundedEnd] & 0xff;
+ k1 *= c1;
+ k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15);
+ k1 *= c2;
+ h1 ^= k1;
+ default:
+ }
+
+ // finalization
+ h1 ^= len;
+
+ // fmix(h1);
+ h1 ^= h1 >>> 16;
+ h1 *= 0x85ebca6b;
+ h1 ^= h1 >>> 13;
+ h1 *= 0xc2b2ae35;
+ h1 ^= h1 >>> 16;
+
+ return h1;
+ }
+
}
View
27 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/TokenRevokedException.java
@@ -0,0 +1,27 @@
+/*
+ * *****************************************************************************
+ * Cloud Foundry
+ * Copyright (c) [2009-2015] Pivotal Software, Inc. All Rights Reserved.
+ * This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ * You may not use this product except in compliance with the License.
+ *
+ * This product includes a number of subcomponents with
+ * separate copyright notices and license terms. Your use of these
+ * subcomponents is subject to the terms and conditions of the
+ * subcomponent's license, as noted in the LICENSE file.
+ * *****************************************************************************
+ */
+
+package org.cloudfoundry.identity.uaa.oauth.token;
+
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+
+public class TokenRevokedException extends InvalidTokenException {
+ public TokenRevokedException(String msg) {
+ super(msg);
+ }
+
+ public TokenRevokedException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
View
129 common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -20,6 +20,7 @@
import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication;
import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal;
import org.cloudfoundry.identity.uaa.client.ClientConstants;
+import org.cloudfoundry.identity.uaa.oauth.Claims;
import org.cloudfoundry.identity.uaa.oauth.approval.Approval;
import org.cloudfoundry.identity.uaa.oauth.approval.Approval.ApprovalStatus;
import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalStore;
@@ -37,6 +38,7 @@
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
@@ -66,7 +68,6 @@
import org.springframework.web.util.UriComponentsBuilder;
import java.net.URI;
-import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -75,6 +76,7 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -82,8 +84,8 @@
import static org.cloudfoundry.identity.uaa.oauth.Claims.ADDITIONAL_AZ_ATTR;
import static org.cloudfoundry.identity.uaa.oauth.Claims.AUD;
-import static org.cloudfoundry.identity.uaa.oauth.Claims.AZP;
import static org.cloudfoundry.identity.uaa.oauth.Claims.AUTHORITIES;
+import static org.cloudfoundry.identity.uaa.oauth.Claims.AZP;
import static org.cloudfoundry.identity.uaa.oauth.Claims.CID;
import static org.cloudfoundry.identity.uaa.oauth.Claims.CLIENT_ID;
import static org.cloudfoundry.identity.uaa.oauth.Claims.EMAIL;
@@ -101,7 +103,7 @@
/**
* This class provides token services for the UAA. It handles the production and
* consumption of UAA tokens.
- *
+ *
*/
public class UaaTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices,
InitializingBean, ApplicationEventPublisherAware {
@@ -169,17 +171,11 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque
// TODO: Need to add a lookup by id so that the refresh token does not
// need to contain a name
UaaUser user = userDatabase.retrieveUserById(userid);
+ ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
Integer refreshTokenIssuedAt = (Integer) claims.get(IAT);
long refreshTokenIssueDate = refreshTokenIssuedAt.longValue() * 1000l;
- // If the user changed their password, expire the refresh token
- if (user.getModified().after(new Date(refreshTokenIssueDate))) {
- logger.debug("User was last modified at " + user.getModified() + " refresh token was issued at "
- + new Date(refreshTokenIssueDate));
- throw new InvalidTokenException("Invalid refresh token (password changed): " + refreshTokenValue);
- }
-
Integer refreshTokenExpiry = (Integer) claims.get(EXP);
long refreshTokenExpireDate = refreshTokenExpiry.longValue() * 1000l;
@@ -208,7 +204,6 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque
// is in the refresh token
// ensure all requested scopes are approved: either automatically or
// explicitly by the user
- ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
String grantType = claims.get(GRANT_TYPE).toString();
checkForApproval(userid, clientId, requestedScopes,
getAutoApprovedScopes(grantType, tokenScopes, client),
@@ -220,6 +215,14 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque
@SuppressWarnings("unchecked")
Map<String, String> additionalAuthorizationInfo = (Map<String, String>) claims.get(ADDITIONAL_AZ_ATTR);
+ String revocableHashSignature = (String)claims.get(Claims.REVOCATION_SIGNATURE);
+ if (StringUtils.hasText(revocableHashSignature)) {
+ String newRevocableHashSignature = getRevocableTokenSignature(client, user);
+ if (!revocableHashSignature.equals(newRevocableHashSignature)) {
+ throw new TokenRevokedException(refreshTokenValue);
+ }
+ }
+
Set<String> audience = new HashSet<>((ArrayList<String>)claims.get(AUD));
OAuth2AccessToken accessToken =
@@ -235,7 +238,8 @@ public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenReque
grantType,
refreshTokenValue,
additionalAuthorizationInfo,
- new HashSet<String>()); //TODO populate response types
+ new HashSet<String>(),
+ revocableHashSignature); //TODO populate response types
return accessToken;
}
@@ -280,7 +284,8 @@ private void checkForApproval(String userid, String clientId, Collection<String>
private OAuth2AccessToken createAccessToken(String userId, String username, String userEmail, int validitySeconds,
Collection<GrantedAuthority> clientScopes, Set<String> requestedScopes, String clientId,
Set<String> resourceIds, String grantType, String refreshToken,
- Map<String, String> additionalAuthorizationAttributes, Set<String> responseTypes) throws AuthenticationException {
+ Map<String, String> additionalAuthorizationAttributes, Set<String> responseTypes,
+ String revocableHashSignature) throws AuthenticationException {
String tokenId = UUID.randomUUID().toString();
OpenIdToken accessToken = new OpenIdToken(tokenId);
if (validitySeconds > 0) {
@@ -305,7 +310,7 @@ private OAuth2AccessToken createAccessToken(String userId, String username, Stri
String content;
try {
content = JsonUtils.writeValueAsString(createJWTAccessToken(accessToken, userId, username, userEmail,
- clientScopes, requestedScopes, clientId, resourceIds, grantType, refreshToken));
+ clientScopes, requestedScopes, clientId, resourceIds, grantType, refreshToken, revocableHashSignature));
} catch (JsonUtils.JsonUtilException e) {
throw new IllegalStateException("Cannot convert access token to JSON", e);
}
@@ -329,7 +334,8 @@ private void populateIdToken(OpenIdToken token, Set<String> scopes, Set<String>
private Map<String, ?> createJWTAccessToken(OAuth2AccessToken token, String userId, String username,
String userEmail, Collection<GrantedAuthority> clientScopes, Set<String> requestedScopes,
String clientId,
- Set<String> resourceIds, String grantType, String refreshToken) {
+ Set<String> resourceIds, String grantType, String refreshToken,
+ String revocableHashSignature) {
Map<String, Object> response = new LinkedHashMap<String, Object>();
@@ -357,6 +363,10 @@ private void populateIdToken(OpenIdToken token, Set<String> scopes, Set<String>
}
}
+ if (StringUtils.hasText(revocableHashSignature)) {
+ response.put(Claims.REVOCATION_SIGNATURE, revocableHashSignature);
+ }
+
response.put(IAT, System.currentTimeMillis() / 1000);
if (token.getExpiration() != null) {
response.put(EXP, token.getExpiration().getTime() / 1000);
@@ -377,12 +387,12 @@ private void populateIdToken(OpenIdToken token, Set<String> scopes, Set<String>
@Override
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
- OAuth2RefreshToken refreshToken = createRefreshToken(authentication);
+
String userId = null;
String username = null;
String userEmail = null;
-
+ UaaUser user = null;
Collection<GrantedAuthority> clientScopes = null;
// Clients should really by different kinds of users
if (authentication.isClientOnly()) {
@@ -391,11 +401,18 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
clientScopes = client.getAuthorities();
} else {
userId = getUserId(authentication);
- UaaUser user = userDatabase.retrieveUserById(userId);
+ user = userDatabase.retrieveUserById(userId);
username = user.getUsername();
userEmail = user.getEmail();
}
+
+ ClientDetails client = clientDetailsService.loadClientByClientId(authentication.getOAuth2Request().getClientId());
+ String revocableHashSignature = getRevocableTokenSignature(client, user);
+
+ OAuth2RefreshToken refreshToken = createRefreshToken(authentication, revocableHashSignature);
+
+
String clientId = authentication.getOAuth2Request().getClientId();
Set<String> userScopes = authentication.getOAuth2Request().getScope();
String grantType = authentication.getOAuth2Request().getRequestParameters().get("grant_type");
@@ -411,7 +428,6 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
Map<String, String> additionalAuthorizationAttributes = getAdditionalAuthorizationAttributes(authentication
.getOAuth2Request().getRequestParameters().get("authorities"));
- ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
Integer validity = client.getAccessTokenValiditySeconds();
Set<String> responseTypes = extractResponseTypes(authentication);
OAuth2AccessToken accessToken =
@@ -427,7 +443,8 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
grantType,
refreshToken != null ? refreshToken.getValue() : null,
additionalAuthorizationAttributes,
- responseTypes);
+ responseTypes,
+ revocableHashSignature);
return accessToken;
}
@@ -457,7 +474,7 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
* additionalAuthorizationAttributes
* and returns a map of these attributes that will later be added to the
* token
- *
+ *
* @param authoritiesJson
* @return
*/
@@ -479,7 +496,7 @@ public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication)
return null;
}
- private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
+ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication, String revocableHashSignature) {
String grantType = authentication.getOAuth2Request().getRequestParameters().get("grant_type");
if (!isRefreshTokenSupported(grantType)) {
@@ -487,13 +504,14 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe
}
Map<String, String> additionalAuthorizationAttributes = getAdditionalAuthorizationAttributes(authentication
- .getOAuth2Request().getRequestParameters().get("authorities"));
+ .getOAuth2Request().getRequestParameters().get("authorities"));
int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
ExpiringOAuth2RefreshToken token = new DefaultExpiringOAuth2RefreshToken(UUID.randomUUID().toString(),
new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
String userId = getUserId(authentication);
+
UaaUser user = userDatabase.retrieveUserById(userId);
String content;
@@ -502,7 +520,8 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe
createJWTRefreshToken(
token, user, authentication.getOAuth2Request().getScope(),
authentication.getOAuth2Request().getClientId(),
- grantType, additionalAuthorizationAttributes,authentication.getOAuth2Request().getResourceIds()
+ grantType, additionalAuthorizationAttributes,authentication.getOAuth2Request().getResourceIds(),
+ revocableHashSignature
)
);
} catch (JsonUtils.JsonUtilException e) {
@@ -515,6 +534,26 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe
return refreshToken;
}
+ protected String getRevocableTokenSignature(ClientDetails client, UaaUser user) {
+ String[] salts = new String[] {
+ client.getClientId(),
+ client.getClientSecret(),
+ (String)client.getAdditionalInformation().get(ClientConstants.TOKEN_SALT),
+ user == null ? null : user.getId(),
+ user == null ? null : user.getPassword(),
+ user == null ? null : user.getSalt(),
+ user == null ? null : user.getEmail(),
+ user == null ? null : user.getUsername(),
+ };
+ List<String> saltlist = new LinkedList<>();
+ for (String s : salts) {
+ if (s!=null) {
+ saltlist.add(s);
+ }
+ }
+ return signerProvider.getRevocationHash(saltlist);
+ }
+
protected String getUserId(OAuth2Authentication authentication) {
return Origin.getUserId(authentication.getUserAuthentication());
}
@@ -526,7 +565,8 @@ protected String getUserId(OAuth2Authentication authentication) {
String clientId,
String grantType,
Map<String, String> additionalAuthorizationAttributes,
- Set<String> resourceIds) {
+ Set<String> resourceIds,
+ String revocableSignature) {
Map<String, Object> response = new LinkedHashMap<String, Object>();
@@ -543,6 +583,7 @@ protected String getUserId(OAuth2Authentication authentication) {
}
response.put(CID, clientId);
+ response.put(CLIENT_ID, clientId);
if (getTokenEndpoint() != null) {
response.put(ISS, getTokenEndpoint());
response.put(ZONE_ID,IdentityZoneHolder.get().getId());
@@ -556,6 +597,10 @@ protected String getUserId(OAuth2Authentication authentication) {
response.put(USER_ID, user.getId());
}
+ if (StringUtils.hasText(revocableSignature)) {
+ response.put(Claims.REVOCATION_SIGNATURE, revocableSignature);
+ }
+
response.put(AUD, resourceIds);
return response;
@@ -564,7 +609,7 @@ protected String getUserId(OAuth2Authentication authentication) {
/**
* Check the current authorization request to indicate whether a refresh
* token should be issued or not.
- *
+ *
* @param grantType the current grant type
* @return boolean to indicate if refresh token is supported
*/
@@ -575,7 +620,7 @@ protected boolean isRefreshTokenSupported(String grantType) {
/**
* The refresh token validity period in seconds
- *
+ *
* @param authorizationRequest the current authorization request
* @return the refresh token validity period in seconds
*/
@@ -661,9 +706,7 @@ public OAuth2Authentication loadAuthentication(String accessToken) throws Authen
Authentication userAuthentication = null;
// Is this a user token?
if (claims.containsKey(EMAIL)) {
- UaaUser user = new UaaUser((String) claims.get(USER_ID), (String) claims.get(USER_NAME), null,
- (String) claims.get(EMAIL), UaaAuthority.USER_AUTHORITIES, null, null, null, null, null, null, false, IdentityZoneHolder.get().getId());
-
+ UaaUser user = userDatabase.retrieveUserById((String)claims.get(USER_ID));
UaaPrincipal principal = new UaaPrincipal(user);
userAuthentication = new UaaAuthentication(principal, UaaAuthority.USER_AUTHORITIES, null);
}
@@ -709,17 +752,10 @@ public OAuth2AccessToken readAccessToken(String accessToken) {
Integer accessTokenIssuedAt = (Integer) claims.get(IAT);
long accessTokenIssueDate = accessTokenIssuedAt.longValue() * 1000l;
- // If the user changed their password, expire the access token
- if (user.getModified().after(new Date(accessTokenIssueDate))) {
- logger.debug("User was last modified at " + user.getModified() + " access token was issued at "
- + new Date(accessTokenIssueDate));
- throw new InvalidTokenException("Invalid access token (password changed): " + accessToken);
- }
-
// Check approvals to make sure they're all valid, approved and not
// more recent
// than the token itself
- String clientId = (String) claims.get(CLIENT_ID);
+ String clientId = (String) claims.get(CID);
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
@SuppressWarnings("unchecked")
@@ -779,6 +815,21 @@ public OAuth2AccessToken readAccessToken(String accessToken) {
throw new InvalidTokenException("Invalid issuer for token:"+claims.get(ISS));
}
+ String signature = (String)claims.get(Claims.REVOCATION_SIGNATURE);
+ if (signature!=null) { //this ensures backwards compatibility during upgrade
+ String clientId = (String) claims.get(Claims.CID);
+ String userId = (String) claims.get(Claims.USER_ID);
+ UaaUser user = null;
+ ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
+ try {
+ user = userDatabase.retrieveUserById(userId);
+ } catch (UsernameNotFoundException x) {
+ }
+ if (signature != null && !signature.equals(getRevocableTokenSignature(client, user))) {
+ throw new TokenRevokedException(token);
+ }
+ }
+
return claims;
}
View
20 common/src/main/java/org/cloudfoundry/identity/uaa/rest/jdbc/SimpleSearchQueryConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -34,6 +34,16 @@
private static Log logger = LogFactory.getLog(SimpleSearchQueryConverter.class);
private AttributeNameMapper mapper = new SimpleAttributeNameMapper(Collections.<String, String> emptyMap());
+ private boolean dbCaseInsensitive = false;
+
+ public boolean isDbCaseInsensitive() {
+ return dbCaseInsensitive;
+ }
+
+ public void setDbCaseInsensitive(boolean caseInsensitive) {
+ this.dbCaseInsensitive = caseInsensitive;
+ }
+
public void setAttributeNameMapper(AttributeNameMapper mapper) {
this.mapper = mapper;
}
@@ -126,9 +136,13 @@ protected String comparisonClause(SCIMFilter filter, String comparator, Map<Stri
} else if (filter.isQuoteFilterValue()) {
Object value = getStringOrDate(filter.getFilterValue());
if (value instanceof String) {
- //TODO - why lower?
+ //lower is used to satisfy the requirement that all quoted values are compared case insensitive
values.put(pName, valuePrefix+value+valueSuffix);
- return "LOWER(" + getAttributeName(filter, mapper) + ") "+comparator+" LOWER(" + paramName+")";
+ if (isDbCaseInsensitive()) {
+ return "" + getAttributeName(filter, mapper) + " "+comparator+" " + paramName+"";
+ } else {
+ return "LOWER(" + getAttributeName(filter, mapper) + ") " + comparator + " LOWER(" + paramName + ")";
+ }
} else {
values.put(pName, value);
return getAttributeName(filter, mapper) + " "+comparator+" " + paramName;
View
14 common/src/main/java/org/cloudfoundry/identity/uaa/security/web/SecurityFilterChainPostProcessor.java
@@ -108,13 +108,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
SecurityFilterChain fc = (SecurityFilterChain) bean;
- Filter uaaFilter;
-
- if (requireHttps) {
- uaaFilter = new HttpsEnforcementFilter(beanName, redirectToHttps.contains(beanName));
- } else {
- uaaFilter = new UaaLoggingFilter(beanName);
- }
+ Filter uaaFilter = new HttpsEnforcementFilter(beanName, redirectToHttps.contains(beanName));
fc.getFilters().add(0, uaaFilter);
if (additionalFilters != null) {
for (Entry<FilterPosition, Filter> entry : additionalFilters.entrySet()) {
@@ -143,6 +137,10 @@ public void setRequireHttps(boolean requireHttps) {
this.requireHttps = requireHttps;
}
+ public boolean isRequireHttps() {
+ return requireHttps;
+ }
+
/**
* Debugging feature. If enabled, and debug logging is enabled
*/
@@ -189,7 +187,7 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
- if (request.isSecure()) {
+ if (request.isSecure() || (!requireHttps)) {
// Ok. Just pass on.
if (redirect) {
// Set HSTS header for browser clients
View
8 common/src/main/java/org/cloudfoundry/identity/uaa/user/JdbcUaaUserDatabase.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -38,7 +38,7 @@
*/
public class JdbcUaaUserDatabase implements UaaUserDatabase {
- public static final String USER_FIELDS = "id,username,password,email,givenName,familyName,created,lastModified,authorities,origin,external_id,verified,identity_zone_id ";
+ public static final String USER_FIELDS = "id,username,password,email,givenName,familyName,created,lastModified,authorities,origin,external_id,verified,identity_zone_id,salt ";
public static final String DEFAULT_USER_BY_USERNAME_QUERY = "select " + USER_FIELDS + "from users "
+ "where lower(username) = ? and active=? and origin=? and identity_zone_id=?";
@@ -98,13 +98,13 @@ public UaaUser mapRow(ResultSet rs, int rowNum) throws SQLException {
if (userAuthoritiesQuery == null) {
return new UaaUser(id, rs.getString(2), rs.getString(3), rs.getString(4),
getDefaultAuthorities(rs.getString(9)), rs.getString(5), rs.getString(6),
- rs.getTimestamp(7), rs.getTimestamp(8), rs.getString(10), rs.getString(11), rs.getBoolean(12), rs.getString(13));
+ rs.getTimestamp(7), rs.getTimestamp(8), rs.getString(10), rs.getString(11), rs.getBoolean(12), rs.getString(13), rs.getString(14));
} else {
List<GrantedAuthority> authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList(getAuthorities(id));
return new UaaUser(id, rs.getString(2), rs.getString(3), rs.getString(4),
authorities, rs.getString(5), rs.getString(6),
- rs.getTimestamp(7), rs.getTimestamp(8), rs.getString(10), rs.getString(11), rs.getBoolean(12), rs.getString(13));
+ rs.getTimestamp(7), rs.getTimestamp(8), rs.getString(10), rs.getString(11), rs.getBoolean(12), rs.getString(13), rs.getString(14));
}
}
View
23 common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaUser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -22,7 +22,7 @@
/**
* User data for authentication against UAA's internal authentication provider.
- *
+ *
* @author Luke Taylor
* @author Dave Syer
* @author Joel D'sa
@@ -49,6 +49,8 @@
private final String externalId;
+ private final String salt;
+
public String getZoneId() {
return zoneId;
}
@@ -61,18 +63,18 @@ public String getZoneId() {
public UaaUser(String username, String password, String email, String givenName, String familyName) {
this("NaN", username, password, email, UaaAuthority.USER_AUTHORITIES, givenName, familyName, new Date(),
- new Date(), null, null, false,null);
+ new Date(), null, null, false,null,null);
}
public UaaUser(String username, String password, String email, String givenName, String familyName, String origin, String zoneId) {
this("NaN", username, password, email, UaaAuthority.USER_AUTHORITIES, givenName, familyName, new Date(),
- new Date(), origin, null, false, zoneId);
+ new Date(), origin, null, false, zoneId,null);
}
public UaaUser(String id, String username, String password, String email,
List<? extends GrantedAuthority> authorities,
String givenName, String familyName, Date created, Date modified,
- String origin, String externalId, boolean verified, String zoneId) {
+ String origin, String externalId, boolean verified, String zoneId, String salt) {
Assert.hasText(username, "Username cannot be empty");
Assert.hasText(id, "Id cannot be null");
Assert.hasText(email, "Email is required");
@@ -90,6 +92,7 @@ public UaaUser(String id, String username, String password, String email,
this.externalId = externalId;
this.verified = verified;
this.zoneId = zoneId;
+ this.salt = salt;
}
public String getId() {
@@ -120,6 +123,8 @@ public String getFamilyName() {
public String getExternalId() { return externalId; }
+ public String getSalt() { return salt; }
+
public List<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@@ -128,7 +133,7 @@ public UaaUser id(String id) {
if (!"NaN".equals(this.id)) {
throw new IllegalStateException("Id already set");
}
- return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId);
+ return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId, salt);
}
public UaaUser authorities(Collection<? extends GrantedAuthority> authorities) {
@@ -140,7 +145,7 @@ public UaaUser authorities(Collection<? extends GrantedAuthority> authorities) {
if (!values.contains(UaaAuthority.UAA_USER)) {
values.add(UaaAuthority.UAA_USER);
}
- UaaUser user = new UaaUser(id, username, password, email, values, givenName, familyName, created, modified, origin, externalId, verified, zoneId);
+ UaaUser user = new UaaUser(id, username, password, email, values, givenName, familyName, created, modified, origin, externalId, verified, zoneId, salt);
return user;
}
@@ -159,11 +164,11 @@ public Date getCreated() {
}
public UaaUser modifySource(String origin, String externalId) {
- return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId);
+ return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId, salt);
}
public UaaUser modifyEmail(String email) {
- return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId);
+ return new UaaUser(id, username, password, email, authorities, givenName, familyName, created, modified, origin, externalId, verified, zoneId, salt);
}
public boolean isVerified() {
View
13 common/src/main/resources/org/cloudfoundry/identity/uaa/db/hsqldb/V2_3_0__Add_SaltFieldsToUsers.sql
@@ -0,0 +1,13 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+ALTER TABLE users ADD COLUMN salt VARCHAR(36) default NULL;
View
15 common/src/main/resources/org/cloudfoundry/identity/uaa/db/hsqldb/V2_3_1__Add_Index_To_Users_Email.sql
@@ -0,0 +1,15 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+
+-- HSQLDB does not support indices with function - but we create this one to keep it in synch with the other schemas
+CREATE INDEX user_perf_email ON users(email);
View
13 common/src/main/resources/org/cloudfoundry/identity/uaa/db/mysql/V2_3_0__Add_SaltFieldsToUsers.sql
@@ -0,0 +1,13 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+ALTER TABLE users ADD COLUMN salt VARCHAR(36) default NULL;
View
16 common/src/main/resources/org/cloudfoundry/identity/uaa/db/mysql/V2_3_1__Add_Index_To_Users_Email.sql
@@ -0,0 +1,16 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+
+
+-- in mysql we turn off lower function during queries
+CREATE INDEX user_perf_email ON users(email);
View
13 common/src/main/resources/org/cloudfoundry/identity/uaa/db/postgresql/V2_3_0__Add_SaltFieldsToUsers.sql
@@ -0,0 +1,13 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+ALTER TABLE users ADD COLUMN salt VARCHAR(36) default NULL;
View
16 common/src/main/resources/org/cloudfoundry/identity/uaa/db/postgresql/V2_3_1__Add_Index_To_Users_Email.sql
@@ -0,0 +1,16 @@
+--
+-- Cloud Foundry
+-- Copyright (c) [2015] Pivotal Software, Inc. All Rights Reserved.
+--
+-- This product is licensed to you under the Apache License, Version 2.0 (the "License").
+-- You may not use this product except in compliance with the License.
+--
+-- This product includes a number of subcomponents with
+-- separate copyright notices and license terms. Your use of these
+-- subcomponents is subject to the terms and conditions of the
+-- subcomponent's license, as noted in the LICENSE file.
+--
+
+
+-- create an index to match the query
+CREATE INDEX user_perf_email ON users(LOWER(email));
View
10 common/src/test/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpointTest.java
@@ -141,6 +141,8 @@ public void testFilterIdpsForDefaultZone() throws Exception {
clientIdp = iterator.next();
assertEquals("my-client-awesome-idp", clientIdp.getIdpEntityAlias());
assertEquals(true, clientIdp.isShowSamlLink());
+ assertEquals(true, model.asMap().get("fieldUsernameShow"));
+ assertEquals(true, model.asMap().get("linkCreateAccountShow"));
}
@Test
@@ -166,6 +168,8 @@ public void testFilterIdpsWithNoSavedRequest() throws Exception {
clientIdp = iterator.next();
assertEquals("my-client-awesome-idp", clientIdp.getIdpEntityAlias());
assertEquals(true, clientIdp.isShowSamlLink());
+ assertEquals(true, model.asMap().get("fieldUsernameShow"));
+ assertEquals(true, model.asMap().get("linkCreateAccountShow"));
}
@Test
@@ -173,7 +177,7 @@ public void testFilterIDPsForAuthcodeClientInDefaultZone() throws Exception {
// mock session and saved request
MockHttpServletRequest request = getMockHttpServletRequest();
- List<String> allowedProviders = Arrays.asList("my-client-awesome-idp1", "my-client-awesome-idp2");
+ List<String> allowedProviders = Arrays.asList("my-client-awesome-idp1", "my-client-awesome-idp2", Origin.LDAP);
// mock Client service
BaseClientDetails clientDetails = new BaseClientDetails();
@@ -201,6 +205,8 @@ public void testFilterIDPsForAuthcodeClientInDefaultZone() throws Exception {
IdentityProviderDefinition clientIdp = idpDefinitions.iterator().next();
assertEquals("my-client-awesome-idp1", clientIdp.getIdpEntityAlias());
assertEquals(true, clientIdp.isShowSamlLink());
+ assertEquals(true, model.asMap().get("fieldUsernameShow"));
+ assertEquals(false, model.asMap().get("linkCreateAccountShow"));
}
@Test
@@ -240,6 +246,8 @@ public void testFilterIDPsForAuthcodeClientInOtherZone() throws Exception {
IdentityProviderDefinition clientIdp = idpDefinitions.iterator().next();
assertEquals("my-client-awesome-idp1", clientIdp.getIdpEntityAlias());
assertEquals(true, clientIdp.isShowSamlLink());
+ assertEquals(false, model.asMap().get("fieldUsernameShow"));
+ assertEquals(false, model.asMap().get("linkCreateAccountShow"));
}
@Test
View
8 .../src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/AuthzAuthenticationManagerTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -67,8 +67,9 @@
@Before
public void setUp() throws Exception {
+ String id = new RandomValueStringGenerator().generate();
user = new UaaUser(
- new RandomValueStringGenerator().generate(),
+ id,
"auser",
PASSWORD,
"auser@blah.com",
@@ -79,7 +80,8 @@ public void setUp() throws Exception {
Origin.UAA,
null,
true,
- IdentityZoneHolder.get().getId());
+ IdentityZoneHolder.get().getId(),
+ id);
db = mock(UaaUserDatabase.class);
publisher = mock(ApplicationEventPublisher.class);
mgr = new AuthzAuthenticationManager(db, encoder);
View
3  .../test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java
@@ -161,6 +161,7 @@ protected UaaUser getUaaUser() {
Origin.ORIGIN,
EXTERNAL_ID,
false,
- IdentityZoneHolder.get().getId());
+ IdentityZoneHolder.get().getId(),
+ null);
}
}
View
64 common/src/test/java/org/cloudfoundry/identity/uaa/login/SamlLoginServerKeyManagerTests.java
@@ -112,32 +112,45 @@ public void testWithWorkingCertificateInvalidPassword() throws Exception {
@Test
public void testWithWorkingCertificateNullPassword() throws Exception {
String key = "-----BEGIN RSA PRIVATE KEY-----\n" +
- "MIICXAIBAAKBgQDFOKafzTldEfTIfixO2AaYO4BJwNFkcGnlpSuku54st7wpFD37\n" +
- "+//8TbK7uJ1+kQzvhnxxgTpJmlZci4zs268IaORj1mN2XKnPfXHiaBmNsK4/Mer/\n" +
- "y2TZ9pUo7I5dDYaXucvB+ZPdV1m2wp4PsRM9sWuQGMNk16TW64Gwy24FpQIDAQAB\n" +
- "AoGAKBxyfxPNM+mgAFrxBgQXq0SGvflSXPwj/YnPS4zBCdVAlpZAWQySrqzayiUt\n" +
- "Gv3DRL/0dV1UDn4uTFoxikbP3Slpxl/fIi9onpERnads8ao3ZapYjUGNWsugq/lo\n" +
- "SJG7DtSD2ZZApZRJ2JxtUioSPL7fTUBpArpkdHPQtZhZTEECQQDvk1NSaA3e2DLR\n" +
- "zg89c+Gb/MwdeVowYprDuimqbnT/Lvll8XsPp+W81pv72sD9LpCffdFDm9E6X6tk\n" +
- "q5nYEiTRAkEA0r38uIBaSaOh+jWMRorW3ofGNZvjmevnQOy2gOem3qkKyxw/nQjg\n" +
- "NiupFuSF2wI4AYGmfBItnxddugSPlXsYlQJATu1zeuerAiqp+3LulGlT/4b2XBN5\n" +
- "wg0KPcdcKLkBNHzuT0aSK2M+DcuKUhwMjpzDqrfRtHtmH9wa5Cygn43CsQJACCrs\n" +
- "3Im89hWtdXEV2rYO1dkVSYadL54A/HcwK5bO1NpgXLbfkEqDxhWzG/wHZBGV8hkA\n" +
- "Rta9hej17Pu4RObccQJBAKs/bHRDXp+yPhVS4HVwhzDALtK5z1nn+dz3U1AxVJkU\n" +
- "L+W+bjRi0v91WH5N6lyhxGNCM0lV3DUJaimFk+N+jp0=\n" +
- "-----END RSA PRIVATE KEY-----";
+ "MIICXgIBAAKBgQDfTLadf6QgJeS2XXImEHMsa+1O7MmIt44xaL77N2K+J/JGpfV3\n" +
+ "AnkyB06wFZ02sBLB7hko42LIsVEOyTuUBird/3vlyHFKytG7UEt60Fl88SbAEfsU\n" +
+ "JN1i1aSUlunPS/NCz+BKwwKFP9Ss3rNImE9Uc2LMvGy153LHFVW2zrjhTwIDAQAB\n" +
+ "AoGBAJDh21LRcJITRBQ3CUs9PR1DYZPl+tUkE7RnPBMPWpf6ny3LnDp9dllJeHqz\n" +
+ "a3ACSgleDSEEeCGzOt6XHnrqjYCKa42Z+Opnjx/OOpjyX1NAaswRtnb039jwv4gb\n" +
+ "RlwT49Y17UAQpISOo7JFadCBoMG0ix8xr4ScY+zCSoG5v0BhAkEA8llNsiWBJF5r\n" +
+ "LWQ6uimfdU2y1IPlkcGAvjekYDkdkHiRie725Dn4qRiXyABeaqNm2bpnD620Okwr\n" +
+ "sf7LY+BMdwJBAOvgt/ZGwJrMOe/cHhbujtjBK/1CumJ4n2r5V1zPBFfLNXiKnpJ6\n" +
+ "J/sRwmjgg4u3Anu1ENF3YsxYabflBnvOP+kCQCQ8VBCp6OhOMcpErT8+j/gTGQUL\n" +
+ "f5zOiPhoC2zTvWbnkCNGlqXDQTnPUop1+6gILI2rgFNozoTU9MeVaEXTuLsCQQDC\n" +
+ "AGuNpReYucwVGYet+LuITyjs/krp3qfPhhByhtndk4cBA5H0i4ACodKyC6Zl7Tmf\n" +
+ "oYaZoYWi6DzbQQUaIsKxAkEA2rXQjQFsfnSm+w/9067ChWg46p4lq5Na2NpcpFgH\n" +
+ "waZKhM1W0oB8MX78M+0fG3xGUtywTx0D4N7pr1Tk2GTgNw==\n" +
+ "-----END RSA PRIVATE KEY-----";
String certificate = "-----BEGIN CERTIFICATE-----\n" +
- "MIIBzzCCATgCCQCWnZlNikBhATANBgkqhkiG9w0BAQUFADAsMSowKAYDVQQDFCFz\n" +
- "YW1sX2xvZ2luLE9VPXRlc3QsTz12bXdhcmUsTz1jb20wHhcNMTMwNzAzMTgwMzUx\n" +
- "WhcNMTQwNzAzMTgwMzUxWjAsMSowKAYDVQQDFCFzYW1sX2xvZ2luLE9VPXRlc3Qs\n" +
- "Tz12bXdhcmUsTz1jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMU4pp/N\n" +
- "OV0R9Mh+LE7YBpg7gEnA0WRwaeWlK6S7niy3vCkUPfv7//xNsru4nX6RDO+GfHGB\n" +
- "OkmaVlyLjOzbrwho5GPWY3Zcqc99ceJoGY2wrj8x6v/LZNn2lSjsjl0Nhpe5y8H5\n" +
- "k91XWbbCng+xEz2xa5AYw2TXpNbrgbDLbgWlAgMBAAEwDQYJKoZIhvcNAQEFBQAD\n" +
- "gYEAcahI6BwiVod/mByeTONw7yjfgYJWjtlrVMIdUwOvtuXY0carOzSL1rJTCSa1\n" +
- "qQQ7uv1sLAI4L/IqvjCwzJ5h7iuY4Uhuxyyy5HAB9hIdE35Jsny7datvJHKL85FA\n" +
- "9U1DYM28B69irMgw+w47v9t9U72jvG2Ikq6l4fEFe94XRM8=\n" +
- "-----END CERTIFICATE-----";
+ "MIIEJTCCA46gAwIBAgIJANIqfxWTfhpkMA0GCSqGSIb3DQEBBQUAMIG+MQswCQYD\n" +
+ "VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n" +
+ "aXNjbzEdMBsGA1UEChMUUGl2b3RhbCBTb2Z0d2FyZSBJbmMxJDAiBgNVBAsTG0Ns\n" +
+ "b3VkIEZvdW5kcnkgSWRlbnRpdHkgVGVhbTEcMBoGA1UEAxMTaWRlbnRpdHkuY2Yt\n" +
+ "YXBwLmNvbTEfMB0GCSqGSIb3DQEJARYQbWFyaXNzYUB0ZXN0Lm9yZzAeFw0xNTA1\n" +
+ "MTQxNzE5MTBaFw0yNTA1MTExNzE5MTBaMIG+MQswCQYDVQQGEwJVUzETMBEGA1UE\n" +
+ "CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEdMBsGA1UEChMU\n" +
+ "UGl2b3RhbCBTb2Z0d2FyZSBJbmMxJDAiBgNVBAsTG0Nsb3VkIEZvdW5kcnkgSWRl\n" +
+ "bnRpdHkgVGVhbTEcMBoGA1UEAxMTaWRlbnRpdHkuY2YtYXBwLmNvbTEfMB0GCSqG\n" +
+ "SIb3DQEJARYQbWFyaXNzYUB0ZXN0Lm9yZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" +
+ "gYkCgYEA30y2nX+kICXktl1yJhBzLGvtTuzJiLeOMWi++zdivifyRqX1dwJ5MgdO\n" +
+ "sBWdNrASwe4ZKONiyLFRDsk7lAYq3f975chxSsrRu1BLetBZfPEmwBH7FCTdYtWk\n" +
+ "lJbpz0vzQs/gSsMChT/UrN6zSJhPVHNizLxstedyxxVVts644U8CAwEAAaOCAScw\n" +
+ "ggEjMB0GA1UdDgQWBBSvWY/TyHysYGxKvII95wD/CzE1AzCB8wYDVR0jBIHrMIHo\n" +
+ "gBSvWY/TyHysYGxKvII95wD/CzE1A6GBxKSBwTCBvjELMAkGA1UEBhMCVVMxEzAR\n" +
+ "BgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xHTAbBgNV\n" +
+ "BAoTFFBpdm90YWwgU29mdHdhcmUgSW5jMSQwIgYDVQQLExtDbG91ZCBGb3VuZHJ5\n" +
+ "IElkZW50aXR5IFRlYW0xHDAaBgNVBAMTE2lkZW50aXR5LmNmLWFwcC5jb20xHzAd\n" +
+ "BgkqhkiG9w0BCQEWEG1hcmlzc2FAdGVzdC5vcmeCCQDSKn8Vk34aZDAMBgNVHRME\n" +
+ "BTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAL5j1JCN5EoXMOOBSBUL8KeVZFQD3Nfy\n" +
+ "YkYKBatFEKdBFlAKLBdG+5KzE7sTYesn7EzBISHXFz3DhdK2tg+IF1DeSFVmFl2n\n" +
+ "iVxQ1sYjo4kCugHBsWo+MpFH9VBLFzsMlP3eIDuVKe8aPXFKYCGhctZEJdQTKlja\n" +
+ "lshe50nayKrT\n" +
+ "-----END CERTIFICATE-----";
String password = null;
keyManager = new SamlLoginServerKeyManager(key, password, certificate);
@@ -145,6 +158,7 @@ public void testWithWorkingCertificateNullPassword() throws Exception {
assertNotNull(credential.getPrivateKey());
assertNotNull(credential.getPublicKey());
assertNotNull(credential);
+ System.out.println("certificate = " + certificate);
}
@Test(expected = IllegalArgumentException.class)
View
195 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpointTests.java
@@ -12,31 +12,19 @@
*******************************************************************************/
package org.cloudfoundry.identity.uaa.oauth;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-
+import org.cloudfoundry.identity.uaa.authentication.Origin;
import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationTestFactory;
-import org.cloudfoundry.identity.uaa.codestore.InMemoryExpiringCodeStore;
-import org.cloudfoundry.identity.uaa.codestore.JdbcExpiringCodeStore;
+import org.cloudfoundry.identity.uaa.client.ClientConstants;
import org.cloudfoundry.identity.uaa.oauth.approval.Approval;
import org.cloudfoundry.identity.uaa.oauth.approval.Approval.ApprovalStatus;
import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalStore;
import org.cloudfoundry.identity.uaa.oauth.approval.InMemoryApprovalStore;
import org.cloudfoundry.identity.uaa.oauth.token.SignerProvider;
+import org.cloudfoundry.identity.uaa.oauth.token.TokenRevokedException;
import org.cloudfoundry.identity.uaa.oauth.token.UaaTokenServices;
-import org.cloudfoundry.identity.uaa.user.MockUaaUserDatabase;
+import org.cloudfoundry.identity.uaa.user.UaaAuthority;
+import org.cloudfoundry.identity.uaa.user.UaaUser;
import org.cloudfoundry.identity.uaa.user.UaaUserDatabase;
-import org.cloudfoundry.identity.uaa.zone.IdentityZone;
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder;
import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture;
import org.junit.Before;
@@ -44,19 +32,33 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
-import org.springframework.security.oauth2.provider.client.BaseClientDetails;
-import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
-import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
+import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.client.BaseClientDetails;
+import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.AdditionalMatchers.not;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-/**
- * @author Dave Syer
- * @author Joel D'sa
- *
- */
@RunWith(Parameterized.class)
public class CheckTokenEndpointTests {
@@ -76,12 +78,39 @@
private String userId = "12345";
private String userName = "olds";
+ private String userEmail = "olds@vmware.com";
private String signerKey;
private String verifierKey;
private AuthorizationRequest authorizationRequest = null;
+ private UaaUser user = new UaaUser(
+ userId,
+ userName,
+ "password",
+ userEmail,
+ UaaAuthority.USER_AUTHORITIES,
+ "GivenName",
+ "FamilyName",
+ new Date(System.currentTimeMillis() - 2000),
+ new Date(System.currentTimeMillis() - 2000),
+ Origin.UAA,
+ "externalId",
+ false,
+ IdentityZoneHolder.get().getId(),
+ "salt");
+
+ private UaaUserDatabase userDatabase = null;
+
+ private BaseClientDetails defaultClient = new BaseClientDetails("client", "scim, cc", "read, write", "authorization_code, password","scim.read, scim.write", "http://localhost:8080/uaa");
+
+ private Map<String, ? extends ClientDetails> clientDetailsStore =
+ Collections.singletonMap(
+ "client",
+ defaultClient
+ );
+
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
@@ -177,8 +206,11 @@ public CheckTokenEndpointTests(String signerKey, String verifierKey) {
@Before
public void setUp() {
+ mockUserDatabase(userId, user);
authorizationRequest = new AuthorizationRequest("client", Collections.singleton("read"));
authorizationRequest.setResourceIds(new HashSet<>(Arrays.asList("client","scim")));
+ Map<String,String> requestParameters = new HashMap<>();
+ authorizationRequest.setRequestParameters(requestParameters);
authentication = new OAuth2Authentication(authorizationRequest.createOAuth2Request(),
UaaAuthenticationTestFactory.getAuthentication(userId, userName, "olds@vmware.com"));
@@ -189,9 +221,6 @@ public void setUp() {
endpoint.setTokenServices(tokenServices);
Date oneSecondAgo = new Date(System.currentTimeMillis() - 1000);
Date thirtySecondsAhead = new Date(System.currentTimeMillis() + 30000);
- UaaUserDatabase userDatabase = new MockUaaUserDatabase(userId, userName, "olds@vmware.com", null, null,
- oneSecondAgo, oneSecondAgo);
- tokenServices.setUserDatabase(userDatabase);
approvalStore.addApproval(new Approval(userId, "client", "read", thirtySecondsAhead, ApprovalStatus.APPROVED,
oneSecondAgo));
@@ -199,15 +228,20 @@ public void setUp() {
oneSecondAgo));
tokenServices.setApprovalStore(approvalStore);
- Map<String, ? extends ClientDetails> clientDetailsStore = Collections.singletonMap("client",
- new BaseClientDetails("client", "scim, cc", "read, write", "authorization_code, password",
- "scim.read, scim.write", "http://localhost:8080/uaa"));
+
clientDetailsService.setClientDetailsStore(clientDetailsStore);
tokenServices.setClientDetailsService(clientDetailsService);
accessToken = tokenServices.createAccessToken(authentication);
}
+ protected void mockUserDatabase(String userId, UaaUser user) {
+ userDatabase = mock(UaaUserDatabase.class);
+ when(userDatabase.retrieveUserById(eq(userId))).thenReturn(user);
+ when(userDatabase.retrieveUserById(not(eq(userId)))).thenThrow(new UsernameNotFoundException("mock"));
+ tokenServices.setUserDatabase(userDatabase);
+ }
+
@Test
public void testClientWildcard() throws Exception {
BaseClientDetails theclient = new BaseClientDetails("client", "zones", "zones.*.admin", "authorization_code, password",
@@ -242,6 +276,105 @@ public void testRejectInvalidVerifier() throws Exception {
endpoint.checkToken(accessToken.getValue());
}
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectUserSaltChange() throws Exception {
+ user = new UaaUser(
+ userId,
+ userName,
+ "password",
+ userEmail,
+ UaaAuthority.USER_AUTHORITIES,
+ "GivenName",
+ "FamilyName",
+ new Date(System.currentTimeMillis() - 2000),
+ new Date(System.currentTimeMillis() - 2000),
+ Origin.UAA,
+ "externalId",
+ false,
+ IdentityZoneHolder.get().getId(),
+ "changedsalt");
+ mockUserDatabase(userId, user);
+ endpoint.checkToken(accessToken.getValue());
+ }
+
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectUserUsernameChange() throws Exception {
+ user = new UaaUser(
+ userId,
+ "newUsername@test.org",
+ "password",
+ userEmail,
+ UaaAuthority.USER_AUTHORITIES,
+ "GivenName",
+ "FamilyName",
+ new Date(System.currentTimeMillis() - 2000),
+ new Date(System.currentTimeMillis() - 2000),
+ Origin.UAA,
+ "externalId",
+ false,
+ IdentityZoneHolder.get().getId(),
+ "salt");
+ mockUserDatabase(userId, user);
+ endpoint.checkToken(accessToken.getValue());
+ }
+
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectUserEmailChange() throws Exception {
+ user = new UaaUser(
+ userId,
+ userName,
+ "password",
+ "newEmail@test.org",
+ UaaAuthority.USER_AUTHORITIES,
+ "GivenName",
+ "FamilyName",
+ new Date(System.currentTimeMillis() - 2000),
+ new Date(System.currentTimeMillis() - 2000),
+ Origin.UAA,
+ "externalId",
+ false,
+ IdentityZoneHolder.get().getId(),
+ "salt");
+ mockUserDatabase(userId, user);
+ endpoint.checkToken(accessToken.getValue());
+ }
+
+
+
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectUserPasswordChange() throws Exception {
+ user = new UaaUser(
+ userId,
+ userName,
+ "changedpassword",
+ userEmail,
+ UaaAuthority.USER_AUTHORITIES,
+ "GivenName",
+ "FamilyName",
+ new Date(System.currentTimeMillis() - 2000),
+ new Date(System.currentTimeMillis() - 2000),
+ Origin.UAA,
+ "externalId",
+ false,
+ IdentityZoneHolder.get().getId(),
+ "salt");
+
+ mockUserDatabase(userId,user);
+ endpoint.checkToken(accessToken.getValue());
+ }
+
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectClientSaltChange() throws Exception {
+ defaultClient.addAdditionalInformation(ClientConstants.TOKEN_SALT, "changedsalt");
+ endpoint.checkToken(accessToken.getValue());
+ }
+
+ @Test(expected = TokenRevokedException.class)
+ public void testRejectClientPasswordChange() throws Exception {
+ defaultClient.setClientSecret("changedsecret");
+ endpoint.checkToken(accessToken.getValue());
+ }
+
@Test
public void testSwitchVerifierKey() throws Exception {
signerProvider.setSigningKey(alternateSignerKey);
View
2  common/src/test/java/org/cloudfoundry/identity/uaa/oauth/UaaAuthorizationRequestManagerTests.java
@@ -75,7 +75,7 @@ public void initUaaAuthorizationRequestManagerTests() {
factory = new UaaAuthorizationRequestManager(clientDetailsService, uaaUserDatabase, providerProvisioning);
factory.setSecurityContextAccessor(new StubSecurityContextAccessor());
when(clientDetailsService.loadClientByClientId("foo")).thenReturn(client);
- user = new UaaUser("testid", "testuser","","test@test.org",AuthorityUtils.commaSeparatedStringToAuthorityList("foo.bar,spam.baz,space.1.developer,space.2.developer,space.1.admin"),"givenname", "familyname", null, null, Origin.UAA, null, true, IdentityZone.getUaa().getId());
+ user = new UaaUser("testid", "testuser","","test@test.org",AuthorityUtils.commaSeparatedStringToAuthorityList("foo.bar,spam.baz,space.1.developer,space.2.developer,space.1.admin"),"givenname", "familyname", null, null, Origin.UAA, null, true, IdentityZone.getUaa().getId(), "testid");
when(uaaUserDatabase.retrieveUserById(anyString())).thenReturn(user);
}
View
27 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/SignerProviderTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -12,14 +12,22 @@
*******************************************************************************/
package org.cloudfoundry.identity.uaa.oauth.token;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import org.junit.Test;
+import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
+import org.springframework.util.StringUtils;
+
+import java.util.LinkedList;
+import java.util.List;
/**
- *
+ *
* @author Joel D'sa
- *
+ *
*/
public class SignerProviderTests {
@@ -84,6 +92,19 @@ public void testSignedProviderAsymmetricKeys() throws Exception {
signerProvider.getVerifier().verify("joel".getBytes(), signedValue);
}
+ @Test
+ public void testRevocationHash() throws Exception {
+ List<String> salts = new LinkedList<>();
+ for (int i=0; i<3; i++) {
+ salts.add(new RandomValueStringGenerator().generate());
+ }
+ String hash1 = signerProvider.getRevocationHash(salts);
+ String hash2 = signerProvider.getRevocationHash(salts);
+ assertFalse("Hash 1 should not be empty",StringUtils.isEmpty(hash1));
+ assertFalse("Hash 2 should not be empty", StringUtils.isEmpty(hash2));
+ assertEquals(hash1, hash2);
+ }
+
@Test(expected = IllegalStateException.class)
public void keysNotMatchingWithMacSigner() throws Exception {
signerProvider.setSigningKey("aKey");
View
63 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Cloud Foundry
+ * Cloud Foundry
* Copyright (c) [2009-2014] Pivotal Software, Inc. All Rights Reserved.
*
* This product is licensed to you under the Apache License, Version 2.0 (the "License").
@@ -74,7 +74,7 @@
/**
* @author Filip Hanik
* @author Joel D'sa
- *
+ *
*/
public class UaaTokenServicesTests {
@@ -100,7 +100,7 @@
private TestApplicationEventPublisher<TokenIssuedEvent> publisher;
private UaaTokenServices tokenServices = new UaaTokenServices();
private SignerProvider signerProvider = new SignerProvider();
-
+