@Test
  public void acceptInvitationWithInvalidRedirectUri() throws Exception {
    ScimUser user = new ScimUser("user-id-001", "*****@*****.**", "first", "last");
    user.setOrigin(UAA);
    BaseClientDetails clientDetails =
        new BaseClientDetails("client-id", null, null, null, null, "http://example.com/redirect");
    when(scimUserProvisioning.verifyUser(anyString(), anyInt())).thenReturn(user);
    when(scimUserProvisioning.update(anyString(), anyObject())).thenReturn(user);
    when(scimUserProvisioning.retrieve(eq("user-id-001"))).thenReturn(user);
    when(clientDetailsService.loadClientByClientId("acmeClientId")).thenReturn(clientDetails);
    Map<String, String> userData = new HashMap<>();
    userData.put(USER_ID, "user-id-001");
    userData.put(EMAIL, "*****@*****.**");
    userData.put(REDIRECT_URI, "http://someother/redirect");
    userData.put(CLIENT_ID, "acmeClientId");
    when(expiringCodeStore.retrieveCode(anyString()))
        .thenReturn(
            new ExpiringCode(
                "code",
                new Timestamp(System.currentTimeMillis()),
                JsonUtils.writeValueAsString(userData)));

    String redirectLocation =
        emailInvitationsService.acceptInvitation("code", "password").getRedirectUri();

    verify(scimUserProvisioning).verifyUser(user.getId(), user.getVersion());
    verify(scimUserProvisioning).changePassword(user.getId(), null, "password");
    assertEquals("/home", redirectLocation);
  }
  @Test
  public void verification_link() throws Exception {
    ScimUser joel = setUpScimUser();

    MockHttpServletRequestBuilder get = setUpVerificationLinkRequest(joel, scimCreateToken);

    MvcResult result = getMockMvc().perform(get).andExpect(status().isOk()).andReturn();

    VerificationResponse verificationResponse =
        JsonUtils.readValue(result.getResponse().getContentAsString(), VerificationResponse.class);
    assertThat(
        verificationResponse.getVerifyLink().toString(),
        startsWith("http://localhost/verify_user"));

    String query = verificationResponse.getVerifyLink().getQuery();

    String code = getQueryStringParam(query, "code");
    assertThat(code, is(notNullValue()));

    ExpiringCode expiringCode = codeStore.retrieveCode(code);
    assertThat(expiringCode.getExpiresAt().getTime(), is(greaterThan(System.currentTimeMillis())));
    assertThat(expiringCode.getIntent(), is(REGISTRATION.name()));
    Map<String, String> data =
        JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {});
    assertThat(data.get(InvitationConstants.USER_ID), is(notNullValue()));
    assertThat(data.get(CLIENT_ID), is(clientDetails.getClientId()));
    assertThat(data.get(REDIRECT_URI), is(HTTP_REDIRECT_EXAMPLE_COM));
  }
  // TODO: add cases for username no existing external user with username not email
  @Test
  public void accept_invitation_with_external_user_that_does_not_have_email_as_their_username() {
    String userId = "user-id-001";
    String email = "*****@*****.**";
    String actualUsername = "******";
    ScimUser userBeforeAccept = new ScimUser(userId, email, "first", "last");
    userBeforeAccept.setPrimaryEmail(email);
    userBeforeAccept.setOrigin(Origin.SAML);

    when(scimUserProvisioning.verifyUser(eq(userId), anyInt())).thenReturn(userBeforeAccept);
    when(scimUserProvisioning.retrieve(eq(userId))).thenReturn(userBeforeAccept);

    BaseClientDetails clientDetails =
        new BaseClientDetails("client-id", null, null, null, null, "http://example.com/redirect");
    when(clientDetailsService.loadClientByClientId("acmeClientId")).thenReturn(clientDetails);

    Map<String, String> userData = new HashMap<>();
    userData.put(USER_ID, userBeforeAccept.getId());
    userData.put(EMAIL, userBeforeAccept.getPrimaryEmail());
    userData.put(REDIRECT_URI, "http://someother/redirect");
    userData.put(CLIENT_ID, "acmeClientId");
    when(expiringCodeStore.retrieveCode(anyString()))
        .thenReturn(
            new ExpiringCode(
                "code",
                new Timestamp(System.currentTimeMillis()),
                JsonUtils.writeValueAsString(userData)));

    ScimUser userAfterAccept =
        new ScimUser(
            userId,
            actualUsername,
            userBeforeAccept.getGivenName(),
            userBeforeAccept.getFamilyName());
    userAfterAccept.setPrimaryEmail(email);

    when(scimUserProvisioning.verifyUser(eq(userId), anyInt())).thenReturn(userAfterAccept);

    ScimUser acceptedUser = emailInvitationsService.acceptInvitation("code", "password").getUser();
    assertEquals(userAfterAccept.getUserName(), acceptedUser.getUserName());
    assertEquals(userAfterAccept.getName(), acceptedUser.getName());
    assertEquals(userAfterAccept.getPrimaryEmail(), acceptedUser.getPrimaryEmail());

    verify(scimUserProvisioning).verifyUser(eq(userId), anyInt());
  }
  @Test
  public void verification_link_in_non_default_zone_using_switch() throws Exception {
    String subdomain = generator.generate().toLowerCase();
    MockMvcUtils.IdentityZoneCreationResult zoneResult =
        utils()
            .createOtherIdentityZoneAndReturnResult(
                subdomain, getMockMvc(), getWebApplicationContext(), null);
    String zonedClientId = "admin";
    String zonedClientSecret = "adminsecret";
    String zonedScimCreateToken =
        utils()
            .getClientCredentialsOAuthAccessToken(
                getMockMvc(), zonedClientId, zonedClientSecret, "uaa.admin", null);

    ScimUser joel = setUpScimUser(zoneResult.getIdentityZone());

    MockHttpServletRequestBuilder get =
        MockMvcRequestBuilders.get("/Users/" + joel.getId() + "/verify-link")
            .header("Host", "localhost")
            .header("Authorization", "Bearer " + zonedScimCreateToken)
            .header(IdentityZoneSwitchingFilter.SUBDOMAIN_HEADER, subdomain)
            .param("redirect_uri", HTTP_REDIRECT_EXAMPLE_COM)
            .accept(APPLICATION_JSON);

    MvcResult result = getMockMvc().perform(get).andExpect(status().isOk()).andReturn();
    VerificationResponse verificationResponse =
        JsonUtils.readValue(result.getResponse().getContentAsString(), VerificationResponse.class);
    assertThat(
        verificationResponse.getVerifyLink().toString(),
        startsWith("http://" + subdomain + ".localhost/verify_user"));

    String query = verificationResponse.getVerifyLink().getQuery();

    String code = getQueryStringParam(query, "code");
    assertThat(code, is(notNullValue()));

    ExpiringCode expiringCode = codeStore.retrieveCode(code);
    assertThat(expiringCode.getExpiresAt().getTime(), is(greaterThan(System.currentTimeMillis())));
    assertThat(expiringCode.getIntent(), is(REGISTRATION.name()));
    Map<String, String> data =
        JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {});
    assertThat(data.get(InvitationConstants.USER_ID), is(notNullValue()));
    assertThat(data.get(CLIENT_ID), is("admin"));
    assertThat(data.get(REDIRECT_URI), is(HTTP_REDIRECT_EXAMPLE_COM));
  }