@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", "pas5Word");
    context.getAccessTokenRequest().putAll(parameters);

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

    HttpHeaders headers = new HttpHeaders();
    ResponseEntity<Void> result =
        client.exchange(
            serverRunning.getUrl(userEndpoint) + "/{id}/password",
            HttpMethod.PUT,
            new HttpEntity<>(change, headers),
            Void.class,
            joe.getId());
    assertEquals(HttpStatus.BAD_REQUEST, result.getStatusCode());
  }
  @Before
  public void createRestTemplate() throws Exception {
    client = (OAuth2RestTemplate) serverRunning.getRestTemplate();
    client.setErrorHandler(
        new OAuth2ErrorHandler(context.getResource()) {
          // Pass errors through in response entity for status code analysis
          @Override
          public boolean hasError(ClientHttpResponse response) throws IOException {
            return false;
          }

          @Override
          public void handleError(ClientHttpResponse response) throws IOException {}
        });
  }
  @Before
  public void createRestTemplate() throws Exception {
    Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
    client = serverRunning.getRestTemplate();
    ((RestTemplate) serverRunning.getRestTemplate())
        .setErrorHandler(
            new OAuth2ErrorHandler(context.getResource()) {
              // Pass errors through in response entity for status code analysis
              @Override
              public boolean hasError(ClientHttpResponse response) throws IOException {
                return false;
              }

              @Override
              public void handleError(ClientHttpResponse response) throws IOException {}
            });
  }
/**
 * @author Ryan Heaton
 * @author Dave Syer
 */
@OAuth2ContextConfiguration(ClientCredentials.class)
public class TestClientCredentialsProvider {

  @Rule public ServerRunning serverRunning = ServerRunning.isRunning();

  @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(serverRunning);

  /** tests the basic provider */
  @Test
  public void testPostForToken() throws Exception {
    OAuth2AccessToken token = context.getAccessToken();
    assertNull(token.getRefreshToken());
  }

  static class ClientCredentials extends ClientCredentialsResourceDetails {
    public ClientCredentials(Object target) {
      setClientId("my-client-with-registered-redirect");
      setScope(Arrays.asList("read"));
      setId(getClientId());
      TestClientCredentialsProvider test = (TestClientCredentialsProvider) target;
      setAccessTokenUri(test.serverRunning.getUrl("/sparklr2/oauth/token"));
    }
  }
}
 /** tests the basic provider */
 @Test
 public void testPostForToken() throws Exception {
   OAuth2AccessToken token = context.getAccessToken();
   assertNull(token.getRefreshToken());
 }
@OAuth2ContextConfiguration(IdentityZoneEndpointsIntegrationTests.IdentityClient.class)
public class IdentityZoneEndpointsIntegrationTests {
  @Rule public ServerRunning serverRunning = ServerRunning.isRunning();

  private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);

  @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.standard(serverRunning);

  @Rule
  public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);

  private RestTemplate client;

  @Before
  public void createRestTemplate() throws Exception {
    client = (OAuth2RestTemplate) serverRunning.getRestTemplate();
    client.setErrorHandler(
        new OAuth2ErrorHandler(context.getResource()) {
          // Pass errors through in response entity for status code analysis
          @Override
          public boolean hasError(ClientHttpResponse response) throws IOException {
            return false;
          }

          @Override
          public void handleError(ClientHttpResponse response) throws IOException {}
        });
  }

  @Test
  public void testCreateZone() throws Exception {
    String zoneId = UUID.randomUUID().toString();
    String requestBody =
        "{\"id\":\""
            + zoneId
            + "\", \"subdomain\":\""
            + zoneId
            + "\", \"name\":\"testCreateZone() "
            + zoneId
            + "\"}";

    HttpHeaders headers = new HttpHeaders();
    headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
    headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);

    ResponseEntity<Void> response =
        client.exchange(
            serverRunning.getUrl("/identity-zones"),
            HttpMethod.POST,
            new HttpEntity<>(requestBody, headers),
            new ParameterizedTypeReference<Void>() {});

    assertEquals(HttpStatus.CREATED, response.getStatusCode());

    RestTemplate adminClient =
        IntegrationTestUtils.getClientCredentialsTemplate(
            IntegrationTestUtils.getClientCredentialsResource(
                serverRunning.getBaseUrl(), new String[0], "admin", "adminsecret"));
    String email = new RandomValueStringGenerator().generate() + "@samltesting.org";
    ScimUser user =
        IntegrationTestUtils.createUser(
            adminClient, serverRunning.getBaseUrl(), email, "firstname", "lastname", email, true);
    IntegrationTestUtils.makeZoneAdmin(client, serverRunning.getBaseUrl(), user.getId(), zoneId);

    String zoneAdminToken =
        IntegrationTestUtils.getAuthorizationCodeToken(
            serverRunning,
            UaaTestAccounts.standard(serverRunning),
            "identity",
            "identitysecret",
            email,
            "secr3T");

    headers.add("Authorization", "bearer " + zoneAdminToken);
    headers.add(IdentityZoneSwitchingFilter.HEADER, zoneId);
    ResponseEntity<List<IdentityProvider>> idpList =
        new RestTemplate()
            .exchange(
                serverRunning.getUrl("/identity-providers"),
                HttpMethod.GET,
                new HttpEntity<>(null, headers),
                new ParameterizedTypeReference<List<IdentityProvider>>() {});

    IdentityProvider identityProvider = idpList.getBody().get(0);
    assertThat(identityProvider.getIdentityZoneId(), is(zoneId));
    assertThat(identityProvider.getOriginKey(), is(Origin.UAA));

    // the default created zone does have a definition, but no policy
    assertNotNull(identityProvider.getConfigValue(UaaIdentityProviderDefinition.class));
    assertNull(
        identityProvider.getConfigValue(UaaIdentityProviderDefinition.class).getPasswordPolicy());
  }

  @Test
  public void testCreateZoneWithClient() throws IOException {
    IdentityZone idZone = new IdentityZone();
    String id = UUID.randomUUID().toString();
    idZone.setId(id);
    idZone.setSubdomain(id);
    idZone.setName("testCreateZone() " + id);
    ResponseEntity<Void> response =
        client.exchange(
            serverRunning.getUrl("/identity-zones"),
            HttpMethod.POST,
            new HttpEntity<>(idZone),
            new ParameterizedTypeReference<Void>() {},
            id);
    assertEquals(HttpStatus.CREATED, response.getStatusCode());

    BaseClientDetails clientDetails =
        new BaseClientDetails("test123", null, "openid", "authorization_code", "uaa.resource");
    clientDetails.setClientSecret("testSecret");
    clientDetails.addAdditionalInformation(
        ClientConstants.ALLOWED_PROVIDERS, Collections.singleton(Origin.UAA));

    ResponseEntity<Void> clientCreateResponse =
        client.exchange(
            serverRunning.getUrl("/identity-zones/" + id + "/clients"),
            HttpMethod.POST,
            new HttpEntity<>(clientDetails),
            new ParameterizedTypeReference<Void>() {},
            id);

    assertEquals(HttpStatus.CREATED, clientCreateResponse.getStatusCode());

    ResponseEntity<Void> clientDeleteResponse =
        client.exchange(
            serverRunning.getUrl(
                "/identity-zones/" + id + "/clients/" + clientDetails.getClientId()),
            HttpMethod.DELETE,
            null,
            new ParameterizedTypeReference<Void>() {},
            id);

    assertEquals(HttpStatus.OK, clientDeleteResponse.getStatusCode());
  }

  @Test
  public void testCreateZoneWithNonUniqueSubdomain() {
    IdentityZone idZone1 = new IdentityZone();
    String id1 = UUID.randomUUID().toString();
    idZone1.setId(id1);
    idZone1.setSubdomain(id1 + "non-unique");
    idZone1.setName("testCreateZone() " + id1);
    ResponseEntity<Void> response1 =
        client.exchange(
            serverRunning.getUrl("/identity-zones"),
            HttpMethod.POST,
            new HttpEntity<>(idZone1),
            new ParameterizedTypeReference<Void>() {},
            id1);
    assertEquals(HttpStatus.CREATED, response1.getStatusCode());

    IdentityZone idZone2 = new IdentityZone();
    String id2 = UUID.randomUUID().toString();
    idZone2.setId(id2);
    idZone2.setSubdomain(id1 + "non-unique");
    idZone2.setName("testCreateZone() " + id2);
    ResponseEntity<Map<String, String>> response2 =
        client.exchange(
            serverRunning.getUrl("/identity-zones"),
            HttpMethod.POST,
            new HttpEntity<>(idZone2),
            new ParameterizedTypeReference<Map<String, String>>() {},
            id2);
    assertEquals(HttpStatus.CONFLICT, response2.getStatusCode());
    Assert.assertTrue(
        response2.getBody().get("error_description").toLowerCase().contains("subdomain"));
  }

  static class IdentityClient extends ClientCredentialsResourceDetails {
    public IdentityClient(Object target) {
      IdentityZoneEndpointsIntegrationTests test = (IdentityZoneEndpointsIntegrationTests) target;
      ClientCredentialsResourceDetails resource =
          test.testAccounts.getClientCredentialsResource(
              new String[] {"zones.write"}, "identity", "identitysecret");
      setClientId(resource.getClientId());
      setClientSecret(resource.getClientSecret());
      setId(getClientId());
      setAccessTokenUri(test.serverRunning.getAccessTokenUri());
    }
  }
}
Esempio n. 7
0
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
@OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
public class AppApprovalIT {

  @Rule public ServerRunning serverRunning = ServerRunning.isRunning();

  UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning);

  @Rule
  public OAuth2ContextSetup context =
      OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts);

  @Rule
  public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts);

  public RestOperations restTemplate;

  @Autowired @Rule public IntegrationTestRule integrationTestRule;

  @Autowired WebDriver webDriver;

  @Value("${integration.test.base_url}")
  String baseUrl;

  @Value("${integration.test.app_url}")
  String appUrl;

  @Before
  @After
  public void logout_and_clear_cookies() {
    restTemplate = serverRunning.getRestTemplate();

    try {
      webDriver.get(baseUrl + "/logout.do");
    } catch (org.openqa.selenium.TimeoutException x) {
      // try again - this should not be happening - 20 second timeouts
      webDriver.get(baseUrl + "/logout.do");
    }
    webDriver.get(appUrl + "/j_spring_security_logout");
    webDriver.manage().deleteAllCookies();
  }

  @Test
  public void testApprovingAnApp() throws Exception {
    ResponseEntity<SearchResults<ScimGroup>> getGroups =
        restTemplate.exchange(
            baseUrl + "/Groups?filter=displayName eq '{displayName}'",
            HttpMethod.GET,
            null,
            new ParameterizedTypeReference<SearchResults<ScimGroup>>() {},
            "cloud_controller.read");
    ScimGroup group = getGroups.getBody().getResources().stream().findFirst().get();

    group.setDescription("Read about your clouds.");
    HttpHeaders headers = new HttpHeaders();
    headers.add("If-Match", Integer.toString(group.getVersion()));
    HttpEntity request = new HttpEntity(group, headers);
    restTemplate.exchange(
        baseUrl + "/Groups/{group-id}", HttpMethod.PUT, request, Object.class, group.getId());

    ScimUser user = createUnapprovedUser();

    // Visit app
    webDriver.get(appUrl);

    // Sign in to login server
    webDriver.findElement(By.name("username")).sendKeys(user.getUserName());
    webDriver.findElement(By.name("password")).sendKeys(user.getPassword());
    webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();

    // Authorize the app for some scopes
    Assert.assertEquals(
        "Application Authorization", webDriver.findElement(By.cssSelector("h1")).getText());

    webDriver
        .findElement(By.xpath("//label[text()='Change your password']/preceding-sibling::input"))
        .click();
    webDriver
        .findElement(
            By.xpath(
                "//label[text()='Read user IDs and retrieve users by ID']/preceding-sibling::input"))
        .click();
    webDriver.findElement(
        By.xpath("//label[text()='Read about your clouds.']/preceding-sibling::input"));

    webDriver.findElement(By.xpath("//button[text()='Authorize']")).click();

    Assert.assertEquals("Sample Home Page", webDriver.findElement(By.cssSelector("h1")).getText());

    // View profile on the login server
    webDriver.get(baseUrl + "/profile");

    Assert.assertFalse(
        webDriver.findElement(By.xpath("//input[@value='app-password.write']")).isSelected());
    Assert.assertFalse(
        webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).isSelected());
    Assert.assertTrue(
        webDriver
            .findElement(By.xpath("//input[@value='app-cloud_controller.read']"))
            .isSelected());
    Assert.assertTrue(
        webDriver
            .findElement(By.xpath("//input[@value='app-cloud_controller.write']"))
            .isSelected());

    // Add approvals
    webDriver.findElement(By.xpath("//input[@value='app-password.write']")).click();
    webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).click();

    webDriver.findElement(By.xpath("//button[text()='Update']")).click();

    Assert.assertTrue(
        webDriver.findElement(By.xpath("//input[@value='app-password.write']")).isSelected());
    Assert.assertTrue(
        webDriver.findElement(By.xpath("//input[@value='app-scim.userids']")).isSelected());
    Assert.assertTrue(
        webDriver
            .findElement(By.xpath("//input[@value='app-cloud_controller.read']"))
            .isSelected());
    Assert.assertTrue(
        webDriver
            .findElement(By.xpath("//input[@value='app-cloud_controller.write']"))
            .isSelected());

    // Revoke app
    webDriver.findElement(By.linkText("Revoke Access")).click();

    Assert.assertEquals(
        "Are you sure you want to revoke access to The Ultimate Oauth App?",
        webDriver.findElement(By.cssSelector(".revocation-modal p")).getText());

    // click cancel
    webDriver.findElement(By.cssSelector("#app-form .revocation-cancel")).click();

    webDriver.findElement(By.linkText("Revoke Access")).click();

    // click confirm
    webDriver.findElement(By.cssSelector("#app-form .revocation-confirm")).click();

    Assert.assertThat(
        webDriver.findElements(By.xpath("//input[@value='app-password.write']")), Matchers.empty());
  }

  @Test
  public void testInvalidAppRedirectDisplaysError() throws Exception {
    ScimUser user = createUnapprovedUser();

    // given we vist the app (specifying an invalid redirect - incorrect protocol https)
    webDriver.get(appUrl + "?redirect_uri=https://localhost:8080/app/");

    // Sign in to login server
    webDriver.findElement(By.name("username")).sendKeys(user.getUserName());
    webDriver.findElement(By.name("password")).sendKeys(user.getPassword());
    webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();

    // Authorize the app for some scopes
    assertThat(
        webDriver.findElement(By.className("alert-error")).getText(),
        RegexMatcher.matchesRegex(
            "^Invalid redirect (.*) did not match one of the registered values"));
  }

  private ScimUser createUnapprovedUser() throws Exception {
    String userName = "******" + new RandomValueStringGenerator().generate();
    String userEmail = userName + "@example.com";

    RestOperations restTemplate = serverRunning.getRestTemplate();

    ScimUser user = new ScimUser();
    user.setUserName(userName);
    user.setPassword("s3Cretsecret");
    user.addEmail(userEmail);
    user.setActive(true);
    user.setVerified(true);

    ResponseEntity<ScimUser> result =
        restTemplate.postForEntity(serverRunning.getUrl("/Users"), user, ScimUser.class);
    assertEquals(HttpStatus.CREATED, result.getStatusCode());

    return user;
  }

  public static class RegexMatcher extends TypeSafeMatcher<String> {

    private final String regex;

    public RegexMatcher(final String regex) {
      this.regex = regex;
    }

    @Override
    public void describeTo(final Description description) {
      description.appendText("matches regex=`" + regex + "`");
    }

    @Override
    public boolean matchesSafely(final String string) {
      return string.matches(regex);
    }

    public static RegexMatcher matchesRegex(final String regex) {
      return new RegexMatcher(regex);
    }
  }
}
/** @author Dave Syer */
public class PasswordChangeEndpointIntegrationTests {

  private final String JOE = "joe_" + 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 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("pas5Word");
    user.setVerified(true);
    return client.postForEntity(serverRunning.getUrl(userEndpoint), user, ScimUser.class);
  }

  @Before
  public void createRestTemplate() throws Exception {
    Assume.assumeTrue(!testAccounts.isProfileActive("vcap"));
    client = serverRunning.getRestTemplate();
    ((RestTemplate) serverRunning.getRestTemplate())
        .setErrorHandler(
            new OAuth2ErrorHandler(context.getResource()) {
              // Pass errors through in response entity for status code analysis
              @Override
              public boolean hasError(ClientHttpResponse response) throws IOException {
                return false;
              }

              @Override
              public void handleError(ClientHttpResponse response) throws IOException {}
            });
  }

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

  // curl -v -H "Content-Type: application/json" -X PUT -H
  // "Accept: application/json" --data
  // "{\"password\":\"newpassword\",\"schemas\":[\"urn:scim:schemas:core:1.0\"]}"
  // http://localhost:8080/uaa/User/{id}/password
  @Test
  @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
  public void testChangePasswordSucceeds() throws Exception {
    PasswordChangeRequest change = new PasswordChangeRequest();
    change.setPassword("Newpasswo3d");

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

  @Test
  @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class)
  public void testChangePasswordSameAsOldFails() {
    PasswordChangeRequest change = new PasswordChangeRequest();
    change.setPassword("pas5Word");

    HttpHeaders headers = new HttpHeaders();
    ResponseEntity<Void> result =
        client.exchange(
            serverRunning.getUrl(userEndpoint) + "/{id}/password",
            HttpMethod.PUT,
            new HttpEntity<>(change, headers),
            Void.class,
            joe.getId());
    assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, 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", "pas5Word");
    context.getAccessTokenRequest().putAll(parameters);

    PasswordChangeRequest change = new PasswordChangeRequest();
    change.setOldPassword("pas5Word");
    change.setPassword("Newpasswo3d");

    HttpHeaders headers = new HttpHeaders();
    ResponseEntity<Void> result =
        client.exchange(
            serverRunning.getUrl(userEndpoint) + "/{id}/password",
            HttpMethod.PUT,
            new HttpEntity<>(change, headers),
            Void.class,
            joe.getId());
    assertEquals(HttpStatus.OK, 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", "pas5Word");
    context.getAccessTokenRequest().putAll(parameters);

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

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

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

    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    headers.set("Authorization", testAccounts.getAuthorizationHeader("app", "appclientsecret"));

    MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>();
    data.put("grant_type", Collections.singletonList("password"));
    data.put("username", Collections.singletonList(joe.getUserName()));
    data.put("password", Collections.singletonList("pas5Word"));

    ResponseEntity<Map> result =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
    assertEquals(HttpStatus.OK, result.getStatusCode());

    // Lock out the account
    data.put("password", Collections.singletonList("randomPassword1"));

    for (int i = 0; i < 5; i++) {
      result =
          serverRunning.postForMap(
              serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
      assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
    }

    // Check that it is locked
    result =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
    assertEquals("Login policy rejected authentication", result.getBody().get("error_description"));
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());

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

    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
    parameters.set("grant_type", "client_credentials");
    parameters.set("username", "admin");
    parameters.set("password", "adminsecret");
    context.getAccessTokenRequest().putAll(parameters);

    // Change the password
    HttpHeaders passwordChangeHeaders = new HttpHeaders();
    ResponseEntity<Void> passwordChangeResult =
        client.exchange(
            serverRunning.getUrl(userEndpoint) + "/{id}/password",
            HttpMethod.PUT,
            new HttpEntity<>(change, passwordChangeHeaders),
            Void.class,
            joe.getId());
    assertEquals(HttpStatus.OK, passwordChangeResult.getStatusCode());

    MultiValueMap<String, String> newData = new LinkedMultiValueMap<String, String>();
    newData.put("grant_type", Collections.singletonList("password"));
    newData.put("username", Collections.singletonList(joe.getUserName()));
    newData.put("password", Collections.singletonList("Newpasswo3d"));

    ResponseEntity<Map> updatedResult =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), newData, headers);
    assertEquals(HttpStatus.OK, updatedResult.getStatusCode());
  }
}
  @Test
  @OAuth2ContextConfiguration(
      resource = OAuth2ContextConfiguration.ClientCredentials.class,
      initialize = false)
  public void testUserAccountGetsUnlockedAfterPasswordChange() throws Exception {

    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    headers.set("Authorization", testAccounts.getAuthorizationHeader("app", "appclientsecret"));

    MultiValueMap<String, String> data = new LinkedMultiValueMap<String, String>();
    data.put("grant_type", Collections.singletonList("password"));
    data.put("username", Collections.singletonList(joe.getUserName()));
    data.put("password", Collections.singletonList("pas5Word"));

    ResponseEntity<Map> result =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
    assertEquals(HttpStatus.OK, result.getStatusCode());

    // Lock out the account
    data.put("password", Collections.singletonList("randomPassword1"));

    for (int i = 0; i < 5; i++) {
      result =
          serverRunning.postForMap(
              serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
      assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());
    }

    // Check that it is locked
    result =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), data, headers);
    assertEquals("Login policy rejected authentication", result.getBody().get("error_description"));
    assertEquals(HttpStatus.UNAUTHORIZED, result.getStatusCode());

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

    MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
    parameters.set("grant_type", "client_credentials");
    parameters.set("username", "admin");
    parameters.set("password", "adminsecret");
    context.getAccessTokenRequest().putAll(parameters);

    // Change the password
    HttpHeaders passwordChangeHeaders = new HttpHeaders();
    ResponseEntity<Void> passwordChangeResult =
        client.exchange(
            serverRunning.getUrl(userEndpoint) + "/{id}/password",
            HttpMethod.PUT,
            new HttpEntity<>(change, passwordChangeHeaders),
            Void.class,
            joe.getId());
    assertEquals(HttpStatus.OK, passwordChangeResult.getStatusCode());

    MultiValueMap<String, String> newData = new LinkedMultiValueMap<String, String>();
    newData.put("grant_type", Collections.singletonList("password"));
    newData.put("username", Collections.singletonList(joe.getUserName()));
    newData.put("password", Collections.singletonList("Newpasswo3d"));

    ResponseEntity<Map> updatedResult =
        serverRunning.postForMap(
            serverRunning.buildUri("/oauth/token").build().toString(), newData, headers);
    assertEquals(HttpStatus.OK, updatedResult.getStatusCode());
  }