@Test
  public void testAddingAndUpdatingAnApprovalPublishesEvents() throws Exception {
    UaaTestAccounts testAccounts = UaaTestAccounts.standard(null);

    Approval approval =
        new Approval()
            .setUserId(testAccounts.getUserName())
            .setClientId("app")
            .setScope("cloud_controller.read")
            .setExpiresAt(Approval.timeFromNow(1000))
            .setStatus(ApprovalStatus.APPROVED);

    eventPublisher.clearEvents();

    MockAuthentication authentication = new MockAuthentication();
    SecurityContextHolder.getContext().setAuthentication(authentication);

    dao.addApproval(approval);

    Assert.assertEquals(1, eventPublisher.getEventCount());

    ApprovalModifiedEvent addEvent = eventPublisher.getLatestEvent();
    Assert.assertEquals(approval, addEvent.getSource());
    Assert.assertEquals(authentication, addEvent.getAuthentication());
    Assert.assertEquals(
        "{\"scope\":\"cloud_controller.read\",\"status\":\"APPROVED\"}",
        addEvent.getAuditEvent().getData());

    approval.setStatus(DENIED);

    eventPublisher.clearEvents();
    dao.addApproval(approval);

    Assert.assertEquals(1, eventPublisher.getEventCount());

    ApprovalModifiedEvent modifyEvent = eventPublisher.getLatestEvent();
    Assert.assertEquals(approval, modifyEvent.getSource());
    Assert.assertEquals(authentication, modifyEvent.getAuthentication());
    Assert.assertEquals(
        "{\"scope\":\"cloud_controller.read\",\"status\":\"DENIED\"}",
        addEvent.getAuditEvent().getData());
  }
  @Test
  public void testSuccessfulAuthorizationCodeFlow() throws Exception {

    HttpHeaders headers = new HttpHeaders();
    // TODO: should be able to handle just TEXT_HTML
    headers.setAccept(Arrays.asList(MediaType.TEXT_HTML, MediaType.ALL));

    AuthorizationCodeResourceDetails resource = testAccounts.getDefaultAuthorizationCodeResource();

    URI uri =
        serverRunning
            .buildUri("/oauth/authorize")
            .queryParam("response_type", "code")
            .queryParam("state", "mystateid5")
            .queryParam("client_id", resource.getClientId())
            .queryParam("redirect_uri", resource.getPreEstablishedRedirectUri())
            .build();
    ResponseEntity<Void> result = serverRunning.getForResponse(uri.toString(), headers);
    assertEquals(HttpStatus.FOUND, result.getStatusCode());
    String location = result.getHeaders().getLocation().toString();

    if (result.getHeaders().containsKey("Set-Cookie")) {
      String cookie = result.getHeaders().getFirst("Set-Cookie");
      headers.set("Cookie", cookie);
    }

    ResponseEntity<String> response = serverRunning.getForString(location, headers);
    // should be directed to the login screen...
    String body = response.getBody();
    assertTrue(body.contains("/login.do"));
    assertTrue(body.contains("username"));
    assertTrue(body.contains("password"));

    MultiValueMap<String, String> formData = new LinkedMultiValueMap<String, String>();
    formData.add("username", testAccounts.getUserName());
    formData.add("password", testAccounts.getPassword());

    // Should be redirected to the original URL, but now authenticated
    result = serverRunning.postForResponse("/login.do", headers, formData);
    assertEquals(HttpStatus.FOUND, result.getStatusCode());

    if (result.getHeaders().containsKey("Set-Cookie")) {
      String cookie = result.getHeaders().getFirst("Set-Cookie");
      headers.set("Cookie", cookie);
    }

    response = serverRunning.getForString(result.getHeaders().getLocation().toString(), headers);
    if (response.getStatusCode() == HttpStatus.OK) {
      body = response.getBody();
      // The grant access page should be returned
      assertTrue(body.contains("Application Authorization"));
      // Forms should have the right action
      assertTrue(body.matches("(?s).*\\saction=\"\\S*oauth/authorize\".*"));

      formData.clear();
      formData.add("user_oauth_approval", "true");
      result = serverRunning.postForResponse("/oauth/authorize", headers, formData);
      assertEquals(HttpStatus.FOUND, result.getStatusCode());
      location = result.getHeaders().getLocation().toString();
    } else {
      // Token cached so no need for second approval
      assertEquals(HttpStatus.FOUND, response.getStatusCode());
      location = response.getHeaders().getLocation().toString();
    }
    assertTrue(
        "Wrong location: " + location,
        location.matches(resource.getPreEstablishedRedirectUri() + ".*code=.+"));
    assertFalse(
        "Location should not contain cookie: " + location,
        location.matches(resource.getPreEstablishedRedirectUri() + ".*cookie=.+"));

    formData.clear();
    formData.add("client_id", resource.getClientId());
    formData.add("redirect_uri", resource.getPreEstablishedRedirectUri());
    formData.add("grant_type", "authorization_code");
    formData.add("code", location.split("code=")[1].split("&")[0]);
    HttpHeaders tokenHeaders = new HttpHeaders();
    tokenHeaders.set(
        "Authorization",
        testAccounts.getAuthorizationHeader(resource.getClientId(), resource.getClientSecret()));
    @SuppressWarnings("rawtypes")
    ResponseEntity<Map> tokenResponse =
        serverRunning.postForMap("/oauth/token", formData, tokenHeaders);
    assertEquals(HttpStatus.OK, tokenResponse.getStatusCode());
  }