From ea0b54f73a9b358f8f0c92f4cff35f0c7bba5c2a Mon Sep 17 00:00:00 2001 From: Chris Dutra <cdutra@pivotal.io> Date: Fri, 1 May 2015 15:56:48 -0700 Subject: [PATCH 1/9] Bump next develop version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d13ea101cca..544df399390 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.2.6 +version=2.2.7-SNAPSHOT From fb40fe91677ee107f685214eba23c013bf23ca5e Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Tue, 5 May 2015 09:09:01 -0600 Subject: [PATCH 2/9] Upgrade to Spring Framework 4.1.x https://www.pivotaltracker.com/story/show/93706906 [#93706906] Spring Security Oauth2 suddenly disallows GET to /oauth/token New event thrown when basic auth failed approvals_deleted becomes additionalInformation so that the clientDetailsModification is simplified. Oauth show case should use same Spring Security Oauth 2 version as parent Bump next dev version to 2.3.0 to indicate minor API change Jackson 1 is no longer supported. --- common/build.gradle | 12 +-- .../uaa/audit/event/AbstractUaaEvent.java | 32 ++++---- .../audit/event/ApprovalModifiedEvent.java | 8 +- .../uaa/audit/event/GroupModifiedEvent.java | 13 ++- .../uaa/audit/event/TokenIssuedEvent.java | 21 ++--- .../uaa/audit/event/UserModifiedEvent.java | 7 +- .../AuthzAuthenticationFilter.java | 12 ++- .../ClientParametersAuthenticationFilter.java | 13 +-- .../login/LoginInfoEndpoint.java | 5 +- .../KeystoneAuthenticationManager.java | 2 +- .../identity/uaa/client/ClientConstants.java | 1 + .../uaa/client/SocialClientUserDetails.java | 12 +-- .../identity/uaa/codestore/ExpiringCode.java | 10 +-- .../uaa/config/IdentityProviderBootstrap.java | 5 +- .../uaa/config/NestedMapPropertySource.java | 13 ++- .../identity/uaa/error/UaaException.java | 20 ++--- .../uaa/error/UaaExceptionDeserializer.java | 17 ++-- .../uaa/error/UaaExceptionSerializer.java | 16 ++-- .../ldap/LdapIdentityProviderDefinition.java | 2 +- .../identity/uaa/login/AutologinRequest.java | 7 +- .../login/PasscodeAuthenticationFilter.java | 18 ++-- .../uaa/login/PasscodeInformation.java | 10 +-- .../identity/uaa/login/SamlUserAuthority.java | 6 +- .../saml/IdentityProviderDefinition.java | 2 +- .../uaa/message/PasswordChangeRequest.java | 4 +- .../uaa/oauth/CheckTokenEndpoint.java | 13 ++- .../uaa/oauth/ClientAdminEndpoints.java | 8 +- .../JdbcQueryableClientDetailsService.java | 7 +- .../uaa/oauth/RemoteTokenServices.java | 8 +- .../uaa/oauth/SecretChangeRequest.java | 7 +- .../identity/uaa/oauth/approval/Approval.java | 11 +-- .../client/ClientDetailsModification.java | 22 ++--- ...sitiveOAuth2SecurityExpressionMethods.java | 12 +-- .../identity/uaa/oauth/token/OpenIdToken.java | 24 +++--- .../uaa/oauth/token/UaaTokenServices.java | 22 +++-- .../web/TokenEndpointPostProcessor.java | 44 ++++++++++ .../identity/uaa/user/UaaAuthority.java | 2 +- .../identity/uaa/util/JsonUtils.java | 17 +++- .../uaa/util/json/JsonDateDeserializer.java | 14 ++-- .../uaa/util/json/JsonDateSerializer.java | 12 +-- .../identity/uaa/zone/IdentityProvider.java | 6 +- .../IdentityProviderValidationRequest.java | 6 +- .../identity/uaa/zone/IdentityZone.java | 6 +- .../MultitenantJdbcClientDetailsService.java | 35 ++++---- .../config/IdentityProviderBootstrapTest.java | 62 +++++++------- .../uaa/oauth/ClientAdminEndpointsTests.java | 13 +-- .../uaa/oauth/RemoteTokenServicesTests.java | 5 +- .../ClientDetailsModificationTests.java | 47 +++++++++++ .../oauth/token/UaaTokenServicesTests.java | 36 ++++---- .../identity/uaa/rest/MessageTests.java | 8 +- .../identity/uaa/test/TestAccountSetup.java | 8 +- gradle.properties | 2 +- .../uaa/login/AccountCreationService.java | 2 +- .../login/AutologinAuthenticationManager.java | 19 ++--- .../identity/uaa/login/DescribedApproval.java | 2 +- .../login/EmailAccountCreationService.java | 11 +-- .../uaa/login/EmailInvitationsService.java | 8 +- .../uaa/login/EmailResetPasswordService.java | 10 +-- .../uaa/login/LoginUaaApprovalsService.java | 20 ++--- .../uaa/login/RestUaaApprovalsService.java | 1 - .../uaa/login/UaaExpiringCodeService.java | 26 +++--- login/src/main/resources/login-ui.xml | 5 +- .../EmailAccountCreationServiceTests.java | 6 +- .../login/EmailResetPasswordServiceTests.java | 3 +- .../uaa/login/test/MockMvcTestClient.java | 10 +-- .../main/webapp/WEB-INF/spring-servlet.xml | 8 +- .../main/webapp/WEB-INF/spring-servlet.xml | 8 +- samples/oauth-showcase/build.gradle | 2 +- .../identity/uaa/scim/ScimCore.java | 2 +- .../identity/uaa/scim/ScimGroup.java | 5 +- .../uaa/scim/ScimGroupExternalMember.java | 5 +- .../uaa/scim/ScimGroupJsonDeserializer.java | 14 ++-- .../uaa/scim/ScimGroupJsonSerializer.java | 11 +-- .../identity/uaa/scim/ScimGroupMember.java | 12 +-- .../identity/uaa/scim/ScimMeta.java | 7 +- .../identity/uaa/scim/ScimUser.java | 18 ++-- .../uaa/scim/ScimUserJsonDeserializer.java | 17 ++-- .../scim/endpoints/ChangeEmailEndpoints.java | 16 ++-- .../endpoints/PasswordResetEndpoints.java | 10 +-- .../uaa/scim/endpoints/PasswordScore.java | 4 +- .../identity/uaa/scim/ScimUserTests.java | 19 ++--- .../endpoints/ChangeEmailEndpointsTest.java | 3 +- .../endpoints/PasswordResetEndpointsTest.java | 3 +- shared_versions.gradle | 10 ++- .../WEB-INF/spring/login-server-security.xml | 4 - .../webapp/WEB-INF/spring/oauth-endpoints.xml | 2 + .../ScimUserEndpointsIntegrationTests.java | 10 +-- .../integration/feature/ImplicitGrantIT.java | 7 +- .../feature/OpenIdTokenGrantsIT.java | 41 ++++------ .../util/IntegrationTestUtils.java | 2 +- .../login/AccountsControllerMockMvcTests.java | 4 +- .../uaa/login/PasscodeMockMvcTests.java | 16 ++-- .../mock/audit/AuditCheckMvcMockTests.java | 52 ++++++------ .../ClientAdminEndpointsMockMvcTests.java | 13 ++- .../ExpiringCodeStoreMockMvcTests.java | 24 +++--- .../token/TokenKeyEndpointMockMvcTests.java | 4 +- .../uaa/mock/token/TokenMvcMockTests.java | 14 ++-- .../identity/uaa/mock/util/MockMvcUtils.java | 68 ++++++++------- ...IdentityProviderEndpointsMockMvcTests.java | 2 +- .../IdentityZoneEndpointsMockMvcTests.java | 82 +++++++++---------- ...dentityZoneSwitchingFilterMockMvcTest.java | 6 +- .../PasswordResetEndpointsMockMvcTests.java | 6 +- .../ScimGroupEndpointsMockMvcTests.java | 18 ++-- .../ScimUserEndpointsMockMvcTests.java | 18 ++-- .../endpoints/ScimUserLookupMockMvcTests.java | 10 +-- .../identity/uaa/test/TestClient.java | 19 ++--- 106 files changed, 731 insertions(+), 713 deletions(-) create mode 100644 common/src/main/java/org/cloudfoundry/identity/uaa/security/web/TokenEndpointPostProcessor.java create mode 100644 common/src/test/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModificationTests.java diff --git a/common/build.gradle b/common/build.gradle index 80ff05ddfc4..2efeee69c54 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,15 +1,15 @@ description = 'CloudFoundry Identity Common Jar' dependencies { - compile group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version:'1.47' - compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version:'1.47' + compile group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version:parent.bcpkixVersion + compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version:parent.bcpkixVersion compile group: 'org.springframework.security', name: 'spring-security-ldap', version:parent.springSecurityVersion compile group: 'org.springframework.ldap', name: 'spring-ldap-core', version:parent.springSecurityLdapVersion compile group: 'org.springframework.ldap', name: 'spring-ldap-core-tiger', version:parent.springSecurityLdapVersion - compile(group: 'org.apache.directory.api', name: 'api-ldap-model', version:'1.0.0-M22') { + compile(group: 'org.apache.directory.api', name: 'api-ldap-model', version:parent.apacheLdapApiVersion) { exclude(module: 'slf4j-api') } - compile group: 'org.springframework.security', name: 'spring-security-jwt', version:'1.0.2.RELEASE' + 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') } @@ -42,7 +42,9 @@ 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: '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: 'com.googlecode.flyway', name: 'flyway-core', version:'2.3.1' diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java index 512e5d8a219..fa7dacaba38 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/AbstractUaaEvent.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,9 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.audit.event; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; - +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; import org.cloudfoundry.identity.uaa.audit.UaaAuditService; @@ -24,9 +22,6 @@ import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; -import org.codehaus.jackson.type.TypeReference; import org.springframework.context.ApplicationEvent; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -36,21 +31,26 @@ import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + /** * Base class for UAA events that want to publish audit records. - * + * * @author Luke Taylor * @author Dave Syer - * + * */ public abstract class AbstractUaaEvent extends ApplicationEvent { - + private static final long serialVersionUID = -7639844193401892160L; private static ObjectMapper mapper = new ObjectMapper(); private transient final IdentityZone identityZone = IdentityZoneHolder.get(); { - mapper.setSerializationConfig(mapper.getSerializationConfig().withSerializationInclusion(Inclusion.NON_NULL)); + mapper.setConfig(mapper.getSerializationConfig().withSerializationInclusion(JsonInclude.Include.NON_NULL)); } private Authentication authentication; @@ -102,7 +102,7 @@ protected String getOrigin(Principal principal) { else { builder.append("caller=").append(caller.getName()); } - + if (caller.getDetails() != null) { builder.append(", details=("); @@ -140,13 +140,13 @@ protected String getOrigin(Principal principal) { } public abstract AuditEvent getAuditEvent(); - + protected static Authentication getContextAuthentication() { Authentication a = SecurityContextHolder.getContext().getAuthentication(); if (a==null) { a = new Authentication() { private static final long serialVersionUID = 1748694836774597624L; - + ArrayList<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); @Override public Collection<? extends GrantedAuthority> getAuthorities() { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/ApprovalModifiedEvent.java b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/ApprovalModifiedEvent.java index 87916cbba4d..e1032c3bfd7 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/ApprovalModifiedEvent.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/ApprovalModifiedEvent.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,7 +17,7 @@ import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.security.core.Authentication; import java.io.IOException; @@ -46,8 +46,8 @@ public AuditEvent getAuditEvent() { private String getData(Approval source) { try { - return new ObjectMapper().writeValueAsString(new ApprovalModifiedEventData(source)); - } catch (IOException e) { + return JsonUtils.writeValueAsString(new ApprovalModifiedEventData(source)); + } catch (JsonUtils.JsonUtilException e) { logger.error("error writing approval event data", e); } return null; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/GroupModifiedEvent.java b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/GroupModifiedEvent.java index db5fc8f71e3..ac87ce4a705 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/GroupModifiedEvent.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/GroupModifiedEvent.java @@ -15,12 +15,12 @@ package org.cloudfoundry.identity.uaa.audit.event; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; -import org.codehaus.jackson.annotate.JsonCreator; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -74,10 +74,7 @@ public static GroupModifiedEvent groupDeleted(String group, String name, String[ @Override public AuditEvent getAuditEvent() { - String data = null; - try { - data = new ObjectMapper().writeValueAsString(new GroupInfo(groupName, members)); - } catch (IOException e) { } + String data = JsonUtils.writeValueAsString(new GroupInfo(groupName, members)); return createAuditRecord( groupId, eventType, diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.java b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.java index e30315aa598..83b55d82d06 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/TokenIssuedEvent.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,22 +12,20 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.audit.event; +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.security.core.Authentication; import org.springframework.security.jwt.Jwt; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.oauth2.common.OAuth2AccessToken; import java.io.IOException; -import java.security.Principal; import java.util.Map; public class TokenIssuedEvent extends AbstractUaaEvent { - private ObjectMapper mapper = new ObjectMapper(); public TokenIssuedEvent(OAuth2AccessToken source, Authentication principal) { super(source, principal); @@ -43,21 +41,14 @@ public OAuth2AccessToken getSource() { @Override public AuditEvent getAuditEvent() { - String data = null; - try { - data = mapper.writeValueAsString(getSource().getScope()); - } catch (IOException e) { } + String data = JsonUtils.writeValueAsString(getSource().getScope()); return createAuditRecord(getPrincipalId(), AuditEventType.TokenIssuedEvent, getOrigin(getAuthentication()), data); } private String getPrincipalId() { OAuth2AccessToken token = getSource(); Jwt jwt = JwtHelper.decode(token.getValue()); - try { - Map<String, Object> claims = mapper.readValue(jwt.getClaims(), new TypeReference<Map<String, Object>>() {}); - return (claims.get("user_id") != null ? claims.get("user_id") : claims.get("client_id")).toString(); - } catch (IOException e) { - return null; - } + Map<String, Object> claims = JsonUtils.readValue(jwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + return (claims.get("user_id") != null ? claims.get("user_id") : claims.get("client_id")).toString(); } } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/UserModifiedEvent.java b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/UserModifiedEvent.java index 611c4fa3065..43381263ae5 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/UserModifiedEvent.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/audit/event/UserModifiedEvent.java @@ -17,7 +17,7 @@ import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.security.core.Authentication; import java.io.IOException; @@ -90,10 +90,7 @@ public static UserModifiedEvent emailChanged(String userId, String username, Str @Override public AuditEvent getAuditEvent() { String[] details = {"user_id="+userId, "username="+username}; - String data = null; - try { - data = new ObjectMapper().writeValueAsString(details); - } catch (IOException e) { } + String data = JsonUtils.writeValueAsString(details); return createAuditRecord( userId, eventType, diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/AuthzAuthenticationFilter.java b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/AuthzAuthenticationFilter.java index 936c3bbdbc1..87115f99432 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/AuthzAuthenticationFilter.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/AuthzAuthenticationFilter.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"). @@ -31,10 +31,10 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; @@ -70,8 +70,6 @@ public class AuthzAuthenticationFilter implements Filter { private AuthenticationManager authenticationManager; - private ObjectMapper mapper = new ObjectMapper(); - private List<String> parameterNames = Collections.emptyList(); private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); @@ -190,11 +188,11 @@ private Map<String, String> getCredentials(HttpServletRequest request) { if (value != null) { if (value.startsWith("{")) { try { - Map<String, String> jsonCredentials = mapper.readValue(value, + Map<String, String> jsonCredentials = JsonUtils.readValue(value, new TypeReference<Map<String, String>>() { }); credentials.putAll(jsonCredentials); - } catch (IOException e) { + } catch (JsonUtils.JsonUtilException e) { logger.warn("Unknown format of value for request param: " + paramName + ". Ignoring."); } } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/ClientParametersAuthenticationFilter.java b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/ClientParametersAuthenticationFilter.java index f3f10b2f4b0..607cc9760b8 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/ClientParametersAuthenticationFilter.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/ClientParametersAuthenticationFilter.java @@ -16,9 +16,6 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; -import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -28,10 +25,8 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.provider.AuthorizationRequest; import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.util.Assert; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -40,17 +35,11 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; /** * Filter which processes and authenticates a client based on @@ -58,7 +47,7 @@ * It sets the authentication to a client only * Oauth2Authentication object as that is expected by * the LoginAuthenticationManager. - * + * */ public class ClientParametersAuthenticationFilter implements Filter { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java index ede2b43b3c9..05903335d01 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java @@ -27,10 +27,10 @@ import org.cloudfoundry.identity.uaa.login.saml.IdentityProviderDefinition; import org.cloudfoundry.identity.uaa.login.saml.LoginSamlAuthenticationToken; import org.cloudfoundry.identity.uaa.user.UaaAuthority; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.UaaStringUtils; import org.cloudfoundry.identity.uaa.util.UaaUrlUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.core.env.Environment; import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.http.HttpStatus; @@ -53,7 +53,6 @@ import org.springframework.web.util.UriComponentsBuilder; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -400,7 +399,7 @@ public String generatePasscode(Map<String, Object> model, Principal principal) protected ExpiringCode doGenerateCode(Object o) throws IOException { return expiringCodeStore.generateCode( - new ObjectMapper().writeValueAsString(o), + JsonUtils.writeValueAsString(o), new Timestamp(System.currentTimeMillis() + (getCodeExpirationMillis())) ); } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/KeystoneAuthenticationManager.java b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/KeystoneAuthenticationManager.java index d6ca687fdb3..9f9d02db503 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/KeystoneAuthenticationManager.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/KeystoneAuthenticationManager.java @@ -15,7 +15,7 @@ package org.cloudfoundry.identity.uaa.authentication.manager; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java b/common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java index 76e96fc5eb6..9f8de7ae4e0 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/client/ClientConstants.java @@ -17,4 +17,5 @@ public class ClientConstants { public static final String AUTO_APPROVE = "autoapprove"; public static final String CREATED_WITH = "createdwith"; public static final String CLIENT_NAME = "name"; + public static final String APPROVALS_DELETED = "approvals_deleted"; } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/client/SocialClientUserDetails.java b/common/src/main/java/org/cloudfoundry/identity/uaa/client/SocialClientUserDetails.java index 5d534c4fdc3..2afd48921d9 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/client/SocialClientUserDetails.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/client/SocialClientUserDetails.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"). @@ -14,17 +14,17 @@ import java.util.Collection; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.cloudfoundry.identity.uaa.user.UaaAuthority; -import org.codehaus.jackson.annotate.JsonCreator; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonDeserialize; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; /** * Customized {@code UserDetails} implementation. - * + * * @author Luke Taylor * @author Dave Syer */ diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/codestore/ExpiringCode.java b/common/src/main/java/org/cloudfoundry/identity/uaa/codestore/ExpiringCode.java index 004b4e799e5..e4afea35e03 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/codestore/ExpiringCode.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/codestore/ExpiringCode.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,11 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.codestore; -import java.sql.Timestamp; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; +import java.sql.Timestamp; @JsonSerialize @JsonDeserialize diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrap.java b/common/src/main/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrap.java index e27c365cf5b..35ca411859c 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrap.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrap.java @@ -27,7 +27,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityProvider; import org.cloudfoundry.identity.uaa.zone.IdentityProviderProvisioning; import org.cloudfoundry.identity.uaa.zone.IdentityZone; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.env.Environment; import org.springframework.dao.EmptyResultDataAccessException; @@ -62,8 +61,8 @@ protected void addSamlProviders() { provider.setOriginKey(def.getIdpEntityAlias()); provider.setName("UAA SAML Identity Provider["+provider.getOriginKey()+"]"); try { - provider.setConfig(new ObjectMapper().writeValueAsString(def)); - } catch (IOException x) { + provider.setConfig(JsonUtils.writeValueAsString(def)); + } catch (JsonUtils.JsonUtilException x) { throw new RuntimeException("Non serializable LDAP config"); } providers.add(provider); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/config/NestedMapPropertySource.java b/common/src/main/java/org/cloudfoundry/identity/uaa/config/NestedMapPropertySource.java index 74b0cb1388f..6fc8ba7a36f 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/config/NestedMapPropertySource.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/config/NestedMapPropertySource.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"). @@ -29,9 +29,9 @@ * A property source based on a map that might contain nested maps and * collections. Property keys can be nested using * period separators. - * + * * @author Dave Syer - * + * */ public class NestedMapPropertySource extends MapPropertySource { @@ -59,10 +59,15 @@ public Object getProperty(String name) { return value; } + @Override + public boolean containsProperty(String name) { + return null != getProperty(name); + } + @Override public String[] getPropertyNames() { populateCache(); - return this.cache.keySet().toArray(EMPTY_NAMES_ARRAY); + return this.cache.keySet().toArray(new String[0]); } private void populateCache() { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaException.java b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaException.java index 4d6c6658d15..cfc4117b9e4 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaException.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaException.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,16 +12,16 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.error; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.Map; import java.util.Set; import java.util.TreeMap; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; - /** * Base exception for UAA exceptions. - * + * * @author Dave Syer */ @JsonSerialize(using = UaaExceptionSerializer.class) @@ -71,7 +71,7 @@ public UaaException(Throwable cause, String error, String description, int statu } /** * The error code. - * + * * @return The error code. */ public String getErrorCode() { @@ -80,7 +80,7 @@ public String getErrorCode() { /** * The HTTP status associated with this error. - * + * * @return The HTTP status associated with this error. */ public int getHttpStatus() { @@ -89,7 +89,7 @@ public int getHttpStatus() { /** * Get any additional information associated with this error. - * + * * @return Additional information, or null if none. */ public Map<String, String> getAdditionalInformation() { @@ -98,7 +98,7 @@ public Map<String, String> getAdditionalInformation() { /** * Add some additional information with this OAuth error. - * + * * @param key The key. * @param value The value. */ @@ -113,7 +113,7 @@ public void addAdditionalInformation(String key, String value) { /** * Creates an {@link UaaException} from a Map<String,String>. - * + * * @param errorParams * @return */ diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionDeserializer.java b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionDeserializer.java index 577dd2954ba..18df7483f91 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionDeserializer.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionDeserializer.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,26 +12,27 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.error; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; /** * @author Dave Syer - * + * */ public class UaaExceptionDeserializer extends JsonDeserializer<UaaException> { @Override public UaaException deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, - JsonProcessingException { + JsonProcessingException { int status = 400; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionSerializer.java b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionSerializer.java index 4687883ddb9..511eca4e532 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionSerializer.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/error/UaaExceptionSerializer.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,23 +12,23 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.error; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + import java.io.IOException; import java.util.Map.Entry; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; - /** * @author Dave Syer - * + * */ public class UaaExceptionSerializer extends JsonSerializer<UaaException> { @Override public void serialize(UaaException value, JsonGenerator jgen, SerializerProvider provider) throws IOException, - JsonProcessingException { + JsonProcessingException { jgen.writeStartObject(); jgen.writeStringField("error", value.getErrorCode()); jgen.writeStringField("error_description", value.getMessage()); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/LdapIdentityProviderDefinition.java b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/LdapIdentityProviderDefinition.java index 896d5b26d9c..a2bcae8d1ca 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/LdapIdentityProviderDefinition.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/LdapIdentityProviderDefinition.java @@ -12,7 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.ldap; -import org.codehaus.jackson.annotate.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.core.env.AbstractEnvironment; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinRequest.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinRequest.java index 86bcca4e495..acdc25b04ac 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinRequest.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinRequest.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,10 +12,9 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; +import com.fasterxml.jackson.annotation.JsonInclude; -@JsonSerialize(include = Inclusion.NON_EMPTY) +@JsonInclude(JsonInclude.Include.NON_EMPTY) public class AutologinRequest { private String username; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeAuthenticationFilter.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeAuthenticationFilter.java index 15a450e5c5a..40f4dc96b12 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeAuthenticationFilter.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeAuthenticationFilter.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"). @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.authentication.BackwardsCompatibleTokenEndpointAuthenticationFilter; @@ -39,9 +40,8 @@ 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.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; @@ -56,7 +56,7 @@ /** * Authentication filter to verify one time passwords with what's cached in the * one time password store. - * + * * */ public class PasscodeAuthenticationFilter extends BackwardsCompatibleTokenEndpointAuthenticationFilter { @@ -65,8 +65,6 @@ public class PasscodeAuthenticationFilter extends BackwardsCompatibleTokenEndpoi private List<String> parameterNames = Collections.emptyList(); - private final ObjectMapper mapper = new ObjectMapper(); - public PasscodeAuthenticationFilter(UaaUserDatabase uaaUserDatabase, AuthenticationManager authenticationManager, OAuth2RequestFactory oAuth2RequestFactory, ExpiringCodeStore expiringCodeStore) { super( new ExpiringCodeAuthenticationManager( @@ -191,8 +189,8 @@ public Authentication authenticate(Authentication authentication) throws Authent PasscodeInformation pi = null; if (eCode != null && eCode.getData() != null) { try { - pi = new ObjectMapper().readValue(eCode.getData(), PasscodeInformation.class); - } catch (IOException e) { + pi = JsonUtils.readValue(eCode.getData(), PasscodeInformation.class); + } catch (JsonUtils.JsonUtilException e) { throw new InsufficientAuthenticationException("Unable to deserialize passcode object.", e); } } @@ -256,11 +254,11 @@ private Map<String, String> getCredentials(HttpServletRequest request) { if (value != null) { if (value.startsWith("{")) { try { - Map<String, String> jsonCredentials = mapper.readValue(value, + Map<String, String> jsonCredentials = JsonUtils.readValue(value, new TypeReference<Map<String, String>>() { }); credentials.putAll(jsonCredentials); - } catch (IOException e) { + } catch (JsonUtils.JsonUtilException e) { logger.warn("Unknown format of value for request param: " + paramName + ". Ignoring."); } } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeInformation.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeInformation.java index d535fb8ddf2..deb523396a1 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeInformation.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/PasscodeInformation.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,16 +12,16 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import org.codehaus.jackson.annotate.JsonCreator; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; - //TODO - make object serialize/deserialize properly with JSON public class PasscodeInformation { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/SamlUserAuthority.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/SamlUserAuthority.java index 0ede539bfce..d174e4ecb4a 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/SamlUserAuthority.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/SamlUserAuthority.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,8 +12,8 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login; -import org.codehaus.jackson.annotate.JsonCreator; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.security.core.GrantedAuthority; @SuppressWarnings("serial") diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/IdentityProviderDefinition.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/IdentityProviderDefinition.java index 04ea0b0cce9..b911b68e256 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/IdentityProviderDefinition.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/saml/IdentityProviderDefinition.java @@ -12,8 +12,8 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login.saml; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.cloudfoundry.identity.uaa.login.util.FileLocator; -import org.codehaus.jackson.annotate.JsonIgnore; import java.io.File; import java.io.IOException; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/message/PasswordChangeRequest.java b/common/src/main/java/org/cloudfoundry/identity/uaa/message/PasswordChangeRequest.java index 333612e5e95..3aed2647ec8 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/message/PasswordChangeRequest.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/message/PasswordChangeRequest.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,7 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.message; -import org.codehaus.jackson.map.annotate.JsonSerialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; /** * @author Dave Syer diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpoint.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpoint.java index 2b8da0c8167..128fd767241 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpoint.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/CheckTokenEndpoint.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"). @@ -14,10 +14,10 @@ import java.util.Map; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.http.ResponseEntity; import org.springframework.security.core.AuthenticationException; @@ -39,7 +39,7 @@ /** * Controller which decodes access tokens for clients who are not able to do so * (or where opaque token values are used). - * + * * @author Luke Taylor * @author Joel D'sa */ @@ -47,7 +47,6 @@ public class CheckTokenEndpoint implements InitializingBean { private ResourceServerTokenServices resourceServerTokenServices; - private ObjectMapper mapper = new ObjectMapper(); protected final Log logger = LogFactory.getLog(getClass()); private WebResponseExceptionTranslator exceptionTranslator = new DefaultWebResponseExceptionTranslator(); @@ -95,9 +94,9 @@ private Map<String, Object> getClaimsForToken(String token) { Map<String, Object> claims = null; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { }); - } catch (Exception e) { + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot read token claims", e); } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java index 62b534a9917..08d30ec0668 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpoints.java @@ -211,7 +211,7 @@ public ClientDetails createClientDetails(@RequestBody BaseClientDetails client) @ResponseStatus(HttpStatus.CREATED) @ResponseBody @Transactional - public ClientDetails[] createClientDetailsTx(@RequestBody BaseClientDetails[] clients) throws Exception { + public ClientDetails[] createClientDetailsTx(@RequestBody ClientDetailsModification[] clients) throws Exception { if (clients==null || clients.length==0) { throw new NoSuchClientException("Message body does not contain any clients."); } @@ -234,7 +234,7 @@ protected ClientDetails[] doInsertClientDetails(ClientDetails[] details) { @ResponseStatus(HttpStatus.OK) @Transactional @ResponseBody - public ClientDetails[] updateClientDetailsTx(@RequestBody BaseClientDetails[] clients) throws Exception { + public ClientDetails[] updateClientDetailsTx(@RequestBody ClientDetailsModification[] clients) throws Exception { if (clients==null || clients.length==0) { throw new InvalidClientDetailsException("No clients specified for update."); } @@ -295,7 +295,7 @@ public ClientDetails updateClientDetails(@RequestBody BaseClientDetails client, @ResponseBody public ClientDetails removeClientDetails(@PathVariable String client) throws Exception { ClientDetails details = clientDetailsService.retrieve(client); - doProcessDeletes(new ClientDetails[] {details}); + doProcessDeletes(new ClientDetails[]{details}); return removeSecret(details); } @@ -303,7 +303,7 @@ public ClientDetails removeClientDetails(@PathVariable String client) throws Exc @ResponseStatus(HttpStatus.OK) @Transactional @ResponseBody - public ClientDetails[] removeClientDetailsTx(@RequestBody BaseClientDetails[] details) throws Exception { + public ClientDetails[] removeClientDetailsTx(@RequestBody ClientDetailsModification[] details) throws Exception { ClientDetails[] result = new ClientDetails[details.length]; for (int i=0; i<result.length; i++) { result[i] = clientDetailsService.retrieve(details[i].getClientId()); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/JdbcQueryableClientDetailsService.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/JdbcQueryableClientDetailsService.java index 2e298334719..3c5d95b20e8 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/JdbcQueryableClientDetailsService.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/JdbcQueryableClientDetailsService.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,8 +22,8 @@ import org.cloudfoundry.identity.uaa.rest.QueryableResourceManager; import org.cloudfoundry.identity.uaa.rest.jdbc.AbstractQueryable; import org.cloudfoundry.identity.uaa.rest.jdbc.JdbcPagingListFactory; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.security.oauth2.provider.client.BaseClientDetails; @@ -100,7 +100,6 @@ public ClientDetails delete(String id, int version) { } private static class ClientDetailsRowMapper implements RowMapper<ClientDetails> { - private ObjectMapper mapper = new ObjectMapper(); @Override public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { @@ -117,7 +116,7 @@ public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { if (json != null) { try { @SuppressWarnings("unchecked") - Map<String, Object> additionalInformation = mapper.readValue(json, Map.class); + Map<String, Object> additionalInformation = JsonUtils.readValue(json, Map.class); details.setAdditionalInformation(additionalInformation); } catch (Exception e) { logger.warn("Could not decode JSON for additional information: " + details, e); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServices.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServices.java index b8982e94109..4093c9e9b96 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServices.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServices.java @@ -23,7 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -69,8 +69,6 @@ public class RemoteTokenServices implements ResourceServerTokenServices { private String clientSecret; - private ObjectMapper mapper = new ObjectMapper(); - private boolean storeClaims = false; public RemoteTokenServices() { @@ -170,8 +168,8 @@ public OAuth2Authentication loadAuthentication(String accessToken) throws Authen if (map.containsKey(Claims.ADDITIONAL_AZ_ATTR)) { try { - requestParameters.put(Claims.ADDITIONAL_AZ_ATTR, mapper.writeValueAsString(map.get(Claims.ADDITIONAL_AZ_ATTR))); - } catch (IOException e) { + requestParameters.put(Claims.ADDITIONAL_AZ_ATTR, JsonUtils.writeValueAsString(map.get(Claims.ADDITIONAL_AZ_ATTR))); + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot convert access token to JSON", e); } } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/SecretChangeRequest.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/SecretChangeRequest.java index 05082c7e786..793119ac379 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/SecretChangeRequest.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/SecretChangeRequest.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,13 +12,14 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth; -import org.codehaus.jackson.map.annotate.JsonSerialize; + +import com.fasterxml.jackson.annotation.JsonInclude; /** * @author Dave Syer * @author Luke Taylor */ -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class SecretChangeRequest { private String oldSecret; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/approval/Approval.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/approval/Approval.java index c77ca39bac8..eb6ba17dbff 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/approval/Approval.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/approval/Approval.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"). @@ -15,13 +15,14 @@ import java.util.Calendar; import java.util.Date; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.cloudfoundry.identity.uaa.util.json.JsonDateDeserializer; import org.cloudfoundry.identity.uaa.util.json.JsonDateSerializer; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class Approval { private String userId; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModification.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModification.java index 31302be94f2..39296bb1bcb 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModification.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModification.java @@ -1,13 +1,14 @@ package org.cloudfoundry.identity.uaa.oauth.client; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.cloudfoundry.identity.uaa.client.ClientConstants; import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT) +@JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) public class ClientDetailsModification extends BaseClientDetails { @@ -20,8 +21,6 @@ public class ClientDetailsModification extends BaseClientDetails { @JsonProperty("action") private String action = NONE; - @JsonProperty("approvals_deleted") - private boolean approvalsDeleted = false; public ClientDetailsModification() { } @@ -65,12 +64,15 @@ public void setAction(String action) { @JsonIgnore public boolean isApprovalsDeleted() { - return approvalsDeleted; + if (getAdditionalInformation().get(ClientConstants.APPROVALS_DELETED)!=null) { + return Boolean.TRUE.equals(getAdditionalInformation().get(ClientConstants.APPROVALS_DELETED)); + } + return false; } @JsonIgnore public void setApprovalsDeleted(boolean approvalsDeleted) { - this.approvalsDeleted = approvalsDeleted; + addAdditionalInformation(ClientConstants.APPROVALS_DELETED, approvalsDeleted); } @JsonIgnore diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/expression/ContextSensitiveOAuth2SecurityExpressionMethods.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/expression/ContextSensitiveOAuth2SecurityExpressionMethods.java index f563e87f280..a920ed323fe 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/expression/ContextSensitiveOAuth2SecurityExpressionMethods.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/expression/ContextSensitiveOAuth2SecurityExpressionMethods.java @@ -12,14 +12,12 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth.expression; -import java.util.Map; - +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; import org.cloudfoundry.identity.uaa.oauth.Claims; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.springframework.security.core.Authentication; import org.springframework.security.jwt.Jwt; import org.springframework.security.jwt.JwtHelper; @@ -27,6 +25,8 @@ import org.springframework.security.oauth2.provider.expression.OAuth2SecurityExpressionMethods; import org.springframework.util.StringUtils; +import java.util.Map; + public class ContextSensitiveOAuth2SecurityExpressionMethods extends OAuth2SecurityExpressionMethods { public static final String ZONE_ID = "{zone.id}"; @@ -120,8 +120,8 @@ private String getZoneIdFromToken(String token) { } Map<String, Object> claims = null; try { - claims = new ObjectMapper().readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); - } catch (Exception e) { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot read token claims", e); } return (String)claims.get(Claims.ZONE_ID); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/OpenIdToken.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/OpenIdToken.java index d0ae54b06b2..a08691a6b7c 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/OpenIdToken.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/OpenIdToken.java @@ -18,14 +18,16 @@ import java.util.Map; import java.util.Set; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.SerializerProvider; -import org.codehaus.jackson.map.deser.StdDeserializer; -import org.codehaus.jackson.map.ser.SerializerBase; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; @@ -33,8 +35,8 @@ import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.util.Assert; -@org.codehaus.jackson.map.annotate.JsonSerialize(using = OpenIdToken.OpenIdTokenJackson1Serializer.class) -@org.codehaus.jackson.map.annotate.JsonDeserialize(using = OpenIdToken.OpenIdTokenJackson1Deserializer.class) +@JsonSerialize(using = OpenIdToken.OpenIdTokenJackson1Serializer.class) +@JsonDeserialize(using = OpenIdToken.OpenIdTokenJackson1Deserializer.class) public class OpenIdToken extends DefaultOAuth2AccessToken { public static String ID_TOKEN = "id_token"; @@ -57,7 +59,7 @@ public OpenIdToken(OAuth2AccessToken accessToken) { super(accessToken); } - public static final class OpenIdTokenJackson1Serializer extends SerializerBase<OAuth2AccessToken> { + public static final class OpenIdTokenJackson1Serializer extends StdSerializer<OAuth2AccessToken> { public OpenIdTokenJackson1Serializer() { super(OAuth2AccessToken.class); diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java index d6a5f170159..67d4b6a5a61 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServices.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth.token; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.audit.event.TokenIssuedEvent; @@ -25,10 +26,9 @@ 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.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.UaaTokenUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; @@ -115,8 +115,6 @@ public class UaaTokenServices implements AuthorizationServerTokenServices, Resou private UaaUserDatabase userDatabase = null; - private ObjectMapper mapper = new ObjectMapper(); - private ClientDetailsService clientDetailsService = null; private SignerProvider signerProvider = new SignerProvider(); @@ -306,9 +304,9 @@ private OAuth2AccessToken createAccessToken(String userId, String username, Stri String content; try { - content = mapper.writeValueAsString(createJWTAccessToken(accessToken, userId, username, userEmail, - clientScopes, requestedScopes, clientId, resourceIds, grantType, refreshToken)); - } catch (Exception e) { + content = JsonUtils.writeValueAsString(createJWTAccessToken(accessToken, userId, username, userEmail, + clientScopes, requestedScopes, clientId, resourceIds, grantType, refreshToken)); + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot convert access token to JSON", e); } String token = JwtHelper.encode(content, signerProvider.getSigner()).getEncoded(); @@ -467,7 +465,7 @@ private Map<String, String> getAdditionalAuthorizationAttributes(String authorit if (StringUtils.hasLength(authoritiesJson)) { try { @SuppressWarnings("unchecked") - Map<String, Object> authorities = mapper.readValue(authoritiesJson.getBytes(), Map.class); + Map<String, Object> authorities = JsonUtils.readValue(authoritiesJson, new TypeReference<Map<String, Object>>() {}); @SuppressWarnings("unchecked") Map<String, String> additionalAuthorizationAttributes = (Map<String, String>) authorities .get("az_attr"); @@ -500,14 +498,14 @@ private ExpiringOAuth2RefreshToken createRefreshToken(OAuth2Authentication authe String content; try { - content = mapper.writeValueAsString( + content = JsonUtils.writeValueAsString( createJWTRefreshToken( token, user, authentication.getOAuth2Request().getScope(), authentication.getOAuth2Request().getClientId(), grantType, additionalAuthorizationAttributes,authentication.getOAuth2Request().getResourceIds() ) ); - } catch (Exception e) { + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot convert access token to JSON", e); } String jwtToken = JwtHelper.encode(content, signerProvider.getSigner()).getEncoded(); @@ -771,9 +769,9 @@ private Map<String, Object> getClaimsForToken(String token) { Map<String, Object> claims = null; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { }); - } catch (Exception e) { + } catch (JsonUtils.JsonUtilException e) { throw new IllegalStateException("Cannot read token claims", e); } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/TokenEndpointPostProcessor.java b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/TokenEndpointPostProcessor.java new file mode 100644 index 00000000000..427041f6d0b --- /dev/null +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/TokenEndpointPostProcessor.java @@ -0,0 +1,44 @@ +/* + * ***************************************************************************** + * 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.security.web; + + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.http.HttpMethod; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; + +import java.util.HashSet; +import java.util.Set; + +public class TokenEndpointPostProcessor implements BeanPostProcessor { + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean != null && bean instanceof TokenEndpoint) { + TokenEndpoint endpoint = (TokenEndpoint)bean; + Set<HttpMethod> methods = new HashSet<>(); + methods.add(HttpMethod.POST); + methods.add(HttpMethod.GET); + endpoint.setAllowedRequestMethods(methods); + } + return bean; + } +} diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaAuthority.java b/common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaAuthority.java index 19f61a1d3cc..19bcd63deb8 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaAuthority.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/user/UaaAuthority.java @@ -16,7 +16,7 @@ import java.util.Collections; import java.util.List; -import org.codehaus.jackson.annotate.JsonCreator; +import com.fasterxml.jackson.annotation.JsonCreator; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/util/JsonUtils.java b/common/src/main/java/org/cloudfoundry/identity/uaa/util/JsonUtils.java index 15aec9b38ec..3fdab46a186 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/util/JsonUtils.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/util/JsonUtils.java @@ -12,10 +12,13 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.util; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; public class JsonUtils { private static ObjectMapper objectMapper = new ObjectMapper(); @@ -60,6 +63,16 @@ public static <T> T convertValue(Object object, Class<T> toClazz) throws JsonUti } } + public static JsonNode readTree(String s) { + try { + return objectMapper.readTree(s); + } catch (JsonProcessingException e) { + throw new JsonUtilException(e); + } catch (IOException e) { + throw new JsonUtilException(e); + } + } + public static class JsonUtilException extends RuntimeException { private static final long serialVersionUID = -4804245225960963421L; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateDeserializer.java b/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateDeserializer.java index 89e0e8c381c..c3df8de4df1 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateDeserializer.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateDeserializer.java @@ -12,17 +12,17 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.util.json; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; - /** * JSON deserializer for Jackson to handle regular date instances as timestamps * in ISO format. @@ -36,7 +36,7 @@ public class JsonDateDeserializer extends JsonDeserializer<Date> { @Override public Date deserialize(JsonParser parser, DeserializationContext context) throws IOException, - JsonProcessingException { + JsonProcessingException { try { return dateFormat.parse(parser.getText()); } catch (ParseException e) { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateSerializer.java b/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateSerializer.java index 5d2c0378de8..7186a0afc40 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateSerializer.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/util/json/JsonDateSerializer.java @@ -12,15 +12,15 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.util.json; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; - /** * JSON serializer for Jackson to handle regular date instances as timestamps in * ISO format. @@ -34,7 +34,7 @@ public class JsonDateSerializer extends JsonSerializer<Date> { @Override public void serialize(Date date, JsonGenerator generator, SerializerProvider provider) throws IOException, - JsonProcessingException { + JsonProcessingException { String formatted = dateFormat.format(date); generator.writeString(formatted); } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProvider.java b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProvider.java index 8d4c0a7591b..51a1830f86d 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProvider.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProvider.java @@ -15,10 +15,10 @@ import javax.validation.constraints.NotNull; import java.util.Date; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.util.JsonUtils; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.type.TypeReference; public class IdentityProvider { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProviderValidationRequest.java b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProviderValidationRequest.java index d907d9e7235..d8957b9173d 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProviderValidationRequest.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityProviderValidationRequest.java @@ -12,9 +12,9 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.zone; -import org.codehaus.jackson.annotate.JsonCreator; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityZone.java b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityZone.java index 1ef750319db..746f1d2dfa9 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityZone.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/IdentityZone.java @@ -12,10 +12,10 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.zone; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.cloudfoundry.identity.uaa.authentication.Origin; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; import javax.validation.constraints.NotNull; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsService.java b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsService.java index 09c0b293ba8..712fed9b262 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsService.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsService.java @@ -12,22 +12,10 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.zone; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -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 java.util.Set; - -import javax.sql.DataSource; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.rest.ResourceMonitor; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -46,9 +34,18 @@ import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * A copy of JdbcClientDetailsService but with IdentityZone awareness */ @@ -299,23 +296,19 @@ interface JsonMapper { } private static JsonMapper createJsonMapper() { - if (ClassUtils.isPresent("org.codehaus.jackson.map.ObjectMapper", null)) { - return new JacksonMapper(); - } - return new NotSupportedJsonMapper(); + return new JacksonMapper(); } private static class JacksonMapper implements JsonMapper { - private org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper(); @Override public String write(Object input) throws Exception { - return mapper.writeValueAsString(input); + return JsonUtils.writeValueAsString(input); } @Override public <T> T read(String input, Class<T> type) throws Exception { - return mapper.readValue(input, type); + return JsonUtils.readValue(input, type); } } diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrapTest.java b/common/src/test/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrapTest.java index 21b1fda4be3..cd64137a225 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrapTest.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/config/IdentityProviderBootstrapTest.java @@ -14,33 +14,33 @@ package org.cloudfoundry.identity.uaa.config; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.login.saml.IdentityProviderConfigurator; import org.cloudfoundry.identity.uaa.login.saml.IdentityProviderDefinition; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityProvider; import org.cloudfoundry.identity.uaa.zone.IdentityProviderProvisioning; -import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.JdbcIdentityProviderProvisioning; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.mock.env.MockEnvironment; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class IdentityProviderBootstrapTest extends JdbcTestBase { @After @@ -79,7 +79,7 @@ public void testLdapBootstrap() throws Exception { IdentityProvider ldapProvider = provisioning.retrieveByOrigin(Origin.LDAP, IdentityZoneHolder.get().getId()); assertNotNull(ldapProvider); - assertEquals(new ObjectMapper().writeValueAsString(ldapConfig), ldapProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(ldapConfig), ldapProvider.getConfig()); assertNotNull(ldapProvider.getCreated()); assertNotNull(ldapProvider.getLastModified()); assertEquals(Origin.LDAP, ldapProvider.getType()); @@ -96,7 +96,7 @@ public void testRemovedLdapBootstrapIsInactive() throws Exception { IdentityProvider ldapProvider = provisioning.retrieveByOrigin(Origin.LDAP, IdentityZoneHolder.get().getId()); assertNotNull(ldapProvider); - assertEquals(new ObjectMapper().writeValueAsString(ldapConfig), ldapProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(ldapConfig), ldapProvider.getConfig()); assertNotNull(ldapProvider.getCreated()); assertNotNull(ldapProvider.getLastModified()); assertEquals(Origin.LDAP, ldapProvider.getType()); @@ -115,7 +115,7 @@ public void testRemovedLdapBootstrapIsInactive() throws Exception { bootstrap.afterPropertiesSet(); ldapProvider = provisioning.retrieveByOrigin(Origin.LDAP, IdentityZoneHolder.get().getId()); assertNotNull(ldapProvider); - assertEquals(new ObjectMapper().writeValueAsString(ldapConfig), ldapProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(ldapConfig), ldapProvider.getConfig()); assertNotNull(ldapProvider.getCreated()); assertNotNull(ldapProvider.getLastModified()); assertEquals(Origin.LDAP, ldapProvider.getType()); @@ -153,7 +153,7 @@ public void testKeystoneBootstrap() throws Exception { IdentityProvider keystoneProvider = provisioning.retrieveByOrigin(Origin.KEYSTONE, IdentityZoneHolder.get().getId()); assertNotNull(keystoneProvider); - assertEquals(new ObjectMapper().writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); assertNotNull(keystoneProvider.getCreated()); assertNotNull(keystoneProvider.getLastModified()); assertEquals(Origin.KEYSTONE, keystoneProvider.getType()); @@ -170,7 +170,7 @@ public void testRemovedKeystoneBootstrapIsInactive() throws Exception { IdentityProvider keystoneProvider = provisioning.retrieveByOrigin(Origin.KEYSTONE, IdentityZoneHolder.get().getId()); assertNotNull(keystoneProvider); - assertEquals(new ObjectMapper().writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); assertNotNull(keystoneProvider.getCreated()); assertNotNull(keystoneProvider.getLastModified()); assertEquals(Origin.KEYSTONE, keystoneProvider.getType()); @@ -189,7 +189,7 @@ public void testRemovedKeystoneBootstrapIsInactive() throws Exception { bootstrap.afterPropertiesSet(); keystoneProvider = provisioning.retrieveByOrigin(Origin.KEYSTONE, IdentityZoneHolder.get().getId()); assertNotNull(keystoneProvider); - assertEquals(new ObjectMapper().writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(keystoneConfig), keystoneProvider.getConfig()); assertNotNull(keystoneProvider.getCreated()); assertNotNull(keystoneProvider.getLastModified()); assertEquals(Origin.KEYSTONE, keystoneProvider.getType()); @@ -219,7 +219,7 @@ public void testSamlBootstrap() throws Exception { IdentityProvider samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); definition.setZoneId(IdentityZoneHolder.get().getId()); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -252,7 +252,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { IdentityProvider samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); definition.setZoneId(IdentityZoneHolder.get().getId()); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -261,7 +261,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { IdentityProvider samlProvider2 = provisioning.retrieveByOrigin(definition2.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider2); definition2.setZoneId(IdentityZoneHolder.get().getId()); - assertEquals(new ObjectMapper().writeValueAsString(definition2), samlProvider2.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition2), samlProvider2.getConfig()); assertNotNull(samlProvider2.getCreated()); assertNotNull(samlProvider2.getLastModified()); assertEquals(Origin.SAML, samlProvider2.getType()); @@ -274,7 +274,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -282,7 +282,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider2 = provisioning.retrieveByOrigin(definition2.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider2); - assertEquals(new ObjectMapper().writeValueAsString(definition2), samlProvider2.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition2), samlProvider2.getConfig()); assertNotNull(samlProvider2.getCreated()); assertNotNull(samlProvider2.getLastModified()); assertEquals(Origin.SAML, samlProvider2.getType()); @@ -295,7 +295,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -303,7 +303,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider2 = provisioning.retrieveByOrigin(definition2.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider2); - assertEquals(new ObjectMapper().writeValueAsString(definition2), samlProvider2.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition2), samlProvider2.getConfig()); assertNotNull(samlProvider2.getCreated()); assertNotNull(samlProvider2.getLastModified()); assertEquals(Origin.SAML, samlProvider2.getType()); @@ -316,7 +316,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -324,7 +324,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider2 = provisioning.retrieveByOrigin(definition2.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider2); - assertEquals(new ObjectMapper().writeValueAsString(definition2), samlProvider2.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition2), samlProvider2.getConfig()); assertNotNull(samlProvider2.getCreated()); assertNotNull(samlProvider2.getLastModified()); assertEquals(Origin.SAML, samlProvider2.getType()); @@ -337,7 +337,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider = provisioning.retrieveByOrigin(definition.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider); - assertEquals(new ObjectMapper().writeValueAsString(definition), samlProvider.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition), samlProvider.getConfig()); assertNotNull(samlProvider.getCreated()); assertNotNull(samlProvider.getLastModified()); assertEquals(Origin.SAML, samlProvider.getType()); @@ -345,7 +345,7 @@ public void testRemovedSamlBootstrapIsInactive() throws Exception { samlProvider2 = provisioning.retrieveByOrigin(definition2.getIdpEntityAlias(), IdentityZoneHolder.get().getId()); assertNotNull(samlProvider2); - assertEquals(new ObjectMapper().writeValueAsString(definition2), samlProvider2.getConfig()); + assertEquals(JsonUtils.writeValueAsString(definition2), samlProvider2.getConfig()); assertNotNull(samlProvider2.getCreated()); assertNotNull(samlProvider2.getLastModified()); assertEquals(Origin.SAML, samlProvider2.getType()); diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpointsTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpointsTests.java index f9cd82b8cb0..efc0e732e54 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpointsTests.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/ClientAdminEndpointsTests.java @@ -33,6 +33,7 @@ import org.cloudfoundry.identity.uaa.error.UaaException; import org.cloudfoundry.identity.uaa.oauth.ClientDetailsValidator.Mode; import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalStore; +import org.cloudfoundry.identity.uaa.oauth.client.ClientDetailsModification; import org.cloudfoundry.identity.uaa.rest.QueryableResourceManager; import org.cloudfoundry.identity.uaa.rest.ResourceMonitor; import org.cloudfoundry.identity.uaa.rest.SearchResults; @@ -68,7 +69,7 @@ public class ClientAdminEndpointsTests { private BaseClientDetails input = null; - private BaseClientDetails[] inputs = new BaseClientDetails[5]; + private ClientDetailsModification[] inputs = new ClientDetailsModification[5]; private BaseClientDetails detail = null; @@ -129,7 +130,7 @@ public void setUp() throws Exception { input.setAuthorizedGrantTypes(Arrays.asList("authorization_code")); for (int i=0; i<inputs.length; i++) { - inputs[i] = new BaseClientDetails(); + inputs[i] = new ClientDetailsModification(); inputs[i].setClientId("foo-"+i); inputs[i].setClientSecret("secret-"+i); inputs[i].setAuthorizedGrantTypes(Arrays.asList("authorization_code")); @@ -208,13 +209,13 @@ public void testMultipleCreateClientDetailsNullArray() throws Exception { @Test(expected = NoSuchClientException.class) public void testMultipleCreateClientDetailsEmptyArray() throws Exception { - endpoints.createClientDetailsTx(new BaseClientDetails[0]); + endpoints.createClientDetailsTx(new ClientDetailsModification[0]); } @Test(expected = InvalidClientDetailsException.class) public void testMultipleCreateClientDetailsNonExistent() throws Exception { - BaseClientDetails nonexist = new BaseClientDetails("unknown","","","",""); - endpoints.createClientDetailsTx(new BaseClientDetails[]{nonexist}); + ClientDetailsModification nonexist = new ClientDetailsModification("unknown","","","",""); + endpoints.createClientDetailsTx(new ClientDetailsModification[]{nonexist}); } @Test(expected = InvalidClientDetailsException.class) @@ -224,7 +225,7 @@ public void testMultipleUpdateClientDetailsNullArray() throws Exception { @Test(expected = InvalidClientDetailsException.class) public void testMultipleUpdateClientDetailsEmptyArray() throws Exception { - endpoints.updateClientDetailsTx(new BaseClientDetails[0]); + endpoints.updateClientDetailsTx(new ClientDetailsModification[0]); } diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServicesTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServicesTests.java index 9850362dad7..85109df64e9 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServicesTests.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/RemoteTokenServicesTests.java @@ -20,7 +20,7 @@ import java.util.HashMap; import java.util.Map; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.Test; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -104,14 +104,13 @@ public void testTokenRetrievalWithUserAuthorities() throws Exception { @Test public void testTokenRetrievalWithAdditionalAuthorizationAttributes() throws Exception { - ObjectMapper mapper = new ObjectMapper(); Map additionalAuthorizationAttributesMap = Collections.singletonMap("test", 1); body.put(Claims.ADDITIONAL_AZ_ATTR, additionalAuthorizationAttributesMap); OAuth2Authentication result = services.loadAuthentication("FOO"); assertNotNull(result); - assertEquals(mapper.writeValueAsString(additionalAuthorizationAttributesMap), result.getOAuth2Request() + assertEquals(JsonUtils.writeValueAsString(additionalAuthorizationAttributesMap), result.getOAuth2Request() .getRequestParameters().get(Claims.ADDITIONAL_AZ_ATTR)); } } diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModificationTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModificationTests.java new file mode 100644 index 00000000000..ee1d019e125 --- /dev/null +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/client/ClientDetailsModificationTests.java @@ -0,0 +1,47 @@ +/* + * ***************************************************************************** + * 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.client; + +import org.cloudfoundry.identity.uaa.util.JsonUtils; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** + * Created by fhanik on 5/5/15. + */ +public class ClientDetailsModificationTests { + + @Test + public void testClientDetailsModificationDeserialize() throws Exception { + String data = "{\"scope\":\n" + + " [\"bar\",\"foo\",\"oauth.approvals\"],\n" + + " \"client_id\":\"Kn30XB\",\n" + + " \"resource_ids\":[\"none\"],\n" + + " \"authorized_grant_types\":[\"password\",\"refresh_token\"],\n" + + " \"autoapprove\":[],\n" + + " \"action\":\"none\",\n" + + " \"approvals_deleted\":true,\n" + + " \"authorities\":[\"uaa.none\"],\n" + + " \"action\":\"none\",\n" + + " \"foo\":[\"bar\"],\n" + + " \"lastModified\":1430849491767\n" + + " }"; + + ClientDetailsModification details = JsonUtils.readValue(data, ClientDetailsModification.class); + assertTrue(details.isApprovalsDeleted()); + + } +} \ No newline at end of file diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java index eb83915f11d..24d52157306 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/oauth/token/UaaTokenServicesTests.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth.token; +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.audit.AuditEvent; import org.cloudfoundry.identity.uaa.audit.AuditEventType; import org.cloudfoundry.identity.uaa.audit.event.TokenIssuedEvent; @@ -28,10 +29,9 @@ import org.cloudfoundry.identity.uaa.user.InMemoryUaaUserDatabase; import org.cloudfoundry.identity.uaa.user.UaaAuthority; import org.cloudfoundry.identity.uaa.user.UaaUser; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -100,7 +100,6 @@ public class UaaTokenServicesTests { private TestApplicationEventPublisher<TokenIssuedEvent> publisher; private UaaTokenServices tokenServices = new UaaTokenServices(); private SignerProvider signerProvider = new SignerProvider(); - private ObjectMapper mapper = new ObjectMapper(); private List<GrantedAuthority> defaultUserAuthorities = Arrays.asList( UaaAuthority.authority("space.123.developer"), @@ -236,7 +235,8 @@ public void testCreateAccessTokenForAClient() { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { + }); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -284,7 +284,7 @@ public void testCreateAccessTokenForAClientInAnotherIdentityZone() { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -382,7 +382,7 @@ public void testCreateAccessTokenRefreshGrant() throws InterruptedException { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -433,7 +433,7 @@ public void testCreateAccessTokenRefreshGrantAllScopesAutoApproved() throws Inte assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -484,7 +484,7 @@ public void testCreateAccessTokenRefreshGrantSomeScopesAutoApprovedDowngradedReq assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -541,7 +541,7 @@ public void testCreateAccessTokenRefreshGrantSomeScopesAutoApproved() throws Int assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -666,7 +666,7 @@ private OAuth2AccessToken testCreateAccessTokenForAUser(OAuth2Authentication aut assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -693,7 +693,7 @@ private OAuth2AccessToken testCreateAccessTokenForAUser(OAuth2Authentication aut assertNotNull(refreshTokenJwt); Map<String, Object> refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -761,7 +761,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -773,7 +773,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(refreshTokenJwt); Map<String, Object> refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -796,7 +796,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(tokenJwt); Map<String, Object> reducedClaims; try { - reducedClaims = mapper.readValue(newTokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + reducedClaims = JsonUtils.readValue(newTokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -826,7 +826,7 @@ public void testCreateAccessTokenAuthcodeGrantExpandedScopes() { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -838,7 +838,7 @@ public void testCreateAccessTokenAuthcodeGrantExpandedScopes() { assertNotNull(refreshTokenJwt); Map<String, Object> refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -877,7 +877,7 @@ public void testChangedExpiryForTokens() { assertNotNull(tokenJwt); Map<String, Object> claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -891,7 +891,7 @@ public void testChangedExpiryForTokens() { assertNotNull(refreshTokenJwt); Map<String, Object> refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference<Map<String, Object>>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/rest/MessageTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/rest/MessageTests.java index fbdb654b475..01ac497fc96 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/rest/MessageTests.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/rest/MessageTests.java @@ -18,7 +18,7 @@ import java.io.StringWriter; import org.cloudfoundry.identity.uaa.message.SimpleMessage; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.Test; /** @@ -30,15 +30,13 @@ public class MessageTests { @Test public void testSerialize() throws Exception { - StringWriter writer = new StringWriter(); - new ObjectMapper().writeValue(writer, new SimpleMessage("ok", "done")); - assertEquals("{\"status\":\"ok\",\"message\":\"done\"}", writer.toString()); + assertEquals("{\"status\":\"ok\",\"message\":\"done\"}", JsonUtils.writeValueAsString(new SimpleMessage("ok", "done"))); } @Test public void testDeserialize() throws Exception { String value = "{\"status\":\"ok\",\"message\":\"done\"}"; - SimpleMessage message = new ObjectMapper().readValue(value, SimpleMessage.class); + SimpleMessage message = JsonUtils.readValue(value, SimpleMessage.class); assertEquals(new SimpleMessage("ok", "done"), message); } diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/test/TestAccountSetup.java b/common/src/test/java/org/cloudfoundry/identity/uaa/test/TestAccountSetup.java index 07fde31eebd..16eead0f5b0 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/test/TestAccountSetup.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/test/TestAccountSetup.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"). @@ -39,7 +39,7 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; -import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; @@ -56,7 +56,7 @@ /** * @author Dave Syer - * + * */ public class TestAccountSetup extends TestWatchman { @@ -278,7 +278,7 @@ public void handleError(ClientHttpResponse response) throws IOException { }); List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>(); list.add(new StringHttpMessageConverter()); - list.add(new MappingJacksonHttpMessageConverter()); + list.add(new MappingJackson2HttpMessageConverter()); client.setMessageConverters(list); return client; } diff --git a/gradle.properties b/gradle.properties index 544df399390..65362284ef9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.2.7-SNAPSHOT +version=2.3.0-SNAPSHOT diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/AccountCreationService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/AccountCreationService.java index 6a34aa62337..276922c8baf 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/AccountCreationService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/AccountCreationService.java @@ -1,7 +1,7 @@ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.annotation.JsonProperty; import org.cloudfoundry.identity.uaa.scim.ScimUser; -import org.codehaus.jackson.annotate.JsonProperty; import java.io.IOException; diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinAuthenticationManager.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinAuthenticationManager.java index 5925f8167cc..d9c384984fe 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinAuthenticationManager.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/AutologinAuthenticationManager.java @@ -13,9 +13,6 @@ package org.cloudfoundry.identity.uaa.login; -import java.io.IOException; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.authentication.AuthzAuthenticationRequest; @@ -25,20 +22,16 @@ import org.cloudfoundry.identity.uaa.client.SocialClientUserDetails; import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; -import org.springframework.web.client.RestTemplate; + +import java.io.IOException; +import java.util.Map; /** * @author Dave Syer @@ -77,9 +70,9 @@ public Authentication authenticate(Authentication authentication) throws Authent SocialClientUserDetails user = null; try { if (ec != null) { - user = new ObjectMapper().readValue(ec.getData(), SocialClientUserDetails.class); + user = JsonUtils.readValue(ec.getData(), SocialClientUserDetails.class); } - } catch (IOException x) { + } catch (JsonUtils.JsonUtilException x) { throw new BadCredentialsException("JsonConversion error", x); } diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/DescribedApproval.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/DescribedApproval.java index 0f5922bdf4e..0320c67ac93 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/DescribedApproval.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/DescribedApproval.java @@ -13,8 +13,8 @@ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.codehaus.jackson.annotate.JsonIgnore; public class DescribedApproval extends Approval { private String description; diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationService.java index 51667378f84..61e7ef31db0 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationService.java @@ -1,5 +1,6 @@ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.authentication.Origin; @@ -9,11 +10,10 @@ import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; import org.cloudfoundry.identity.uaa.scim.exception.ScimResourceAlreadyExistsException; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.UaaUrlUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.springframework.http.HttpStatus; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; @@ -42,10 +42,8 @@ public class EmailAccountCreationService implements AccountCreationService { private final ClientDetailsService clientDetailsService; private final String brand; private final UaaUrlUtils uaaUrlUtils; - private final ObjectMapper objectMapper; public EmailAccountCreationService( - ObjectMapper objectMapper, SpringTemplateEngine templateEngine, MessageService messageService, ExpiringCodeStore codeStore, @@ -54,7 +52,6 @@ public EmailAccountCreationService( UaaUrlUtils uaaUrlUtils, String brand) { - this.objectMapper = objectMapper; this.templateEngine = templateEngine; this.messageService = messageService; this.codeStore= codeStore; @@ -103,7 +100,7 @@ private ExpiringCode getExpiringCode(String userId, String clientId, Timestamp e Map<String, String> codeData = new HashMap<>(); codeData.put("user_id", userId); codeData.put("client_id", clientId); - String codeDataString = objectMapper.writeValueAsString(codeData); + String codeDataString = JsonUtils.writeValueAsString(codeData); return new ExpiringCode(null, expiresAt, codeDataString); } @@ -116,7 +113,7 @@ public AccountCreationResponse completeActivation(String code) throws IOExceptio throw new HttpClientErrorException(HttpStatus.BAD_REQUEST); } - Map<String, String> data = objectMapper.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); + Map<String, String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); ScimUser user = scimUserProvisioning.retrieve(data.get("user_id")); user = scimUserProvisioning.verifyUser(user.getId(), user.getVersion()); diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailInvitationsService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailInvitationsService.java index 288febf317c..5050af807ac 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailInvitationsService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailInvitationsService.java @@ -8,15 +8,13 @@ import org.cloudfoundry.identity.uaa.oauth.ClientAdminEndpoints; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.ClientDetails; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.thymeleaf.context.Context; import org.thymeleaf.spring4.SpringTemplateEngine; @@ -97,7 +95,7 @@ public void inviteUser(String email, String currentUser) { } catch (HttpClientErrorException e) { String uaaResponse = e.getResponseBodyAsString(); try { - ExistingUserResponse existingUserResponse = new ObjectMapper().readValue(uaaResponse, ExistingUserResponse.class); + ExistingUserResponse existingUserResponse = JsonUtils.readValue(uaaResponse, ExistingUserResponse.class); if (existingUserResponse.getVerified()) { throw new UaaException(e.getStatusText(), e.getStatusCode().value()); } @@ -106,6 +104,8 @@ public void inviteUser(String email, String currentUser) { data.put("email", email); String code = expiringCodeService.generateCode(data, INVITATION_EXPIRY_DAYS, TimeUnit.DAYS); sendInvitationEmail(email, existingUserResponse.getUserId(), currentUser, code); + } catch (JsonUtils.JsonUtilException ioe) { + logger.warn("couldn't invite user",ioe); } catch (IOException ioe) { logger.warn("couldn't invite user",ioe); } diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordService.java index af90c828a37..7ab0c5a47cf 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordService.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,15 +12,15 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.error.UaaException; import org.cloudfoundry.identity.uaa.scim.endpoints.PasswordResetEndpoints; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.UaaUrlUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; @@ -71,10 +71,10 @@ public void forgotPassword(String email) { if (e.getStatusCode() == HttpStatus.CONFLICT) { htmlContent = getResetUnavailableEmailHtml(email); try { - Map<String, String> body = new ObjectMapper().readValue(e.getResponseBodyAsString(), new TypeReference<Map<String, String>>() { + Map<String, String> body = JsonUtils.readValue(e.getResponseBodyAsString(), new TypeReference<Map<String, String>>() { }); userId = body.get("user_id"); - } catch (IOException ioe) { + } catch (JsonUtils.JsonUtilException ioe) { logger.error("Bad response from UAA", ioe); } diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/LoginUaaApprovalsService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/LoginUaaApprovalsService.java index a4ced9ac16c..6622ce41538 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/LoginUaaApprovalsService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/LoginUaaApprovalsService.java @@ -12,27 +12,17 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.login; +import org.cloudfoundry.identity.uaa.authentication.Origin; +import org.cloudfoundry.identity.uaa.oauth.approval.Approval; +import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalsControllerService; +import org.springframework.beans.factory.annotation.Autowired; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; - -import javassist.runtime.Desc; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.cloudfoundry.identity.uaa.authentication.Origin; -import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalsAdminEndpoints; -import org.cloudfoundry.identity.uaa.oauth.approval.ApprovalsControllerService; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestOperations; public class LoginUaaApprovalsService implements ApprovalsService { diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/RestUaaApprovalsService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/RestUaaApprovalsService.java index 81eb6fe409c..ef37632e853 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/RestUaaApprovalsService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/RestUaaApprovalsService.java @@ -16,7 +16,6 @@ import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.codehaus.jackson.annotate.JsonIgnore; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaExpiringCodeService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaExpiringCodeService.java index e0904cebc16..ba758400864 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaExpiringCodeService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaExpiringCodeService.java @@ -1,19 +1,16 @@ package org.cloudfoundry.identity.uaa.login; +import com.fasterxml.jackson.core.type.TypeReference; +import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; +import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore; +import org.cloudfoundry.identity.uaa.util.JsonUtils; +import org.springframework.stereotype.Component; + import java.io.IOException; import java.sql.Timestamp; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; -import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; - -import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.RestTemplate; - @Component public class UaaExpiringCodeService implements ExpiringCodeService { @@ -26,7 +23,7 @@ public UaaExpiringCodeService(ExpiringCodeStore codeStore) { @Override public String generateCode(Object data, int expiryTime, TimeUnit timeUnit) throws IOException { Timestamp expiry = new Timestamp(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(expiryTime, timeUnit)); - String dataJsonString = new ObjectMapper().writeValueAsString(data); + String dataJsonString = JsonUtils.writeValueAsString(data); return codeStore.generateCode(dataJsonString, expiry).getCode(); } @@ -37,8 +34,8 @@ public <T> T verifyCode(Class<T> clazz, String code) throws IOException, CodeNot if (code==null || expiringCode==null) { throw new CodeNotFoundException(); } - return new ObjectMapper().readValue(expiringCode.getData(), clazz); - } catch (IOException e) { + return JsonUtils.readValue(expiringCode.getData(), clazz); + } catch (JsonUtils.JsonUtilException e) { throw new CodeNotFoundException(); } } @@ -50,8 +47,9 @@ public Map<String,String> verifyCode(String code) throws IOException, CodeNotFou if (expiringCode==null) { throw new CodeNotFoundException(); } - return new ObjectMapper().readValue(expiringCode.getData(), new TypeReference<Map<String,String>>() {}); - } catch (IOException e) { + return JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() { + }); + } catch (JsonUtils.JsonUtilException e) { throw new CodeNotFoundException(); } } diff --git a/login/src/main/resources/login-ui.xml b/login/src/main/resources/login-ui.xml index 9fa70c18a9d..e3d326deaae 100644 --- a/login/src/main/resources/login-ui.xml +++ b/login/src/main/resources/login-ui.xml @@ -309,7 +309,7 @@ </list> </property> <property name="defaultViews"> - <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"> + <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"> <property name="extractValueFromSingleKeyModel" value="true" /> </bean> </property> @@ -341,9 +341,6 @@ </bean> <bean id="accountCreationService" class="org.cloudfoundry.identity.uaa.login.EmailAccountCreationService"> - <constructor-arg> - <bean class="org.codehaus.jackson.map.ObjectMapper"/> - </constructor-arg> <constructor-arg ref="mailTemplateEngine"/> <constructor-arg ref="messageService"/> <constructor-arg ref="codeStore"/> diff --git a/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationServiceTests.java b/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationServiceTests.java index 80f7d9d74d2..2578682401b 100644 --- a/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationServiceTests.java +++ b/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailAccountCreationServiceTests.java @@ -26,10 +26,10 @@ import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; import org.cloudfoundry.identity.uaa.scim.exception.ScimResourceAlreadyExistsException; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.UaaUrlUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; -import org.codehaus.jackson.map.ObjectMapper; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; @@ -76,7 +76,6 @@ public void setUp() throws Exception { clientDetailsService = mock(ClientDetailsService.class); details = mock(ClientDetails.class); emailAccountCreationService = new EmailAccountCreationService( - new ObjectMapper(), templateEngine, messageService, codeStore, @@ -144,7 +143,6 @@ public void testBeginActivationInOtherZone() throws Exception { @Test public void testBeginActivationWithOssBrand() throws Exception { emailAccountCreationService = new EmailAccountCreationService( - new ObjectMapper(), templateEngine, messageService, codeStore, @@ -304,7 +302,7 @@ private void setUpForSuccess() throws Exception { Map<String,Object> data = new HashMap<>(); data.put("user_id","newly-created-user-id"); data.put("client_id", "login"); - code = new ExpiringCode("the_secret_code", ts, new ObjectMapper().writeValueAsString(data)); + code = new ExpiringCode("the_secret_code", ts, JsonUtils.writeValueAsString(data)); Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put(EmailAccountCreationService.SIGNUP_REDIRECT_URL, "http://example.com/redirect"); diff --git a/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordServiceTests.java b/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordServiceTests.java index 8c795cd7eb8..588b4f3f3cd 100644 --- a/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordServiceTests.java +++ b/login/src/test/java/org/cloudfoundry/identity/uaa/login/EmailResetPasswordServiceTests.java @@ -38,7 +38,6 @@ import org.cloudfoundry.identity.uaa.util.UaaUrlUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; -import org.codehaus.jackson.map.ObjectMapper; import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; @@ -79,7 +78,7 @@ public void setUp() throws Exception { messageService = mock(EmailService.class); scimUserProvisioning = mock(ScimUserProvisioning.class); codeStore = mock(ExpiringCodeStore.class); - passwordResetEndpoints = new PasswordResetEndpoints(new ObjectMapper(), scimUserProvisioning, codeStore); + passwordResetEndpoints = new PasswordResetEndpoints(scimUserProvisioning, codeStore); uaaUrlUtils = new UaaUrlUtils("http://uaa.example.com/uaa"); emailResetPasswordService = new EmailResetPasswordService(templateEngine, messageService, passwordResetEndpoints, uaaUrlUtils, "pivotal"); } diff --git a/login/src/test/java/org/cloudfoundry/identity/uaa/login/test/MockMvcTestClient.java b/login/src/test/java/org/cloudfoundry/identity/uaa/login/test/MockMvcTestClient.java index 309f45eef66..43d53011df8 100644 --- a/login/src/test/java/org/cloudfoundry/identity/uaa/login/test/MockMvcTestClient.java +++ b/login/src/test/java/org/cloudfoundry/identity/uaa/login/test/MockMvcTestClient.java @@ -15,10 +15,10 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.codec.binary.Base64; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; @@ -31,11 +31,9 @@ public class MockMvcTestClient { //TODO - nullify? private MockMvc mockMvc; - private final ObjectMapper objectMapper; public MockMvcTestClient(MockMvc mockMvc) { this.mockMvc = mockMvc; - objectMapper = new ObjectMapper(); } public String getOAuthAccessToken(String username, String password, String grantType, String scope) @@ -48,7 +46,7 @@ public String getOAuthAccessToken(String username, String password, String grant .param("client_id", username) .param("scope", scope); MvcResult result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - OAuthToken oauthToken = objectMapper.readValue(result.getResponse().getContentAsByteArray(), OAuthToken.class); + OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), OAuthToken.class); return oauthToken.accessToken; } diff --git a/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml index 20d8fa6b1ea..4e397a54845 100755 --- a/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, 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 +<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, 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. --> <beans xmlns="http://www.springframework.org/schema/beans" @@ -92,7 +92,7 @@ </bean> </property> <property name="defaultViews"> - <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> + <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> </property> </bean> diff --git a/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml index 79110c9434e..88b41d9cad2 100755 --- a/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, 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 +<!-- Cloud Foundry 2012.02.03 Beta Copyright (c) [2009-2012] VMware, 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. --> <beans xmlns="http://www.springframework.org/schema/beans" @@ -93,7 +93,7 @@ </map> </property> <property name="defaultViews"> - <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> + <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> </property> </bean> diff --git a/samples/oauth-showcase/build.gradle b/samples/oauth-showcase/build.gradle index ab17af9255b..b11c7e32a0c 100644 --- a/samples/oauth-showcase/build.gradle +++ b/samples/oauth-showcase/build.gradle @@ -41,7 +41,7 @@ configurations { dependencies { compile("org.springframework.boot:spring-boot-starter-security") compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.security.oauth:spring-security-oauth2:2.0.3.RELEASE' + compile(group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version:parent.springSecurityOAuthVersion) runtime 'org.apache.httpcomponents:httpclient' runtime("org.springframework.boot:spring-boot-starter-actuator") compile("org.springframework.boot:spring-boot-starter-web") diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimCore.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimCore.java index b2dd1ad61f9..1fdd6a8bd5e 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimCore.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimCore.java @@ -14,7 +14,7 @@ import java.util.Arrays; -import org.codehaus.jackson.annotate.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.util.Assert; public abstract class ScimCore { diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroup.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroup.java index f2e2a89bf42..bc01395159e 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroup.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroup.java @@ -12,10 +12,11 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + import java.util.List; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; @JsonSerialize(using = ScimGroupJsonSerializer.class, include = JsonSerialize.Inclusion.NON_NULL) @JsonDeserialize(using = ScimGroupJsonDeserializer.class) diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupExternalMember.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupExternalMember.java index e9cfb1adb21..0cc5e9fbf9f 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupExternalMember.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupExternalMember.java @@ -12,9 +12,10 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim; -import org.codehaus.jackson.map.annotate.JsonSerialize; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_NULL) public class ScimGroupExternalMember extends ScimCore { private String groupId; diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonDeserializer.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonDeserializer.java index fe6729a3613..912998e3dfb 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonDeserializer.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonDeserializer.java @@ -12,6 +12,12 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; @@ -21,17 +27,11 @@ import java.util.Map; import java.util.Set; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; - public class ScimGroupJsonDeserializer extends JsonDeserializer<ScimGroup> { @Override public ScimGroup deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, - JsonProcessingException { + JsonProcessingException { ScimGroup group = new ScimGroup(); Map<ScimGroupMember.Role, List<ScimGroupMember>> roles = new HashMap<ScimGroupMember.Role, List<ScimGroupMember>>(); diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonSerializer.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonSerializer.java index d8d97840fc2..ddcc1819999 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonSerializer.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupJsonSerializer.java @@ -12,6 +12,11 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -19,15 +24,11 @@ import java.util.List; import java.util.Map; -import org.codehaus.jackson.JsonGenerator; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.map.JsonSerializer; -import org.codehaus.jackson.map.SerializerProvider; public class ScimGroupJsonSerializer extends JsonSerializer<ScimGroup> { @Override public void serialize(ScimGroup group, JsonGenerator jgen, SerializerProvider provider) throws IOException, - JsonProcessingException { + JsonProcessingException { Map<String, List<ScimGroupMember>> roles = new HashMap<String, List<ScimGroupMember>>(); for (ScimGroupMember.Role authority : ScimGroupMember.Role.values()) { String role = authority.toString().toLowerCase() + "s"; diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupMember.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupMember.java index a410c7cb6e2..3147056d26c 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupMember.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimGroupMember.java @@ -15,15 +15,15 @@ import java.util.Arrays; import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; import org.cloudfoundry.identity.uaa.authentication.Origin; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonSerialize; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class ScimGroupMember { - @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @JsonInclude(JsonInclude.Include.NON_NULL) public static enum Role { MEMBER, READER, WRITER; } @@ -36,7 +36,7 @@ public static enum Role { private String origin = Origin.UAA; - @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @JsonInclude(JsonInclude.Include.NON_NULL) public enum Type { USER, GROUP } diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimMeta.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimMeta.java index 8da98bef046..a37d27b90c1 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimMeta.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimMeta.java @@ -14,12 +14,13 @@ import java.util.Date; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import org.cloudfoundry.identity.uaa.util.json.JsonDateDeserializer; import org.cloudfoundry.identity.uaa.util.json.JsonDateSerializer; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class ScimMeta { private int version = 0; diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUser.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUser.java index 8d4f7979b70..ad26227ad43 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUser.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUser.java @@ -18,11 +18,11 @@ import java.util.List; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.annotate.JsonDeserialize; -import org.codehaus.jackson.map.annotate.JsonSerialize; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -35,11 +35,11 @@ * * @author Luke Taylor */ -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) @JsonDeserialize(using = ScimUserJsonDeserializer.class) public final class ScimUser extends ScimCore { - @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @JsonInclude(JsonInclude.Include.NON_NULL) public static final class Group { String value; @@ -129,7 +129,7 @@ public String toString() { } } - @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) + @JsonInclude(JsonInclude.Include.NON_NULL) public static final class Name { String formatted; @@ -202,7 +202,7 @@ public void setHonorificSuffix(String honorificSuffix) { } - @JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT) + @JsonInclude(JsonInclude.Include.NON_NULL) public static final class Email { private String value; @@ -258,7 +258,7 @@ public int hashCode() { } } - @JsonSerialize(include = JsonSerialize.Inclusion.NON_DEFAULT) + @JsonInclude(JsonInclude.Include.NON_NULL) public static final class PhoneNumber { private String value; diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUserJsonDeserializer.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUserJsonDeserializer.java index 45dcdf55166..eab181ffaf5 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUserJsonDeserializer.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/ScimUserJsonDeserializer.java @@ -14,16 +14,17 @@ import java.io.IOException; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.oauth.approval.Approval; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; -import org.codehaus.jackson.map.exc.UnrecognizedPropertyException; public class ScimUserJsonDeserializer extends JsonDeserializer<ScimUser> { @Override @@ -81,10 +82,10 @@ public ScimUser deserialize(JsonParser jp, DeserializationContext ctxt) throws I } else if ("zoneId".equalsIgnoreCase(fieldName)) { user.setZoneId(jp.readValueAs(String.class)); } else if ("approvals".equalsIgnoreCase(fieldName)) { - user.setApprovals(new HashSet<Approval>(Arrays.asList(jp.readValueAs(Approval[].class)))); + user.setApprovals(new HashSet<>(Arrays.asList(jp.readValueAs(Approval[].class)))); } else { throw new UnrecognizedPropertyException("unrecognized field", jp.getCurrentLocation(), - ScimUser.class, fieldName); + ScimUser.class, fieldName, Collections.emptySet()); } } } diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpoints.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpoints.java index f4f50112d70..eddb1cbef9c 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpoints.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpoints.java @@ -1,5 +1,7 @@ package org.cloudfoundry.identity.uaa.scim.endpoints; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.audit.event.UserModifiedEvent; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; @@ -8,9 +10,7 @@ import org.cloudfoundry.identity.uaa.rest.QueryableResourceManager; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.http.ResponseEntity; @@ -34,17 +34,15 @@ public class ChangeEmailEndpoints implements ApplicationEventPublisherAware { private final ScimUserProvisioning scimUserProvisioning; private final ExpiringCodeStore expiringCodeStore; - private final ObjectMapper objectMapper; private ApplicationEventPublisher publisher; private final QueryableResourceManager<ClientDetails> clientDetailsService; private static final int EMAIL_CHANGE_LIFETIME = 30 * 60 * 1000; public static final String CHANGE_EMAIL_REDIRECT_URL = "change_email_redirect_url"; - public ChangeEmailEndpoints(ScimUserProvisioning scimUserProvisioning, ExpiringCodeStore expiringCodeStore, ObjectMapper objectMapper, QueryableResourceManager<ClientDetails> clientDetailsService) { + public ChangeEmailEndpoints(ScimUserProvisioning scimUserProvisioning, ExpiringCodeStore expiringCodeStore, QueryableResourceManager<ClientDetails> clientDetailsService) { this.scimUserProvisioning = scimUserProvisioning; this.expiringCodeStore = expiringCodeStore; - this.objectMapper = objectMapper; this.clientDetailsService = clientDetailsService; } @@ -63,8 +61,8 @@ public ResponseEntity<String> generateEmailVerificationCode(@RequestBody EmailCh String code; try { - code = expiringCodeStore.generateCode(objectMapper.writeValueAsString(emailChange), new Timestamp(System.currentTimeMillis() + EMAIL_CHANGE_LIFETIME)).getCode(); - } catch (IOException e) { + code = expiringCodeStore.generateCode(JsonUtils.writeValueAsString(emailChange), new Timestamp(System.currentTimeMillis() + EMAIL_CHANGE_LIFETIME)).getCode(); + } catch (JsonUtils.JsonUtilException e) { throw new UaaException("Error while generating change email code", e); } @@ -75,7 +73,7 @@ public ResponseEntity<String> generateEmailVerificationCode(@RequestBody EmailCh public ResponseEntity<EmailChangeResponse> changeEmail(@RequestBody String code) throws IOException { ExpiringCode expiringCode = expiringCodeStore.retrieveCode(code); if (expiringCode != null) { - Map<String, String> data = objectMapper.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); + Map<String, String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); String userId = data.get("userId"); String email = data.get("email"); ScimUser user = scimUserProvisioning.retrieve(userId); diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpoints.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpoints.java index 716fe2f05cb..2f779992848 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpoints.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpoints.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim.endpoints; +import com.fasterxml.jackson.annotation.JsonProperty; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; import org.cloudfoundry.identity.uaa.codestore.ExpiringCodeStore; @@ -24,8 +25,6 @@ import org.cloudfoundry.identity.uaa.user.UaaUser; import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.JsonUtils.JsonUtilException; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; @@ -51,7 +50,6 @@ import static org.springframework.http.HttpStatus.NOT_FOUND; import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.UNAUTHORIZED; -import static org.springframework.http.HttpStatus.UNPROCESSABLE_ENTITY; @Controller public class PasswordResetEndpoints implements ApplicationEventPublisherAware { @@ -59,11 +57,9 @@ public class PasswordResetEndpoints implements ApplicationEventPublisherAware { public static final int PASSWORD_RESET_LIFETIME = 30 * 60 * 1000; private final ScimUserProvisioning scimUserProvisioning; private final ExpiringCodeStore expiringCodeStore; - private final ObjectMapper objectMapper; private ApplicationEventPublisher publisher; - public PasswordResetEndpoints(ObjectMapper objectMapper, ScimUserProvisioning scimUserProvisioning, ExpiringCodeStore expiringCodeStore) { - this.objectMapper = objectMapper; + public PasswordResetEndpoints(ScimUserProvisioning scimUserProvisioning, ExpiringCodeStore expiringCodeStore) { this.scimUserProvisioning = scimUserProvisioning; this.expiringCodeStore = expiringCodeStore; } @@ -75,7 +71,7 @@ public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { @RequestMapping(value = "/password_resets", method = RequestMethod.POST) public ResponseEntity<Map<String,String>> resetPassword(@RequestBody String email) throws IOException { - String jsonEmail = objectMapper.writeValueAsString(email); + String jsonEmail = JsonUtils.writeValueAsString(email); Map<String,String> response = new HashMap<>(); List<ScimUser> results = scimUserProvisioning.query("userName eq " + jsonEmail + " and origin eq \"" + Origin.UAA + "\""); if (results.isEmpty()) { diff --git a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordScore.java b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordScore.java index 68a556bb399..4b1f8e0fa53 100644 --- a/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordScore.java +++ b/scim/src/main/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordScore.java @@ -13,9 +13,9 @@ package org.cloudfoundry.identity.uaa.scim.endpoints; -import org.codehaus.jackson.map.annotate.JsonSerialize; +import com.fasterxml.jackson.annotation.JsonInclude; -@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_NULL) public class PasswordScore { private int score; private int requiredScore; diff --git a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserTests.java b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserTests.java index 6ba405cc7fd..904680b19a2 100644 --- a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserTests.java +++ b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/ScimUserTests.java @@ -30,7 +30,7 @@ import org.cloudfoundry.identity.uaa.oauth.approval.Approval; import org.cloudfoundry.identity.uaa.scim.ScimUser.Group; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.Assert; import org.junit.Test; import org.springframework.expression.spel.standard.SpelExpressionParser; @@ -40,7 +40,6 @@ * @author Luke Taylor */ public class ScimUserTests { - ObjectMapper mapper = new ObjectMapper(); private static final String SCHEMAS = "\"schemas\": [\"urn:scim:schemas:core:1.0\"],"; @@ -50,7 +49,7 @@ public void minimalJsonMapsToUser() throws Exception { " \"userName\": \"bjensen@example.com\"\n" + "}"; - ScimUser user = mapper.readValue(minimal, ScimUser.class); + ScimUser user = JsonUtils.readValue(minimal, ScimUser.class); assertEquals("bjensen@example.com", user.getUserName()); assertEquals(null, user.getPassword()); } @@ -62,7 +61,7 @@ public void passwordJsonMapsToUser() throws Exception { " \"password\": \"foo\"\n" + "}"; - ScimUser user = mapper.readValue(minimal, ScimUser.class); + ScimUser user = JsonUtils.readValue(minimal, ScimUser.class); assertEquals("foo", user.getPassword()); } @@ -73,7 +72,7 @@ public void minimalUserMapsToJson() throws Exception { user.setUserName("joe"); user.getMeta().setCreated(new SimpleDateFormat("yyyy-MM-dd").parse("2011-11-30")); - String json = mapper.writeValueAsString(user); + String json = JsonUtils.writeValueAsString(user); // System.err.println(json); assertTrue(json.contains("\"userName\":\"joe\"")); assertTrue(json.contains("\"id\":\"123\"")); @@ -93,7 +92,7 @@ public void anotherUserMapsToJson() throws Exception { user.addEmail("joe@test.org"); user.addPhoneNumber("+1-222-1234567"); - String json = mapper.writeValueAsString(user); + String json = JsonUtils.writeValueAsString(user); // System.err.println(json); assertTrue(json.contains("\"emails\":")); assertTrue(json.contains("\"phoneNumbers\":")); @@ -107,7 +106,7 @@ public void userWithGroupsMapsToJson() throws Exception { user.setUserName("joe"); user.setGroups(Collections.singleton(new Group(null, "foo"))); - String json = mapper.writeValueAsString(user); + String json = JsonUtils.writeValueAsString(user); // System.err.println(json); assertTrue(json.contains("\"groups\":")); } @@ -121,7 +120,7 @@ public void emailsAreMappedCorrectly() throws Exception { "{\"value\": \"babs@jensen.org\",\"type\": \"home\"}" + "],\n" + "\"schemas\":[\"urn:scim:schemas:core:1.0\"]}"; - ScimUser user = mapper.readValue(json, ScimUser.class); + ScimUser user = JsonUtils.readValue(json, ScimUser.class); assertEquals(3, user.getEmails().size()); assertEquals("bjensen@example.com", user.getEmails().get(1).getValue()); assertEquals("babs@jensen.org", user.getEmails().get(2).getValue()); @@ -138,7 +137,7 @@ public void groupsAreMappedCorrectly() throws Exception { "{\"value\": \"123456\",\"display\": \"dash.admin\"}" + "],\n" + "\"schemas\":[\"urn:scim:schemas:core:1.0\"]}"; - ScimUser user = mapper.readValue(json, ScimUser.class); + ScimUser user = JsonUtils.readValue(json, ScimUser.class); assertEquals(2, user.getGroups().size()); // System.out.println(mapper.writeValueAsString(user)); } @@ -147,7 +146,7 @@ public void groupsAreMappedCorrectly() throws Exception { public void datesAreMappedCorrectly() throws Exception { String json = "{ \"userName\":\"bjensen\"," + "\"meta\":{\"version\":10,\"created\":\"2011-11-30T10:46:16.475Z\"}}"; - ScimUser user = mapper.readValue(json, ScimUser.class); + ScimUser user = JsonUtils.readValue(json, ScimUser.class); assertEquals(10, user.getVersion()); assertEquals("2011-11-30", new SimpleDateFormat("yyyy-MM-dd").format(user.getMeta().getCreated())); // System.out.println(mapper.writeValueAsString(user)); diff --git a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpointsTest.java b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpointsTest.java index 29676281aab..e004df8a36d 100644 --- a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpointsTest.java +++ b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ChangeEmailEndpointsTest.java @@ -8,7 +8,6 @@ import org.cloudfoundry.identity.uaa.rest.QueryableResourceManager; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -52,7 +51,7 @@ public void setUp() throws Exception { expiringCodeStore = Mockito.mock(ExpiringCodeStore.class); publisher = Mockito.mock(ApplicationEventPublisher.class); clientDetailsService = Mockito.mock(QueryableResourceManager.class); - ChangeEmailEndpoints changeEmailEndpoints = new ChangeEmailEndpoints(scimUserProvisioning, expiringCodeStore, new ObjectMapper(), clientDetailsService); + ChangeEmailEndpoints changeEmailEndpoints = new ChangeEmailEndpoints(scimUserProvisioning, expiringCodeStore, clientDetailsService); changeEmailEndpoints.setApplicationEventPublisher(publisher); mockMvc = MockMvcBuilders.standaloneSetup(changeEmailEndpoints).build(); } diff --git a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsTest.java b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsTest.java index 5d1701f261f..1fe878639b8 100644 --- a/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsTest.java +++ b/scim/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsTest.java @@ -22,7 +22,6 @@ import org.cloudfoundry.identity.uaa.scim.endpoints.PasswordResetEndpoints.PasswordChange; import org.cloudfoundry.identity.uaa.test.MockAuthentication; import org.cloudfoundry.identity.uaa.util.JsonUtils; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; @@ -55,7 +54,7 @@ public class PasswordResetEndpointsTest extends TestClassNullifier { public void setUp() throws Exception { scimUserProvisioning = Mockito.mock(ScimUserProvisioning.class); expiringCodeStore = Mockito.mock(ExpiringCodeStore.class); - PasswordResetEndpoints controller = new PasswordResetEndpoints(new ObjectMapper(), scimUserProvisioning, expiringCodeStore); + PasswordResetEndpoints controller = new PasswordResetEndpoints(scimUserProvisioning, expiringCodeStore); mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); Mockito.when(expiringCodeStore.generateCode(eq("id001"), any(Timestamp.class))) diff --git a/shared_versions.gradle b/shared_versions.gradle index 08067038551..52338d51d01 100644 --- a/shared_versions.gradle +++ b/shared_versions.gradle @@ -1,8 +1,12 @@ ext { - springVersion = '4.0.8.RELEASE' - springSecurityVersion = '3.2.4.RELEASE' - springSecurityOAuthVersion = '2.0.3.RELEASE' + springVersion = '4.1.6.RELEASE' + springSecurityVersion = '3.2.7.RELEASE' + springSecurityOAuthVersion = '2.0.7.RELEASE' springSecurityLdapVersion = '1.3.2.RELEASE' postgresqlVersion = '9.1-901.jdbc3' tomcatVersion = '7.0.54' + springSecurityJwtVersion = '1.0.3.RELEASE' + bcpkixVersion = '1.47' + apacheLdapApiVersion = '1.0.0-M22' + jacksonVersion = '2.5.3' } diff --git a/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml b/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml index 23527ffa037..19e8913c028 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml @@ -186,10 +186,7 @@ <constructor-arg ref="dataSource" /> </bean> - <bean id="objectMapper" class="org.codehaus.jackson.map.ObjectMapper"/> - <bean id="passwordResetEndpoints" class="org.cloudfoundry.identity.uaa.scim.endpoints.PasswordResetEndpoints"> - <constructor-arg ref="objectMapper"/> <constructor-arg ref="scimUserProvisioning"/> <constructor-arg ref="codeStore"/> </bean> @@ -197,7 +194,6 @@ <bean id="changeEmailEndpoints" class="org.cloudfoundry.identity.uaa.scim.endpoints.ChangeEmailEndpoints"> <constructor-arg ref="scimUserProvisioning"/> <constructor-arg ref="codeStore"/> - <constructor-arg ref="objectMapper"/> <constructor-arg ref="clientDetailsService"/> </bean> diff --git a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml index 14218da6250..49ad5fd29b5 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml @@ -29,6 +29,8 @@ <!--</bean>--> <bean id="oauth2RequestValidator" class="org.cloudfoundry.identity.uaa.oauth.token.UaaOauth2RequestValidator"/> + <bean id="tokenEndpointPostProcessor" class="org.cloudfoundry.identity.uaa.security.web.TokenEndpointPostProcessor"/> + <oauth:authorization-server client-details-service-ref="jdbcClientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userManagedApprovalHandler" authorization-request-manager-ref="authorizationRequestManager" request-validator-ref="oauth2RequestValidator"> diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointsIntegrationTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointsIntegrationTests.java index 3d5625536cf..0652a4439cf 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointsIntegrationTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/ScimUserEndpointsIntegrationTests.java @@ -29,7 +29,7 @@ import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.test.TestAccountSetup; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; @@ -293,9 +293,8 @@ public void updateUserWithBadAttributeFails() throws Exception { ScimUser joe = created.getBody(); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); - ObjectMapper mapper = new ObjectMapper(); - Map<String, Object> map = new HashMap<String, Object>(mapper.readValue(mapper.writeValueAsString(joe), - Map.class)); + Map<String, Object> map = new HashMap<String, Object>(JsonUtils.readValue(JsonUtils.writeValueAsString(joe), + Map.class)); map.put("nottheusername", JOE + "0"); ResponseEntity<Map> response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<Map>(map, headers), Map.class, joe.getId()); @@ -313,8 +312,7 @@ public void testJsonCaseInsensitivity() throws Exception { ScimUser joe = created.getBody(); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); - ObjectMapper mapper = new ObjectMapper(); - Map<String, Object> map = new HashMap<String, Object>(mapper.readValue(mapper.writeValueAsString(joe), + Map<String, Object> map = new HashMap<String, Object>(JsonUtils.readValue(JsonUtils.writeValueAsString(joe), Map.class)); map.put("username", JOE + "0"); map.remove("userName"); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ImplicitGrantIT.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ImplicitGrantIT.java index 43a18560367..19d0a017a2f 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ImplicitGrantIT.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ImplicitGrantIT.java @@ -21,8 +21,9 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.isEmptyOrNullString; import static org.hamcrest.Matchers.not; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; + +import com.fasterxml.jackson.core.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Rule; @@ -115,7 +116,7 @@ public void testDefaultScopes() throws Exception { Jwt access_token = JwtHelper.decode(params.getFirst("access_token")); - Map<String, Object> claims = new ObjectMapper().readValue(access_token.getClaims(), new TypeReference<Map<String, Object>>() { + Map<String, Object> claims = JsonUtils.readValue(access_token.getClaims(), new TypeReference<Map<String, Object>>() { }); Assert.assertThat((String) claims.get("jti"), is(params.getFirst("jti"))); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/OpenIdTokenGrantsIT.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/OpenIdTokenGrantsIT.java index 4a25d952626..7dfb5a3de0a 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/OpenIdTokenGrantsIT.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/OpenIdTokenGrantsIT.java @@ -12,27 +12,11 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.integration.feature; -import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.codec.binary.Base64; -import org.apache.http.client.HttpClient; -import org.apache.http.impl.client.HttpClientBuilder; import org.cloudfoundry.identity.uaa.integration.util.IntegrationTestUtils; import org.cloudfoundry.identity.uaa.scim.ScimUser; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; @@ -48,16 +32,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.security.jwt.Jwt; import org.springframework.security.jwt.JwtHelper; -import org.springframework.security.oauth2.client.OAuth2RestTemplate; -import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.test.TestAccounts; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; -import org.springframework.security.oauth2.common.AuthenticationScheme; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -69,6 +48,20 @@ import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriUtils; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = DefaultIntegrationTestConfig.class) @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) @@ -170,7 +163,7 @@ public void testImplicitGrant() throws Exception { private void validateToken(String paramName, Map params, String[] scopes) throws java.io.IOException { Jwt access_token = JwtHelper.decode((String)params.get(paramName)); - Map<String, Object> claims = new ObjectMapper().readValue(access_token.getClaims(), new TypeReference<Map<String, Object>>() { + Map<String, Object> claims = JsonUtils.readValue(access_token.getClaims(), new TypeReference<Map<String, Object>>() { }); Assert.assertThat((String) claims.get("jti"), is(params.get("jti"))); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/util/IntegrationTestUtils.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/util/IntegrationTestUtils.java index 3dc60f58c60..63259cc49bf 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/util/IntegrationTestUtils.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/util/IntegrationTestUtils.java @@ -14,6 +14,7 @@ package org.cloudfoundry.identity.uaa.integration.util; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.cloudfoundry.identity.uaa.ServerRunning; @@ -25,7 +26,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityProvider; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter; -import org.codehaus.jackson.type.TypeReference; import org.junit.Assert; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java index 828463abe3f..ed67ec27b17 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java @@ -11,9 +11,9 @@ import org.cloudfoundry.identity.uaa.login.test.MockMvcTestClient; import org.cloudfoundry.identity.uaa.mock.util.MockMvcUtils; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.SetServerNameRequestPostProcessor; import org.cloudfoundry.identity.uaa.zone.IdentityZone; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; @@ -253,7 +253,7 @@ public void testCreatingAnAccountInAnotherZoneWithNoClientRedirect() throws Exce mockMvc.perform(post("/identity-zones") .header("Authorization", "Bearer " + zonesCreateToken) .contentType(MediaType.APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().isCreated()); mockMvc.perform(post("/create_account.do") diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java index 9610cfadfaa..1cc761ffa2b 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java @@ -12,7 +12,7 @@ import org.cloudfoundry.identity.uaa.oauth.RemoteUserAuthentication; import org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher; import org.cloudfoundry.identity.uaa.user.UaaUserDatabase; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -132,11 +132,11 @@ public void testLoginUsingPasscodeWithSamlToken() throws Exception { .accept(APPLICATION_JSON) .session(session); - String passcode = new ObjectMapper().readValue( + String passcode = JsonUtils.readValue( mockMvc.perform(get) - .andExpect(status().isOk()) - .andDo(print()) - .andReturn().getResponse().getContentAsString(), + .andExpect(status().isOk()) + .andDo(print()) + .andReturn().getResponse().getContentAsString(), String.class); mockSecurityContext.setAuthentication(null); @@ -158,7 +158,7 @@ public void testLoginUsingPasscodeWithSamlToken() throws Exception { Map accessToken = - new ObjectMapper().readValue( + JsonUtils.readValue( mockMvc.perform(post) .andDo(print()) .andExpect(status().isOk()) @@ -199,7 +199,7 @@ public void testLoginUsingPasscodeWithUaaToken() throws Exception { .accept(APPLICATION_JSON) .session(session); - String passcode = new ObjectMapper().readValue( + String passcode = JsonUtils.readValue( mockMvc.perform(get) .andExpect(status().isOk()) .andDo(print()) @@ -225,7 +225,7 @@ public void testLoginUsingPasscodeWithUaaToken() throws Exception { Map accessToken = - new ObjectMapper().readValue( + JsonUtils.readValue( mockMvc.perform(post) .andDo(print()) .andExpect(status().isOk()) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMvcMockTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMvcMockTests.java index 57299a0c8f3..66cd8143051 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMvcMockTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/audit/AuditCheckMvcMockTests.java @@ -46,7 +46,7 @@ import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -428,7 +428,7 @@ public void loginServerPasswordChange() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + loginToken) - .content(new ObjectMapper().writeValueAsBytes(pwch)); + .content(JsonUtils.writeValueAsBytes(pwch)); mockMvc.perform(changePasswordPost) .andExpect(status().isOk()); @@ -447,7 +447,7 @@ public void loginServerPasswordChange() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + loginToken) - .content(new ObjectMapper().writeValueAsBytes(pwch)); + .content(JsonUtils.writeValueAsBytes(pwch)); mockMvc.perform(changePasswordPost) .andExpect(status().isOk()); @@ -466,7 +466,7 @@ public void loginServerInvalidPasswordChange() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + loginToken) - .content(new ObjectMapper().writeValueAsBytes(pwch)); + .content(JsonUtils.writeValueAsBytes(pwch)); mockMvc.perform(changePasswordPost) .andExpect(status().isUnauthorized()); @@ -514,9 +514,11 @@ public void clientAuthenticationFailureClientNotFound() throws Exception { .param("client_id", "login") .param("scope", "oauth.login"); mockMvc.perform(oauthTokenPost).andExpect(status().isUnauthorized()); - verify(listener, times(1)).onApplicationEvent(captor.capture()); - ClientAuthenticationFailureEvent event = (ClientAuthenticationFailureEvent)captor.getValue(); - assertEquals("login", event.getClientId()); + verify(listener, atLeast(1)).onApplicationEvent(captor.capture()); + PrincipalAuthenticationFailureEvent event0 = (PrincipalAuthenticationFailureEvent) captor.getAllValues().get(0); + assertEquals("login2", event0.getAuditEvent().getPrincipalId()); + ClientAuthenticationFailureEvent event1 = (ClientAuthenticationFailureEvent)captor.getAllValues().get(1); + assertEquals("login", event1.getClientId()); } @Test public void testUserApprovalAdded() throws Exception { @@ -529,7 +531,7 @@ public void testUserApprovalAdded() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + marissaToken) - .content(new ObjectMapper().writeValueAsBytes(approvals)); + .content(JsonUtils.writeValueAsBytes(approvals)); testListener.clearEvents(); @@ -559,7 +561,7 @@ public void testUserCreatedEvent() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); testListener.clearEvents(); @@ -630,12 +632,12 @@ public void testUserModifiedAndDeleteEvent() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); ResultActions result = mockMvc.perform(userPost) .andExpect(status().isCreated()); - user = new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsByteArray(), ScimUser.class); + user = JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimUser.class); testListener.clearEvents(); user.setName(new ScimUser.Name(modifiedFirstName, lastName)); @@ -644,7 +646,7 @@ public void testUserModifiedAndDeleteEvent() throws Exception { .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) .header("If-Match", user.getVersion()) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); mockMvc.perform(userPut).andExpect(status().isOk()); @@ -690,11 +692,11 @@ public void testUserVerifiedEvent() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); ResultActions result = mockMvc.perform(userPost) .andExpect(status().isCreated()); - user = new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsByteArray(), ScimUser.class); + user = JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimUser.class); testListener.clearEvents(); @@ -770,10 +772,10 @@ public void testGroupEvents() throws Exception { .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) - .content(new ObjectMapper().writeValueAsBytes(group)); + .content(JsonUtils.writeValueAsBytes(group)); ResultActions result = mockMvc.perform(groupPost).andExpect(status().isCreated()); - group = new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); + group = JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); assertEquals(1, testListener.getEventCount()); assertEquals(GroupModifiedEvent.class, testListener.getLatestEvent().getClass()); @@ -781,7 +783,7 @@ public void testGroupEvents() throws Exception { assertEquals(AuditEventType.GroupCreatedEvent, event.getAuditEvent().getType()); assertEquals(group.getId(), event.getAuditEvent().getPrincipalId()); assertEquals(new GroupModifiedEvent.GroupInfo(group.getDisplayName(), ScimEventPublisher.getMembers(group)), - new ObjectMapper().readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); + JsonUtils.readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); //update the group with one additional member List<ScimGroupMember> members = group.getMembers(); @@ -792,11 +794,11 @@ public void testGroupEvents() throws Exception { .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) .header("If-Match", group.getVersion()) - .content(new ObjectMapper().writeValueAsBytes(group)); + .content(JsonUtils.writeValueAsBytes(group)); testListener.clearEvents(); result = mockMvc.perform(groupPut).andExpect(status().isOk()); - group = new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); + group = JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); assertEquals(1, testListener.getEventCount()); assertEquals(GroupModifiedEvent.class, testListener.getLatestEvent().getClass()); @@ -804,7 +806,7 @@ public void testGroupEvents() throws Exception { assertEquals(AuditEventType.GroupModifiedEvent, event.getAuditEvent().getType()); assertEquals(group.getId(), event.getAuditEvent().getPrincipalId()); assertEquals(new GroupModifiedEvent.GroupInfo(group.getDisplayName(), ScimEventPublisher.getMembers(group)), - new ObjectMapper().readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); + JsonUtils.readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); //delete the group @@ -813,11 +815,11 @@ public void testGroupEvents() throws Exception { .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) .header("If-Match", group.getVersion()) - .content(new ObjectMapper().writeValueAsBytes(group)); + .content(JsonUtils.writeValueAsBytes(group)); testListener.clearEvents(); result = mockMvc.perform(groupDelete).andExpect(status().isOk()); - group = new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); + group = JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimGroup.class); assertEquals(1, testListener.getEventCount()); assertEquals(GroupModifiedEvent.class, testListener.getLatestEvent().getClass()); @@ -825,7 +827,7 @@ public void testGroupEvents() throws Exception { assertEquals(AuditEventType.GroupDeletedEvent, event.getAuditEvent().getType()); assertEquals(group.getId(), event.getAuditEvent().getPrincipalId()); assertEquals(new GroupModifiedEvent.GroupInfo(group.getDisplayName(), ScimEventPublisher.getMembers(group)), - new ObjectMapper().readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); + JsonUtils.readValue(event.getAuditEvent().getData(), GroupModifiedEvent.GroupInfo.class)); } @@ -842,7 +844,7 @@ private ScimUser createUser(String adminToken, String username, String firstname .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", "Bearer " + adminToken) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); testListener.clearEvents(); @@ -855,7 +857,7 @@ private ScimUser createUser(String adminToken, String username, String firstname assertEquals(username, userModifiedEvent.getUsername()); assertEquals(AuditEventType.UserCreatedEvent, userModifiedEvent.getAuditEvent().getType()); - return new ObjectMapper().readValue(result.andReturn().getResponse().getContentAsString(), ScimUser.class); + return JsonUtils.readValue(result.andReturn().getResponse().getContentAsString(), ScimUser.class); } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/clients/ClientAdminEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/clients/ClientAdminEndpointsMockMvcTests.java index 1809ba0588d..8c9bd7f9a67 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/clients/ClientAdminEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/clients/ClientAdminEndpointsMockMvcTests.java @@ -1,5 +1,6 @@ package org.cloudfoundry.identity.uaa.mock.clients; +import com.fasterxml.jackson.core.type.TypeReference; import com.googlecode.flyway.core.Flyway; import org.cloudfoundry.identity.uaa.TestClassNullifier; import org.cloudfoundry.identity.uaa.audit.AuditEventType; @@ -26,8 +27,6 @@ import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; import org.cloudfoundry.identity.uaa.user.UaaUser; import org.cloudfoundry.identity.uaa.util.JsonUtils; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -1188,11 +1187,11 @@ private ClientDetailsModification[] createBaseClients(int length, String grantTy } private String toString(Object client) throws Exception { - return new ObjectMapper().writeValueAsString(client); + return JsonUtils.writeValueAsString(client); } private String toString(Object[] clients) throws Exception { - return new ObjectMapper().writeValueAsString(clients); + return JsonUtils.writeValueAsString(clients); } private ClientDetails clientFromString(String client) throws Exception { @@ -1200,8 +1199,7 @@ private ClientDetails clientFromString(String client) throws Exception { } private Object fromString(String body, Class<?> clazz) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - return mapper.readValue(body, clazz); + return JsonUtils.readValue(body, clazz); } private ClientDetails[] clientArrayFromString(String clients) throws Exception { @@ -1209,8 +1207,7 @@ private ClientDetails[] clientArrayFromString(String clients) throws Exception { } private Object[] arrayFromString(String body, Class<?> clazz) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - return (Object[])mapper.readValue(body, clazz); + return (Object[])JsonUtils.readValue(body, clazz); } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/codestore/ExpiringCodeStoreMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/codestore/ExpiringCodeStoreMockMvcTests.java index 6d763a1af16..e66e3095910 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/codestore/ExpiringCodeStoreMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/codestore/ExpiringCodeStoreMockMvcTests.java @@ -17,7 +17,7 @@ import org.cloudfoundry.identity.uaa.codestore.ExpiringCode; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -73,7 +73,7 @@ public void testGenerateCode() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + 60000); ExpiringCode code = new ExpiringCode(null, ts, "{}"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -95,7 +95,7 @@ public void testGenerateCodeWithInvalidScope() throws Exception { TestClient testClient = new TestClient(mockMvc); String loginToken = testClient.getClientCredentialsOAuthAccessToken("admin", "adminsecret", "scim.read"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -111,7 +111,7 @@ public void testGenerateCodeAnonymous() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + 60000); ExpiringCode code = new ExpiringCode(null, ts, "{}"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .contentType(APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) @@ -125,7 +125,7 @@ public void testGenerateCodeAnonymous() throws Exception { public void testGenerateCodeWithNullData() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + 60000); ExpiringCode code = new ExpiringCode(null, ts, null); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -140,7 +140,7 @@ public void testGenerateCodeWithNullData() throws Exception { @Test public void testGenerateCodeWithNullExpiresAt() throws Exception { ExpiringCode code = new ExpiringCode(null, null, "{}"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -156,7 +156,7 @@ public void testGenerateCodeWithNullExpiresAt() throws Exception { public void testGenerateCodeWithExpiresAtInThePast() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() - 60000); ExpiringCode code = new ExpiringCode(null, ts, null); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -172,7 +172,7 @@ public void testGenerateCodeWithExpiresAtInThePast() throws Exception { public void testRetrieveCode() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + 60000); ExpiringCode code = new ExpiringCode(null, ts, "{}"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -183,7 +183,7 @@ public void testRetrieveCode() throws Exception { .andExpect(status().isCreated()) .andReturn(); - ExpiringCode rc = new ObjectMapper().readValue(result.getResponse().getContentAsString(), ExpiringCode.class); + ExpiringCode rc = JsonUtils.readValue(result.getResponse().getContentAsString(), ExpiringCode.class); MockHttpServletRequestBuilder get = get("/Codes/" + rc.getCode()) .header("Authorization", "Bearer " + loginToken) @@ -193,7 +193,7 @@ public void testRetrieveCode() throws Exception { .andExpect(status().isOk()) .andReturn(); - ExpiringCode rc1 = new ObjectMapper().readValue(result.getResponse().getContentAsString(), ExpiringCode.class); + ExpiringCode rc1 = JsonUtils.readValue(result.getResponse().getContentAsString(), ExpiringCode.class); assertEquals(rc, rc1); } @@ -202,7 +202,7 @@ public void testRetrieveCode() throws Exception { public void testRetrieveCodeThatIsExpired() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + 1000); ExpiringCode code = new ExpiringCode(null, ts, "{}"); - String requestBody = new ObjectMapper().writeValueAsString(code); + String requestBody = JsonUtils.writeValueAsString(code); MockHttpServletRequestBuilder post = post("/Codes") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) @@ -213,7 +213,7 @@ public void testRetrieveCodeThatIsExpired() throws Exception { .andExpect(status().isCreated()) .andReturn(); - ExpiringCode rc = new ObjectMapper().readValue(result.getResponse().getContentAsString(), ExpiringCode.class); + ExpiringCode rc = JsonUtils.readValue(result.getResponse().getContentAsString(), ExpiringCode.class); Thread.sleep(1001); MockHttpServletRequestBuilder get = get("/Codes/" + rc.getCode()) .header("Authorization", "Bearer " + loginToken) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java index 7929318ed37..8e277ebbaaf 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java @@ -18,7 +18,7 @@ import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -124,7 +124,7 @@ public void checkTokenKeyValues() throws Exception { .andExpect(status().isOk()) .andReturn(); - Map<String,Object> key = new ObjectMapper().readValue(result.getResponse().getContentAsString(), Map.class); + Map<String,Object> key = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); Object kty = key.get("kty"); assertNotNull(kty); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java index 6099bfd0d6d..cae04c40fbe 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.mock.token; +import com.fasterxml.jackson.core.type.TypeReference; import com.googlecode.flyway.core.Flyway; import org.cloudfoundry.identity.uaa.TestClassNullifier; import org.cloudfoundry.identity.uaa.authentication.Origin; @@ -33,14 +34,13 @@ 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.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.SetServerNameRequestPostProcessor; import org.cloudfoundry.identity.uaa.zone.IdentityProvider; import org.cloudfoundry.identity.uaa.zone.IdentityProviderProvisioning; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.IdentityZoneProvisioning; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; @@ -692,7 +692,7 @@ public void testOpenIdToken() throws Exception { .param("password", SECRET) .param(OAuth2Utils.SCOPE, "openid"); MvcResult result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - Map token = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), Map.class); + Map token = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); assertNotNull(token.get("access_token")); assertNotNull(token.get("refresh_token")); assertNotNull(token.get("id_token")); @@ -761,7 +761,7 @@ public void testOpenIdToken() throws Exception { .param(OAuth2Utils.CLIENT_ID, clientId) .param(OAuth2Utils.REDIRECT_URI, TEST_REDIRECT_URI); result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - token = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), Map.class); + token = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); assertNotNull(token.get("access_token")); assertNotNull(token.get("refresh_token")); assertNotNull(token.get("id_token")); @@ -889,7 +889,7 @@ private Map<String, Object> getClaimsForToken(String token) { Map<String, Object> claims = null; try { - claims = new ObjectMapper().readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference<Map<String, Object>>() { }); } catch (Exception e) { throw new IllegalStateException("Cannot read token claims", e); @@ -1520,7 +1520,7 @@ public void testGetClientCredentialsTokenForOtherIdentityZoneFromDefaultZoneFail IdentityZoneHolder.clear(); mockMvc.perform(post("http://localhost/oauth/token") .accept(MediaType.APPLICATION_JSON_VALUE) - .header("Host", subdomain + ".localhost") + //.header("Host", subdomain + ".localhost") - with updated Spring, this now works for request.getServerName .header("Authorization", "Basic "+new String(Base64.encode((clientId + ":" + SECRET).getBytes()))) .param("grant_type", "client_credentials") .param("client_id", clientId) @@ -1670,7 +1670,7 @@ public void testGetTokenScopesNotInAuthentication() throws Exception { .param(OAuth2Utils.CLIENT_ID, "identity") .param(OAuth2Utils.REDIRECT_URI, "http://localhost/test"); result = mockMvc.perform(authRequest).andDo(print()).andExpect(status().is2xxSuccessful()).andReturn(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), TestClient.OAuthToken.class); + TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), TestClient.OAuthToken.class); OAuth2Authentication a1 = tokenServices.loadAuthentication(oauthToken.accessToken); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java index f579966ea6f..c19fed6cd13 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java @@ -14,6 +14,7 @@ package org.cloudfoundry.identity.uaa.mock.util; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.codec.binary.Base64; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; @@ -33,8 +34,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.Assert; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; @@ -69,7 +68,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class MockMvcUtils { - private final ObjectMapper objectMapper = new ObjectMapper(); public static MockMvcUtils utils() { return new MockMvcUtils(); @@ -82,9 +80,9 @@ public IdentityZone createZoneUsingWebRequest(MockMvc mockMvc, String accessToke MvcResult result = mockMvc.perform(post("/identity-zones") .header("Authorization", "Bearer " + accessToken) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().isCreated()).andReturn(); - return new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), IdentityZone.class); + return JsonUtils.readValue(result.getResponse().getContentAsString(), IdentityZone.class); } public static class IdentityZoneCreationResult { @@ -123,7 +121,7 @@ public IdentityZoneCreationResult createOtherIdentityZoneAndReturnResult(String .header("Authorization", "Bearer " + identityToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().isCreated()); // use the identity client to grant the zones.<id>.admin scope to a user @@ -137,7 +135,7 @@ public IdentityZoneCreationResult createOtherIdentityZoneAndReturnResult(String .header("Authorization", "Bearer " + identityToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(group))) + .content(JsonUtils.writeValueAsString(group))) .andExpect(status().isCreated()); // use that user to create an admin client in the new zone @@ -149,7 +147,7 @@ public IdentityZoneCreationResult createOtherIdentityZoneAndReturnResult(String .header("X-Identity-Zone-Id", identityZone.getId()) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(bootstrapClient))) + .content(JsonUtils.writeValueAsString(bootstrapClient))) .andExpect(status().isCreated()); return new IdentityZoneCreationResult(identityZone, marissa, zoneAdminAuthcodeToken); @@ -208,9 +206,9 @@ public ScimUser createUser(MockMvc mockMvc, String accessToken, ScimUser user) t MvcResult userResult = mockMvc.perform(post("/Users") .header("Authorization", "Bearer " + accessToken) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(user))) + .content(JsonUtils.writeValueAsBytes(user))) .andExpect(status().isCreated()).andReturn(); - return new ObjectMapper().readValue(userResult.getResponse().getContentAsString(), ScimUser.class); + return JsonUtils.readValue(userResult.getResponse().getContentAsString(), ScimUser.class); } public ScimGroup getGroup(MockMvc mockMvc, String accessToken, String displayName) throws Exception { @@ -230,25 +228,25 @@ public ScimGroup getGroup(MockMvc mockMvc, String accessToken, String displayNam } public ScimGroup createGroup(MockMvc mockMvc, String accessToken, ScimGroup group) throws Exception { - return new ObjectMapper().readValue( - mockMvc.perform(post("/Groups") - .header("Authorization", "Bearer " + accessToken) - .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(group))) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsByteArray(), - ScimGroup.class); + return JsonUtils.readValue( + mockMvc.perform(post("/Groups") + .header("Authorization", "Bearer " + accessToken) + .contentType(APPLICATION_JSON) + .content(JsonUtils.writeValueAsString(group))) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(), + ScimGroup.class); } public ScimGroup updateGroup(MockMvc mockMvc, String accessToken, ScimGroup group) throws Exception { - return new ObjectMapper().readValue( + return JsonUtils.readValue( mockMvc.perform(put("/Groups/" + group.getId()) .header("If-Match", group.getVersion()) .header("Authorization", "Bearer " + accessToken) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(group))) + .content(JsonUtils.writeValueAsString(group))) .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsByteArray(), + .andReturn().getResponse().getContentAsString(), ScimGroup.class); } public BaseClientDetails createClient(MockMvc mockMvc, String accessToken, BaseClientDetails clientDetails) throws Exception { @@ -261,14 +259,14 @@ public BaseClientDetails createClient(MockMvc mockMvc, String accessToken, BaseC .header("Authorization", "Bearer " + accessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(clientDetails)); + .content(JsonUtils.writeValueAsString(clientDetails)); if (! zone.equals(IdentityZone.getUaa())) { createClientPost = createClientPost.header(IdentityZoneSwitchingFilter.HEADER, zone.getId()); } - return new ObjectMapper().readValue( - mockMvc.perform(createClientPost) - .andExpect(status().isCreated()) - .andReturn().getResponse().getContentAsByteArray(), BaseClientDetails.class); + return JsonUtils.readValue( + mockMvc.perform(createClientPost) + .andExpect(status().isCreated()) + .andReturn().getResponse().getContentAsString(), BaseClientDetails.class); } public BaseClientDetails updateClient(MockMvc mockMvc, String accessToken, BaseClientDetails clientDetails, IdentityZone zone) @@ -278,15 +276,15 @@ public BaseClientDetails updateClient(MockMvc mockMvc, String accessToken, BaseC .header("Authorization", "Bearer " + accessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(clientDetails)); + .content(JsonUtils.writeValueAsString(clientDetails)); if (! zone.equals(IdentityZone.getUaa())) { updateClientPut = updateClientPut.header(IdentityZoneSwitchingFilter.HEADER, zone.getId()); } - return new ObjectMapper().readValue( + return JsonUtils.readValue( mockMvc.perform(updateClientPut) .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsByteArray(), BaseClientDetails.class); + .andReturn().getResponse().getContentAsString(), BaseClientDetails.class); } public String getZoneAdminToken(MockMvc mockMvc, String adminToken, String zoneId) throws Exception { @@ -315,8 +313,8 @@ public String getUserOAuthAccessToken(MockMvc mockMvc, String clientId, String c .param("password", password) .param("scope", scope); MvcResult result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), - TestClient.OAuthToken.class); + TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), + TestClient.OAuthToken.class); return oauthToken.accessToken; } @@ -330,7 +328,7 @@ public String getClientOAuthAccessToken(MockMvc mockMvc, String clientId, String .param("client_id", clientId) .param("scope", scope); MvcResult result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), TestClient.OAuthToken.class); + TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), TestClient.OAuthToken.class); return oauthToken.accessToken; } @@ -376,8 +374,8 @@ public String getUserOAuthAccessTokenAuthCode(MockMvc mockMvc, String clientId, .param(OAuth2Utils.CLIENT_ID, clientId) .param(OAuth2Utils.REDIRECT_URI, "http://localhost/test"); result = mockMvc.perform(authRequest).andDo(print()).andExpect(status().is2xxSuccessful()).andReturn(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), - TestClient.OAuthToken.class); + TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), + TestClient.OAuthToken.class); return oauthToken.accessToken; } @@ -397,7 +395,7 @@ public String getClientCredentialsOAuthAccessToken(MockMvc mockMvc, String usern MvcResult result = mockMvc.perform(oauthTokenPost) .andExpect(status().isOk()) .andReturn(); - OAuthToken oauthToken = objectMapper.readValue(result.getResponse().getContentAsByteArray(), OAuthToken.class); + OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), OAuthToken.class); return oauthToken.accessToken; } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityProviderEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityProviderEndpointsMockMvcTests.java index e89559c904d..5e816f98ce1 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityProviderEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityProviderEndpointsMockMvcTests.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.mock.zones; +import com.fasterxml.jackson.core.type.TypeReference; import com.googlecode.flyway.core.Flyway; import org.apache.commons.lang.RandomStringUtils; import org.cloudfoundry.identity.uaa.TestClassNullifier; @@ -32,7 +33,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; import org.cloudfoundry.identity.uaa.zone.event.IdentityProviderModifiedEvent; -import org.codehaus.jackson.type.TypeReference; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java index 415dd7bb253..223d29de5b6 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java @@ -1,5 +1,7 @@ package org.cloudfoundry.identity.uaa.mock.zones; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; import com.googlecode.flyway.core.Flyway; import org.cloudfoundry.identity.uaa.TestClassNullifier; @@ -25,9 +27,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; import org.cloudfoundry.identity.uaa.zone.event.IdentityZoneModifiedEvent; -import org.codehaus.jackson.JsonNode; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -75,7 +74,7 @@ public class IdentityZoneEndpointsMockMvcTests extends TestClassNullifier { private static TestApplicationEventListener<ClientDeleteEvent> clientDeleteEventListener; private static TestApplicationEventListener<GroupModifiedEvent> groupModifiedEventListener; private static TestApplicationEventListener<UserModifiedEvent> userModifiedEventListener; - + @BeforeClass public static void setUp() throws Exception { webApplicationContext = new XmlWebApplicationContext(); @@ -94,7 +93,7 @@ public static void setUp() throws Exception { clientDeleteEventListener = mockMvcUtils.addEventListener(webApplicationContext, ClientDeleteEvent.class); groupModifiedEventListener = mockMvcUtils.addEventListener(webApplicationContext, GroupModifiedEvent.class); userModifiedEventListener = mockMvcUtils.addEventListener(webApplicationContext, UserModifiedEvent.class); - + identityClientToken = testClient.getClientCredentialsOAuthAccessToken( "identity", @@ -131,7 +130,7 @@ public void after() { private ScimUser createUser(String token, String subdomain) throws Exception { ScimUser user = getScimUser(); - byte[] requestBody = new ObjectMapper().writeValueAsBytes(user); + byte[] requestBody = JsonUtils.writeValueAsBytes(user); MockHttpServletRequestBuilder post = post("/Users") .header("Authorization", "Bearer " + token) .contentType(APPLICATION_JSON) @@ -147,7 +146,7 @@ private ScimUser createUser(String token, String subdomain) throws Exception { .andExpect(jsonPath("$.name.givenName").value(user.getGivenName())) .andReturn(); - return new ObjectMapper().readValue(result.getResponse().getContentAsString(), ScimUser.class); + return JsonUtils.readValue(result.getResponse().getContentAsString(), ScimUser.class); } private ScimUser getScimUser() { @@ -169,7 +168,7 @@ public void testGetZoneAsIdentityClient() throws Exception { assertEquals(created.getSubdomain(), retrieved.getSubdomain()); assertEquals(created.getDescription(), retrieved.getDescription()); } - + @Test public void testGetZonesAsIdentityClient() throws Exception { String id = generator.generate(); @@ -178,8 +177,8 @@ public void testGetZonesAsIdentityClient() throws Exception { .header("Authorization", "Bearer " + identityClientToken)) .andExpect(status().isOk()) .andReturn(); - - + + List<IdentityZone> zones = JsonUtils.readValue(result.getResponse().getContentAsString(), new TypeReference<List<IdentityZone>>() {}); IdentityZone retrieved = null; for (IdentityZone identityZone : zones) { @@ -187,7 +186,7 @@ public void testGetZonesAsIdentityClient() throws Exception { retrieved = identityZone; } } - + assertEquals(created.getId(), retrieved.getId()); assertEquals(created.getName(), retrieved.getName()); assertEquals(created.getSubdomain(), retrieved.getSubdomain()); @@ -264,9 +263,9 @@ public void testUpdateWithSameDataReturns200() throws Exception { String id = generator.generate(); IdentityZone created = createZone(id, HttpStatus.CREATED, identityClientToken); - + checkZoneAuditEventInUaa(1, AuditEventType.IdentityZoneCreatedEvent); - + updateZone(created, HttpStatus.OK, identityClientToken); checkZoneAuditEventInUaa(2, AuditEventType.IdentityZoneModifiedEvent); } @@ -320,7 +319,7 @@ public void testUpdateZoneInsufficientScope() throws Exception { public void testCreateDuplicateZoneReturns409() throws Exception { String id = generator.generate(); createZone(id, HttpStatus.CREATED, identityClientToken); - + checkZoneAuditEventInUaa(1, AuditEventType.IdentityZoneCreatedEvent); createZone(id, HttpStatus.CONFLICT, identityClientToken); @@ -336,7 +335,7 @@ public void testCreateZoneAndIdentityProvider() throws Exception { mockMvc.perform(post("/identity-zones") .header("Authorization", "Bearer "+identityClientToken) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().isCreated()) .andReturn(); @@ -347,7 +346,7 @@ public void testCreateZoneAndIdentityProvider() throws Exception { IdentityProvider idp2 = idpp.retrieveByOrigin(Origin.UAA, IdentityZone.getUaa().getId()); assertNotEquals(idp1, idp2); } - + @Test public void testCreateAndDeleteLimitedClientInNewZoneUsingZoneEndpoint() throws Exception { String id = generator.generate(); @@ -361,20 +360,20 @@ public void testCreateAndDeleteLimitedClientInNewZoneUsingZoneEndpoint() throws .header("Authorization", "Bearer " + identityClientToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(client))) + .content(JsonUtils.writeValueAsString(client))) .andExpect(status().isCreated()).andReturn(); - BaseClientDetails created = new ObjectMapper().readValue(result.getResponse().getContentAsString(), BaseClientDetails.class); + BaseClientDetails created = JsonUtils.readValue(result.getResponse().getContentAsString(), BaseClientDetails.class); assertNull(created.getClientSecret()); assertEquals("zones.write", created.getAdditionalInformation().get(ClientConstants.CREATED_WITH)); assertEquals(Collections.singletonList(Origin.UAA), created.getAdditionalInformation().get(ClientConstants.ALLOWED_PROVIDERS)); assertEquals("bar", created.getAdditionalInformation().get("foo")); checkAuditEventListener(1, AuditEventType.ClientCreateSuccess, clientCreateEventListener, id, "http://localhost:8080/uaa/oauth/token", "identity"); - + mockMvc.perform(delete("/identity-zones/"+zone.getId()+"/clients/"+created.getClientId(), IdentityZone.getUaa().getId()) .header("Authorization", "Bearer " + identityClientToken) .accept(APPLICATION_JSON)) .andExpect(status().isOk()); - + checkAuditEventListener(1, AuditEventType.ClientDeleteSuccess, clientDeleteEventListener, id, "http://localhost:8080/uaa/oauth/token", "identity"); } @@ -388,18 +387,18 @@ public void testCreateAndDeleteLimitedClientInUAAZoneReturns403() throws Excepti .header("Authorization", "Bearer " + identityClientToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(client))) + .content(JsonUtils.writeValueAsString(client))) .andExpect(status().isForbidden()); assertEquals(0, clientCreateEventListener.getEventCount()); - + mockMvc.perform(delete("/identity-zones/uaa/clients/admin") .header("Authorization", "Bearer " + identityClientToken) .accept(APPLICATION_JSON)) .andExpect(status().isForbidden()); - + assertEquals(0, clientDeleteEventListener.getEventCount()); } - + @Test public void testCreateAdminClientInNewZoneUsingZoneEndpointReturns400() throws Exception { String id = generator.generate(); @@ -411,7 +410,7 @@ public void testCreateAdminClientInNewZoneUsingZoneEndpointReturns400() throws E .header("Authorization", "Bearer " + identityClientToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(client))) + .content(JsonUtils.writeValueAsString(client))) .andExpect(status().isBadRequest()); } @@ -430,7 +429,7 @@ public void testCreateInvalidZone() throws Exception { mockMvc.perform(post("/identity-zones") .header("Authorization", "Bearer "+identityClientToken) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().isBadRequest()); assertEquals(0, zoneModifiedEventListener.getEventCount()); @@ -449,7 +448,7 @@ public void testCreatesZonesWithDuplicateSubdomains() throws Exception { .header("Authorization", "Bearer "+identityClientToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone1))) + .content(JsonUtils.writeValueAsString(identityZone1))) .andExpect(status().isCreated()); checkZoneAuditEventInUaa(1, AuditEventType.IdentityZoneCreatedEvent); @@ -458,7 +457,7 @@ public void testCreatesZonesWithDuplicateSubdomains() throws Exception { .header("Authorization", "Bearer "+identityClientToken) .contentType(APPLICATION_JSON) .accept(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone2))) + .content(JsonUtils.writeValueAsString(identityZone2))) .andExpect(status().isConflict()); assertEquals(1, zoneModifiedEventListener.getEventCount()); @@ -471,7 +470,7 @@ public void testSuccessfulUserManagementInZoneUsingAdminClient() throws Exceptio adminClient.setClientSecret("admin-secret"); IdentityZoneCreationResult creationResult = mockMvcUtils.createOtherIdentityZoneAndReturnResult(subdomain, mockMvc, webApplicationContext, adminClient); IdentityZone identityZone = creationResult.getIdentityZone(); - + checkZoneAuditEventInUaa(1, AuditEventType.IdentityZoneCreatedEvent); checkAuditEventListener(1, AuditEventType.GroupCreatedEvent, groupModifiedEventListener, IdentityZone.getUaa().getId(), "http://localhost:8080/uaa/oauth/token", "identity"); checkAuditEventListener(1, AuditEventType.ClientCreateSuccess, clientCreateEventListener, identityZone.getId(), "http://localhost:8080/uaa/oauth/token", creationResult.getZoneAdminUser().getId()); @@ -479,22 +478,22 @@ public void testSuccessfulUserManagementInZoneUsingAdminClient() throws Exceptio String zoneAdminToken = testClient.getClientCredentialsOAuthAccessToken("admin", "admin-secret", "scim.write,scim.read", subdomain); ScimUser user = createUser(zoneAdminToken, subdomain); checkAuditEventListener(1, AuditEventType.UserCreatedEvent, userModifiedEventListener, identityZone.getId(), "http://"+subdomain+".localhost:8080/uaa/oauth/token", "admin"); - + user.setUserName("updated-username@test.com"); MockHttpServletRequestBuilder put = put("/Users/" + user.getId()) .header("Authorization", "Bearer " + zoneAdminToken) .header("If-Match", "\"" + user.getVersion() + "\"") .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(user)) + .content(JsonUtils.writeValueAsString(user)) .with(new SetServerNameRequestPostProcessor(subdomain + ".localhost")); MvcResult result = mockMvc.perform(put) .andExpect(status().isOk()) .andExpect(jsonPath("$.userName").value(user.getUserName())) .andReturn(); - + checkAuditEventListener(2, AuditEventType.UserModifiedEvent, userModifiedEventListener, identityZone.getId(), "http://"+subdomain+".localhost:8080/uaa/oauth/token", "admin"); - user = new ObjectMapper().readValue(result.getResponse().getContentAsString(), ScimUser.class); + user = JsonUtils.readValue(result.getResponse().getContentAsString(), ScimUser.class); List<ScimUser> users = getUsersInZone(subdomain, zoneAdminToken); assertTrue(users.contains(user)); assertEquals(1, users.size()); @@ -521,8 +520,9 @@ private List<ScimUser> getUsersInZone(String subdomain, String token) throws Exc MvcResult mvcResult = mockMvc.perform(get).andExpect(status().isOk()).andReturn(); - JsonNode root = new ObjectMapper().readTree(mvcResult.getResponse().getContentAsString()); - return new ObjectMapper().readValue(root.get("resources").toString(), new TypeReference<List<ScimUser>>() {}); + JsonNode root = JsonUtils.readTree(mvcResult.getResponse().getContentAsString()); + return JsonUtils.readValue(root.get("resources").toString(), new TypeReference<List<ScimUser>>() { + }); } @Test @@ -536,7 +536,7 @@ public void testCreateAndListUsersInOtherZoneIsUnauthorized() throws Exception { ScimUser user = getScimUser(); - byte[] requestBody = new ObjectMapper().writeValueAsBytes(user); + byte[] requestBody = JsonUtils.writeValueAsBytes(user); MockHttpServletRequestBuilder post = post("/Users") .with(new SetServerNameRequestPostProcessor(subdomain + ".localhost")) .header("Authorization", "Bearer " + defaultZoneAdminToken) @@ -568,7 +568,7 @@ public void testModifyandDeleteUserInOtherZoneIsUnauthorized() throws Exception .header("Authorization", "Bearer " + zoneAdminToken) .header("If-Match", "\"" + user.getVersion() + "\"") .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(user)); + .content(JsonUtils.writeValueAsString(user)); mockMvc.perform(put) .andExpect(status().isUnauthorized()) @@ -601,7 +601,7 @@ private IdentityZone createZone(String id, HttpStatus expect, String token) thro MvcResult result = mockMvc.perform(post("/identity-zones") .header("Authorization", "Bearer " + token) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().is(expect.value())) .andReturn(); @@ -615,7 +615,7 @@ private IdentityZone updateZone(IdentityZone identityZone, HttpStatus expect, St MvcResult result = mockMvc.perform(put("/identity-zones/" + identityZone.getId()) .header("Authorization", "Bearer " + token) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(identityZone))) + .content(JsonUtils.writeValueAsString(identityZone))) .andExpect(status().is(expect.value())) .andReturn(); @@ -624,11 +624,11 @@ private IdentityZone updateZone(IdentityZone identityZone, HttpStatus expect, St } return null; } - + private <T extends AbstractUaaEvent> void checkZoneAuditEventInUaa(int eventCount, AuditEventType eventType) { checkAuditEventListener(eventCount, eventType, zoneModifiedEventListener, IdentityZone.getUaa().getId(), "http://localhost:8080/uaa/oauth/token", "identity"); } - + private <T extends AbstractUaaEvent> void checkAuditEventListener(int eventCount, AuditEventType eventType, TestApplicationEventListener<T> eventListener, String identityZoneId, String issuer, String subject) { T event = eventListener.getLatestEvent(); assertEquals(eventCount, eventListener.getEventCount()); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneSwitchingFilterMockMvcTest.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneSwitchingFilterMockMvcTest.java index c87375f3fbb..c3f1a0a4e98 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneSwitchingFilterMockMvcTest.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneSwitchingFilterMockMvcTest.java @@ -21,10 +21,10 @@ import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.SetServerNameRequestPostProcessor; import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneSwitchingFilter; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -96,7 +96,7 @@ public void testSwitchingZones() throws Exception { .header("Authorization", "Bearer " + zoneAdminToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(client))) + .content(JsonUtils.writeValueAsString(client))) .andExpect(status().isCreated()); // Authenticate with new Client in new Zone @@ -156,7 +156,7 @@ private void createClientInOtherZone(String accessToken, String zoneId, ResultMa .header("Authorization", "Bearer " + accessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(client))) + .content(JsonUtils.writeValueAsString(client))) .andExpect(statusMatcher); } } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsMockMvcTests.java index 762b7d1f5f6..5c9271f6805 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/PasswordResetEndpointsMockMvcTests.java @@ -12,13 +12,13 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.scim.endpoints; +import com.fasterxml.jackson.core.type.TypeReference; import com.googlecode.flyway.core.Flyway; import org.cloudfoundry.identity.uaa.TestClassNullifier; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -83,7 +83,7 @@ public void testAPasswordReset() throws Exception { .andReturn(); String responseString = result.getResponse().getContentAsString(); - Map<String,String> response = new ObjectMapper().readValue(responseString, new TypeReference<Map<String, String>>() { + Map<String,String> response = JsonUtils.readValue(responseString, new TypeReference<Map<String, String>>() { }); post = post("/password_change") diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java index 9b7683533db..5bf4373a8ae 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java @@ -29,8 +29,8 @@ import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimGroupProvisioning; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.zone.IdentityZone; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Assume; @@ -149,7 +149,7 @@ public void testIdentityClientManagesZoneAdmins() throws Exception { .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) .header("Authorization", "Bearer " + identityClientToken) - .content(new ObjectMapper().writeValueAsBytes(group)); + .content(JsonUtils.writeValueAsBytes(group)); //create the zones.{id}.admin mockMvc.perform(post) .andDo(print()) @@ -170,7 +170,7 @@ public void testIdentityClientManagesZoneAdmins() throws Exception { .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) .header("Authorization", "Bearer " + scimWriteToken) - .content(new ObjectMapper().writeValueAsBytes(group))) + .content(JsonUtils.writeValueAsBytes(group))) .andExpect(status().isForbidden()); mockMvc.perform( @@ -201,7 +201,7 @@ public void testIdentityClientManagesZoneAdmins() throws Exception { .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) .header("Authorization", "Bearer " + identityClientToken) - .content(new ObjectMapper().writeValueAsBytes(group)); + .content(JsonUtils.writeValueAsBytes(group)); //create the zones.{id}.admin mockMvc.perform(post) .andExpect(status().isCreated()); @@ -381,7 +381,7 @@ protected ResultActions createGroup(String id, String name, String externalName) if (id!=null) em.setGroupId(id); if (externalName!=null) em.setExternalGroup(externalName); if (name!=null) em.setDisplayName(name); - String content = new ObjectMapper().writeValueAsString(em); + String content = JsonUtils.writeValueAsString(em); MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post("/Groups/External") .header("Authorization", "Bearer " + scimWriteToken) .contentType(MediaType.APPLICATION_JSON) @@ -548,7 +548,7 @@ protected void checkGetExternalGroupsFilter(String fieldName, String fieldValue) String content = result.andReturn().getResponse().getContentAsString(); SearchResults<ScimGroupExternalMember> members = null; - Map<String,Object> map = new ObjectMapper().readValue(content, Map.class); + Map<String,Object> map = JsonUtils.readValue(content, Map.class); List<Map<String,String>> resources = (List<Map<String,String>>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -621,7 +621,7 @@ protected void checkGetExternalGroupsPagination(int start, int count) throws Exc String content = result.andReturn().getResponse().getContentAsString(); SearchResults<ScimGroupExternalMember> members = null; - Map<String,Object> map = new ObjectMapper().readValue(content, Map.class); + Map<String,Object> map = JsonUtils.readValue(content, Map.class); List<Map<String,String>> resources = (List<Map<String,String>>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -668,7 +668,7 @@ protected void checkGetExternalGroups(String path) throws Exception { String content = result.andReturn().getResponse().getContentAsString(); SearchResults<ScimGroupExternalMember> members = null; - Map<String,Object> map = new ObjectMapper().readValue(content, Map.class); + Map<String,Object> map = JsonUtils.readValue(content, Map.class); List<Map<String,String>> resources = (List<Map<String,String>>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -737,7 +737,7 @@ private void createScimClient(String adminAccessToken, String id, String secret) .header("Authorization", "Bearer " + adminAccessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(client)); + .content(JsonUtils.writeValueAsBytes(client)); mockMvc.perform(createClientPost).andExpect(status().isCreated()); } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserEndpointsMockMvcTests.java index 5c40ca7b830..8585a35bc00 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserEndpointsMockMvcTests.java @@ -19,16 +19,13 @@ import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.SetServerNameRequestPostProcessor; -import org.cloudfoundry.identity.uaa.zone.IdentityZone; -import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; -import org.codehaus.jackson.map.ObjectMapper; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.http.HttpStatus; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.web.FilterChainProxy; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; @@ -37,9 +34,6 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.support.XmlWebApplicationContext; -import java.util.ArrayList; -import java.util.List; - import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; @@ -93,7 +87,7 @@ private ScimUser createUser(String token, String subdomain) throws Exception { } private ScimUser createUser(ScimUser user, String token, String subdomain) throws Exception { - byte[] requestBody = new ObjectMapper().writeValueAsBytes(user); + byte[] requestBody = JsonUtils.writeValueAsBytes(user); MockHttpServletRequestBuilder post = post("/Users") .header("Authorization", "Bearer " + token) .contentType(APPLICATION_JSON) @@ -109,7 +103,7 @@ private ScimUser createUser(ScimUser user, String token, String subdomain) throw .andExpect(jsonPath("$.name.givenName").value(user.getGivenName())) .andReturn(); - return new ObjectMapper().readValue(result.getResponse().getContentAsString(), ScimUser.class); + return JsonUtils.readValue(result.getResponse().getContentAsString(), ScimUser.class); } private ScimUser getScimUser() { @@ -172,7 +166,7 @@ public void testCreateUserInOtherZoneIsUnauthorized() throws Exception { ScimUser user = getScimUser(); - byte[] requestBody = new ObjectMapper().writeValueAsBytes(user); + byte[] requestBody = JsonUtils.writeValueAsBytes(user); MockHttpServletRequestBuilder post = post("/Users") .with(new SetServerNameRequestPostProcessor(otherSubdomain + ".localhost")) .header("Authorization", "Bearer " + zoneAdminToken) @@ -255,7 +249,7 @@ private void updateUser(String token, int status) throws Exception { .header("If-Match", "\"" + user.getVersion() + "\"") .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(user)); + .content(JsonUtils.writeValueAsBytes(user)); if (status==HttpStatus.OK.value()) { mockMvc.perform(put) @@ -289,7 +283,7 @@ private void createScimClient(String adminAccessToken, String id, String secret) .header("Authorization", "Bearer " + adminAccessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(client)); + .content(JsonUtils.writeValueAsBytes(client)); mockMvc.perform(createClientPost).andExpect(status().isCreated()); } } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java index 3e0f4f50257..d483b4a9f1f 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java @@ -20,7 +20,7 @@ import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.test.YamlServletProfileInitializerContextInitializer; -import org.codehaus.jackson.map.ObjectMapper; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -222,7 +222,7 @@ private static void createScimClient(String adminAccessToken, String id, String .header("Authorization", "Bearer " + adminAccessToken) .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsBytes(client)); + .content(JsonUtils.writeValueAsBytes(client)); mockMvc.perform(createClientPost).andExpect(status().isCreated()); } @@ -253,7 +253,7 @@ private MockHttpServletRequestBuilder getUsernameLookupRequest(String token, Str } private void validateLookupResults(String[] usernames, String body) throws java.io.IOException { - Map<String, Object> map = new ObjectMapper().readValue(body, Map.class); + Map<String, Object> map = JsonUtils.readValue(body, Map.class); assertTrue("Response should contain 'resources' object", map.get("resources")!=null); assertTrue("Response should contain 'startIndex' object", map.get("startIndex")!=null); assertTrue("Response should contain 'itemsPerPage' object", map.get("itemsPerPage")!=null); @@ -298,7 +298,7 @@ private static String[][] createUsers(String token, int count) throws Exception user.setName(new ScimUser.Name("Joe", "User")); user.addEmail(email); - byte[] requestBody = new ObjectMapper().writeValueAsBytes(user); + byte[] requestBody = JsonUtils.writeValueAsBytes(user); MockHttpServletRequestBuilder post = post("/Users") .header("Authorization", "Bearer " + token) .contentType(APPLICATION_JSON) @@ -312,7 +312,7 @@ private static String[][] createUsers(String token, int count) throws Exception .andExpect(jsonPath("$.name.familyName").value("User")) .andExpect(jsonPath("$.name.givenName").value("Joe")) .andReturn().getResponse().getContentAsString(); - Map<String,Object> map = new ObjectMapper().readValue(body, Map.class); + Map<String,Object> map = JsonUtils.readValue(body, Map.class); result[i] = new String[] {map.get("id").toString(), email}; } return result; diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java index 714488df6f4..a3615675591 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java @@ -12,28 +12,25 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.test; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.codec.binary.Base64; +import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.cloudfoundry.identity.uaa.util.SetServerNameRequestPostProcessor; -import org.codehaus.jackson.annotate.JsonIgnoreProperties; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.map.ObjectMapper; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + public class TestClient { //TODO nullify fields? private MockMvc mockMvc; - private final ObjectMapper objectMapper; public TestClient(MockMvc mockMvc) { this.mockMvc = mockMvc; - objectMapper = new ObjectMapper(); } public String getClientCredentialsOAuthAccessToken(String username, String password, String scope) throws Exception { @@ -53,7 +50,7 @@ public String getClientCredentialsOAuthAccessToken(String username, String passw MvcResult result = mockMvc.perform(oauthTokenPost) .andExpect(status().isOk()) .andReturn(); - OAuthToken oauthToken = objectMapper.readValue(result.getResponse().getContentAsByteArray(), OAuthToken.class); + OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), OAuthToken.class); return oauthToken.accessToken; } @@ -69,7 +66,7 @@ public String getUserOAuthAccessToken(String clientId, String clientSecret, Stri .param("password", password) .param("scope", scope); MvcResult result = mockMvc.perform(oauthTokenPost).andExpect(status().isOk()).andReturn(); - OAuthToken oauthToken = objectMapper.readValue(result.getResponse().getContentAsByteArray(), OAuthToken.class); + OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), OAuthToken.class); return oauthToken.accessToken; } From b7908503dc654693f61eaeb80bd949895a02c51f Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Tue, 5 May 2015 17:47:03 -0600 Subject: [PATCH 3/9] Attempt to upgrade to Spring Security 4 http://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-xml.html#m3to4-xmlnamespace-http Check for hasAuthority when we are dealing with clients only, hasRole no longer checks authorities Upgrade Spring Security SAML to 1.0.1 https://www.pivotaltracker.com/story/show/93706906 [#93706906] --- common/build.gradle | 2 +- .../uaa/ldap/ExtendedLdapUserMapper.java | 19 ++++++++- .../ldap/PasswordComparisonAuthenticator.java | 2 +- .../extension/SpringSecurityLdapTemplate.java | 2 +- .../uaa/login/XFrameOptionsFilter.java | 2 +- .../web/DelegatingRequestMatcher.java | 8 ++-- .../uaa/security/web/UaaRequestMatcher.java | 10 ++--- login/src/main/resources/login-ui.xml | 29 +++++++++----- .../main/webapp/WEB-INF/spring-servlet.xml | 12 +++--- .../main/webapp/WEB-INF/spring-servlet.xml | 16 ++++---- shared_versions.gradle | 5 ++- uaa/src/main/resources/ldap-integration.xml | 2 +- .../main/webapp/WEB-INF/spring-servlet.xml | 40 +++++++++---------- .../WEB-INF/spring/approvals-endpoints.xml | 9 +++-- .../WEB-INF/spring/client-admin-endpoints.xml | 13 +++--- .../WEB-INF/spring/codestore-endpoints.xml | 28 ++++++++----- .../WEB-INF/spring/login-server-security.xml | 34 +++++++++------- .../WEB-INF/spring/multitenant-endpoints.xml | 4 +- .../webapp/WEB-INF/spring/oauth-endpoints.xml | 20 ++++++---- .../WEB-INF/spring/openid-endpoints.xml | 7 ++-- .../WEB-INF/spring/resource-endpoints.xml | 9 +++-- .../webapp/WEB-INF/spring/saml-providers.xml | 15 +++---- .../webapp/WEB-INF/spring/scim-endpoints.xml | 34 +++++++++------- .../NativeApplicationIntegrationTests.java | 11 +++-- .../RefreshTokenSupportIntegrationTests.java | 4 +- .../token/TokenKeyEndpointMockMvcTests.java | 21 +++++++++- uaa/src/test/resources/test-security.xml | 2 +- 27 files changed, 222 insertions(+), 138 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index 2efeee69c54..de82dbb63f0 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -50,7 +50,7 @@ dependencies { compile group: 'com.googlecode.flyway', name: 'flyway-core', version:'2.3.1' compile group: 'org.hsqldb', name: 'hsqldb', version:'2.3.1' - compile(group: 'org.springframework.security.extensions', name: 'spring-security-saml2-core', version:'1.0.0.RELEASE') { + compile(group: 'org.springframework.security.extensions', name: 'spring-security-saml2-core', version:parent.springSecuritySamlVersion) { exclude(module: 'bcprov-jdk15') } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/ExtendedLdapUserMapper.java b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/ExtendedLdapUserMapper.java index 425e9beed80..aefd8c0a959 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/ExtendedLdapUserMapper.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/ExtendedLdapUserMapper.java @@ -23,9 +23,14 @@ import org.springframework.security.ldap.userdetails.LdapUserDetails; import org.springframework.security.ldap.userdetails.LdapUserDetailsMapper; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -47,7 +52,19 @@ public UserDetails mapUserFromContext(DirContextOperations ctx, String username, List<String> attributeNames = Collections.list(adapter.getAttributes().getIDs()); for (String attributeName : attributeNames) { try { - String[] values = adapter.getStringAttributes(attributeName); + Object[] objValues = adapter.getObjectAttributes(attributeName); + String[] values = new String[objValues!=null ? objValues.length : 0]; + for (int i=0; i<values.length; i++) { + if (objValues[i] != null) { + if (objValues[i].getClass().isAssignableFrom(String.class)) { + values[i] = (String)objValues[i]; + } else if (objValues[i] instanceof byte[]) { + values[i] = new String((byte[])objValues[i]); + } else { + values[i] = objValues[i].toString(); + } + } + } if (values == null || values.length == 0) { logger.debug("No attribute value found for '" + attributeName + "'"); } else { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/PasswordComparisonAuthenticator.java b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/PasswordComparisonAuthenticator.java index 8e9ae68a7e5..58caad3d66c 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/PasswordComparisonAuthenticator.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/PasswordComparisonAuthenticator.java @@ -75,7 +75,7 @@ public DirContextOperations authenticate(Authentication authentication) { } if (user == null) { - throw new UsernameNotFoundException("User not found: " + username, username); + throw new UsernameNotFoundException("User not found: " + username); } if (logger.isDebugEnabled()) { diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/extension/SpringSecurityLdapTemplate.java b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/extension/SpringSecurityLdapTemplate.java index 0cfa4923b42..ab16ef724af 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/extension/SpringSecurityLdapTemplate.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/ldap/extension/SpringSecurityLdapTemplate.java @@ -24,8 +24,8 @@ import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.core.DirContextOperations; import org.springframework.ldap.core.DistinguishedName; -import org.springframework.ldap.core.LdapEncoder; import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.support.LdapEncoder; import org.springframework.security.ldap.LdapUtils; import org.springframework.util.Assert; diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/login/XFrameOptionsFilter.java b/common/src/main/java/org/cloudfoundry/identity/uaa/login/XFrameOptionsFilter.java index e5ca82d61af..93c70aeb47a 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/login/XFrameOptionsFilter.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/login/XFrameOptionsFilter.java @@ -12,7 +12,7 @@ public class XFrameOptionsFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - response.addHeader("X-Frame-Options", "DENY"); + response.setHeader("X-Frame-Options", "DENY"); filterChain.doFilter(request, response); } } diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/DelegatingRequestMatcher.java b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/DelegatingRequestMatcher.java index a7eead4eeac..f1dd6e893c4 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/DelegatingRequestMatcher.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/DelegatingRequestMatcher.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"). @@ -13,13 +13,13 @@ package org.cloudfoundry.identity.uaa.security.web; +import org.springframework.security.web.util.matcher.RequestMatcher; + import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.springframework.security.web.util.RequestMatcher; - /** * @author Luke Taylor */ @@ -27,7 +27,7 @@ public class DelegatingRequestMatcher implements RequestMatcher { private final List<RequestMatcher> matchers; public DelegatingRequestMatcher(List<RequestMatcher> matchers) { - this.matchers = new ArrayList<RequestMatcher>(matchers); + this.matchers = new ArrayList<>(matchers); } @Override diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/UaaRequestMatcher.java b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/UaaRequestMatcher.java index bd23a5bdb75..8cb881a02e5 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/UaaRequestMatcher.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/security/web/UaaRequestMatcher.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"). @@ -26,7 +26,7 @@ import org.springframework.beans.factory.BeanNameAware; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.security.web.util.RequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.util.Assert; /** @@ -67,7 +67,7 @@ public UaaRequestMatcher(String path) { /** * The HttpMethod that the request should be made with. Optional (if null, * then all values match) - * + * * @param method */ public void setMethod(HttpMethod method) { @@ -78,7 +78,7 @@ public void setMethod(HttpMethod method) { * A media type that should be present in the accept header for a request to * match. Optional (if null then all * values match). - * + * * @param accepts the accept header value to set */ public void setAccept(List<String> accepts) { @@ -90,7 +90,7 @@ public void setAccept(List<String> accepts) { * A map of request parameter name and values to match against. If all the * specified parameters are present and * match the values given then the accept header will be ignored. - * + * * @param parameters the parameter matches to set */ public void setParameters(Map<String, String> parameters) { diff --git a/login/src/main/resources/login-ui.xml b/login/src/main/resources/login-ui.xml index e3d326deaae..4226b60c2ee 100644 --- a/login/src/main/resources/login-ui.xml +++ b/login/src/main/resources/login-ui.xml @@ -22,7 +22,7 @@ xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd @@ -41,31 +41,35 @@ </bean> <!-- Pattern: /oauth/authorize parameters:{response_type=code,code=?} --> - <http request-matcher-ref="autologinAuthorizeRequestMatcher" entry-point-ref="loginEntryPoint" + <http name="secFilterAutologinAuthorize" request-matcher-ref="autologinAuthorizeRequestMatcher" entry-point-ref="loginEntryPoint" xmlns="http://www.springframework.org/schema/security"> <!-- TODO: add entry point that can redirect back to client app? --> <anonymous enabled="false" /> <custom-filter ref="autologinAuthenticationFilter" position="FORM_LOGIN_FILTER" /> + <csrf disabled="true"/> </http> <!-- Pattern:/autologin --> - <http name="autologinSecurity" pattern="/autologin" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint" - xmlns="http://www.springframework.org/schema/security" authentication-manager-ref="emptyAuthenticationManager"> + <http name="secFilterAutologin" pattern="/autologin" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint" + xmlns="http://www.springframework.org/schema/security" authentication-manager-ref="emptyAuthenticationManager" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> + <csrf disabled="true"/> </http> <bean id="backwardsCompatibleScopeParameter" class="org.cloudfoundry.identity.uaa.oauth.BackwardsCompatibleScopeParsingFilter"/> - <http name="uiSecurity" request-matcher-ref="uiRequestMatcher" access-denied-page="/" + <http name="uiSecurity" request-matcher-ref="uiRequestMatcher" use-expressions="false" authentication-manager-ref="zoneAwareAuthzAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> + <access-denied-handler error-page="/"/> <intercept-url pattern="/login**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <form-login login-page="/login" username-parameter="username" password-parameter="password" login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" authentication-details-source-ref="authenticationDetailsSource"/> <logout logout-url="/logout.do" success-handler-ref="logoutHandler" /> + <csrf disabled="true"/> </http> @@ -81,30 +85,34 @@ </bean> <security:http name="resetPasswordSecurity" pattern="/reset_password.do" disable-url-rewriting="true" - entry-point-ref="loginEntryPoint"> + entry-point-ref="loginEntryPoint" use-expressions="false"> <security:intercept-url pattern="/reset_password.do" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <security:anonymous enabled="true" /> + <security:csrf disabled="true"/> </security:http> <security:http name="verifyEmailSecurity" pattern="/verify_email" disable-url-rewriting="true" - entry-point-ref="loginEntryPoint"> + entry-point-ref="loginEntryPoint" use-expressions="false"> <security:intercept-url pattern="/verify_email" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <security:anonymous enabled="true" /> + <security:csrf disabled="true"/> </security:http> <security:http name="verifyUserSecurity" pattern="/verify_user" disable-url-rewriting="true" - entry-point-ref="loginEntryPoint"> + entry-point-ref="loginEntryPoint" use-expressions="false"> <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <security:anonymous enabled="true" /> + <security:csrf disabled="true"/> </security:http> <security:http name="acceptInvitationSecurity" pattern="/invitations/accept" disable-url-rewriting="true" - entry-point-ref="loginEntryPoint"> + entry-point-ref="loginEntryPoint" use-expressions="false"> <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <security:anonymous enabled="true" /> + <security:csrf disabled="true"/> </security:http> - <security:http name="openIdSecurity"> + <security:http name="openIdSecurity" use-expressions="false"> <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <security:custom-filter before="FIRST" ref="metadataGeneratorFilter" /> <security:custom-filter after="FIRST" ref="httpsHeaderFilter" /> @@ -131,6 +139,7 @@ </security:attribute-exchange> </security:openid-login> <security:anonymous enabled="false" /> + <security:csrf disabled="true"/> </security:http> diff --git a/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml index 4e397a54845..1d73aa23d70 100755 --- a/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml @@ -10,23 +10,25 @@ xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> - <http pattern="/index.html" security="none" xmlns="http://www.springframework.org/schema/security" /> + <http pattern="/index.html" security="none" xmlns="http://www.springframework.org/schema/security"/> <http pattern="/browse" security="none" xmlns="http://www.springframework.org/schema/security" /> <http pattern="/denied" security="none" xmlns="http://www.springframework.org/schema/security" /> <http pattern="/js/**" security="none" xmlns="http://www.springframework.org/schema/security" /> <!-- TODO: make an access denied view that tells me something useful --> - <http access-denied-page="/denied" entry-point-ref="authenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" - xmlns="http://www.springframework.org/schema/security"> + <http name="apiDefaultFilter" entry-point-ref="authenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> + <access-denied-handler error-page="/denied"/> <intercept-url pattern="/info" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/apps" access="scope=cloud_controller.read" /> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="oauth2ServiceFilter" position="PRE_AUTH_FILTER" /> <custom-filter ref="contentTypeFilter" after="EXCEPTION_TRANSLATION_FILTER" /> <anonymous /> + <csrf disabled="true"/> </http> <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans"> @@ -44,7 +46,7 @@ <bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/beans"> - <property name="loginFormUrl" value="${auth.url}" /> + <constructor-arg value="${auth.url}" /> </bean> <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" diff --git a/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml index 88b41d9cad2..05503183abe 100755 --- a/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/samples/app/src/main/webapp/WEB-INF/spring-servlet.xml @@ -11,23 +11,24 @@ xmlns:sec="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> - <sec:http pattern="/logout" security="none" /> - <sec:http pattern="/login_error.jsp" security="none" /> - <sec:http pattern="/resources/**" security="none" /> - <sec:http pattern="/favicon.ico" security="none" /> + <sec:http name="appFilterLogout" pattern="/logout" security="none" /> + <sec:http name="appFilterLoginError" pattern="/login_error.jsp" security="none" /> + <sec:http name="appFilterResources" pattern="/resources/**" security="none" /> + <sec:http name="appFilterFavIcon" pattern="/favicon.ico" security="none" /> - <http pattern="/apps.*" request-matcher="regex" xmlns="http://www.springframework.org/schema/security" + <http name="appFilterApps" pattern="/apps.*" request-matcher="regex" xmlns="http://www.springframework.org/schema/security" entry-point-ref="loginEntryPoint" disable-url-rewriting="true" use-expressions="true" authentication-manager-ref="authenticationManager"> <intercept-url pattern="/apps.*" access="hasRole('cloud_controller.read')" /> <anonymous enabled="false" /> <custom-filter ref="oauth2ClientFilter" before="PRE_AUTH_FILTER" /> <custom-filter ref="accessTokenFilter" position="PRE_AUTH_FILTER" /> + <csrf disabled="true"/> </http> - <http xmlns="http://www.springframework.org/schema/security" entry-point-ref="loginEntryPoint" + <http name="appFilterDefault" xmlns="http://www.springframework.org/schema/security" entry-point-ref="loginEntryPoint" disable-url-rewriting="true" use-expressions="true" authentication-manager-ref="authenticationManager" security-context-repository-ref="securityContextRepository"> <intercept-url pattern="/**" access="isFullyAuthenticated()" /> @@ -35,6 +36,7 @@ <anonymous enabled="false" /> <custom-filter ref="oauth2ClientFilter" before="PRE_AUTH_FILTER" /> <custom-filter ref="socialClientFilter" position="PRE_AUTH_FILTER" /> + <csrf disabled="true"/> </http> <bean id="securityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"> diff --git a/shared_versions.gradle b/shared_versions.gradle index 52338d51d01..cefb7e8b1d6 100644 --- a/shared_versions.gradle +++ b/shared_versions.gradle @@ -1,8 +1,9 @@ ext { springVersion = '4.1.6.RELEASE' - springSecurityVersion = '3.2.7.RELEASE' + springSecurityVersion = '4.0.1.RELEASE' springSecurityOAuthVersion = '2.0.7.RELEASE' - springSecurityLdapVersion = '1.3.2.RELEASE' + springSecurityLdapVersion = '2.0.3.RELEASE' + springSecuritySamlVersion = '1.0.1.RELEASE' postgresqlVersion = '9.1-901.jdbc3' tomcatVersion = '7.0.54' springSecurityJwtVersion = '1.0.3.RELEASE' diff --git a/uaa/src/main/resources/ldap-integration.xml b/uaa/src/main/resources/ldap-integration.xml index 06a961fdb04..aacf04e10f5 100644 --- a/uaa/src/main/resources/ldap-integration.xml +++ b/uaa/src/main/resources/ldap-integration.xml @@ -18,7 +18,7 @@ xmlns:sec="http://www.springframework.org/schema/security" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> diff --git a/uaa/src/main/webapp/WEB-INF/spring-servlet.xml b/uaa/src/main/webapp/WEB-INF/spring-servlet.xml index 56f66244ad0..a29e3a554ff 100755 --- a/uaa/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/uaa/src/main/webapp/WEB-INF/spring-servlet.xml @@ -19,7 +19,7 @@ xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> @@ -37,20 +37,20 @@ <import resource="classpath:spring/env.xml" /> <import resource="spring/audit.xml" /> - <sec:http pattern="/resources/**" security="none" /> - <sec:http pattern="/favicon.ico" security="none" /> - <sec:http pattern="/info" security="none" /> - <sec:http pattern="/password/**" security="none" /> - <sec:http pattern="/healthz/**" security="none" name="healthz"/> - <sec:http pattern="/saml/web/**" security="none" /> - <sec:http pattern="/vendor/**" security="none" /> + <sec:http name="secFilterOpen01" pattern="/resources/**" security="none" /> + <sec:http name="secFilterOpen02" pattern="/favicon.ico" security="none" /> + <sec:http name="secFilterOpen03" pattern="/info" security="none" /> + <sec:http name="secFilterOpen04" pattern="/password/**" security="none" /> + <sec:http name="secFilterOpen05Healthz" pattern="/healthz/**" security="none" /> + <sec:http name="secFilterOpen06" pattern="/saml/web/**" security="none" /> + <sec:http name="secFilterOpen07" pattern="/vendor/**" security="none" /> <!--<sec:http pattern="/login" security="none" />--> - <sec:http pattern="/error" security="none" /> - <sec:http pattern="/forgot_password*" security="none" /> - <sec:http pattern="/reset_password" security="none" /> - <sec:http pattern="/email_sent" security="none" /> - <sec:http pattern="/create_account*" security="none" /> - <sec:http pattern="/accounts/email_sent" security="none" /> + <sec:http name="secFilterOpen08" pattern="/error" security="none" /> + <sec:http name="secFilterOpen09" pattern="/forgot_password*" security="none" /> + <sec:http name="secFilterOpen10" pattern="/reset_password" security="none" /> + <sec:http name="secFilterOpen11" pattern="/email_sent" security="none" /> + <sec:http name="secFilterOpen12" pattern="/create_account*" security="none" /> + <sec:http name="secFilterOpen13" pattern="/accounts/email_sent" security="none" /> <bean id="xFrameOptionsFilter" class="org.cloudfoundry.identity.uaa.login.XFrameOptionsFilter" /> <bean id="oauth2TokenParseFilter" class="java.lang.Class" factory-method="forName"> @@ -68,7 +68,7 @@ </property> <property name="ignore"> <list> - <value>healthz</value> + <value>secFilterOpen05Healthz</value> </list> </property> <property name="errorMap"> @@ -184,19 +184,19 @@ <bean id="uiRequestMatcher" class="org.cloudfoundry.identity.uaa.security.web.DelegatingRequestMatcher"> <constructor-arg> <list> - <bean class="org.springframework.security.web.util.AntPathRequestMatcher"> + <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/" /> </bean> - <bean class="org.springframework.security.web.util.AntPathRequestMatcher"> + <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/spring_security_login" /> </bean> - <bean class="org.springframework.security.web.util.AntPathRequestMatcher"> + <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/oauth/**" /> </bean> - <bean class="org.springframework.security.web.util.AntPathRequestMatcher"> + <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/login**" /> </bean> - <bean class="org.springframework.security.web.util.AntPathRequestMatcher"> + <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> <constructor-arg value="/logout.do*" /> </bean> </list> diff --git a/uaa/src/main/webapp/WEB-INF/spring/approvals-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/approvals-endpoints.xml index 51d7a5b6af4..c01435c4434 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/approvals-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/approvals-endpoints.xml @@ -16,9 +16,9 @@ xmlns:sec="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <sec:global-method-security pre-post-annotations="enabled" /> @@ -50,11 +50,12 @@ </bean> <http name="approvalsSecurity" pattern="/approvals/**" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="scope=oauth.approvals" /> <custom-filter ref="approvalsResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <oauth:resource-server id="approvalsResourceAuthenticationFilter" token-services-ref="tokenServices" diff --git a/uaa/src/main/webapp/WEB-INF/spring/client-admin-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/client-admin-endpoints.xml index 84f9d62e271..6acc488345d 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/client-admin-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/client-admin-endpoints.xml @@ -15,16 +15,17 @@ <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd - http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> + http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <http name="clientSecretSecurity" pattern="/oauth/clients/*/secret" create-session="stateless" - authentication-manager-ref="emptyAuthenticationManager" entry-point-ref="oauthAuthenticationEntryPoint" + authentication-manager-ref="emptyAuthenticationManager" entry-point-ref="oauthAuthenticationEntryPoint" use-expressions="false" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/oauth/clients/*/secret" access="IS_AUTHENTICATED_FULLY,scope=clients.secret" /> <custom-filter ref="oauthWithoutResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <http name="clientTxAdminSecurity" pattern="/oauth/clients/tx/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" @@ -35,6 +36,7 @@ <custom-filter ref="oauthWithoutResourceAuthenticationFilter" before="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> <expression-handler ref="oauthWebExpressionHandler" /> + <csrf disabled="true"/> </http> <http name="clientAdminSecurity" pattern="/oauth/clients/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" @@ -46,6 +48,7 @@ <custom-filter ref="oauthWithoutResourceAuthenticationFilter" before="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> <expression-handler ref="oauthWebExpressionHandler" /> + <csrf disabled="true"/> </http> <oauth:resource-server id="clientResourceAuthenticationFilter" token-services-ref="tokenServices" @@ -75,7 +78,7 @@ </property> <property name="clientDetailsValidator" ref="clientDetailsValidator"/> </bean> - + <bean id="clientDetailsValidator" class="org.cloudfoundry.identity.uaa.oauth.ClientAdminEndpointsValidator"> <property name="clientDetailsService" ref="clientDetailsService" /> </bean> diff --git a/uaa/src/main/webapp/WEB-INF/spring/codestore-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/codestore-endpoints.xml index f6c7aac8d7a..5d8c6e80d05 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/codestore-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/codestore-endpoints.xml @@ -1,11 +1,20 @@ -<?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:security="http://www.springframework.org/schema/security" - xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/security - http://www.springframework.org/schema/security/spring-security.xsd"> +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + 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. + +--> +<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" + xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="codeStoreEndpoints" class="org.cloudfoundry.identity.uaa.codestore.CodeStoreEndpoints"> <property name="expiringCodeStore" ref="codeStore" /> @@ -15,10 +24,11 @@ </bean> <http create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="emptyAuthenticationManager" - access-decision-manager-ref="userAccessDecisionManager" pattern="/Codes/**" xmlns="http://www.springframework.org/schema/security"> + access-decision-manager-ref="userAccessDecisionManager" pattern="/Codes/**" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="scope=scim.create,scope=scim.write,scope=password.write" /> <custom-filter ref="resourceAgnosticAuthenticationFilter" position="PRE_AUTH_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> </beans> \ No newline at end of file diff --git a/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml b/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml index 19e8913c028..5db433ceceb 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/login-server-security.xml @@ -16,21 +16,22 @@ xmlns:sec="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <oauth:resource-server id="oauthResourceAuthenticationFilter" token-services-ref="tokenServices" resource-id="oauth" entry-point-ref="oauthAuthenticationEntryPoint" /> - <http request-matcher-ref="loginAuthenticateRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" - authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerAuthenticate" request-matcher-ref="loginAuthenticateRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" + authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="oauthResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <!-- scope authentication filter configured with a scope authentication manager --> <custom-filter ref="oauthLoginScopeAuthenticatingFilter" after="PRE_AUTH_FILTER"/> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="loginAuthenticateRequestMatcher" class="org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher"> @@ -43,10 +44,10 @@ </property> </bean> - <sec:http pattern="/authenticate/**" security="none" /> + <sec:http name="secFilterAuthenticateOpen" pattern="/authenticate/**" security="none" /> - <http request-matcher-ref="loginAuthorizeRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" - authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerAuthorize" request-matcher-ref="loginAuthorizeRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" + authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="backwardsCompatibleScopeParameter" position="FIRST"/> <custom-filter ref="oauthResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> @@ -55,6 +56,7 @@ <custom-filter ref="loginAuthenticationFilter" position="FORM_LOGIN_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="loginAuthorizeRequestMatcher" class="org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher"> @@ -67,8 +69,8 @@ </property> </bean> - <http request-matcher-ref="loginTokenRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" - authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerToken" request-matcher-ref="loginTokenRequestMatcher" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" + authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <!-- This represents a /oauth/token requests that gets passed through from the login server. It assumes that the User has been authenticated @@ -92,6 +94,7 @@ <custom-filter ref="loginServerTokenEndpointAuthenticationFilter" position="BASIC_AUTH_FILTER"/> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="oauthLoginScopeAuthenticatingFilter" class="org.cloudfoundry.identity.uaa.authentication.manager.ScopeAuthenticationFilter"> @@ -137,14 +140,15 @@ <!-- Support for older login servers --> - <http request-matcher-ref="loginAuthorizeRequestMatcherOld" create-session="always" entry-point-ref="oauthAuthenticationEntryPoint" - authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerAuthorizeOld" request-matcher-ref="loginAuthorizeRequestMatcherOld" create-session="always" entry-point-ref="oauthAuthenticationEntryPoint" + authentication-manager-ref="loginAuthenticationMgr" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="backwardsCompatibleScopeParameter" position="FIRST"/> <custom-filter ref="oauthResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <custom-filter ref="loginAuthenticationFilter" position="FORM_LOGIN_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="loginAuthorizeRequestMatcherOld" class="org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher"> @@ -197,19 +201,21 @@ <constructor-arg ref="clientDetailsService"/> </bean> - <http create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="emptyAuthenticationManager" - access-decision-manager-ref="accessDecisionManager" pattern="/password_*" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerPasswordEndpoints" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="emptyAuthenticationManager" + access-decision-manager-ref="accessDecisionManager" pattern="/password_*" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="scope=oauth.login" /> <custom-filter ref="oauthResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> - <http create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="emptyAuthenticationManager" - access-decision-manager-ref="accessDecisionManager" pattern="/email_*" xmlns="http://www.springframework.org/schema/security"> + <http name="secFilterLoginServerEmailEndpoints" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="emptyAuthenticationManager" + access-decision-manager-ref="accessDecisionManager" pattern="/email_*" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="scope=oauth.login" /> <custom-filter ref="oauthResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> </beans> diff --git a/uaa/src/main/webapp/WEB-INF/spring/multitenant-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/multitenant-endpoints.xml index ff5dc35ed17..597d4758dd2 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/multitenant-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/multitenant-endpoints.xml @@ -1,6 +1,6 @@ <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" - xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> @@ -57,6 +57,7 @@ <custom-filter ref="resourceAgnosticAuthenticationFilter" before="PRE_AUTH_FILTER"/> <access-denied-handler ref="oauthAccessDeniedHandler"/> <expression-handler ref="oauthWebExpressionHandler"/> + <csrf disabled="true"/> </http> @@ -115,6 +116,7 @@ method="GET"/> <custom-filter ref="resourceAgnosticAuthenticationFilter" before="PRE_AUTH_FILTER"/> <expression-handler ref="oauthWebExpressionHandler"/> + <csrf disabled="true"/> </http> <bean id="idpEventPublisher" class="org.cloudfoundry.identity.uaa.zone.event.IdentityProviderEventPublisher"/> diff --git a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml index 49ad5fd29b5..9d25ddd3604 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml @@ -16,10 +16,10 @@ xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd - http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <!--<bean id="tokenEndpoint" class="org.springframework.security.oauth2.provider.endpoint.TokenEndpoint" autowire="byType">--> <!--<property name="OAuth2RequestValidator">--> @@ -43,7 +43,7 @@ <!-- Owner password flow for external authentication (SAML) --> <!-- Pattern: /oauth/token parameters:{grant_type=password,passcode= --> - <http name="tokenEndpointSecurityForPasscodes" request-matcher-ref="passcodeTokenMatcher" create-session="stateless" + <http name="tokenEndpointSecurityForPasscodes" request-matcher-ref="passcodeTokenMatcher" create-session="stateless" use-expressions="false" entry-point-ref="basicAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security" authentication-manager-ref="emptyAuthenticationManager"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> @@ -51,6 +51,7 @@ <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> <custom-filter ref="passcodeAuthenticationFilter" after="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="passcodeAuthenticationFilter" class="org.cloudfoundry.identity.uaa.login.PasscodeAuthenticationFilter"> @@ -98,7 +99,7 @@ </bean> <!--/oauth/token with any match --> - <http name="tokenEndpointSecurity" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" + <http name="tokenEndpointSecurity" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" use-expressions="false" pattern="/oauth/token/**" entry-point-ref="basicAuthenticationEntryPoint" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <anonymous enabled="false" /> @@ -106,6 +107,7 @@ <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> <custom-filter ref="tokenEndpointAuthenticationFilter" after="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <!-- Version of the /authorize endpoint for stateless clients such as cf @@ -113,12 +115,13 @@ --> <http name="statelessAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcher" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="zoneAwareAuthzAuthenticationManager" - xmlns="http://www.springframework.org/schema/security"> + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="backwardsCompatibleScopeParameter" position="FIRST"/> <custom-filter ref="authzAuthenticationFilter" position="FORM_LOGIN_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="clientAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"> @@ -194,12 +197,13 @@ --> <http name="oldAuthzEndpointSecurity" request-matcher-ref="oauthAuthorizeRequestMatcherOld" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="zoneAwareAuthzAuthenticationManager" - xmlns="http://www.springframework.org/schema/security"> + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <custom-filter ref="backwardsCompatibleScopeParameter" position="FIRST"/> <custom-filter ref="authzAuthenticationFilter" position="FORM_LOGIN_FILTER" /> <anonymous enabled="false" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="oauthAuthorizeRequestMatcherOld" class="org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher"> diff --git a/uaa/src/main/webapp/WEB-INF/spring/openid-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/openid-endpoints.xml index 2993d4380d7..d71d2cf95e7 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/openid-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/openid-endpoints.xml @@ -15,15 +15,16 @@ <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <http name="userInfoSecurity" pattern="/userinfo" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="scope=openid" /> <custom-filter ref="openidResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <oauth:resource-server id="openidResourceAuthenticationFilter" token-services-ref="tokenServices" diff --git a/uaa/src/main/webapp/WEB-INF/spring/resource-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/resource-endpoints.xml index 72a55746cc5..ddb56f72cb2 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/resource-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/resource-endpoints.xml @@ -13,25 +13,27 @@ --> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" - xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd + xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <http name="checkTokenSecurity" pattern="/check_token" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager" use-expressions="true" xmlns="http://www.springframework.org/schema/security"> - <intercept-url pattern="/**" access="hasRole('uaa.resource')" /> + <intercept-url pattern="/**" access="hasAuthority('uaa.resource')" /> <anonymous enabled="false" /> <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <http name="tokenKeySecurity" pattern="/token_key" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager" use-expressions="true" xmlns="http://www.springframework.org/schema/security"> - <intercept-url pattern="/**" access="isAnonymous() or hasRole('uaa.resource')" /> + <intercept-url pattern="/**" access="isAnonymous() or hasAuthority('uaa.resource')" /> <anonymous enabled="true" /> <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <http name="clientInfoSecurity" pattern="/clientinfo" create-session="stateless" entry-point-ref="basicAuthenticationEntryPoint" @@ -41,6 +43,7 @@ <anonymous enabled="false" /> <custom-filter ref="clientAuthenticationFilter" position="BASIC_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="checkTokenEndpoint" class="org.cloudfoundry.identity.uaa.oauth.CheckTokenEndpoint"> diff --git a/uaa/src/main/webapp/WEB-INF/spring/saml-providers.xml b/uaa/src/main/webapp/WEB-INF/spring/saml-providers.xml index f0d59c6d29b..7106edccb19 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/saml-providers.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/saml-providers.xml @@ -13,16 +13,11 @@ --> -<beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" - xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" - xmlns:cache="http://www.springframework.org/schema/cache" +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:security="http://www.springframework.org/schema/security" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd - http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd"> + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd"> <!-- Register authentication manager with SAML provider --> @@ -31,7 +26,7 @@ </security:authentication-manager> <bean id="samlFilter" class="org.springframework.security.web.FilterChainProxy"> - <security:filter-chain-map path-type="ant"> + <security:filter-chain-map request-matcher="ant"> <security:filter-chain pattern="/saml/login/**" filters="samlEntryPoint" /> <security:filter-chain pattern="/saml/logout/**" filters="samlLogoutFilter" /> <security:filter-chain pattern="/saml/metadata/**" filters="metadataDisplayFilter" /> diff --git a/uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml index 954692cc7fd..c2ecedbbb3d 100644 --- a/uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/scim-endpoints.xml @@ -16,10 +16,10 @@ xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd - http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd - http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> + http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <bean id="scimUserProvisioning" class="org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimUserProvisioning"> <constructor-arg ref="jdbcTemplate" /> @@ -144,21 +144,23 @@ </constructor-arg> </bean> - <http request-matcher-ref="groupsUpdateRequestMatcher" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="groupAccessDecisionManager" + <http name="scimGroupUpdate" request-matcher-ref="groupsUpdateRequestMatcher" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="groupAccessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="scope=scim.write,scope=groups.update,memberScope=writer" method="PUT" /> <custom-filter ref="scimResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> - <http request-matcher-ref="groupsReadRequestMatcher" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="groupAccessDecisionManager" + <http name="scimGroupRead" request-matcher-ref="groupsReadRequestMatcher" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="groupAccessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="scope=scim.read,memberScope=reader" method="GET" /> <custom-filter ref="scimResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="groupsUpdateRequestMatcher" class="org.cloudfoundry.identity.uaa.security.web.UaaRequestMatcher"> @@ -184,6 +186,7 @@ <custom-filter ref="scimResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> <expression-handler ref="oauthWebExpressionHandler" /> + <csrf disabled="true"/> </http> <bean id="userIdsEnabled" class="java.lang.Boolean"> @@ -213,12 +216,13 @@ </aop:aspect> </aop:config> - <http pattern="/User*/*/password" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" + <http name="scimUserPassword" pattern="/User*/*/password" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/User*/*/password" access="IS_AUTHENTICATED_FULLY,scope=password.write" /> <custom-filter ref="passwordResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <bean id="userAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> @@ -235,9 +239,9 @@ </constructor-arg> </bean> - <http pattern="/Users/**" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" + <http name="scimUsers" pattern="/Users/**" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="userAccessDecisionManager" - xmlns="http://www.springframework.org/schema/security"> + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> <intercept-url pattern="/Users/*/verify" access="scope=scim.write,scope=scim.create" method="GET" /> <intercept-url pattern="/Users/**" access="scope=scim.read,user=self" method="GET" /> <intercept-url pattern="/Users/*" access="scope=scim.write" method="DELETE" /> @@ -246,14 +250,16 @@ <intercept-url pattern="/**" access="ROLE_NONEXISTENT" /> <custom-filter ref="scimResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> - <http pattern="/ids/Users*" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" - entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" + <http name="scimUserIds" pattern="/ids/Users*" create-session="stateless" authentication-manager-ref="emptyAuthenticationManager" + entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" use-expressions="false" xmlns="http://www.springframework.org/schema/security"> <intercept-url pattern="/**" access="scope=scim.userids" /> <custom-filter ref="idsResourceAuthenticationFilter" position="PRE_AUTH_FILTER" /> <access-denied-handler ref="oauthAccessDeniedHandler" /> + <csrf disabled="true"/> </http> <oauth:resource-server id="passwordResourceAuthenticationFilter" token-services-ref="tokenServices" diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.java index 6527683b538..d9dd42d4d69 100755 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/NativeApplicationIntegrationTests.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"). @@ -75,7 +75,7 @@ public void testHappyDay() throws Exception { headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); ResponseEntity<String> response = serverRunning.postForString("/oauth/token", formData, headers); assertEquals(HttpStatus.OK, response.getStatusCode()); - assertEquals("no-store", response.getHeaders().getFirst("Cache-Control")); + assertEquals("no-cache, no-store, max-age=0, must-revalidate", response.getHeaders().getFirst("Cache-Control")); } /** @@ -101,11 +101,14 @@ public void testInvalidClient() throws Exception { if (newCookies != null && !newCookies.isEmpty()) { fail("No cookies should be set. Found: " + newCookies.get(0) + "."); } - assertEquals("no-store", response.getHeaders().getFirst("Cache-Control")); + assertEquals("no-cache, no-store, max-age=0, must-revalidate", response.getHeaders().getFirst("Cache-Control")); + + assertEquals(401, response.getStatusCode().value()); @SuppressWarnings("unchecked") OAuth2Exception error = OAuth2Exception.valueOf(response.getBody()); - assertEquals("invalid_client", error.getOAuth2ErrorCode()); + assertEquals("Bad credentials", error.getMessage()); + assertEquals("invalid_request", error.getOAuth2ErrorCode()); } /** diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java index 6f91a0f77c1..f2d3b3378cb 100755 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/RefreshTokenSupportIntegrationTests.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"). @@ -139,7 +139,7 @@ public void testTokenRefreshedCorrectFlow() throws Exception { formData.add("refresh_token", accessToken.getRefreshToken().getValue()); tokenResponse = serverRunning.postForMap("/oauth/token", formData, tokenHeaders); assertEquals(HttpStatus.OK, tokenResponse.getStatusCode()); - assertEquals("no-store", tokenResponse.getHeaders().getFirst("Cache-Control")); + assertEquals("no-cache, no-store, max-age=0, must-revalidate", tokenResponse.getHeaders().getFirst("Cache-Control")); @SuppressWarnings("unchecked") OAuth2AccessToken newAccessToken = DefaultOAuth2AccessToken.valueOf(tokenResponse.getBody()); try { diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java index 8e277ebbaaf..02fe6464763 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java @@ -37,6 +37,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class TokenKeyEndpointMockMvcTests extends TestClassNullifier { @@ -121,11 +122,29 @@ public void checkTokenKeyValues() throws Exception { get("/token_key") .accept(MediaType.APPLICATION_JSON) .header("Authorization", basicDigestHeaderValue)) + .andDo(print()) .andExpect(status().isOk()) .andReturn(); - Map<String,Object> key = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); + Map<String, Object> key = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); + validateKey(key); + } + + @Test + public void checkTokenKeyValuesAnonymous() throws Exception { + + MvcResult result = mockMvc.perform( + get("/token_key") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andReturn(); + + Map<String, Object> key = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); + validateKey(key); + } + public void validateKey(Map<String,Object> key) { Object kty = key.get("kty"); assertNotNull(kty); assertTrue(kty instanceof String); diff --git a/uaa/src/test/resources/test-security.xml b/uaa/src/test/resources/test-security.xml index a8cd2b110a0..e7acfe1a6d6 100755 --- a/uaa/src/test/resources/test-security.xml +++ b/uaa/src/test/resources/test-security.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8" ?> <!-- - 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"). From dcdc82b5e62e267234284646440525dc61b537d6 Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Wed, 6 May 2015 07:59:56 -0600 Subject: [PATCH 4/9] Remove print() statements to reduce log output --- .../uaa/login/AccountsControllerMockMvcTests.java | 4 ---- .../identity/uaa/login/PasscodeMockMvcTests.java | 8 +------- .../identity/uaa/mock/ldap/LdapMockMvcTests.java | 2 -- .../identity/uaa/mock/token/TokenMvcMockTests.java | 12 ++++-------- .../identity/uaa/mock/util/MockMvcUtils.java | 2 +- .../endpoints/ScimGroupEndpointsMockMvcTests.java | 1 - .../scim/endpoints/ScimUserLookupMockMvcTests.java | 1 - .../cloudfoundry/identity/uaa/test/TestClient.java | 1 + 8 files changed, 7 insertions(+), 24 deletions(-) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java index ed67ec27b17..8007ce07d9d 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/AccountsControllerMockMvcTests.java @@ -162,7 +162,6 @@ public void testCreatingAnAccount() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/verify_user") .param("code", "test"+generator.counter.get())) - .andDo(print()) .andExpect(status().isFound()) .andExpect(redirectedUrl("home")) .andReturn(); @@ -191,7 +190,6 @@ public void testCreatingAnAccountWithAnEmptyClientId() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/verify_user") .param("code", "test"+generator.counter.get())) - .andDo(print()) .andExpect(status().isFound()) .andExpect(redirectedUrl("home")) .andReturn(); @@ -225,7 +223,6 @@ public void testCreatingAnAccountWithClientRedirect() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/verify_user") .param("code", "test"+generator.counter.get())) - .andDo(print()) .andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost:8080/app/")) .andReturn(); @@ -329,7 +326,6 @@ public void testCreatingAnAccountInAnotherZoneWithClientRedirect() throws Except MvcResult mvcResult = mockMvc.perform(get("/verify_user") .param("code", "test" + generator.counter.get()) .with(new SetServerNameRequestPostProcessor("mysubdomain.localhost"))) - .andDo(print()) .andExpect(status().isFound()) .andExpect(redirectedUrl("http://myzoneclient.example.com")) .andReturn(); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java index 1cc761ffa2b..28dcf2126ee 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java @@ -135,7 +135,6 @@ public void testLoginUsingPasscodeWithSamlToken() throws Exception { String passcode = JsonUtils.readValue( mockMvc.perform(get) .andExpect(status().isOk()) - .andDo(print()) .andReturn().getResponse().getContentAsString(), String.class); @@ -160,7 +159,6 @@ public void testLoginUsingPasscodeWithSamlToken() throws Exception { Map accessToken = JsonUtils.readValue( mockMvc.perform(post) - .andDo(print()) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(), Map.class); @@ -202,7 +200,6 @@ public void testLoginUsingPasscodeWithUaaToken() throws Exception { String passcode = JsonUtils.readValue( mockMvc.perform(get) .andExpect(status().isOk()) - .andDo(print()) .andReturn().getResponse().getContentAsString(), String.class); @@ -227,7 +224,6 @@ public void testLoginUsingPasscodeWithUaaToken() throws Exception { Map accessToken = JsonUtils.readValue( mockMvc.perform(post) - .andDo(print()) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(), Map.class); @@ -270,9 +266,7 @@ public void testLoginUsingPasscodeWithUnknownToken() throws Exception { .session(session); mockMvc.perform(get) - .andExpect(status().isForbidden()) - .andDo(print()); - + .andExpect(status().isForbidden()); } public static class MockSecurityContext implements SecurityContext { diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/ldap/LdapMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/ldap/LdapMockMvcTests.java index d0504c13001..9d914513f79 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/ldap/LdapMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/ldap/LdapMockMvcTests.java @@ -263,7 +263,6 @@ public void testLdapConfigurationBeforeSave() throws Exception { .header(IdentityZoneSwitchingFilter.HEADER, zone.getId()); MvcResult result = mockMvc.perform(post) - .andDo(print()) .andExpect(status().isOk()) .andReturn(); @@ -619,7 +618,6 @@ public void testLogin() throws Exception { mockMvc.perform(post("/login.do").accept(TEXT_HTML_VALUE) .param("username", "marissa2") .param("password", "ldap")) - .andDo(print()) .andExpect(status().isFound()) .andExpect(redirectedUrl("/")); } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java index cae04c40fbe..40d0cc81766 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenMvcMockTests.java @@ -285,7 +285,6 @@ public void testClientIdentityProviderWithoutAllowedProvidersForPasswordGrantWor .param(OAuth2Utils.RESPONSE_TYPE,"token") .param(OAuth2Utils.GRANT_TYPE, "password") .param(OAuth2Utils.CLIENT_ID, clientId)) - .andDo(print()) .andExpect(status().isOk()); mockMvc.perform(post("/oauth/token") @@ -296,7 +295,6 @@ public void testClientIdentityProviderWithoutAllowedProvidersForPasswordGrantWor .param(OAuth2Utils.RESPONSE_TYPE,"token") .param(OAuth2Utils.GRANT_TYPE, "password") .param(OAuth2Utils.CLIENT_ID, clientId2)) - .andDo(print()) .andExpect(status().isOk()); @@ -347,7 +345,7 @@ public void testClientIdentityProviderClientWithoutAllowedProvidersForAuthCodeAl .param(OAuth2Utils.STATE, state) .param(OAuth2Utils.CLIENT_ID, clientId) .param(OAuth2Utils.REDIRECT_URI, TEST_REDIRECT_URI)) - .andDo(print()).andExpect(status().isFound()); + .andExpect(status().isFound()); //correct provider is ok MvcResult result = mockMvc.perform(get("/oauth/authorize") @@ -357,7 +355,7 @@ public void testClientIdentityProviderClientWithoutAllowedProvidersForAuthCodeAl .param(OAuth2Utils.STATE, state) .param(OAuth2Utils.CLIENT_ID, clientId2) .param(OAuth2Utils.REDIRECT_URI, TEST_REDIRECT_URI)) - .andDo(print()).andExpect(status().isFound()) + .andExpect(status().isFound()) .andReturn(); //other provider, not ok @@ -368,7 +366,7 @@ public void testClientIdentityProviderClientWithoutAllowedProvidersForAuthCodeAl .param(OAuth2Utils.STATE, state) .param(OAuth2Utils.CLIENT_ID, clientId3) .param(OAuth2Utils.REDIRECT_URI, TEST_REDIRECT_URI)) - .andDo(print()).andExpect(status().isUnauthorized()) + .andExpect(status().isUnauthorized()) .andExpect(model().attributeExists("error")) .andExpect(model().attribute("error_message_code","login.invalid_idp")); @@ -407,7 +405,6 @@ public void testClientIdentityProviderRestrictionForPasswordGrant() throws Excep .param(OAuth2Utils.RESPONSE_TYPE,"token") .param(OAuth2Utils.GRANT_TYPE, "password") .param(OAuth2Utils.CLIENT_ID, clientId)) - .andDo(print()) .andExpect(status().isUnauthorized()); mockMvc.perform(post("/oauth/token") @@ -417,7 +414,6 @@ public void testClientIdentityProviderRestrictionForPasswordGrant() throws Excep .param(OAuth2Utils.RESPONSE_TYPE, "token") .param(OAuth2Utils.GRANT_TYPE, "password") .param(OAuth2Utils.CLIENT_ID, clientId2)) - .andDo(print()) .andExpect(status().isOk()); } @@ -1669,7 +1665,7 @@ public void testGetTokenScopesNotInAuthentication() throws Exception { .param("code", code) .param(OAuth2Utils.CLIENT_ID, "identity") .param(OAuth2Utils.REDIRECT_URI, "http://localhost/test"); - result = mockMvc.perform(authRequest).andDo(print()).andExpect(status().is2xxSuccessful()).andReturn(); + result = mockMvc.perform(authRequest).andExpect(status().is2xxSuccessful()).andReturn(); TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), TestClient.OAuthToken.class); OAuth2Authentication a1 = tokenServices.loadAuthentication(oauthToken.accessToken); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java index c19fed6cd13..ece9e54421b 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java @@ -373,7 +373,7 @@ public String getUserOAuthAccessTokenAuthCode(MockMvc mockMvc, String clientId, .param("code", code) .param(OAuth2Utils.CLIENT_ID, clientId) .param(OAuth2Utils.REDIRECT_URI, "http://localhost/test"); - result = mockMvc.perform(authRequest).andDo(print()).andExpect(status().is2xxSuccessful()).andReturn(); + result = mockMvc.perform(authRequest).andExpect(status().is2xxSuccessful()).andReturn(); TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), TestClient.OAuthToken.class); return oauthToken.accessToken; diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java index 5bf4373a8ae..c8e227cdadd 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimGroupEndpointsMockMvcTests.java @@ -152,7 +152,6 @@ public void testIdentityClientManagesZoneAdmins() throws Exception { .content(JsonUtils.writeValueAsBytes(group)); //create the zones.{id}.admin mockMvc.perform(post) - .andDo(print()) .andExpect(status().isCreated()); //it is already created mockMvc.perform(post) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java index d483b4a9f1f..de84ba394ce 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/scim/endpoints/ScimUserLookupMockMvcTests.java @@ -116,7 +116,6 @@ public void testLookupUsingOnlyOrigin() throws Exception { .param("count", String.valueOf(50)); mockMvc.perform(post) - .andDo(print()) .andExpect(status().isBadRequest()); } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java index a3615675591..b2f152d5e1e 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/test/TestClient.java @@ -22,6 +22,7 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class TestClient { From 6944cc03b7de4e94147633bd1d9f5ad50a7b0352 Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Wed, 6 May 2015 15:06:43 -0600 Subject: [PATCH 5/9] Added CSRF protection just to /change_email end points --- login/src/main/resources/login-ui.xml | 15 +- .../identity/uaa/login/LoginMockMvcTests.java | 134 +++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/login/src/main/resources/login-ui.xml b/login/src/main/resources/login-ui.xml index 4226b60c2ee..0bc9d3358d7 100644 --- a/login/src/main/resources/login-ui.xml +++ b/login/src/main/resources/login-ui.xml @@ -61,13 +61,26 @@ <bean id="backwardsCompatibleScopeParameter" class="org.cloudfoundry.identity.uaa.oauth.BackwardsCompatibleScopeParsingFilter"/> + <http name="changeEmailSecurity" + use-expressions="false" + pattern="/change_email**" + xmlns="http://www.springframework.org/schema/security"> + <access-denied-handler error-page="/"/> + <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> + <form-login login-page="/login" username-parameter="username" password-parameter="password" + login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" + authentication-details-source-ref="authenticationDetailsSource"/> + <csrf disabled="false"/> + </http> + <http name="uiSecurity" request-matcher-ref="uiRequestMatcher" use-expressions="false" authentication-manager-ref="zoneAwareAuthzAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> <access-denied-handler error-page="/"/> <intercept-url pattern="/login**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> <form-login login-page="/login" username-parameter="username" password-parameter="password" - login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" authentication-details-source-ref="authenticationDetailsSource"/> + login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" + authentication-details-source-ref="authenticationDetailsSource"/> <logout logout-url="/logout.do" success-handler-ref="logoutHandler" /> <csrf disabled="true"/> </http> diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java index 3bb26c81dec..1b4c8df9b7d 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java @@ -35,6 +35,7 @@ import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.mock.env.MockEnvironment; @@ -49,6 +50,8 @@ import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.PortResolverImpl; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; +import org.springframework.security.web.csrf.CsrfToken; +import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; import org.springframework.security.web.savedrequest.DefaultSavedRequest; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.test.web.servlet.MockMvc; @@ -66,13 +69,17 @@ import java.util.Locale; import java.util.Map; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertNotNull; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.http.MediaType.TEXT_HTML; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; @@ -454,7 +461,7 @@ public String[] getParameterValues(String name) { .session(session) .with(new SetServerNameRequestPostProcessor(identityZone.getSubdomain() + ".localhost"))) .andExpect(status().isFound()) - .andExpect(redirectedUrl("saml/discovery?returnIDParam=idp&entityID="+identityZone.getSubdomain()+".cloudfoundry-saml-login&idp=active-saml&isPassive=true")); + .andExpect(redirectedUrl("saml/discovery?returnIDParam=idp&entityID=" + identityZone.getSubdomain() + ".cloudfoundry-saml-login&idp=active-saml&isPassive=true")); } @Test @@ -487,4 +494,129 @@ public void testDeactivatedProviderIsRemovedFromSamlLoginLinks() throws Exceptio .andExpect(status().isOk()) .andExpect(xpath("//a[text()='" + identityProviderDefinition.getLinkText() + "']").doesNotExist()); } + + @Test + public void testChangeEmailWithoutAuthenticationReturnsRedirect() throws Exception { + mockMvc.perform(get("/change_email").accept(TEXT_HTML)) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")); + } + + @Test + public void testChangeEmailPageHasCsrf() throws Exception { + ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); + ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); + UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); + MockHttpSession session = new MockHttpSession(); + SecurityContext securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(principal); + session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .session(session) + .principal(principal); + mockMvc.perform(get) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("_csrf"))); + assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); + } + + @Test + public void testChangeEmailSubmitWithMissingCsrf() throws Exception { + ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); + ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); + UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); + MockHttpSession session = new MockHttpSession(); + SecurityContext securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(principal); + session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .session(session) + .principal(principal); + mockMvc.perform(get) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("_csrf"))); + assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); + + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .session(session) + .principal(principal) + .param("newEmail", "test@test.org") + .param("client_id", ""); + mockMvc.perform(changeEmail) + .andExpect(status().is4xxClientError()); + } + + @Test + public void testChangeEmailSubmitWithInvalidCsrf() throws Exception { + ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); + ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); + UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); + MockHttpSession session = new MockHttpSession(); + SecurityContext securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(principal); + session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .session(session) + .principal(principal); + mockMvc.perform(get) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("_csrf"))); + assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); + + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .session(session) + .principal(principal) + .param("newEmail", "test@test.org") + .param("client_id", "") + .param("_csrf", "invalid csrf token"); + mockMvc.perform(changeEmail) + .andExpect(status().is4xxClientError()); + } + + @Test + public void testChangeEmailSubmitWithCorrectCsrf() throws Exception { + ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); + ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); + UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); + MockHttpSession session = new MockHttpSession(); + SecurityContext securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(principal); + session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .session(session) + .principal(principal); + mockMvc.perform(get) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("_csrf"))); + assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); + CsrfToken csrfToken = (CsrfToken)session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN")); + + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .session(session) + .principal(principal) + .param("newEmail", "test@test.org") + .param("client_id", "") + .param("_csrf", csrfToken.getToken()); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("email_sent?code=email_change")); + + } + + } From 062fce1a57b898ee67c668158fce239b5ba75107 Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Wed, 6 May 2015 15:39:03 -0600 Subject: [PATCH 6/9] Enhance tests with Spring Security Test helpers --- common/build.gradle | 1 + .../identity/uaa/login/LoginMockMvcTests.java | 96 +++++++++---------- .../identity/uaa/mock/util/MockMvcUtils.java | 15 ++- 3 files changed, 60 insertions(+), 52 deletions(-) diff --git a/common/build.gradle b/common/build.gradle index de82dbb63f0..d13752fe49c 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -65,6 +65,7 @@ dependencies { testCompile group: 'postgresql', name: 'postgresql', version:parent.postgresqlVersion testCompile group: 'org.mockito', name: 'mockito-all', version:'1.8.5' testCompile group: 'org.apache.tomcat', name: 'tomcat-jdbc', version:parent.tomcatVersion + testCompile group: 'org.springframework.security', name: 'spring-security-test', version:parent.springSecurityVersion } apply from: file('build_properties.gradle') diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java index 1b4c8df9b7d..8d120ab5e4f 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java @@ -55,6 +55,7 @@ import org.springframework.security.web.savedrequest.DefaultSavedRequest; import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; @@ -62,6 +63,7 @@ import org.springframework.web.context.support.XmlWebApplicationContext; import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -69,6 +71,7 @@ import java.util.Locale; import java.util.Map; +import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; @@ -77,12 +80,15 @@ import static org.junit.Assert.assertNotNull; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.http.MediaType.TEXT_HTML; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.securityContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; @@ -504,49 +510,33 @@ public void testChangeEmailWithoutAuthenticationReturnsRedirect() throws Excepti @Test public void testChangeEmailPageHasCsrf() throws Exception { - ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); - ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); - UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); - UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); - MockHttpSession session = new MockHttpSession(); - SecurityContext securityContext = new SecurityContextImpl(); - securityContext.setAuthentication(principal); - session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); MockHttpServletRequestBuilder get = get("/change_email") .accept(TEXT_HTML) - .session(session) - .principal(principal); + .with(securityContext(marissaContext)); mockMvc.perform(get) .andExpect(status().isOk()) .andExpect(content().string(containsString("_csrf"))); - assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); } @Test public void testChangeEmailSubmitWithMissingCsrf() throws Exception { - ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); - ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); - UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); - UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); - MockHttpSession session = new MockHttpSession(); - SecurityContext securityContext = new SecurityContextImpl(); - securityContext.setAuthentication(principal); - session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); MockHttpServletRequestBuilder get = get("/change_email") .accept(TEXT_HTML) - .session(session) - .principal(principal); - mockMvc.perform(get) + .with(securityContext(marissaContext)); + MockHttpSession session = (MockHttpSession)mockMvc.perform(get) .andExpect(status().isOk()) - .andExpect(content().string(containsString("_csrf"))); + .andExpect(content().string(containsString("_csrf"))) + .andReturn().getRequest().getSession(); assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); MockHttpServletRequestBuilder changeEmail = post("/change_email.do") .accept(TEXT_HTML) .session(session) - .principal(principal) + .with(securityContext(marissaContext)) .param("newEmail", "test@test.org") .param("client_id", ""); mockMvc.perform(changeEmail) @@ -555,28 +545,21 @@ public void testChangeEmailSubmitWithMissingCsrf() throws Exception { @Test public void testChangeEmailSubmitWithInvalidCsrf() throws Exception { - ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); - ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); - UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); - UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); - MockHttpSession session = new MockHttpSession(); - SecurityContext securityContext = new SecurityContextImpl(); - securityContext.setAuthentication(principal); - session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); MockHttpServletRequestBuilder get = get("/change_email") .accept(TEXT_HTML) - .session(session) - .principal(principal); - mockMvc.perform(get) + .with(securityContext(marissaContext)); + MockHttpSession session = (MockHttpSession)mockMvc.perform(get) .andExpect(status().isOk()) - .andExpect(content().string(containsString("_csrf"))); + .andExpect(content().string(containsString("_csrf"))) + .andReturn().getRequest().getSession(); assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); MockHttpServletRequestBuilder changeEmail = post("/change_email.do") .accept(TEXT_HTML) .session(session) - .principal(principal) + .with(securityContext(marissaContext)) .param("newEmail", "test@test.org") .param("client_id", "") .param("_csrf", "invalid csrf token"); @@ -584,31 +567,42 @@ public void testChangeEmailSubmitWithInvalidCsrf() throws Exception { .andExpect(status().is4xxClientError()); } + @Test + public void testChangeEmailSubmitWithSpringSecurityForcedCsrf() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + //example shows to to test a request that is secured by csrf and you wish to bypass it + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)) + .with(csrf()) + .param("newEmail", "test@test.org") + .param("client_id", ""); + + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("email_sent?code=email_change")); + } + @Test public void testChangeEmailSubmitWithCorrectCsrf() throws Exception { - ScimUserProvisioning userProvisioning = webApplicationContext.getBean(JdbcScimUserProvisioning.class); - ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); - UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); - UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); - MockHttpSession session = new MockHttpSession(); - SecurityContext securityContext = new SecurityContextImpl(); - securityContext.setAuthentication(principal); - session.putValue("SPRING_SECURITY_CONTEXT", securityContext); + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); MockHttpServletRequestBuilder get = get("/change_email") .accept(TEXT_HTML) - .session(session) - .principal(principal); - mockMvc.perform(get) + .with(securityContext(marissaContext)); + + MvcResult result = mockMvc.perform(get) .andExpect(status().isOk()) - .andExpect(content().string(containsString("_csrf"))); - assertNotNull(session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN"))); + .andExpect(content().string(containsString("_csrf"))) + .andReturn(); + + MockHttpSession session = (MockHttpSession)result.getRequest().getSession(); CsrfToken csrfToken = (CsrfToken)session.getAttribute(HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN")); MockHttpServletRequestBuilder changeEmail = post("/change_email.do") .accept(TEXT_HTML) + .with(securityContext(marissaContext)) .session(session) - .principal(principal) .param("newEmail", "test@test.org") .param("client_id", "") .param("_csrf", csrfToken.getToken()); diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java index ece9e54421b..74037a050d7 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/util/MockMvcUtils.java @@ -22,6 +22,8 @@ import org.cloudfoundry.identity.uaa.scim.ScimGroup; import org.cloudfoundry.identity.uaa.scim.ScimGroupMember; import org.cloudfoundry.identity.uaa.scim.ScimUser; +import org.cloudfoundry.identity.uaa.scim.ScimUserProvisioning; +import org.cloudfoundry.identity.uaa.scim.jdbc.JdbcScimUserProvisioning; import org.cloudfoundry.identity.uaa.test.TestApplicationEventListener; import org.cloudfoundry.identity.uaa.test.TestClient; import org.cloudfoundry.identity.uaa.test.TestClient.OAuthToken; @@ -44,6 +46,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.security.oauth2.common.util.OAuth2Utils; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.security.oauth2.provider.ClientDetails; @@ -297,7 +300,7 @@ public String getZoneAdminToken(MockMvc mockMvc, String adminToken, String zoneI group.setMembers(Arrays.asList(new ScimGroupMember(user.getId()))); MockMvcUtils.utils().createGroup(mockMvc, adminToken, group); return getUserOAuthAccessTokenAuthCode(mockMvc, "identity", "identitysecret", user.getId(), user.getUserName(), - "secret", group.getDisplayName()); + "secret", group.getDisplayName()); } public String getUserOAuthAccessToken(MockMvc mockMvc, String clientId, String clientSecret, String username, @@ -399,6 +402,16 @@ public String getClientCredentialsOAuthAccessToken(MockMvc mockMvc, String usern return oauthToken.accessToken; } + public SecurityContext getMarissaSecurityContext(ApplicationContext context) { + ScimUserProvisioning userProvisioning = context.getBean(JdbcScimUserProvisioning.class); + ScimUser marissa = userProvisioning.query("username eq \"marissa\" and origin eq \"uaa\"").get(0); + UaaPrincipal uaaPrincipal = new UaaPrincipal(marissa.getId(), marissa.getUserName(), marissa.getPrimaryEmail(), marissa.getOrigin(), marissa.getExternalId(), IdentityZoneHolder.get().getId()); + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, Arrays.asList(UaaAuthority.fromAuthorities("uaa.user"))); + SecurityContext securityContext = new SecurityContextImpl(); + securityContext.setAuthentication(principal); + return securityContext; + } + public <T extends ApplicationEvent> TestApplicationEventListener<T> addEventListener(ConfigurableApplicationContext applicationContext, Class<T> clazz) { TestApplicationEventListener<T> listener = TestApplicationEventListener.forEventClass(clazz); applicationContext.addApplicationListener(listener); From 7903b9af8990e3dd024ab627cc4587f7cbeb348f Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Thu, 7 May 2015 10:48:17 -0600 Subject: [PATCH 7/9] Support whitelist URLs for the logout redirect parameter --- .../WhitelistLogoutHandler.java | 47 +++++++++++++++ login/src/main/resources/login-ui.xml | 8 ++- uaa/src/main/resources/login.yml | 5 +- .../identity/uaa/login/LoginMockMvcTests.java | 57 +++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 login/src/main/java/org/cloudfoundry/identity/uaa/authentication/WhitelistLogoutHandler.java diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/authentication/WhitelistLogoutHandler.java b/login/src/main/java/org/cloudfoundry/identity/uaa/authentication/WhitelistLogoutHandler.java new file mode 100644 index 00000000000..6cac6a9914b --- /dev/null +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/authentication/WhitelistLogoutHandler.java @@ -0,0 +1,47 @@ +package org.cloudfoundry.identity.uaa.authentication; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +public class WhitelistLogoutHandler extends SimpleUrlLogoutSuccessHandler { + private static final Log logger = LogFactory.getLog(WhitelistLogoutHandler.class); + + private List<String> whitelist = null; + + public WhitelistLogoutHandler(List<String> whitelist) { + this.whitelist = whitelist; + } + + public List<String> getWhitelist() { + return whitelist; + } + + public void setWhitelist(List<String> whitelist) { + this.whitelist = whitelist; + } + + @Override + protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) { + String url = super.determineTargetUrl(request, response); + boolean whitelisted = false; + if (whitelist!=null) { + for (String s : whitelist) { + if (url.equals(s)) { + whitelisted = true; + break; + } + } + if (!whitelisted) { + url = getDefaultTargetUrl(); + } + } + logger.debug("Logout redirect[whitelisted:"+whitelisted+"; redirect:"+request.getParameter(getTargetUrlParameter())+"] returning:"+url); + return url; + + } +} diff --git a/login/src/main/resources/login-ui.xml b/login/src/main/resources/login-ui.xml index 0bc9d3358d7..c35f6ca6e44 100644 --- a/login/src/main/resources/login-ui.xml +++ b/login/src/main/resources/login-ui.xml @@ -169,8 +169,12 @@ <constructor-arg value="/login" /> </bean> - <bean id="logoutHandler" class="org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler"> - <property name="targetUrlParameter" value="redirect" /> + <bean id="logoutHandler" class="org.cloudfoundry.identity.uaa.authentication.WhitelistLogoutHandler"> + <constructor-arg value="#{@config['logout']==null ? null : + @config['logout']['redirect']==null ? null : + @config['logout']['redirect']['parameter']==null ? null : + @config['logout']['redirect']['parameter']['whitelist']}"/> + <property name="targetUrlParameter" value="redirect" /> <property name="defaultTargetUrl" value="${logout.redirect.url:/login}" /> <property name="alwaysUseDefaultTargetUrl" value="${logout.redirect.parameter.disable:true}"/> </bean> diff --git a/uaa/src/main/resources/login.yml b/uaa/src/main/resources/login.yml index 66d36afebc1..9e9247522ae 100644 --- a/uaa/src/main/resources/login.yml +++ b/uaa/src/main/resources/login.yml @@ -41,7 +41,10 @@ links: # redirect: # url: /login # parameter: -# disable: true +# disable: false +# whitelist: +# - https://url1.domain1.com/logout-success +# - https://url2.domain2.com/logout-success login: # Enable create account and forgot password links on the Login Server (enabled by default) diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java index 8d120ab5e4f..02272f7072e 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java @@ -17,6 +17,7 @@ import org.cloudfoundry.identity.uaa.TestClassNullifier; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; +import org.cloudfoundry.identity.uaa.authentication.WhitelistLogoutHandler; import org.cloudfoundry.identity.uaa.authentication.login.LoginInfoEndpoint; import org.cloudfoundry.identity.uaa.authentication.login.Prompt; import org.cloudfoundry.identity.uaa.client.ClientConstants; @@ -167,6 +168,62 @@ public void testLogOutEnableRedirectParameter() throws Exception { } } + @Test + public void testLogOutWhitelistedRedirectParameter() throws Exception { + WhitelistLogoutHandler logoutSuccessHandler = webApplicationContext.getBean(WhitelistLogoutHandler.class); + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(false); + logoutSuccessHandler.setWhitelist(Arrays.asList("https://www.google.com")); + try { + mockMvc.perform(get("/logout.do").param("redirect", "https://www.google.com")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("https://www.google.com")); + } finally { + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(true); + } + } + + @Test + public void testLogOutNotWhitelistedRedirectParameter() throws Exception { + WhitelistLogoutHandler logoutSuccessHandler = webApplicationContext.getBean(WhitelistLogoutHandler.class); + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(false); + logoutSuccessHandler.setWhitelist(Arrays.asList("https://www.yahoo.com")); + try { + mockMvc.perform(get("/logout.do").param("redirect", "https://www.google.com")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("/login")); + } finally { + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(true); + } + } + + @Test + public void testLogOutNullWhitelistedRedirectParameter() throws Exception { + WhitelistLogoutHandler logoutSuccessHandler = webApplicationContext.getBean(WhitelistLogoutHandler.class); + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(false); + logoutSuccessHandler.setWhitelist(null); + try { + mockMvc.perform(get("/logout.do").param("redirect", "https://www.google.com")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("https://www.google.com")); + } finally { + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(true); + } + } + + @Test + public void testLogOutEmptyWhitelistedRedirectParameter() throws Exception { + WhitelistLogoutHandler logoutSuccessHandler = webApplicationContext.getBean(WhitelistLogoutHandler.class); + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(false); + logoutSuccessHandler.setWhitelist(Collections.<String>emptyList()); + try { + mockMvc.perform(get("/logout.do").param("redirect", "https://www.google.com")) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("/login")); + } finally { + logoutSuccessHandler.setAlwaysUseDefaultTargetUrl(true); + } + } + @Test public void testLogOutChangeUrlValue() throws Exception { SimpleUrlLogoutSuccessHandler logoutSuccessHandler = webApplicationContext.getBean(SimpleUrlLogoutSuccessHandler.class); From ca0b9297762ac320f68886f17d5f054ead06b0a6 Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Fri, 8 May 2015 14:00:17 -0600 Subject: [PATCH 8/9] Properly handle redirects for change_email csrf protection Handle avoid redirects if request requests JSON Ensure that reset_password has csrf token on it Add CSRF around the invitations, reset password and forgot password forms form --- .../login/LoginInfoEndpoint.java | 5 + .../uaa/login/ChangePasswordController.java | 7 +- .../uaa/login/UaaChangePasswordService.java | 10 +- .../CsrfAwareEntryPointAndDeniedHandler.java | 120 +++++++++++++ login/src/main/resources/login-ui.xml | 51 ++++-- .../templates/web/invalid_request.html | 20 +++ ...rfAwareEntryPointAndDeniedHandlerTest.java | 112 +++++++++++++ .../main/webapp/WEB-INF/spring-servlet.xml | 3 +- .../integration/feature/ResetPasswordIT.java | 14 +- .../identity/uaa/login/LoginMockMvcTests.java | 157 +++++++++++++++++- .../ResetPasswordControllerMockMvcTests.java | 24 +++ 11 files changed, 497 insertions(+), 26 deletions(-) create mode 100644 login/src/main/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandler.java create mode 100644 login/src/main/resources/templates/web/invalid_request.html create mode 100644 login/src/test/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandlerTest.java diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java index 05903335d01..f9f381114fe 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/authentication/login/LoginInfoEndpoint.java @@ -185,6 +185,11 @@ public String loginForHtml(Model model, Principal principal, HttpServletRequest return login(model, principal, Arrays.asList("passcode"), false, request); } + @RequestMapping(value = {"/invalid_request" }) + public String invalidRequest(HttpServletRequest request) { + return "invalid_request"; + } + protected String getZonifiedEntityId() { if (UaaUrlUtils.isUrl(entityID)) { return UaaUrlUtils.addSubdomainToUrl(entityID); diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/ChangePasswordController.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/ChangePasswordController.java index 0b4502f4155..0279ef4a0d1 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/ChangePasswordController.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/ChangePasswordController.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"). @@ -16,6 +16,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST; import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; @@ -61,7 +62,9 @@ public String changePassword( try { changePasswordService.changePassword(username, currentPassword, newPassword); return "redirect:profile"; - } catch (RestClientException e) { + } catch (BadCredentialsException e) { + model.addAttribute("message_code", "unauthorized"); + } catch (RestClientException e) { //left over from login-server days model.addAttribute("message_code", "unauthorized"); } response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value()); diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaChangePasswordService.java b/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaChangePasswordService.java index 0d43ee5d559..8775e963b01 100644 --- a/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaChangePasswordService.java +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/login/UaaChangePasswordService.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"). @@ -13,6 +13,8 @@ package org.cloudfoundry.identity.uaa.login; import org.cloudfoundry.identity.uaa.scim.endpoints.PasswordResetEndpoints; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.BadCredentialsException; import org.springframework.web.client.RestTemplate; import java.util.HashMap; @@ -32,6 +34,10 @@ public void changePassword(String username, String currentPassword, String newPa change.setUsername(username); change.setCurrentPassword(currentPassword); change.setNewPassword(newPassword); - passwordResetEndpoints.changePassword(change); + ResponseEntity<Map<String,String>> response = passwordResetEndpoints.changePassword(change); + if (! response.getStatusCode().is2xxSuccessful()) { + //throw an error + throw new BadCredentialsException(username); + } } } diff --git a/login/src/main/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandler.java b/login/src/main/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandler.java new file mode 100644 index 00000000000..d0c4478ac2d --- /dev/null +++ b/login/src/main/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandler.java @@ -0,0 +1,120 @@ +/* + * ***************************************************************************** + * 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.security; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.WebAttributes; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.csrf.InvalidCsrfTokenException; +import org.springframework.security.web.csrf.MissingCsrfTokenException; +import org.springframework.util.StringUtils; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + + +public class CsrfAwareEntryPointAndDeniedHandler implements AccessDeniedHandler, AuthenticationEntryPoint { + + private static Log logger = LogFactory.getLog(CsrfAwareEntryPointAndDeniedHandler.class); + + private LoginUrlAuthenticationEntryPoint loginEntryPoint; + private LoginUrlAuthenticationEntryPoint csrfEntryPoint; + + public CsrfAwareEntryPointAndDeniedHandler(String redirectCsrf, String redirectNotLoggedIn) { + if (redirectCsrf == null || !redirectCsrf.startsWith("/")) { + throw new NullPointerException("Invalid CSRF redirect URL, must start with '/'"); + } + if (redirectNotLoggedIn == null || !redirectNotLoggedIn.startsWith("/")) { + throw new NullPointerException("Invalid login redirect URL, must start with '/'"); + } + loginEntryPoint = new LoginUrlAuthenticationEntryPoint(redirectNotLoggedIn); + csrfEntryPoint = new LoginUrlAuthenticationEntryPoint(redirectCsrf); + } + + protected boolean isUserLoggedIn() { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + return auth!=null && auth.isAuthenticated() && auth.getPrincipal() instanceof UaaPrincipal; + } + + protected boolean wantJson(HttpServletRequest request) { + String accept = request.getHeader("Accept"); + boolean json = false; + if (StringUtils.hasText(accept)) { + for (MediaType mediaType : MediaType.parseMediaTypes(accept)) { + if (mediaType.equals(MediaType.APPLICATION_JSON)) { + json = true; + break; + } + } + } + return json; + } + + protected void internalHandle(HttpServletRequest request, + HttpServletResponse response, + Exception exception) throws IOException, ServletException { + AuthenticationException authEx = (exception instanceof AuthenticationException) ? + (AuthenticationException)exception : + new InternalAuthenticationServiceException("Access denied.", exception); + + if (wantJson(request)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.getWriter().append(String.format("{\"error\":\"%s\"}", exception.getMessage())); + } else { + LoginUrlAuthenticationEntryPoint entryPoint = getLoginUrlAuthenticationEntryPoint(exception); + entryPoint.commence(request, response, authEx); + } + } + + protected LoginUrlAuthenticationEntryPoint getLoginUrlAuthenticationEntryPoint(Exception exception) { + if (exception instanceof MissingCsrfTokenException || exception instanceof InvalidCsrfTokenException) { + return csrfEntryPoint; + } else if (isUserLoggedIn()) { + logger.debug("Redirecting to CSRF endpoint based on error.", exception); + return csrfEntryPoint; + } else { + return loginEntryPoint; + } + } + + @Override + public void handle(HttpServletRequest request, + HttpServletResponse response, + AccessDeniedException accessDeniedException) throws IOException, + ServletException { + request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException); + //if we get any other access denied we end up here + internalHandle(request, response, accessDeniedException); + } + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + //if there is insufficient authentication, this will be called + internalHandle(request, response, authException); + } +} diff --git a/login/src/main/resources/login-ui.xml b/login/src/main/resources/login-ui.xml index c35f6ca6e44..c09cf5a32a9 100644 --- a/login/src/main/resources/login-ui.xml +++ b/login/src/main/resources/login-ui.xml @@ -62,17 +62,48 @@ <bean id="backwardsCompatibleScopeParameter" class="org.cloudfoundry.identity.uaa.oauth.BackwardsCompatibleScopeParsingFilter"/> <http name="changeEmailSecurity" + entry-point-ref="loginEntryPoint" use-expressions="false" pattern="/change_email**" xmlns="http://www.springframework.org/schema/security"> - <access-denied-handler error-page="/"/> + <access-denied-handler ref="loginEntryPoint"/> <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> - <form-login login-page="/login" username-parameter="username" password-parameter="password" - login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" - authentication-details-source-ref="authenticationDetailsSource"/> <csrf disabled="false"/> </http> + <http name="invitationsSecurity" + entry-point-ref="loginEntryPoint" + use-expressions="false" + pattern="/invitations/**" + xmlns="http://www.springframework.org/schema/security"> + <access-denied-handler ref="loginEntryPoint"/> + <intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> + <csrf disabled="false"/> + </http> + + <http name="resetPasswordSecurity" + pattern="/reset_password**" + disable-url-rewriting="true" + entry-point-ref="loginEntryPoint" + use-expressions="false" + xmlns="http://www.springframework.org/schema/security"> + <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> + <csrf disabled="false"/> + <access-denied-handler ref="loginEntryPoint"/> + </http> + + <http name="forgotPasswordSecurity" + pattern="/forgot_password**" + disable-url-rewriting="true" + entry-point-ref="loginEntryPoint" + use-expressions="false" + xmlns="http://www.springframework.org/schema/security"> + <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" /> + <csrf disabled="false"/> + <access-denied-handler ref="loginEntryPoint"/> + </http> + + <http name="uiSecurity" request-matcher-ref="uiRequestMatcher" use-expressions="false" authentication-manager-ref="zoneAwareAuthzAuthenticationManager" xmlns="http://www.springframework.org/schema/security"> <access-denied-handler error-page="/"/> @@ -97,13 +128,6 @@ <property name="defaultFailureUrl" value="/login?error=login_failure" /> </bean> - <security:http name="resetPasswordSecurity" pattern="/reset_password.do" disable-url-rewriting="true" - entry-point-ref="loginEntryPoint" use-expressions="false"> - <security:intercept-url pattern="/reset_password.do" access="IS_AUTHENTICATED_ANONYMOUSLY" /> - <security:anonymous enabled="true" /> - <security:csrf disabled="true"/> - </security:http> - <security:http name="verifyEmailSecurity" pattern="/verify_email" disable-url-rewriting="true" entry-point-ref="loginEntryPoint" use-expressions="false"> <security:intercept-url pattern="/verify_email" access="IS_AUTHENTICATED_ANONYMOUSLY" /> @@ -165,8 +189,9 @@ <bean id="samlFilter" class="org.cloudfoundry.identity.web.NoOpFilter" /> - <bean id="loginEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> - <constructor-arg value="/login" /> + <bean id="loginEntryPoint" class="org.cloudfoundry.identity.uaa.security.CsrfAwareEntryPointAndDeniedHandler"> + <constructor-arg name="redirectCsrf" value="/invalid_request" /> + <constructor-arg name="redirectNotLoggedIn" value="/login" /> </bean> <bean id="logoutHandler" class="org.cloudfoundry.identity.uaa.authentication.WhitelistLogoutHandler"> diff --git a/login/src/main/resources/templates/web/invalid_request.html b/login/src/main/resources/templates/web/invalid_request.html new file mode 100644 index 00000000000..e0f489a8448 --- /dev/null +++ b/login/src/main/resources/templates/web/invalid_request.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layouts/main"> +<head> +</head> +<body> +<div class="island" layout:fragment="page-content"> + <div class="island-content"> + <div class="alert alert-error"> + <p>Warning</p> + </div> + <img src="/resources/images/sad_cloud.png" th:src="@{/resources/images/sad_cloud.png}" role="presentation" /> + </div> + <h2> + Invalid Request Error<br/> + You have attempted to make a request that does not meet our security requirements.<br/> + This may indicate that the request was not originated by you. + </h2> +</div> +</body> +</html> \ No newline at end of file diff --git a/login/src/test/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandlerTest.java b/login/src/test/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandlerTest.java new file mode 100644 index 00000000000..86bfac0676d --- /dev/null +++ b/login/src/test/java/org/cloudfoundry/identity/uaa/security/CsrfAwareEntryPointAndDeniedHandlerTest.java @@ -0,0 +1,112 @@ +/* + * ***************************************************************************** + * 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.security; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.WebAttributes; +import org.springframework.security.web.csrf.MissingCsrfTokenException; + +import javax.servlet.http.HttpServletResponse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class CsrfAwareEntryPointAndDeniedHandlerTest { + + protected CsrfAwareEntryPointAndDeniedHandler handler = new CsrfAwareEntryPointAndDeniedHandler("/csrf", "/login"); + protected MockHttpServletRequest request = new MockHttpServletRequest(); + protected MockHttpServletResponse response = new MockHttpServletResponse(); + + @Before + public void setUpCsrfAccessDeniedHandler() throws Exception { + response.setCommitted(false); + } + + @After + public void cleanUpAuth() { + SecurityContextHolder.clearContext(); + } + + @Test + public void testHandleWhenCsrfMissing() throws Exception { + AccessDeniedException ex = new MissingCsrfTokenException("something"); + handler.handle(request, response, ex); + assertEquals(HttpServletResponse.SC_FOUND, response.getStatus()); + assertSame(request.getAttribute(WebAttributes.ACCESS_DENIED_403), ex); + assertTrue(response.isCommitted()); + assertEquals("http://localhost/csrf", response.getHeader("Location")); + assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatus()); + } + + @Test + public void testHandleWhenCsrfMissingForJson() throws Exception { + request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE); + AccessDeniedException ex = new MissingCsrfTokenException("something"); + handler.handle(request, response, ex); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); + assertEquals("{\"error\":\"Expected CSRF token not found. Has your session expired?\"}", response.getContentAsString()); + assertEquals(null, response.getErrorMessage()); + } + + @Test + public void testHandleWhenNotLoggedIn() throws Exception { + AccessDeniedException ex = new AccessDeniedException("something"); + handler.handle(request, response, ex); + assertEquals(HttpServletResponse.SC_FOUND, response.getStatus()); + assertSame(request.getAttribute(WebAttributes.ACCESS_DENIED_403), ex); + assertTrue(response.isCommitted()); + assertEquals("http://localhost/login", response.getHeader("Location")); + assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatus()); + } + + @Test + public void testHandleWhenNotLoggedInJson() throws Exception { + request.addHeader("Accept", MediaType.APPLICATION_JSON_VALUE); + AccessDeniedException ex = new AccessDeniedException("something"); + handler.handle(request, response, ex); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); + assertEquals("{\"error\":\"something\"}", response.getContentAsString()); + assertEquals(null, response.getErrorMessage()); + } + + @Test(expected = NullPointerException.class) + public void testNullCsrfUrl() { + new CsrfAwareEntryPointAndDeniedHandler(null, "/login"); + } + + @Test(expected = NullPointerException.class) + public void testInvalidCsrfUrl() { + new CsrfAwareEntryPointAndDeniedHandler("csrf", "/login"); + } + + @Test(expected = NullPointerException.class) + public void testNullLoginfUrl() { + new CsrfAwareEntryPointAndDeniedHandler("/csrf", null); + } + + @Test(expected = NullPointerException.class) + public void testInvalidLoginUrl() { + new CsrfAwareEntryPointAndDeniedHandler("/csrf", "login"); + } + +} \ No newline at end of file diff --git a/uaa/src/main/webapp/WEB-INF/spring-servlet.xml b/uaa/src/main/webapp/WEB-INF/spring-servlet.xml index a29e3a554ff..105604fc934 100755 --- a/uaa/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/uaa/src/main/webapp/WEB-INF/spring-servlet.xml @@ -46,11 +46,10 @@ <sec:http name="secFilterOpen07" pattern="/vendor/**" security="none" /> <!--<sec:http pattern="/login" security="none" />--> <sec:http name="secFilterOpen08" pattern="/error" security="none" /> - <sec:http name="secFilterOpen09" pattern="/forgot_password*" security="none" /> - <sec:http name="secFilterOpen10" pattern="/reset_password" security="none" /> <sec:http name="secFilterOpen11" pattern="/email_sent" security="none" /> <sec:http name="secFilterOpen12" pattern="/create_account*" security="none" /> <sec:http name="secFilterOpen13" pattern="/accounts/email_sent" security="none" /> + <sec:http name="secFilterCsrfLandingPage14" pattern="/invalid_request" security="none" /> <bean id="xFrameOptionsFilter" class="org.cloudfoundry.identity.uaa.login.XFrameOptionsFilter" /> <bean id="oauth2TokenParseFilter" class="java.lang.Class" factory-method="forName"> diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ResetPasswordIT.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ResetPasswordIT.java index 468ad2ee94d..00663a8f1e5 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ResetPasswordIT.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/integration/feature/ResetPasswordIT.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,6 +12,8 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.integration.feature; +import java.io.File; +import java.io.IOException; import java.security.SecureRandom; import java.util.Iterator; @@ -20,6 +22,7 @@ import static org.junit.Assert.assertThat; import com.dumbster.smtp.SimpleSmtpServer; import com.dumbster.smtp.SmtpMessage; +import org.apache.commons.io.FileUtils; import org.cloudfoundry.identity.uaa.login.test.LoginServerClassRunner; import org.cloudfoundry.identity.uaa.login.test.UnlessProfileActive; import org.hamcrest.Matchers; @@ -30,6 +33,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.openqa.selenium.By; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -167,4 +172,11 @@ public void resettingAPasswordForANonExistentUser() throws Exception { assertEquals(receivedEmailSize, simpleSmtpServer.getReceivedEmailSize()); } + + public void takeScreenShot() throws IOException { + File scrFile = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE); + File destFile = new File("testscreenshot-" + System.currentTimeMillis() + ".png"); + FileUtils.copyFile(scrFile, destFile); + System.out.println("Screenshot in : " + destFile.getAbsolutePath()); + } } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java index 02272f7072e..d0d0be9dad1 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java @@ -36,7 +36,6 @@ import org.cloudfoundry.identity.uaa.zone.IdentityZone; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.springframework.mock.env.MockEnvironment; @@ -64,7 +63,6 @@ import org.springframework.web.context.support.XmlWebApplicationContext; import javax.servlet.http.Cookie; -import javax.servlet.http.HttpSession; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -72,7 +70,6 @@ import java.util.Locale; import java.util.Map; -import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.hasKey; @@ -85,11 +82,11 @@ import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.securityContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; @@ -112,6 +109,7 @@ public class LoginMockMvcTests extends TestClassNullifier { public static void setUpContext() throws Exception { SecurityContextHolder.clearContext(); webApplicationContext = new XmlWebApplicationContext(); + mockEnvironment.setProperty("login.invitationsEnabled", "true"); webApplicationContext.setEnvironment(mockEnvironment); new YamlServletProfileInitializerContextInitializer().initializeContext(webApplicationContext, "login.yml,uaa.yml"); webApplicationContext.setConfigLocation("file:./src/main/webapp/WEB-INF/spring-servlet.xml"); @@ -597,7 +595,8 @@ public void testChangeEmailSubmitWithMissingCsrf() throws Exception { .param("newEmail", "test@test.org") .param("client_id", ""); mockMvc.perform(changeEmail) - .andExpect(status().is4xxClientError()); + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); } @Test @@ -621,7 +620,8 @@ public void testChangeEmailSubmitWithInvalidCsrf() throws Exception { .param("client_id", "") .param("_csrf", "invalid csrf token"); mockMvc.perform(changeEmail) - .andExpect(status().is4xxClientError()); + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); } @Test @@ -669,5 +669,150 @@ public void testChangeEmailSubmitWithCorrectCsrf() throws Exception { } + @Test + public void testChangeEmailDoNotLoggedIn() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .with(csrf()); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")); + + changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .with(csrf().useInvalidToken()); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + + changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .with(csrf().useInvalidToken()) + .with(securityContext(marissaContext)); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + } + + @Test + public void testChangeEmailNoCsrfReturns403AndInvalidRequest() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)); + + mockMvc.perform(get) + .andExpect(status().isOk()) + .andExpect(content().string(containsString("_csrf"))) + .andReturn(); + + MockHttpServletRequestBuilder changeEmail = post("/change_email.do") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)) + .param("newEmail", "test@test.org") + .param("client_id", ""); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + } + + @Test + public void testCsrfForInvitationPost() throws Exception { + RandomValueStringGenerator generator = new RandomValueStringGenerator(); + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + //logged in with valid CSRF + MockHttpServletRequestBuilder post = post("/invitations/new.do") + .with(securityContext(marissaContext)) + .with(csrf()) + .param("email", generator.generate()+"@example.com"); + + mockMvc.perform(post) + .andDo(print()) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("sent")); + + //logged in, invalid CSRF + post = post("/invitations/new.do") + .with(securityContext(marissaContext)) + .with(csrf().useInvalidToken()) + .param("email", generator.generate()+"@example.com"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + + //not logged in, no CSRF + post = post("/invitations/new.do") + .param("email", generator.generate()+"@example.com"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + + //not logged in, valid CSRF(can't happen) + post = post("/invitations/new.do") + .with(csrf()) + .param("email", generator.generate()+"@example.com"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")); + + } + + @Test + public void testCsrfForInvitationAcceptPost() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + //logged in with valid CSRF + MockHttpServletRequestBuilder post = post("/invitations/accept.do") + .with(securityContext(marissaContext)) + .with(csrf()) + .param("client_id", "random") + .param("password", "password") + .param("password_confirmation", "yield_unprocessable_entity"); + + mockMvc.perform(post) + .andDo(print()) + .andExpect(status().isUnprocessableEntity()); + + //logged in, invalid CSRF + post = post("/invitations/accept.do") + .with(securityContext(marissaContext)) + .with(csrf().useInvalidToken()) + .param("client_id", "random") + .param("password", "password") + .param("password_confirmation", "yield_unprocessable_entity"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + + //not logged in, no CSRF + post = post("/invitations/accept.do") + .param("client_id", "random") + .param("password", "password") + .param("password_confirmation", "yield_unprocessable_entity"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + + //not logged in, valid CSRF(can't happen) + post = post("/invitations/accept.do") + .with(csrf()) + .param("client_id", "random") + .param("password", "password") + .param("password_confirmation", "yield_unprocessable_entity"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/login")); + + } } diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerMockMvcTests.java index 3a7e7f2097a..485dd6d80b3 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/ResetPasswordControllerMockMvcTests.java @@ -46,7 +46,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -92,6 +94,7 @@ public void testResettingAPasswordUsingUsernameToEnsureNoModification() throws E ExpiringCode code = codeStore.generateCode(JsonUtils.writeValueAsString(change), new Timestamp(System.currentTimeMillis()+ PASSWORD_RESET_LIFETIME)); MockHttpServletRequestBuilder post = post("/reset_password.do") + .with(csrf()) .param("code", code.getCode()) .param("email", users.get(0).getPrimaryEmail()) .param("password", "newpassword") @@ -131,6 +134,7 @@ public void testResettingAPasswordFailsWhenUsernameChanged() throws Exception { user = userProvisioning.update(user.getId(), user); try { MockHttpServletRequestBuilder post = post("/reset_password.do") + .with(csrf()) .param("code", code.getCode()) .param("email", user.getPrimaryEmail()) .param("password", "newpassword") @@ -144,6 +148,24 @@ public void testResettingAPasswordFailsWhenUsernameChanged() throws Exception { } } + @Test + public void testResettingAPasswordNoCsrfParameter() throws Exception { + List<ScimUser> users = webApplicationContext.getBean(ScimUserProvisioning.class).query("username eq \"marissa\""); + assertNotNull(users); + assertEquals(1, users.size()); + ExpiringCode code = codeStore.generateCode(users.get(0).getId(), new Timestamp(System.currentTimeMillis() + PASSWORD_RESET_LIFETIME)); + + MockHttpServletRequestBuilder post = post("/reset_password.do") + .param("code", code.getCode()) + .param("email", users.get(0).getPrimaryEmail()) + .param("password", "newpassword") + .param("password_confirmation", "newpassword"); + + mockMvc.perform(post) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + } + @Test public void testResettingAPasswordUsingTimestampForUserModification() throws Exception { List<ScimUser> users = webApplicationContext.getBean(ScimUserProvisioning.class).query("username eq \"marissa\""); @@ -152,6 +174,7 @@ public void testResettingAPasswordUsingTimestampForUserModification() throws Exc ExpiringCode code = codeStore.generateCode(users.get(0).getId(), new Timestamp(System.currentTimeMillis()+ PASSWORD_RESET_LIFETIME)); MockHttpServletRequestBuilder post = post("/reset_password.do") + .with(csrf()) .param("code", code.getCode()) .param("email", users.get(0).getPrimaryEmail()) .param("password", "newpassword") @@ -182,6 +205,7 @@ public void testResettingAPasswordUsingTimestampUserModified() throws Exception ExpiringCode code = codeStore.generateCode(user.getId(), new Timestamp(System.currentTimeMillis() + PASSWORD_RESET_LIFETIME)); MockHttpServletRequestBuilder post = post("/reset_password.do") + .with(csrf()) .param("code", code.getCode()) .param("email", user.getPrimaryEmail()) .param("password", "newpassword") From d78c6be93ff5d5c778501bb6caf0f5b7cd761f0a Mon Sep 17 00:00:00 2001 From: Filip Hanik <fhanik@pivotal.io> Date: Fri, 8 May 2015 20:50:41 -0600 Subject: [PATCH 9/9] Bump release version to 2.3.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 65362284ef9..7ad95fa51f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.3.0-SNAPSHOT +version=2.3.0