diff --git a/common/build.gradle b/common/build.gradle index 80ff05ddfc4..d13752fe49c 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,13 +42,15 @@ 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' 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') } @@ -63,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/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 authorities = new ArrayList(); @Override public Collection 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 claims = mapper.readValue(jwt.getClaims(), new TypeReference>() {}); - return (claims.get("user_id") != null ? claims.get("user_id") : claims.get("client_id")).toString(); - } catch (IOException e) { - return null; - } + Map claims = JsonUtils.readValue(jwt.getClaims(), new TypeReference>() {}); + 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 parameterNames = Collections.emptyList(); private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint(); @@ -190,11 +188,11 @@ private Map getCredentials(HttpServletRequest request) { if (value != null) { if (value.startsWith("{")) { try { - Map jsonCredentials = mapper.readValue(value, + Map jsonCredentials = JsonUtils.readValue(value, new TypeReference>() { }); 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..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 @@ -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; @@ -186,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); @@ -400,7 +404,7 @@ public String generatePasscode(Map 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 getAdditionalInformation() { @@ -98,7 +98,7 @@ public Map 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. - * + * * @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 { @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 { @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/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 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 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 getCredentials(HttpServletRequest request) { if (value != null) { if (value.startsWith("{")) { try { - Map jsonCredentials = mapper.readValue(value, + Map jsonCredentials = JsonUtils.readValue(value, new TypeReference>() { }); 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/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/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 getClaimsForToken(String token) { Map claims = null; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() { }); - } 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 { - 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 additionalInformation = mapper.readValue(json, Map.class); + Map 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 claims = null; try { - claims = new ObjectMapper().readValue(tokenJwt.getClaims(), new TypeReference>() {}); - } catch (Exception e) { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + } 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 { + public static final class OpenIdTokenJackson1Serializer extends StdSerializer { 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 getAdditionalAuthorizationAttributes(String authorit if (StringUtils.hasLength(authoritiesJson)) { try { @SuppressWarnings("unchecked") - Map authorities = mapper.readValue(authoritiesJson.getBytes(), Map.class); + Map authorities = JsonUtils.readValue(authoritiesJson, new TypeReference>() {}); @SuppressWarnings("unchecked") Map additionalAuthorizationAttributes = (Map) 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 getClaimsForToken(String token) { Map claims = null; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() { }); - } 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/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 matchers; public DelegatingRequestMatcher(List matchers) { - this.matchers = new ArrayList(matchers); + this.matchers = new ArrayList<>(matchers); } @Override 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 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/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 accepts) { @@ -90,7 +90,7 @@ public void setAccept(List 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 parameters) { 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 convertValue(Object object, Class 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 { @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 { @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 read(String input, Class 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 publisher; private UaaTokenServices tokenServices = new UaaTokenServices(); private SignerProvider signerProvider = new SignerProvider(); - private ObjectMapper mapper = new ObjectMapper(); private List defaultUserAuthorities = Arrays.asList( UaaAuthority.authority("space.123.developer"), @@ -236,7 +235,8 @@ public void testCreateAccessTokenForAClient() { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() { + }); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -284,7 +284,7 @@ public void testCreateAccessTokenForAClientInAnotherIdentityZone() { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(),new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -382,7 +382,7 @@ public void testCreateAccessTokenRefreshGrant() throws InterruptedException { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(),new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(),new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -433,7 +433,7 @@ public void testCreateAccessTokenRefreshGrantAllScopesAutoApproved() throws Inte assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -484,7 +484,7 @@ public void testCreateAccessTokenRefreshGrantSomeScopesAutoApprovedDowngradedReq assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -541,7 +541,7 @@ public void testCreateAccessTokenRefreshGrantSomeScopesAutoApproved() throws Int assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -666,7 +666,7 @@ private OAuth2AccessToken testCreateAccessTokenForAUser(OAuth2Authentication aut assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -693,7 +693,7 @@ private OAuth2AccessToken testCreateAccessTokenForAUser(OAuth2Authentication aut assertNotNull(refreshTokenJwt); Map refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -761,7 +761,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -773,7 +773,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(refreshTokenJwt); Map refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -796,7 +796,7 @@ public void testCreateAccessTokenAuthcodeGrantNarrowerScopes() { assertNotNull(tokenJwt); Map reducedClaims; try { - reducedClaims = mapper.readValue(newTokenJwt.getClaims(), new TypeReference>() {}); + reducedClaims = JsonUtils.readValue(newTokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -826,7 +826,7 @@ public void testCreateAccessTokenAuthcodeGrantExpandedScopes() { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -838,7 +838,7 @@ public void testCreateAccessTokenAuthcodeGrantExpandedScopes() { assertNotNull(refreshTokenJwt); Map refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -877,7 +877,7 @@ public void testChangedExpiryForTokens() { assertNotNull(tokenJwt); Map claims; try { - claims = mapper.readValue(tokenJwt.getClaims(), new TypeReference>() {}); + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() {}); } catch (Exception e) { throw new IllegalStateException(CANNOT_READ_TOKEN_CLAIMS, e); } @@ -891,7 +891,7 @@ public void testChangedExpiryForTokens() { assertNotNull(refreshTokenJwt); Map refreshTokenClaims; try { - refreshTokenClaims = mapper.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); + refreshTokenClaims = JsonUtils.readValue(refreshTokenJwt.getClaims(),new TypeReference>() {}); } 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> list = new ArrayList>(); 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 d13ea101cca..7ad95fa51f7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version=2.2.6 +version=2.3.0 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 whitelist = null; + + public WhitelistLogoutHandler(List whitelist) { + this.whitelist = whitelist; + } + + public List getWhitelist() { + return whitelist; + } + + public void setWhitelist(List 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/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/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/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 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 data = objectMapper.readValue(expiringCode.getData(), new TypeReference>() {}); + Map data = JsonUtils.readValue(expiringCode.getData(), new TypeReference>() {}); 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 body = new ObjectMapper().readValue(e.getResponseBodyAsString(), new TypeReference>() { + Map body = JsonUtils.readValue(e.getResponseBodyAsString(), new TypeReference>() { }); 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/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> 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/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 verifyCode(Class 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 verifyCode(String code) throws IOException, CodeNotFou if (expiringCode==null) { throw new CodeNotFoundException(); } - return new ObjectMapper().readValue(expiringCode.getData(), new TypeReference>() {}); - } catch (IOException e) { + return JsonUtils.readValue(expiringCode.getData(), new TypeReference>() { + }); + } catch (JsonUtils.JsonUtilException e) { throw new CodeNotFoundException(); } } 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 9fa70c18a9d..c09cf5a32a9 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,79 @@ - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + login-processing-url="/login.do" authentication-failure-handler-ref="loginAuthenticationFailureHandler" + authentication-details-source-ref="authenticationDetailsSource"/> + @@ -80,31 +128,28 @@ - - - - - + entry-point-ref="loginEntryPoint" use-expressions="false"> + + entry-point-ref="loginEntryPoint" use-expressions="false"> + + entry-point-ref="loginEntryPoint" use-expressions="false"> + - + @@ -131,6 +176,7 @@ + @@ -143,12 +189,17 @@ - - + + + - - + + + @@ -309,7 +360,7 @@ - + @@ -341,9 +392,6 @@ - - - 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 @@ + + + + + +
+
+
+

Warning

+
+ +
+

+ Invalid Request Error
+ You have attempted to make a request that does not meet our security requirements.
+ This may indicate that the request was not originated by you. +

+
+ + \ No newline at end of file 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 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 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/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/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml b/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml index 20d8fa6b1ea..1d73aa23d70 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 @@ - - + - + + + @@ -44,7 +46,7 @@ - + - + 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..05503183abe 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 @@ - - - - - + + + + - + - @@ -35,6 +36,7 @@ + @@ -93,7 +95,7 @@ - + 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 { @Override public ScimGroup deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, - JsonProcessingException { + JsonProcessingException { ScimGroup group = new ScimGroup(); Map> roles = new HashMap>(); 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 { @Override public void serialize(ScimGroup group, JsonGenerator jgen, SerializerProvider provider) throws IOException, - JsonProcessingException { + JsonProcessingException { Map> roles = new HashMap>(); 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 { @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(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 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 clientDetailsService) { + public ChangeEmailEndpoints(ScimUserProvisioning scimUserProvisioning, ExpiringCodeStore expiringCodeStore, QueryableResourceManager clientDetailsService) { this.scimUserProvisioning = scimUserProvisioning; this.expiringCodeStore = expiringCodeStore; - this.objectMapper = objectMapper; this.clientDetailsService = clientDetailsService; } @@ -63,8 +61,8 @@ public ResponseEntity 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 generateEmailVerificationCode(@RequestBody EmailCh public ResponseEntity changeEmail(@RequestBody String code) throws IOException { ExpiringCode expiringCode = expiringCodeStore.retrieveCode(code); if (expiringCode != null) { - Map data = objectMapper.readValue(expiringCode.getData(), new TypeReference>() {}); + Map data = JsonUtils.readValue(expiringCode.getData(), new TypeReference>() {}); 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> resetPassword(@RequestBody String email) throws IOException { - String jsonEmail = objectMapper.writeValueAsString(email); + String jsonEmail = JsonUtils.writeValueAsString(email); Map response = new HashMap<>(); List 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..cefb7e8b1d6 100644 --- a/shared_versions.gradle +++ b/shared_versions.gradle @@ -1,8 +1,13 @@ ext { - springVersion = '4.0.8.RELEASE' - springSecurityVersion = '3.2.4.RELEASE' - springSecurityOAuthVersion = '2.0.3.RELEASE' - springSecurityLdapVersion = '1.3.2.RELEASE' + springVersion = '4.1.6.RELEASE' + springSecurityVersion = '4.0.1.RELEASE' + springSecurityOAuthVersion = '2.0.7.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' + bcpkixVersion = '1.47' + apacheLdapApiVersion = '1.0.0-M22' + jacksonVersion = '2.5.3' } 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/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/main/webapp/WEB-INF/spring-servlet.xml b/uaa/src/main/webapp/WEB-INF/spring-servlet.xml index 56f66244ad0..105604fc934 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,19 @@ - - - - - - - + + + + + + + - - - - - - + + + + + @@ -68,7 +67,7 @@ - healthz + secFilterOpen05Healthz @@ -184,19 +183,19 @@ - + - + - + - + - + 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"> @@ -50,11 +50,12 @@ + + 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"> + + + - + 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 @@ - - + + + @@ -15,10 +24,11 @@ + access-decision-manager-ref="userAccessDecisionManager" pattern="/Codes/**" xmlns="http://www.springframework.org/schema/security" use-expressions="false"> + \ 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 23527ffa037..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"> - + + @@ -43,10 +44,10 @@ - + - + @@ -55,6 +56,7 @@ + @@ -67,8 +69,8 @@ - + - + + @@ -186,10 +190,7 @@ - - - @@ -197,23 +198,24 @@ - - + + - + + 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 @@ @@ -57,6 +57,7 @@ + @@ -115,6 +116,7 @@ method="GET"/> + 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..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"> @@ -29,6 +29,8 @@ + + @@ -41,7 +43,7 @@ - @@ -49,6 +51,7 @@ + @@ -96,7 +99,7 @@ - @@ -104,6 +107,7 @@ + + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> + @@ -192,12 +197,13 @@ --> + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> + 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 @@ + 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"> + - + + - + + + 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 @@ --> - + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd"> @@ -31,7 +26,7 @@ - + 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"> @@ -144,21 +144,23 @@ - + - + @@ -184,6 +186,7 @@ + @@ -213,12 +216,13 @@ - + @@ -235,9 +239,9 @@
- + xmlns="http://www.springframework.org/schema/security" use-expressions="false"> @@ -246,14 +250,16 @@ + - + 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/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 map = new HashMap(mapper.readValue(mapper.writeValueAsString(joe), - Map.class)); + Map map = new HashMap(JsonUtils.readValue(JsonUtils.writeValueAsString(joe), + Map.class)); map.put("nottheusername", JOE + "0"); ResponseEntity response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity(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 map = new HashMap(mapper.readValue(mapper.writeValueAsString(joe), + Map map = new HashMap(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 claims = new ObjectMapper().readValue(access_token.getClaims(), new TypeReference>() { + Map claims = JsonUtils.readValue(access_token.getClaims(), new TypeReference>() { }); 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 claims = new ObjectMapper().readValue(access_token.getClaims(), new TypeReference>() { + Map claims = JsonUtils.readValue(access_token.getClaims(), new TypeReference>() { }); Assert.assertThat((String) claims.get("jti"), is(params.get("jti"))); 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/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..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 @@ -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; @@ -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(); @@ -253,7 +250,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") @@ -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/LoginMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/LoginMockMvcTests.java index 3bb26c81dec..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 @@ -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; @@ -49,9 +50,12 @@ 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; +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; @@ -66,13 +70,20 @@ 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.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.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; @@ -98,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"); @@ -154,6 +166,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.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); @@ -454,7 +522,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 +555,264 @@ 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 { + 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"))); + } + + @Test + public void testChangeEmailSubmitWithMissingCsrf() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)); + MockHttpSession session = (MockHttpSession)mockMvc.perform(get) + .andExpect(status().isOk()) + .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) + .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 testChangeEmailSubmitWithInvalidCsrf() throws Exception { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)); + MockHttpSession session = (MockHttpSession)mockMvc.perform(get) + .andExpect(status().isOk()) + .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) + .with(securityContext(marissaContext)) + .param("newEmail", "test@test.org") + .param("client_id", "") + .param("_csrf", "invalid csrf token"); + mockMvc.perform(changeEmail) + .andExpect(status().isFound()) + .andExpect(redirectedUrl("http://localhost/invalid_request")); + } + + @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 { + SecurityContext marissaContext = MockMvcUtils.utils().getMarissaSecurityContext(webApplicationContext); + + MockHttpServletRequestBuilder get = get("/change_email") + .accept(TEXT_HTML) + .with(securityContext(marissaContext)); + + MvcResult result = mockMvc.perform(get) + .andExpect(status().isOk()) + .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) + .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")); + + } + + @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/PasscodeMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/login/PasscodeMockMvcTests.java index 9610cfadfaa..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 @@ -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,10 @@ 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()) + .andReturn().getResponse().getContentAsString(), String.class); mockSecurityContext.setAuthentication(null); @@ -158,9 +157,8 @@ public void testLoginUsingPasscodeWithSamlToken() throws Exception { Map accessToken = - new ObjectMapper().readValue( + JsonUtils.readValue( mockMvc.perform(post) - .andDo(print()) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(), Map.class); @@ -199,10 +197,9 @@ 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()) .andReturn().getResponse().getContentAsString(), String.class); @@ -225,9 +222,8 @@ public void testLoginUsingPasscodeWithUaaToken() throws Exception { Map accessToken = - new ObjectMapper().readValue( + 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/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 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 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") 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 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/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/TokenKeyEndpointMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenKeyEndpointMockMvcTests.java index 7929318ed37..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 @@ -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; @@ -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 key = new ObjectMapper().readValue(result.getResponse().getContentAsString(), Map.class); + Map 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 key = JsonUtils.readValue(result.getResponse().getContentAsString(), Map.class); + validateKey(key); + } + public void validateKey(Map key) { Object kty = key.get("kty"); assertNotNull(kty); assertTrue(kty instanceof String); 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..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 @@ -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; @@ -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()); } @@ -692,7 +688,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 +757,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 +885,7 @@ private Map getClaimsForToken(String token) { Map claims = null; try { - claims = new ObjectMapper().readValue(tokenJwt.getClaims(), new TypeReference>() { + claims = JsonUtils.readValue(tokenJwt.getClaims(), new TypeReference>() { }); } catch (Exception e) { throw new IllegalStateException("Cannot read token claims", e); @@ -1520,7 +1516,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) @@ -1669,8 +1665,8 @@ 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(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), TestClient.OAuthToken.class); + 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 f579966ea6f..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 @@ -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; @@ -21,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; @@ -33,8 +36,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; @@ -45,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; @@ -69,7 +71,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 +83,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 +124,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..admin scope to a user @@ -137,7 +138,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 +150,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 +209,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 +231,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 +262,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 +279,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 { @@ -299,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, @@ -315,8 +316,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 +331,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; } @@ -375,9 +376,9 @@ 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(); - TestClient.OAuthToken oauthToken = new ObjectMapper().readValue(result.getResponse().getContentAsByteArray(), - TestClient.OAuthToken.class); + result = mockMvc.perform(authRequest).andExpect(status().is2xxSuccessful()).andReturn(); + TestClient.OAuthToken oauthToken = JsonUtils.readValue(result.getResponse().getContentAsString(), + TestClient.OAuthToken.class); return oauthToken.accessToken; } @@ -397,10 +398,20 @@ 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; } + 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 TestApplicationEventListener addEventListener(ConfigurableApplicationContext applicationContext, Class clazz) { TestApplicationEventListener listener = TestApplicationEventListener.forEventClass(clazz); applicationContext.addApplicationListener(listener); 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 clientDeleteEventListener; private static TestApplicationEventListener groupModifiedEventListener; private static TestApplicationEventListener 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 zones = JsonUtils.readValue(result.getResponse().getContentAsString(), new TypeReference>() {}); 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 users = getUsersInZone(subdomain, zoneAdminToken); assertTrue(users.contains(user)); assertEquals(1, users.size()); @@ -521,8 +520,9 @@ private List 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>() {}); + JsonNode root = JsonUtils.readTree(mvcResult.getResponse().getContentAsString()); + return JsonUtils.readValue(root.get("resources").toString(), new TypeReference>() { + }); } @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 void checkZoneAuditEventInUaa(int eventCount, AuditEventType eventType) { checkAuditEventListener(eventCount, eventType, zoneModifiedEventListener, IdentityZone.getUaa().getId(), "http://localhost:8080/uaa/oauth/token", "identity"); } - + private void checkAuditEventListener(int eventCount, AuditEventType eventType, TestApplicationEventListener 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 response = new ObjectMapper().readValue(responseString, new TypeReference>() { + Map response = JsonUtils.readValue(responseString, new TypeReference>() { }); 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..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 @@ -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,10 +149,9 @@ 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()) .andExpect(status().isCreated()); //it is already created mockMvc.perform(post) @@ -170,7 +169,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 +200,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 +380,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 +547,7 @@ protected void checkGetExternalGroupsFilter(String fieldName, String fieldValue) String content = result.andReturn().getResponse().getContentAsString(); SearchResults members = null; - Map map = new ObjectMapper().readValue(content, Map.class); + Map map = JsonUtils.readValue(content, Map.class); List> resources = (List>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -621,7 +620,7 @@ protected void checkGetExternalGroupsPagination(int start, int count) throws Exc String content = result.andReturn().getResponse().getContentAsString(); SearchResults members = null; - Map map = new ObjectMapper().readValue(content, Map.class); + Map map = JsonUtils.readValue(content, Map.class); List> resources = (List>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -668,7 +667,7 @@ protected void checkGetExternalGroups(String path) throws Exception { String content = result.andReturn().getResponse().getContentAsString(); SearchResults members = null; - Map map = new ObjectMapper().readValue(content, Map.class); + Map map = JsonUtils.readValue(content, Map.class); List> resources = (List>)map.get("resources"); int startIndex = Integer.parseInt(map.get("startIndex").toString()); int itemsPerPage = Integer.parseInt(map.get("itemsPerPage").toString()); @@ -737,7 +736,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..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 @@ -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; @@ -116,7 +116,6 @@ public void testLookupUsingOnlyOrigin() throws Exception { .param("count", String.valueOf(50)); mockMvc.perform(post) - .andDo(print()) .andExpect(status().isBadRequest()); } @@ -222,7 +221,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 +252,7 @@ private MockHttpServletRequestBuilder getUsernameLookupRequest(String token, Str } private void validateLookupResults(String[] usernames, String body) throws java.io.IOException { - Map map = new ObjectMapper().readValue(body, Map.class); + Map 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 +297,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 +311,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 map = new ObjectMapper().readValue(body, Map.class); + Map 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..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 @@ -12,28 +12,26 @@ *******************************************************************************/ 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.MockMvcResultHandlers.print; +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 +51,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 +67,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; } 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 @@