package org.cloudfoundry.identity.uaa.login; import org.cloudfoundry.identity.uaa.authentication.Origin; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; import org.cloudfoundry.identity.uaa.error.UaaException; import org.cloudfoundry.identity.uaa.user.UaaAuthority; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.http.HttpStatus; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; import java.util.Map; @Controller public class ChangeEmailController { private final ChangeEmailService changeEmailService; public ChangeEmailController(ChangeEmailService changeEmailService) { this.changeEmailService = changeEmailService; } @RequestMapping(value = "/change_email", method = RequestMethod.GET) public String changeEmailPage(Model model, @RequestParam(value = "client_id", required = false) String clientId) { SecurityContext securityContext = SecurityContextHolder.getContext(); model.addAttribute("email", ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getEmail()); model.addAttribute("client_id", clientId); return "change_email"; } @RequestMapping(value = "/change_email.do", method = RequestMethod.POST) public String changeEmail(Model model, @Valid @ModelAttribute("newEmail") ValidEmail newEmail, BindingResult result, @RequestParam("client_id") String clientId, RedirectAttributes redirectAttributes, HttpServletResponse response) { SecurityContext securityContext = SecurityContextHolder.getContext(); if(result.hasErrors()) { model.addAttribute("error_message_code", "invalid_email"); model.addAttribute("email", ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getEmail()); response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value()); return "change_email"; } String origin = ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getOrigin(); if (!origin.equals(Origin.UAA)) { redirectAttributes.addAttribute("error_message_code", "email_change.non-uaa-origin"); return "redirect:profile"; } String userId = ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getId(); String userEmail = ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getName(); try { changeEmailService.beginEmailChange(userId, userEmail, newEmail.getNewEmail(), clientId); } catch (UaaException e) { if (e.getHttpStatus() == 409) { model.addAttribute("error_message_code", "username_exists"); model.addAttribute("email", ((UaaPrincipal)securityContext.getAuthentication().getPrincipal()).getEmail()); response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value()); return "change_email"; } } return "redirect:email_sent?code=email_change"; } @RequestMapping(value = "/verify_email", method = RequestMethod.GET) public String verifyEmail(Model model, @RequestParam("code") String code, RedirectAttributes redirectAttributes, HttpServletResponse httpServletResponse) { Map<String,String> response; try { response = changeEmailService.completeVerification(code); } catch (UaaException e) { if (SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken) { model.addAttribute("error_message_code", "email_change.invalid_code"); httpServletResponse.setStatus(422); return "error"; } else { return "redirect:profile?error_message_code=email_change.invalid_code"; } } UaaPrincipal uaaPrincipal = new UaaPrincipal(response.get("userId"), response.get("username"), response.get("email"), Origin.UAA, null); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, UaaAuthority.USER_AUTHORITIES); SecurityContextHolder.getContext().setAuthentication(token); String redirectLocation = response.get("redirect_url"); if (redirectLocation == null) { redirectLocation = "profile"; redirectAttributes.addAttribute("success_message_code", "email_change.success"); } return "redirect:" + redirectLocation; } public static class ValidEmail { @Email @NotEmpty String newEmail; public String getNewEmail() { return newEmail; } public void setNewEmail(String email) { this.newEmail = email; } } }