private ExpiringCode checkIfUserExists(ExpiringCode code) { if (code==null) { logger.debug("reset_password ExpiringCode object is null. Aborting."); return null; } if (!hasText(code.getData())) { logger.debug("reset_password ExpiringCode["+code.getCode()+"] data string is null or empty. Aborting."); return null; } Map<String,String> data = JsonUtils.readValue(code.getData(), new TypeReference<Map<String,String>>() {}); if (!hasText(data.get("user_id"))) { logger.debug("reset_password ExpiringCode["+code.getCode()+"] user_id string is null or empty. Aborting."); return null; } String userId = data.get("user_id"); try { userDatabase.retrieveUserById(userId); } catch (UsernameNotFoundException e) { logger.debug("reset_password ExpiringCode["+code.getCode()+"] user_id is invalid. Aborting."); return null; } return code; }
private String processErrorReload(String code, Model model, String email, HttpServletResponse response, String errorCode, String error) { ExpiringCode expiringCode = expiringCodeStore.retrieveCode(code, IdentityZoneHolder.get().getId()); Map<String, String> codeData = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); try { String newCode = expiringCodeStore.generateCode(expiringCode.getData(), new Timestamp(System.currentTimeMillis() + (10 * 60 * 1000)), expiringCode.getIntent(), IdentityZoneHolder.get().getId()).getCode(); model.addAttribute(errorCode, error); model.addAttribute("code", newCode); return "redirect:accept"; } catch (EmptyResultDataAccessException noProviderFound) { logger.debug(String.format("No available invitation providers for email:%s, id:%s", codeData.get("email"), codeData.get("user_id"))); return handleUnprocessableEntity(model, response, "error_message_code", "no_suitable_idp", "invitations/accept_invite"); } }
private void refreshCode(HttpServletRequest request, ExpiringCode expiringCode) { ExpiringCode newCode = expiringCodeStore.generateCode(expiringCode.getData(), new Timestamp(System.currentTimeMillis() + 1000 * 60 * 10), expiringCode.getIntent(), IdentityZoneHolder.get().getId()); request.setAttribute("code", newCode.getCode()); }
@RequestMapping(value = { "/Codes" }, method = RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) @ResponseBody public ExpiringCode generateCode(@RequestBody ExpiringCode expiringCode) { try { return expiringCodeStore.generateCode(expiringCode.getData(), expiringCode.getExpiresAt(), null, IdentityZoneHolder.get().getId()); } catch (NullPointerException e) { throw new CodeStoreException("data and expiresAt are required.", HttpStatus.BAD_REQUEST); } catch (IllegalArgumentException e) { throw new CodeStoreException("expiresAt must be in the future.", HttpStatus.BAD_REQUEST); } catch (DataIntegrityViolationException e) { throw new CodeStoreException("Duplicate code generated.", HttpStatus.INTERNAL_SERVER_ERROR); } }
@RequestMapping(value = "/reset_password", method = RequestMethod.GET, params = { "code" }) public String resetPasswordPage(Model model, HttpServletResponse response, @RequestParam("code") String code) { ExpiringCode expiringCode = checkIfUserExists(codeStore.retrieveCode(code, IdentityZoneHolder.get().getId())); if (expiringCode==null) { return handleUnprocessableEntity(model, response, "message_code", "bad_code"); } else { PasswordChange passwordChange = JsonUtils.readValue(expiringCode.getData(), PasswordChange.class); String userId = passwordChange.getUserId(); UaaUser uaaUser = userDatabase.retrieveUserById(userId); String newCode = codeStore.generateCode(expiringCode.getData(), new Timestamp(System.currentTimeMillis() + (10 * 60 * 1000)), expiringCode.getIntent(), IdentityZoneHolder.get().getId()).getCode(); model.addAttribute("code", newCode); model.addAttribute("email", uaaUser.getEmail()); model.addAttribute("username", uaaUser.getUsername()); return "reset_password"; } }
if (expiringCode == null || expiringCode.getData() == null) { logger.debug("Failing invitation. Code not found."); SecurityContextHolder.clearContext(); return handleUnprocessableEntity(model, response, "error_message_code", "code_expired", "invitations/accept_invite"); Map<String,String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String,String>>() {}); if (principal == null || data.get("user_id") == null || !data.get("user_id").equals(principal.getId())) { logger.debug("Failing invitation. Code and user ID mismatch."); final String newCode = expiringCodeStore.generateCode(expiringCode.getData(), new Timestamp(System.currentTimeMillis() + (10 * 60 * 1000)), expiringCode.getIntent(), IdentityZoneHolder.get().getId()).getCode(); BrandingInformation zoneBranding = IdentityZoneHolder.get().getConfig().getBranding(); if (zoneBranding != null && zoneBranding.getConsent() != null && !doesUserConsent) {
Map<String, String> codeData = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); String userId = codeData.get("user_id"); String email = codeData.get("email");
@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); }
@RequestMapping(value="/email_changes", method = RequestMethod.POST) public ResponseEntity<EmailChangeResponse> changeEmail(@RequestBody String code) throws IOException { ExpiringCode expiringCode = expiringCodeStore.retrieveCode(code, IdentityZoneHolder.get().getId()); if ((null != expiringCode) && ((null == expiringCode.getIntent()) || EMAIL.name().equals(expiringCode.getIntent()))) { Map<String, String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); String userId = data.get("userId"); String email = data.get("email"); ScimUser user = scimUserProvisioning.retrieve(userId, IdentityZoneHolder.get().getId()); if (user.getUserName().equals(user.getPrimaryEmail())) { user.setUserName(email); } user.setPrimaryEmail(email); scimUserProvisioning.update(userId, user, IdentityZoneHolder.get().getId()); String redirectLocation = null; String clientId = data.get("client_id"); if (clientId != null && !clientId.equals("")) { ClientDetails clientDetails = clientDetailsService.retrieve(clientId, IdentityZoneHolder.get().getId()); redirectLocation = (String) clientDetails.getAdditionalInformation().get(CHANGE_EMAIL_REDIRECT_URL); } publisher.publishEvent(UserModifiedEvent.emailChanged(userId, user.getUserName(), user.getPrimaryEmail())); EmailChangeResponse emailChangeResponse = new EmailChangeResponse(); emailChangeResponse.setEmail(email); emailChangeResponse.setUserId(userId); emailChangeResponse.setUsername(user.getUserName()); emailChangeResponse.setRedirectUrl(redirectLocation); return new ResponseEntity<>(emailChangeResponse, OK); } else { return new ResponseEntity<>(UNPROCESSABLE_ENTITY); } }
@Test public void forgotPassword_ResetCodeIsReturnedSuccessfully() throws Exception { ScimUser user = new ScimUser("user-id-001","exampleUser","firstName","lastName"); user.setPasswordLastModified(new Date(1234)); user.setPrimaryEmail("user@example.com"); String zoneID = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.query(contains("origin"), eq(zoneID))).thenReturn(Arrays.asList(user)); Timestamp expiresAt = new Timestamp(System.currentTimeMillis()); ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); when(codeStore.generateCode(eq("{\"user_id\":\"user-id-001\",\"username\":\"exampleUser\",\"passwordModifiedTime\":1234,\"client_id\":\"example\",\"redirect_uri\":\"redirect.example.com\"}"), any(Timestamp.class), anyString(), anyString())).thenReturn(new ExpiringCode("code", expiresAt, "user-id-001", null)); ForgotPasswordInfo forgotPasswordInfo = uaaResetPasswordService.forgotPassword("exampleUser", "example", "redirect.example.com"); verify(codeStore).expireByIntent(captor.capture(), anyString()); assertEquals(UaaResetPasswordService.FORGOT_PASSWORD_INTENT_PREFIX+user.getId(), captor.getValue()); assertThat(forgotPasswordInfo.getUserId(), equalTo("user-id-001")); assertThat(forgotPasswordInfo.getEmail(), equalTo("user@example.com")); ExpiringCode resetPasswordCode = forgotPasswordInfo.getResetPasswordCode(); assertThat(resetPasswordCode.getCode(), equalTo("code")); assertThat(resetPasswordCode.getExpiresAt(), equalTo(expiresAt)); assertThat(resetPasswordCode.getData(), equalTo("user-id-001")); }
Map<String,String> userData = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); String userId = userData.get(USER_ID); String clientId = userData.get(CLIENT_ID);
@Test public void testGenerateCode() { String data = "{}"; Timestamp expiresAt = new Timestamp(currentTime.get() + 60000); ExpiringCode expiringCode = new ExpiringCode(null, expiresAt, data, null); ExpiringCode result = codeStoreEndpoints.generateCode(expiringCode); assertNotNull(result); assertNotNull(result.getCode()); assertTrue(result.getCode().trim().length() == 10); assertEquals(expiresAt, result.getExpiresAt()); assertEquals(data, result.getData()); }
@Test public void testGenerateCode() throws Exception { String data = "{}"; Timestamp expiresAt = new Timestamp(System.currentTimeMillis() + 60000); ExpiringCode expiringCode = expiringCodeStore.generateCode(data, expiresAt, null, IdentityZoneHolder.get().getId()); Assert.assertNotNull(expiringCode); Assert.assertNotNull(expiringCode.getCode()); Assert.assertTrue(expiringCode.getCode().trim().length() > 0); Assert.assertEquals(expiresAt, expiringCode.getExpiresAt()); Assert.assertEquals(data, expiringCode.getData()); }
assertThat(expiringCode.getExpiresAt().getTime(), is(greaterThan(System.currentTimeMillis()))); assertThat(expiringCode.getIntent(), is(ExpiringCodeType.INVITATION.name())); Map<String, String> data = readValue(expiringCode.getData(), new TypeReference<Map<String, String>>() {}); assertThat(data.get(InvitationConstants.USER_ID), is(notNullValue())); assertThat(data.get(InvitationConstants.EMAIL), is(emails[i]));
@Test void verification_link() throws Exception { ScimUser joel = setUpScimUser(); MockHttpServletRequestBuilder get = setUpVerificationLinkRequest(joel, scimCreateToken); MvcResult result = mockMvc.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, IdentityZoneHolder.get().getId()); 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)); }
@Test public void changePassword_isSuccessful() throws Exception { MockMvcUtils.PredictableGenerator generator = new MockMvcUtils.PredictableGenerator(); JdbcExpiringCodeStore store = getWebApplicationContext().getBean(JdbcExpiringCodeStore.class); store.setGenerator(generator); String code = getExpiringCode(null, null); MockHttpServletRequestBuilder post = post("/password_change") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) .content("{\"code\":\"" + code + "\",\"new_password\":\"new_secr3T\"}") .accept(APPLICATION_JSON); getMockMvc().perform(post) .andExpect(status().isOk()) .andExpect(jsonPath("$.user_id").exists()) .andExpect(jsonPath("$.username").value(user.getUserName())) .andExpect(jsonPath("$.code").value("test" + generator.counter.get())); ExpiringCode expiringCode = store.retrieveCode("test" + generator.counter.get(), IdentityZoneHolder.get().getId()); assertThat(expiringCode.getIntent(), is(ExpiringCodeType.AUTOLOGIN.name())); Map<String,String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String,String>>() {}); assertThat(data.get("user_id"), is(user.getId())); assertThat(data.get("username"), is(user.getUserName())); assertThat(data.get(OAuth2Utils.CLIENT_ID), is("login")); assertThat(data.get(OriginKeys.ORIGIN), is(OriginKeys.UAA)); }
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(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()));
@Test public void changePassword_with_clientid_and_redirecturi() throws Exception { String code = getExpiringCode("app", "redirect.example.com"); String email = user.getUserName(); MockHttpServletRequestBuilder get = get("/reset_password") .param("code", code) .param("email", email); MvcResult result = getMockMvc().perform(get) .andExpect(status().isOk()) .andExpect(content().string(containsString(String.format("<input type=\"hidden\" name=\"email\" value=\"%s\"/>", email)))) .andReturn(); String resultingCodeString = getCodeFromPage(result); ExpiringCodeStore expiringCodeStore = (ExpiringCodeStore) getWebApplicationContext().getBean("codeStore"); ExpiringCode resultingCode = expiringCodeStore.retrieveCode(resultingCodeString, IdentityZoneHolder.get().getId()); Map<String, String> resultingCodeData = JsonUtils.readValue(resultingCode.getData(), new TypeReference<Map<String, String>>() { }); assertEquals("app", resultingCodeData.get("client_id")); assertEquals(email, resultingCodeData.get("username")); assertEquals(user.getId(), resultingCodeData.get("user_id")); assertEquals("redirect.example.com", resultingCodeData.get("redirect_uri")); }
@Test public void changePassword_isSuccessful_withOverridenClientId() throws Exception { MockMvcUtils.PredictableGenerator generator = new MockMvcUtils.PredictableGenerator(); JdbcExpiringCodeStore store = getWebApplicationContext().getBean(JdbcExpiringCodeStore.class); store.setGenerator(generator); String code = getExpiringCode("another-client", null); MockHttpServletRequestBuilder post = post("/password_change") .header("Authorization", "Bearer " + loginToken) .contentType(APPLICATION_JSON) .content("{\"code\":\"" + code + "\",\"new_password\":\"new_secr3T\"}") .accept(APPLICATION_JSON); getMockMvc().perform(post) .andExpect(status().isOk()) .andExpect(jsonPath("$.user_id").exists()) .andExpect(jsonPath("$.username").value(user.getUserName())) .andExpect(jsonPath("$.code").value("test" + generator.counter.get())); ExpiringCode expiringCode = store.retrieveCode("test" + generator.counter.get(), IdentityZoneHolder.get().getId()); Map<String,String> data = JsonUtils.readValue(expiringCode.getData(), new TypeReference<Map<String,String>>() {}); assertThat(data.get(OAuth2Utils.CLIENT_ID), is("another-client")); }