org.cloudfoundry.identity.uaa.integration.PasswordChangeEndpointIntegrationTests.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudfoundry.identity.uaa.integration.PasswordChangeEndpointIntegrationTests.java

Source

/*
 * Cloud Foundry 2012.02.03 Beta
 * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved.
 *
 * This product is licensed to you under the Apache License, Version 2.0 (the "License").
 * You may not use this product except in compliance with the License.
 *
 * This product includes a number of subcomponents with
 * separate copyright notices and license terms. Your use of these
 * subcomponents is subject to the terms and conditions of the
 * subcomponent's license, as noted in the LICENSE file.
 */

package org.cloudfoundry.identity.uaa.integration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.net.URI;
import java.util.Arrays;
import org.cloudfoundry.identity.uaa.message.PasswordChangeRequest;
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.MediaType;
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.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestOperations;

/**
 * @author Dave Syer
 *
 */
public class PasswordChangeEndpointIntegrationTests {

    private final String JOE = "joe_" + new RandomValueStringGenerator().generate().toLowerCase();
    private final String BOB = "bob_" + new RandomValueStringGenerator().generate().toLowerCase();

    private final String userEndpoint = "/Users";

    @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);

    private RestOperations client;

    private ScimUser joe;
    private ScimUser bob;

    private ResponseEntity<ScimUser> createUser(String username, String firstName, String lastName, String email) {
        ScimUser user = new ScimUser();
        user.setUserName(username);
        user.setName(new ScimUser.Name(firstName, lastName));
        user.addEmail(email);
        user.setPassword("password");
        return client.postForEntity(serverRunning.getUrl(userEndpoint), user, ScimUser.class);
    }

    @Before
    public void createRestTemplate() throws Exception {
        // Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
        client = serverRunning.getRestTemplate();
    }

    @BeforeOAuth2Context
    @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
    public void createAccount() throws Exception {
        client = serverRunning.getRestTemplate();
        ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com");
        joe = response.getBody();
        assertEquals(JOE, joe.getUserName());
        response = createUser(BOB, "Bob", "User", "bob@blah.com");
        bob = response.getBody();
        assertEquals(BOB, bob.getUserName());
    }

    private String implicitUrl() {
        URI uri = serverRunning.buildUri("/oauth/authorize").queryParam("response_type", "token")
                .queryParam("client_id", "vmc")
                .queryParam("redirect_uri", "https://uaa.cloudfoundry.com/redirect/vmc")
                .queryParam("scope", "cloud_controller.read").build();
        return uri.toString();
    }

    // XXX I (aocole) believe this test is incorrect. This allows a client with the password.change scope
    // change any user's password, even without uaa.admin scope. This contradicts docs at:
    // https://github.com/cloudfoundry/uaa/blob/master/docs/UAA-Security.md#password-change
    @Test
    @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
    public void testChangePasswordSucceeds() throws Exception {
        PasswordChangeRequest change = new PasswordChangeRequest();
        change.setPassword("newpassword");

        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<Void> result = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}/password",
                HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers), null, joe.getId());
        assertEquals(HttpStatus.OK, result.getStatusCode());

    }

    @Test
    @OAuth2ContextConfiguration(resource = OAuth2ContextConfiguration.Implicit.class, initialize = false)
    public void testUserChangesOwnPassword() throws Exception {

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
        parameters.set("source", "credentials");
        parameters.set("username", joe.getUserName());
        parameters.set("password", "password");
        context.getAccessTokenRequest().putAll(parameters);

        PasswordChangeRequest change = new PasswordChangeRequest();
        change.setOldPassword("password");
        change.setPassword("newpassword");

        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<Void> result = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}/password",
                HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers), null, joe.getId());
        assertEquals(HttpStatus.OK, result.getStatusCode());

        // Now try logging in with the new credentials
        headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));

        String credentials = String.format("{ \"username\":\"%s\", \"password\":\"%s\" }", joe.getUserName(),
                "newpassword");

        MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
        formData.add("credentials", credentials);
        result = serverRunning.postForResponse(implicitUrl(), headers, formData);

        assertNotNull(result.getHeaders().getLocation());
        assertTrue(result.getHeaders().getLocation().toString()
                .matches("https://uaa.cloudfoundry.com/redirect/vmc#access_token=.+"));
    }

    @Test
    @OAuth2ContextConfiguration(resource = OAuth2ContextConfiguration.Implicit.class, initialize = false)
    public void testUserChangesOthersPasswordFails() throws Exception {

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
        parameters.set("source", "credentials");
        parameters.set("username", joe.getUserName());
        parameters.set("password", "password");
        context.getAccessTokenRequest().putAll(parameters);

        PasswordChangeRequest change = new PasswordChangeRequest();
        change.setPassword("newpassword");

        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<Void> result = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}/password",
                HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers), null, bob.getId());
        assertEquals(HttpStatus.FORBIDDEN, result.getStatusCode());

    }

    @Test
    @OAuth2ContextConfiguration(resource = OAuth2ContextConfiguration.Implicit.class, initialize = false)
    public void testUserMustSupplyOldPassword() throws Exception {

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
        parameters.set("source", "credentials");
        parameters.set("username", joe.getUserName());
        parameters.set("password", "password");
        context.getAccessTokenRequest().putAll(parameters);

        PasswordChangeRequest change = new PasswordChangeRequest();
        change.setPassword("newpassword");

        HttpHeaders headers = new HttpHeaders();
        ResponseEntity<Void> result = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}/password",
                HttpMethod.PUT, new HttpEntity<PasswordChangeRequest>(change, headers), null, joe.getId());
        assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode());

    }

}