private ExpiringCode getCode(String id, String username, String clientId) { Map<String, String> codeData = new HashMap<>(); codeData.put("user_id", id); codeData.put("username", username); codeData.put(OAuth2Utils.CLIENT_ID, clientId); codeData.put(OriginKeys.ORIGIN, OriginKeys.UAA); return codeStore.generateCode(JsonUtils.writeValueAsString(codeData), new Timestamp(System.currentTimeMillis() + 5 * 60 * 1000), ExpiringCodeType.AUTOLOGIN.name(), IdentityZoneHolder.get().getId()); }
private String generateExpiringCode(String userId, String newEmail, String clientId, String redirectUri) { Map<String, String> codeData = new HashMap<>(); codeData.put("user_id", userId); codeData.put("client_id", clientId); codeData.put("redirect_uri", redirectUri); codeData.put("email", newEmail); return codeStore.generateCode(JsonUtils.writeValueAsString(codeData), new Timestamp(System.currentTimeMillis() + EMAIL_CHANGE_LIFETIME), EMAIL.name(), IdentityZoneHolder.get().getId()).getCode(); }
private ExpiringCode createCode(Map<String, String> codeData) { return new ExpiringCode("code", new Timestamp(System.currentTimeMillis()), JsonUtils.writeValueAsString(codeData), INVITATION.name()); }
@Test(expected = BadCredentialsException.class) public void authentication_fails_withInvalidClient() { Map<String,String> codeData = new HashMap<>(); codeData.put("user_id", "test-user-id"); codeData.put("client_id", "actual-client-id"); codeData.put("username", "test-username"); codeData.put(OriginKeys.ORIGIN, OriginKeys.UAA); codeData.put("action", ExpiringCodeType.AUTOLOGIN.name()); when(codeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())).thenReturn(new ExpiringCode("the_secret_code", new Timestamp(123), JsonUtils.writeValueAsString(codeData), null)); manager.authenticate(authenticationToken); }
@RequestMapping(value="/email_verifications", method = RequestMethod.POST) public ResponseEntity<String> generateEmailVerificationCode(@RequestBody EmailChange emailChange) { String userId = emailChange.getUserId(); String email = emailChange.getEmail(); ScimUser user = scimUserProvisioning.retrieve(userId, IdentityZoneHolder.get().getId()); if (user.getUserName().equals(user.getPrimaryEmail())) { List<ScimUser> results = scimUserProvisioning.query("userName eq \"" + email + "\" and origin eq \"" + OriginKeys.UAA + "\"", IdentityZoneHolder.get().getId()); if (!results.isEmpty()) { return new ResponseEntity<>(CONFLICT); } } String code; try { code = expiringCodeStore.generateCode(JsonUtils.writeValueAsString(emailChange), new Timestamp(System.currentTimeMillis() + EMAIL_CHANGE_LIFETIME), EMAIL.name(), IdentityZoneHolder.get().getId()).getCode(); } catch (JsonUtils.JsonUtilException e) { throw new UaaException("Error while generating change email code", e); } return new ResponseEntity<>(code, CREATED); }
@Test(expected = BadCredentialsException.class) public void authentication_fails_withNoClientId() { Map<String,String> codeData = new HashMap<>(); codeData.put("user_id", "test-user-id"); codeData.put("username", "test-username"); codeData.put(OriginKeys.ORIGIN, OriginKeys.UAA); codeData.put("action", ExpiringCodeType.AUTOLOGIN.name()); when(codeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())).thenReturn(new ExpiringCode("the_secret_code", new Timestamp(123), JsonUtils.writeValueAsString(codeData), null)); manager.authenticate(authenticationToken); }
@Test public void acceptInvitation_onlyMarksInternalUsersAsVerified() { ScimUser user = new ScimUser("ldap-user-id", "ldapuser", "Charlie", "Brown"); user.setOrigin(LDAP); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.retrieve(eq("ldap-user-id"), eq(zoneId))).thenReturn(user); Map<String, String> userData = new HashMap<>(); userData.put(USER_ID, "ldap-user-id"); userData.put(EMAIL, "ldapuser"); when(expiringCodeStore.retrieveCode(anyString(), eq(zoneId))).thenReturn(new ExpiringCode("code", new Timestamp(System.currentTimeMillis()), JsonUtils.writeValueAsString(userData), INVITATION.name())); emailInvitationsService.acceptInvitation("code", "").getRedirectUri(); verify(scimUserProvisioning, never()).verifyUser(anyString(), anyInt(), anyString()); }
@Test public void acceptInvitation_withoutPasswordUpdate() throws Exception { ScimUser user = new ScimUser("user-id-001", "user@example.com", "first", "last"); user.setOrigin(UAA); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.retrieve(eq("user-id-001"), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); Map<String,String> userData = new HashMap<>(); userData.put(USER_ID, "user-id-001"); userData.put(EMAIL, "user@example.com"); when(expiringCodeStore.retrieveCode(anyString(), eq(zoneId))).thenReturn(new ExpiringCode("code", new Timestamp(System.currentTimeMillis()), JsonUtils.writeValueAsString(userData), INVITATION.name())); emailInvitationsService.acceptInvitation("code", "").getRedirectUri(); verify(scimUserProvisioning).verifyUser(user.getId(), user.getVersion(), zoneId); verify(scimUserProvisioning, never()).changePassword(anyString(), anyString(), anyString(), eq(zoneId)); }
@Test public void testBeginActivation() throws Exception { String redirectUri = ""; String data = setUpForSuccess(redirectUri); String zoneId = "BeginActivationZone"; identityZone.setId(zoneId); identityZone.setSubdomain("uaa"); IdentityZoneHolder.set(identityZone); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.generateCode(eq(data), any(Timestamp.class), eq(REGISTRATION.name()), anyString())).thenReturn(code); emailAccountCreationService.beginActivation("user@example.com", "password", "login", redirectUri); String emailBody = captorEmailBody("Activate your account"); assertThat(emailBody, containsString("an account")); assertThat(emailBody, containsString("<a href=\"http://uaa.example.com/verify_user?code=the_secret_code\">Activate your account</a>")); }
@Test public void acceptInvitationNoClientId() throws Exception { ScimUser user = new ScimUser("user-id-001", "user@example.com", "first", "last"); user.setOrigin(UAA); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.retrieve(eq("user-id-001"), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.update(anyString(), any(), eq(zoneId))).thenReturn(user); Map<String,String> userData = new HashMap<>(); userData.put(USER_ID, "user-id-001"); userData.put(EMAIL, "user@example.com"); when(expiringCodeStore.retrieveCode(anyString(), eq(zoneId))).thenReturn(new ExpiringCode("code", new Timestamp(System.currentTimeMillis()), JsonUtils.writeValueAsString(userData), INVITATION.name())); String redirectLocation = emailInvitationsService.acceptInvitation("code", "password").getRedirectUri(); verify(scimUserProvisioning).verifyUser(user.getId(), user.getVersion(), zoneId); verify(scimUserProvisioning).changePassword(user.getId(), null, "password", zoneId); assertEquals("/home", redirectLocation); }
@Override public AccountCreationResponse completeActivation(String code) throws IOException { ExpiringCode expiringCode = codeStore.retrieveCode(code, IdentityZoneHolder.get().getId()); if ((null == expiringCode) || ((null != expiringCode.getIntent()) && !REGISTRATION.name().equals(expiringCode.getIntent()))) { throw new HttpClientErrorException(BAD_REQUEST); } Map<String, String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); ScimUser user = scimUserProvisioning.retrieve(data.get("user_id"), IdentityZoneHolder.get().getId()); user = scimUserProvisioning.verifyUser(user.getId(), user.getVersion(), IdentityZoneHolder.get().getId()); String clientId = data.get("client_id"); String redirectUri = data.get("redirect_uri") != null ? data.get("redirect_uri") : ""; String redirectLocation = getRedirect(clientId, redirectUri); return new AccountCreationResponse(user.getId(), user.getUserName(), user.getUserName(), redirectLocation); }
@Test public void acceptInvitationWithClientNotFound() throws Exception { ScimUser user = new ScimUser("user-id-001", "user@example.com", "first", "last"); user.setOrigin(OriginKeys.UAA); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.update(anyString(), any(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.retrieve(eq("user-id-001"), eq(zoneId))).thenReturn(user); doThrow(new NoSuchClientException("Client not found")).when(clientDetailsService).loadClientByClientId("client-not-found"); Map<String,String> userData = new HashMap<>(); userData.put(USER_ID, "user-id-001"); userData.put(EMAIL, "user@example.com"); userData.put(CLIENT_ID, "client-not-found"); when(expiringCodeStore.retrieveCode(anyString(), eq(zoneId))).thenReturn(new ExpiringCode("code", new Timestamp(System.currentTimeMillis()), JsonUtils.writeValueAsString(userData), INVITATION.name())); String redirectLocation = emailInvitationsService.acceptInvitation("code", "password").getRedirectUri(); verify(scimUserProvisioning).verifyUser(user.getId(), user.getVersion(), zoneId); verify(scimUserProvisioning).changePassword(user.getId(), null, "password", zoneId); assertEquals("/home", redirectLocation); }
@Test public void testAcceptInvite_doesNotDisplayConsentCheckboxWhenNotConfiguredForZone() throws Exception { IdentityProvider identityProvider = new IdentityProvider(); identityProvider.setType(OriginKeys.UAA); when(providerProvisioning.retrieveByOrigin(anyString(), anyString())).thenReturn(identityProvider); Map<String,String> codeData = getInvitationsCode(OriginKeys.UAA); String codeDataString = JsonUtils.writeValueAsString(codeData); ExpiringCode expiringCode = new ExpiringCode("thecode", new Timestamp(1), codeDataString, INVITATION.name()); when(expiringCodeStore.retrieveCode("thecode", IdentityZoneHolder.get().getId())) .thenReturn(expiringCode, null); when(expiringCodeStore.generateCode(anyString(), any(), eq(INVITATION.name()), eq(IdentityZoneHolder.get().getId()))) .thenReturn(expiringCode); mockMvc.perform(get("/invitations/accept") .param("code", "thecode")) .andExpect(content().string(not(containsString("I agree")))); }
@Test public void invalidCodeOnAcceptPost() throws Exception { UaaPrincipal uaaPrincipal = new UaaPrincipal("user-id-001", "user@example.com", "user@example.com", OriginKeys.UAA, null,IdentityZoneHolder.get().getId()); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, UaaAuthority.USER_AUTHORITIES); SecurityContextHolder.getContext().setAuthentication(token); Map<String,String> codeData = getInvitationsCode(OriginKeys.UAA); String codeDataString = JsonUtils.writeValueAsString(codeData); when(expiringCodeStore.retrieveCode("thecode", IdentityZoneHolder.get().getId())).thenReturn(new ExpiringCode("thecode", new Timestamp(1), codeDataString, INVITATION.name()), null); when(expiringCodeStore.generateCode(eq(codeDataString), any(), eq(INVITATION.name()), eq(IdentityZoneHolder.get().getId()))).thenReturn(new ExpiringCode("thenewcode", new Timestamp(1), codeDataString, INVITATION.name())); doThrow(new HttpClientErrorException(BAD_REQUEST)).when(invitationsService).acceptInvitation(anyString(), anyString()); MockHttpServletRequestBuilder post = post("/invitations/accept.do") .param("code","thecode") .param("password", "password") .param("password_confirmation", "password"); mockMvc.perform(post) .andExpect(status().isUnprocessableEntity()) .andExpect(model().attribute("error_message_code", "code_expired")) .andExpect(view().name("invitations/accept_invite")); }
@Test public void testGenerateEmailChangeCode() throws Exception { String data = "{\"userId\":\"user-id-001\",\"email\":\"new@example.com\",\"client_id\":null}"; when(expiringCodeStore.generateCode(eq(data), any(Timestamp.class), eq(EMAIL.name()), eq(IdentityZoneHolder.get().getId()))) .thenReturn(new ExpiringCode("secret_code", new Timestamp(System.currentTimeMillis() + 1000), data, EMAIL.name())); ScimUser userChangingEmail = new ScimUser("user-id-001", "user@example.com", null, null); userChangingEmail.setOrigin("test"); userChangingEmail.setPrimaryEmail("user@example.com"); when(scimUserProvisioning.retrieve("user-id-001", IdentityZoneHolder.get().getId())).thenReturn(userChangingEmail); MockHttpServletRequestBuilder post = post("/email_verifications") .contentType(APPLICATION_JSON) .content(data) .accept(APPLICATION_JSON); mockMvc.perform(post) .andExpect(status().isCreated()) .andExpect(content().string("secret_code")); }
@Test public void invalid_principal_id() throws Exception { MockHttpServletRequestBuilder post = startAcceptInviteFlow("a", "a"); Map<String,String> codeData = getInvitationsCode(OriginKeys.UAA); codeData.put("user_id", "invalid id"); String codeDataString = JsonUtils.writeValueAsString(codeData); when(expiringCodeStore.retrieveCode("thecode", IdentityZoneHolder.get().getId())).thenReturn(new ExpiringCode("thecode", new Timestamp(1), codeDataString, INVITATION.name()), null); IdentityProvider identityProvider = new IdentityProvider(); identityProvider.setType(OriginKeys.UAA); when(providerProvisioning.retrieveByOrigin("uaa", "uaa")).thenReturn(identityProvider); mockMvc.perform(post) .andExpect(status().isUnprocessableEntity()) .andExpect(model().attribute("error_message_code", "code_expired")) .andExpect(view().name("invitations/accept_invite")); verify(expiringCodeStore).retrieveCode("thecode", IdentityZoneHolder.get().getId()); verify(expiringCodeStore, never()).generateCode(anyString(), any(), anyString(), eq(IdentityZoneHolder.get().getId())); verify(invitationsService, never()).acceptInvitation(anyString(), anyString()); }
@Test public void testChangeEmailWhenUsernameNotTheSame() throws Exception { when(expiringCodeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())) .thenReturn(new ExpiringCode("the_secret_code", new Timestamp(System.currentTimeMillis()), "{\"userId\":\"user-id-001\",\"email\":\"new@example.com\",\"client_id\":null}", EMAIL.name())); ScimUser scimUser = new ScimUser(); scimUser.setUserName("username"); scimUser.setPrimaryEmail("user@example.com"); when(scimUserProvisioning.retrieve("user-id-001", IdentityZoneHolder.get().getId())).thenReturn(scimUser); mockMvc.perform(post("/email_changes") .contentType(APPLICATION_JSON) .content("the_secret_code") .accept(APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.status().isOk()); ArgumentCaptor<ScimUser> user = ArgumentCaptor.forClass(ScimUser.class); verify(scimUserProvisioning).update(eq("user-id-001"), user.capture(), eq(IdentityZoneHolder.get().getId())); Assert.assertEquals("new@example.com", user.getValue().getPrimaryEmail()); Assert.assertEquals("username", user.getValue().getUserName()); }
@Test public void acceptInvitePage_for_unverifiedOIDCUser() throws Exception { Map<String,String> codeData = getInvitationsCode("test-oidc"); when(expiringCodeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())).thenReturn(createCode(codeData)); when(expiringCodeStore.generateCode(anyString(), any(), eq(INVITATION.name()), eq(IdentityZoneHolder.get().getId()))).thenReturn(createCode(codeData)); OIDCIdentityProviderDefinition definition = new OIDCIdentityProviderDefinition(); definition.setAuthUrl(new URL("https://oidc10.auth.url")); IdentityProvider provider = new IdentityProvider(); provider.setConfig(definition); provider.setType(OriginKeys.OIDC10); when(providerProvisioning.retrieveByOrigin(eq("test-oidc"), anyString())).thenReturn(provider); MockHttpServletRequestBuilder get = get("/invitations/accept") .param("code", "the_secret_code"); MvcResult result = mockMvc.perform(get) .andExpect(redirectedUrl("https://oidc10.auth.url?client_id=" + definition.getRelyingPartyId() + "&response_type=code&redirect_uri=http://null/login/callback/" + provider.getOriginKey())) .andReturn(); assertEquals(true, result.getRequest().getSession().getAttribute("IS_INVITE_ACCEPTANCE")); assertEquals("user-id-001", result.getRequest().getSession().getAttribute("user_id")); }
@Test public void acceptInvitePage_for_unverifiedLdapUser() throws Exception { Map<String, String> codeData = getInvitationsCode(LDAP); when(expiringCodeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())).thenReturn(createCode(codeData)); when(expiringCodeStore.generateCode(anyString(), any(), eq(INVITATION.name()), eq(IdentityZoneHolder.get().getId()))).thenReturn(createCode(codeData)); IdentityProvider provider = new IdentityProvider(); provider.setType(LDAP); when(providerProvisioning.retrieveByOrigin(eq(LDAP), anyString())).thenReturn(provider); MockHttpServletRequestBuilder get = get("/invitations/accept") .param("code", "the_secret_code"); mockMvc.perform(get) .andExpect(view().name("invitations/accept_invite")) .andExpect(status().isOk()) .andExpect(content().string(containsString("Email: " + "user@example.com"))) .andExpect(content().string(containsString("Sign in with enterprise credentials:"))) .andExpect(content().string(containsString("username"))) .andExpect(model().attribute("code", "code")) .andReturn(); }