private EmailAccountCreationService initEmailAccountCreationService() { return new EmailAccountCreationService( templateEngine, messageService, codeStore, scimUserProvisioning, clientDetailsService, passwordValidator ); }
@Override public void beginActivation(String email, String password, String clientId, String redirectUri) { passwordValidator.validate(password); String subject = buildSubjectText(); try { ScimUser scimUser = createUser(email, password, OriginKeys.UAA); generateAndSendCode(email, clientId, subject, scimUser.getId(), redirectUri); } catch (ScimResourceAlreadyExistsException e) { List<ScimUser> users = scimUserProvisioning.query("userName eq \""+email+"\" and origin eq \""+ OriginKeys.UAA+"\"", IdentityZoneHolder.get().getId()); try { if (users.size()>0) { if (users.get(0).isVerified()) { throw new UaaException("User already active.", HttpStatus.CONFLICT.value()); } else { generateAndSendCode(email, clientId, subject, users.get(0).getId(), redirectUri); } } } catch (IOException ioe) { ioe.printStackTrace(); } } catch (IOException e) { logger.error("Exception raised while creating account activation email for " + email, e); } }
@Test public void completeActivationWithValidClientRedirect() throws Exception { String zoneId = IdentityZoneHolder.get().getId(); setUpForSuccess("http://example.com/redirect"); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.retrieveCode("the_secret_code", zoneId)).thenReturn(code); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.retrieve(anyString(), eq(zoneId))).thenReturn(user); when(clientDetailsService.loadClientByClientId(anyString(), anyString())).thenReturn(details); AccountCreationService.AccountCreationResponse accountCreation = emailAccountCreationService.completeActivation("the_secret_code"); assertEquals("http://example.com/redirect", accountCreation.getRedirectLocation()); }
@Test public void testBeginActivationWithExistingUser() throws Exception { setUpForSuccess(null); user.setVerified(true); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.query(anyString(), eq(zoneId))).thenReturn(Arrays.asList(new ScimUser[]{user})); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenThrow(new ScimResourceAlreadyExistsException("duplicate")); Assertions.assertThrows(UaaException.class, () -> emailAccountCreationService.beginActivation("user@example.com", "password", "login", null)); }
private String getRedirect(String clientId, String redirectUri) throws IOException { if (clientId != null) { try { ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId, IdentityZoneHolder.get().getId()); Set<String> registeredRedirectUris = clientDetails.getRegisteredRedirectUri() == null ? Collections.emptySet() : clientDetails.getRegisteredRedirectUri(); String signupRedirectUrl = (String) clientDetails.getAdditionalInformation().get(SIGNUP_REDIRECT_URL); String matchingRedirectUri = findMatchingRedirectUri(registeredRedirectUris, redirectUri, Optional.ofNullable(signupRedirectUrl).orElse("home")); if (matchingRedirectUri != null) { return matchingRedirectUri; } } catch (NoSuchClientException nsce) { logger.debug(String.format("Unable to find client with ID:%s for account activation redirect", clientId), nsce); } } return getDefaultRedirect(); }
private void generateAndSendCode(String email, String clientId, String subject, String userId, String redirectUri) throws IOException { ExpiringCode expiringCode = ScimUtils.getExpiringCode(codeStore, userId, email, clientId, redirectUri, REGISTRATION); String htmlContent = getEmailHtml(expiringCode.getCode(), email); messageService.sendMessage(email, MessageType.CREATE_ACCOUNT_CONFIRMATION, subject, htmlContent); }
@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 beginActivation_throwsException_ifPasswordViolatesPolicy() throws Exception { doThrow(new InvalidPasswordException("Oh hell no")).when(passwordValidator).validate(anyString()); Assertions.assertThrows(InvalidPasswordException.class, () -> emailAccountCreationService.beginActivation("user@example.com", "some password", null, null)); verify(passwordValidator).validate("some password"); }
@Test public void completeActivitionWithClientNotFound() throws Exception { setUpForSuccess(""); String zoneId = IdentityZoneHolder.get().getId(); when(codeStore.retrieveCode("the_secret_code", zoneId)).thenReturn(code); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.retrieve(anyString(), eq(zoneId))).thenReturn(user); doThrow(new NoSuchClientException("Client not found")).when(clientDetailsService).loadClientByClientId(anyString(), anyString()); AccountCreationService.AccountCreationResponse accountCreation = emailAccountCreationService.completeActivation("the_secret_code"); assertEquals("home", accountCreation.getRedirectLocation()); }
@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 completeActivation_usesAntPathMatching() throws Exception { setUpForSuccess("http://redirect.uri/"); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.retrieveCode("the_secret_code", zoneId)).thenReturn(code); when(scimUserProvisioning.retrieve(anyString(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); ClientDetails client = mock(ClientDetails.class); when(clientDetailsService.loadClientByClientId(anyString(), anyString())).thenReturn(client); when(client.getRegisteredRedirectUri()).thenReturn(Collections.singleton("http://redirect.uri/*")); AccountCreationService.AccountCreationResponse accountCreation = emailAccountCreationService.completeActivation("the_secret_code"); assertThat(accountCreation.getRedirectLocation(), equalTo("http://redirect.uri/")); }
@Test public void testBeginActivationWithUnverifiedExistingUser() throws Exception { String data = setUpForSuccess("existing-user-id", null); user.setId("existing-user-id"); user.setVerified(false); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenThrow(new ScimResourceAlreadyExistsException("duplicate")); when(scimUserProvisioning.query(anyString(), eq(zoneId))).thenReturn(Arrays.asList(new ScimUser[]{user})); when(codeStore.generateCode(eq(data), any(Timestamp.class), eq(REGISTRATION.name()), anyString())).thenReturn(code); MockHttpServletRequest request = new MockHttpServletRequest(); request.setProtocol("http"); request.setContextPath("/login"); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); emailAccountCreationService.beginActivation("user@example.com", "password", "login", null); verify(messageService).sendMessage( eq("user@example.com"), eq(MessageType.CREATE_ACCOUNT_CONFIRMATION), anyString(), anyString() ); }
@Test public void nonMatchingCodeTypeDisallowsActivation() throws Exception { Timestamp ts = new Timestamp(System.currentTimeMillis() + (60 * 60 * 1000)); Map<String, Object> data = new HashMap<>(); data.put("user_id", "user-id"); data.put("email", "user@example.com"); data.put("client_id", "login"); code = new ExpiringCode("the_secret_code", ts, JsonUtils.writeValueAsString(data), "incorrect-intent-type"); when(codeStore.retrieveCode("the_secret_code", IdentityZoneHolder.get().getId())).thenReturn(code); HttpClientErrorException httpClientErrorException = Assertions.assertThrows(HttpClientErrorException.class, () -> emailAccountCreationService.completeActivation("the_secret_code")); assertThat(httpClientErrorException.getMessage(), containsString("400 BAD_REQUEST")); }
@Test public void testBeginActivationInOtherZone() throws Exception { String redirectUri = "http://login.example.com/redirect/"; String data = setUpForSuccess(redirectUri); IdentityZone zone = MultitenancyFixture.identityZone("test-zone-id", "test"); IdentityZoneHolder.set(zone); MockHttpServletRequest request = new MockHttpServletRequest(); request.setScheme("http"); request.setServerName("test.uaa.example.com"); ServletRequestAttributes attrs = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(attrs); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.generateCode(eq(data), any(Timestamp.class), eq(REGISTRATION.name()), eq(zoneId))).thenReturn(code); emailAccountCreationService.beginActivation("user@example.com", "password", "login", redirectUri); String emailBody = captorEmailBody("Activate your account"); assertThat(emailBody, containsString("A request has been made to activate an account for:")); assertThat(emailBody, containsString("<a href=\"http://test.uaa.example.com/verify_user?code=the_secret_code\">Activate your account</a>")); assertThat(emailBody, containsString("Thank you,<br />\n " + zone.getName())); assertThat(emailBody, not(containsString("Cloud Foundry"))); }
@Test public void testCompleteActivation() throws Exception { setUpForSuccess(""); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.retrieveCode("the_secret_code", zoneId)).thenReturn(code); when(scimUserProvisioning.retrieve(anyString(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); ClientDetails client = mock(ClientDetails.class); when(clientDetailsService.loadClientByClientId(anyString(), anyString())).thenReturn(client); when(client.getRegisteredRedirectUri()).thenReturn(Collections.emptySet()); Map<String, Object> map = new HashMap<>(); map.put(EmailAccountCreationService.SIGNUP_REDIRECT_URL, "http://fallback.url/redirect"); when(client.getAdditionalInformation()).thenReturn(map); AccountCreationService.AccountCreationResponse accountCreation = emailAccountCreationService.completeActivation("the_secret_code"); assertEquals("user@example.com", accountCreation.getUsername()); assertEquals("newly-created-user-id", accountCreation.getUserId()); assertNotNull(accountCreation.getUserId()); }
public void testBeginActivationWithCompanyNameConfigured(String companyName) throws Exception { IdentityZoneConfiguration defaultConfig = IdentityZoneHolder.get().getConfig(); BrandingInformation branding = new BrandingInformation(); branding.setCompanyName(companyName); IdentityZoneConfiguration config = new IdentityZoneConfiguration(); config.setBranding(branding); IdentityZoneHolder.get().setConfig(config); try { emailAccountCreationService = initEmailAccountCreationService(); String data = setUpForSuccess(null); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.generateCode(eq(data), any(Timestamp.class), eq(REGISTRATION.name()), eq(zoneId))).thenReturn(code); emailAccountCreationService.beginActivation("user@example.com", "password", "login", null); String emailBody = captorEmailBody("Activate your " + companyName + " account"); assertThat(emailBody, containsString(companyName + " account")); assertThat(emailBody, containsString("<a href=\"http://uaa.example.com/verify_user?code=the_secret_code\">Activate your account</a>")); } finally { IdentityZoneHolder.get().setConfig(defaultConfig); } }
@Test public void completeActivationWithInvalidClientRedirect() throws Exception { setUpForSuccess("http://redirect_not_found.example.com/"); String zoneId = IdentityZoneHolder.get().getId(); when(scimUserProvisioning.createUser(any(ScimUser.class), anyString(), eq(zoneId))).thenReturn(user); when(codeStore.retrieveCode("the_secret_code", zoneId)).thenReturn(code); when(scimUserProvisioning.verifyUser(anyString(), anyInt(), eq(zoneId))).thenReturn(user); when(scimUserProvisioning.retrieve(anyString(), eq(zoneId))).thenReturn(user); when(clientDetailsService.loadClientByClientId(anyString(), anyString())).thenReturn(details); AccountCreationService.AccountCreationResponse accountCreation = emailAccountCreationService.completeActivation("the_secret_code"); assertEquals("user@example.com", accountCreation.getUsername()); assertEquals("newly-created-user-id", accountCreation.getUserId()); assertEquals("home", accountCreation.getRedirectLocation()); }
@Test public void testCompleteActivationWithExpiredCode() throws Exception { when(codeStore.retrieveCode("expiring_code", IdentityZoneHolder.get().getId())).thenReturn(null); try { emailAccountCreationService.completeActivation("expiring_code"); fail(); } catch (HttpClientErrorException e) { assertThat(e.getStatusCode(), equalTo(BAD_REQUEST)); } }