@Override
  protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
    // If something went wrong, log the error message.
    if (req.getParameter("error") != null) {
      LOG.severe("Something went wrong during auth: " + req.getParameter("error"));
      res.setContentType("text/plain");
      res.getWriter().write("Something went wrong during auth. Please check your log for details");
      return;
    }

    // If we have a code, finish the OAuth 2.0 dance
    if (req.getParameter("code") != null) {
      LOG.info("Got a code. Attempting to exchange for access token.");

      AuthorizationCodeFlow flow = AuthUtil.newAuthorizationCodeFlow();
      TokenResponse tokenResponse =
          flow.newTokenRequest(req.getParameter("code"))
              .setRedirectUri(WebUtil.buildUrl(req, "/oauth2callback"))
              .execute();

      // Extract the Google User ID from the ID token in the auth response
      String userId = ((GoogleTokenResponse) tokenResponse).parseIdToken().getPayload().getUserId();

      LOG.info("Code exchange worked. User " + userId + " logged in.");

      // Set it into the session
      AuthUtil.setUserId(req, userId);
      flow.createAndStoreCredential(tokenResponse, userId);

      // TODO: Store it into ListableMemoryCrednetialStore
      // AuthUtil.storeUserIdCredential(userId, credential);

      // The dance is done. Do our bootstrapping stuff for this user
      Credential credential = AuthUtil.newAuthorizationCodeFlow().loadCredential(userId);

      Contacts.insert(req, userId, credential);
      Subscriber.insert(req, userId, credential);

      // Redirect back to get started
      res.sendRedirect(WebUtil.buildUrl(req, "/get_started.jsp"));

      // TEST - PLEASE DELETE IT
      // MovieInfoCard.insert(req, credential);
      // TicketPurchaseCard.insert(req, credential);
      // DirectionCard.insert(req, credential);

      return;
    }

    // Else, we have a new flow. Initiate a new flow.
    LOG.info("No auth context found. Kicking off a new auth flow.");

    AuthorizationCodeFlow flow = AuthUtil.newAuthorizationCodeFlow();
    GenericUrl url =
        flow.newAuthorizationUrl().setRedirectUri(WebUtil.buildUrl(req, "/oauth2callback"));
    url.set("approval_prompt", "force");
    res.sendRedirect(url.build());
  }
 @Override
 protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
     GenericUrl url = new GenericUrl(req.getRequestURL().toString());
     url.setRawPath("/oauth2callback");
     return url.build();
 }
 static String getRedirectUri(HttpServletRequest req) {
   GenericUrl url = new GenericUrl(req.getRequestURL().toString());
   url.setRawPath("/oauth2callback");
   return url.build();
 }