/*******************************************************************************
* Cloud Foundry
* Copyright (c) [2009-2016] 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.integration;
import org.cloudfoundry.identity.uaa.ServerRunning;
import org.cloudfoundry.identity.uaa.account.PasswordChangeRequest;
import org.cloudfoundry.identity.uaa.oauth.UaaOauth2ErrorHandler;
import org.cloudfoundry.identity.uaa.scim.ScimUser;
import org.cloudfoundry.identity.uaa.test.TestAccountSetup;
import org.cloudfoundry.identity.uaa.test.UaaTestAccounts;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.BeforeOAuth2Context;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
import org.springframework.security.oauth2.client.test.OAuth2ContextSetup;
import org.springframework.security.oauth2.common.util.RandomValueStringGenerator;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Integration test to verify that the trusted client use cases are supported
* adequately for cf.
*
* @author Luke Taylor
* @author Dave Syer
*/
@OAuth2ContextConfiguration(OAuth2ContextConfiguration.Implicit.class)
public class CfScimUserEndpointIntegrationTests {
private final String JOE = "joe" + new RandomValueStringGenerator().generate().toLowerCase();
private final String usersEndpoint = "/Users";
private ScimUser joe;
@Rule
public ServerRunning serverRunning = ServerRunning.isRunning();
private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);
@Rule
public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);
@Rule
public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts);
@BeforeOAuth2Context
@OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
public void setUpUserAccounts() {
// If running against vcap we don't want to run these tests because they
// create new user accounts
Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
RestOperations client = serverRunning.getRestTemplate();
ScimUser user = new ScimUser();
user.setPassword("password");
user.setUserName(JOE);
user.setName(new ScimUser.Name("Joe", "User"));
user.addEmail("joe@blah.com");
user.setVerified(true);
user.setPassword("Passwo3d124!");
ResponseEntity<ScimUser> newuser = client.postForEntity(serverRunning.getUrl(usersEndpoint), user,
ScimUser.class);
joe = newuser.getBody();
assertEquals(JOE, joe.getUserName());
PasswordChangeRequest change = new PasswordChangeRequest();
change.setPassword("Passwo3d");
HttpHeaders headers = new HttpHeaders();
ResponseEntity<Void> result = client
.exchange(serverRunning.getUrl(usersEndpoint) + "/{id}/password",
HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers),
Void.class, joe.getId());
assertEquals(HttpStatus.OK, result.getStatusCode());
// The implicit grant for cf requires extra parameters in the
// authorization request
context.setParameters(Collections.singletonMap("credentials",
testAccounts.getJsonCredentials(joe.getUserName(), "Passwo3d")));
}
@Before
public void setUp() throws Exception {
((RestTemplate)serverRunning.getRestTemplate()).setErrorHandler(
new UaaOauth2ErrorHandler(context.getResource(), HttpStatus.Series.SERVER_ERROR)
);
}
@SuppressWarnings("rawtypes")
private ResponseEntity<Map> deleteUser(RestOperations client, String id, int version) {
HttpHeaders headers = new HttpHeaders();
headers.add("If-Match", "\"" + version + "\"");
return client.exchange(serverRunning.getUrl(usersEndpoint + "/{id}"), HttpMethod.DELETE, new HttpEntity<Void>(
headers), Map.class, id);
}
@Test
public void changePasswordSucceeds() throws Exception {
PasswordChangeRequest change = new PasswordChangeRequest();
change.setOldPassword("Passwo3d");
change.setPassword("Newpasswo3d");
HttpHeaders headers = new HttpHeaders();
RestOperations client = serverRunning.getRestTemplate();
ResponseEntity<Void> result = client
.exchange(serverRunning.getUrl(usersEndpoint) + "/{id}/password",
HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers),
Void.class, joe.getId());
assertEquals(HttpStatus.OK, result.getStatusCode());
}
@Test
public void userInfoSucceeds() throws Exception {
HttpHeaders headers = new HttpHeaders();
RestOperations client = serverRunning.getRestTemplate();
ResponseEntity<Void> result = client.exchange(serverRunning.getUrl("/userinfo"), HttpMethod.GET,
new HttpEntity<Void>(null, headers), Void.class, joe.getId());
assertEquals(HttpStatus.OK, result.getStatusCode());
}
@Test
public void deleteUserFails() throws Exception {
RestOperations client = serverRunning.getRestTemplate();
@SuppressWarnings("rawtypes")
ResponseEntity<Map> response = deleteUser(client, joe.getId(), joe.getVersion());
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
@SuppressWarnings("unchecked")
Map<String, String> error = response.getBody();
// System.err.println(error);
assertEquals("insufficient_scope", error.get("error"));
}
@Test
public void findUsersFails() throws Exception {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint, Map.class);
@SuppressWarnings("unchecked")
Map<String, Object> results = response.getBody();
assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
assertNotNull("There should be an error", results.get("error"));
}
}