@Override
  protected ModelAndView handleRequestInternal(
      final HttpServletRequest request, final HttpServletResponse response) throws Exception {
    // get CAS ticket
    final String ticket = request.getParameter(OAuthConstants.TICKET);
    log.debug("ticket : {}", ticket);

    ServiceTicket serviceTicket = (ServiceTicket) ticketRegistry.getTicket(ticket);
    TicketGrantingTicket grantingTicket = serviceTicket.getGrantingTicket();
    log.debug("granting ticket : {}", grantingTicket);
    if (grantingTicket == null) return null;

    // retrieve callback url from session
    final HttpSession session = request.getSession();
    String callbackUrl = (String) session.getAttribute(OAuthConstants.OAUTH20_CALLBACKURL);
    log.debug("callbackUrl : {}", callbackUrl);
    session.removeAttribute(OAuthConstants.OAUTH20_CALLBACKURL);
    // and state
    final String state = (String) session.getAttribute(OAuthConstants.OAUTH20_STATE);
    log.debug("state : {}", state);
    session.removeAttribute(OAuthConstants.OAUTH20_STATE);

    if (callbackUrl == null) return null;

    // return callback url with code & state
    callbackUrl = OAuthUtils.addParameter(callbackUrl, OAuthConstants.CODE, ticket);
    if (state != null) {
      callbackUrl = OAuthUtils.addParameter(callbackUrl, OAuthConstants.STATE, state);
    }
    log.debug("callbackUrl : {}", callbackUrl);

    final Map<String, Object> model = new HashMap<String, Object>();
    model.put("callbackUrl", callbackUrl);
    // retrieve service name from session
    final String serviceName = (String) session.getAttribute(OAuthConstants.OAUTH20_SERVICE_NAME);
    log.debug("serviceName : {}", serviceName);
    model.put("serviceName", serviceName);

    model.put("userId", grantingTicket.getAuthentication().getPrincipal().getId());

    return new ModelAndView(OAuthConstants.CONFIRM_VIEW, model);
  }
  @Override
  protected ModelAndView handleRequestInternal(
      final HttpServletRequest request, final HttpServletResponse response) throws Exception {
    final HttpSession session = request.getSession();

    // get cas login service ticket
    final String serviceTicketId = request.getParameter(OAuthConstants.TICKET);
    LOGGER.debug("{} : {}", OAuthConstants.TICKET, serviceTicketId);

    // first time this url is requested the login ticket will be a query parameter
    if (serviceTicketId != null) {
      // create the login ticket granting ticket
      final ServiceTicket serviceTicket = (ServiceTicket) ticketRegistry.getTicket(serviceTicketId);
      // login service ticket should be valid
      if (serviceTicket == null || serviceTicket.isExpired()) {
        LOGGER.error("Service Ticket expired : {}", serviceTicketId);
        return OAuthUtils.writeTextError(
            response, OAuthConstants.INVALID_GRANT, HttpStatus.SC_BAD_REQUEST);
      }
      final TicketGrantingTicket ticketGrantingTicket = serviceTicket.getGrantingTicket();
      // remove login service ticket
      ticketRegistry.deleteTicket(serviceTicket.getId());

      // store the login tgt id in the user's session, used to create service tickets for validation
      // and
      // oauth credentials later in the flow.
      session.setAttribute(OAuthConstants.OAUTH20_LOGIN_TICKET_ID, ticketGrantingTicket.getId());

      // redirect back to self, clears the service ticket from the url, allows the url to be
      // requested multiple
      // times w/o error
      return OAuthUtils.redirectTo(request.getRequestURL().toString());
    }

    // get cas login service ticket from the session
    String ticketGrantingTicketId =
        (String) session.getAttribute(OAuthConstants.OAUTH20_LOGIN_TICKET_ID);
    LOGGER.debug("{} : {}", OAuthConstants.TICKET, ticketGrantingTicketId);
    if (StringUtils.isBlank(ticketGrantingTicketId)) {
      LOGGER.error("Missing Ticket Granting Ticket");
      return OAuthUtils.writeTextError(
          response, OAuthConstants.INVALID_GRANT, HttpStatus.SC_BAD_REQUEST);
    }

    // verify the login ticket granting ticket is still valid
    TicketGrantingTicket ticketGrantingTicket =
        (TicketGrantingTicket) ticketRegistry.getTicket(ticketGrantingTicketId);
    if (ticketGrantingTicket == null || ticketGrantingTicket.isExpired()) {
      LOGGER.error("Ticket Granting Ticket expired : {}", ticketGrantingTicketId);
      return OAuthUtils.writeTextError(
          response, OAuthConstants.INVALID_GRANT, HttpStatus.SC_BAD_REQUEST);
    }

    String callbackUrl =
        request
            .getRequestURL()
            .toString()
            .replace(
                "/" + OAuthConstants.CALLBACK_AUTHORIZE_URL,
                "/" + OAuthConstants.CALLBACK_AUTHORIZE_ACTION_URL);
    LOGGER.debug("{} : {}", OAuthConstants.CALLBACK_AUTHORIZE_ACTION_URL, callbackUrl);

    String allowCallbackUrl =
        OAuthUtils.addParameter(
            callbackUrl,
            OAuthConstants.OAUTH20_APPROVAL_PROMPT_ACTION,
            OAuthConstants.OAUTH20_APPROVAL_PROMPT_ACTION_ALLOW);

    final Map<String, Object> model = new HashMap<>();
    model.put("callbackUrl", callbackUrl);

    final Boolean bypassApprovalPrompt =
        (Boolean) session.getAttribute(OAuthConstants.BYPASS_APPROVAL_PROMPT);
    LOGGER.debug("bypassApprovalPrompt : {}", bypassApprovalPrompt);
    if (bypassApprovalPrompt != null && bypassApprovalPrompt) {
      return OAuthUtils.redirectTo(allowCallbackUrl);
    }

    final String clientId = (String) session.getAttribute(OAuthConstants.OAUTH20_CLIENT_ID);
    LOGGER.debug("{} : {}", OAuthConstants.CLIENT_ID, clientId);

    final Principal loginPrincipal = ticketGrantingTicket.getAuthentication().getPrincipal();

    final String approvalPrompt =
        (String) session.getAttribute(OAuthConstants.OAUTH20_APPROVAL_PROMPT);
    LOGGER.debug("approvalPrompt : {}", approvalPrompt);
    if (StringUtils.isBlank(approvalPrompt)
        || !approvalPrompt.equalsIgnoreCase(OAuthConstants.APPROVAL_PROMPT_FORCE)) {
      final TicketGrantingTicket refreshToken =
          OAuthTokenUtils.getRefreshToken(centralAuthenticationService, clientId, loginPrincipal);
      if (refreshToken != null) {
        return OAuthUtils.redirectTo(allowCallbackUrl);
      }
    }

    // retrieve service name from session
    final String serviceName = (String) session.getAttribute(OAuthConstants.OAUTH20_SERVICE_NAME);
    LOGGER.debug("serviceName : {}", serviceName);
    model.put("serviceName", serviceName);

    return new ModelAndView(OAuthConstants.CONFIRM_VIEW, model);
  }