package flapjack.controller; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Map; import java.util.UUID; import javax.inject.Inject; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; import flapjack.auth.Role; import flapjack.entity.Person; import flapjack.entity.Session; import flapjack.manager.PersonManager; import flapjack.utils.AppUtils; /** * Controller handling authentication * * @author Ray Vanderborght */ @Path("/auth") public class AuthController { private static final Logger log = LoggerFactory.getLogger(AuthController.class); private static final ObjectMapper mapper = new ObjectMapper(); private static final String PERSONA_VERIFIER_URL = "https://verifier.login.persona.org/verify"; private static final String PERSONA_SUCCESS = "okay"; @Inject private PersonManager personManager; /** * Handle mozilla persona login */ @POST @Path("/login") @Produces(MediaType.APPLICATION_JSON) public Map<String, String> login(@Context HttpServletRequest request, @Context HttpServletResponse response, @FormParam("assertion") String assertion) { try { HttpURLConnection connection = (HttpURLConnection) new URL(PERSONA_VERIFIER_URL).openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); writer.write("assertion=" + URLEncoder.encode(assertion, "UTF-8")); writer.write("&audience=" + request.getServerName()); writer.close(); if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { @SuppressWarnings("unchecked") Map<String, Object> results = mapper.readValue(connection.getInputStream(), Map.class); // persona has authenticated the user if (PERSONA_SUCCESS.equals(results.get("status"))) { String email = (String) results.get("email"); // find user in our system, or trigger creation of new user Person user = personManager.findByEmail(email); if (user == null) { user = new Person(email); user.setRole(Role.USER); personManager.save(user); } String value = user.getId() + ":" + UUID.randomUUID().toString(); Session session = new Session(user, value, new DateTime()); personManager.save(session); Cookie loginCookie = new Cookie(AppUtils.LOGIN_COOKIE_NAME, value); loginCookie.setPath("/"); loginCookie.setMaxAge(Long.valueOf(((Long) results.get("expires")) / 1000).intValue()); response.addCookie(loginCookie); String name = Objects.firstNonNull(user.getName(), ""); return ImmutableMap.of("email", user.getEmail(), "name", name); } } } catch (MalformedURLException e) { log.error("error", e); } catch (IOException e) { log.error("error", e); } return null; } /** * Handle logout */ @POST @Path("/logout") @Produces(MediaType.APPLICATION_JSON) public boolean logout(@Context HttpServletRequest request, @Context HttpServletResponse response) { Cookie loginCookie = AppUtils.findCookie(request.getCookies(), AppUtils.LOGIN_COOKIE_NAME); if (loginCookie != null) { personManager.logout(loginCookie.getValue()); loginCookie.setMaxAge(0); loginCookie.setPath("/"); response.addCookie(loginCookie); return true; } return false; } }