private HttpResponse handleAccessTokenUrl(HttpRequest request) throws Exception {
    MessageInfo info = parseMessage(request);
    String requestToken = info.message.getParameter("oauth_token");
    TokenState state = tokenState.get(requestToken);
    if (throttled) {
      return makeOAuthProblemReport(
          OAuthConstants.PROBLEM_CONSUMER_KEY_REFUSED, "exceeded quota", HttpResponse.SC_FORBIDDEN);
    } else if (unauthorized) {
      return makeOAuthProblemReport(
          OAuthConstants.PROBLEM_PERMISSION_DENIED,
          "user refused access",
          HttpResponse.SC_UNAUTHORIZED);
    } else if (state == null) {
      return makeOAuthProblemReport(
          OAuthConstants.PROBLEM_TOKEN_REJECTED,
          "Unknown request token",
          HttpResponse.SC_UNAUTHORIZED);
    }
    if (rejectExtraParams) {
      String extra = hasExtraParams(info.message);
      if (extra != null) {
        return makeOAuthProblemReport(
            OAuthConstants.PROBLEM_PARAMETER_REJECTED, extra, HttpResponse.SC_BAD_REQUEST);
      }
    }

    OAuthAccessor accessor = new OAuthAccessor(oauthConsumer);
    accessor.requestToken = requestToken;
    accessor.tokenSecret = state.tokenSecret;
    validateMessage(accessor, info, true);

    if (state.getState() == State.APPROVED_UNCLAIMED) {
      String sentVerifier = info.message.getParameter("oauth_verifier");
      if (state.verifier != null && !state.verifier.equals(sentVerifier)) {
        return makeOAuthProblemReport(
            OAuthConstants.PROBLEM_BAD_VERIFIER,
            "wrong oauth verifier",
            HttpResponse.SC_UNAUTHORIZED);
      }
      state.claimToken();
    } else if (state.getState() == State.APPROVED) {
      // Verify can refresh
      String sentHandle = info.message.getParameter("oauth_session_handle");
      if (sentHandle == null) {
        return makeOAuthProblemReport(
            OAuthConstants.PROBLEM_PARAMETER_ABSENT,
            "no oauth_session_handle",
            HttpResponse.SC_BAD_REQUEST);
      }
      if (!sentHandle.equals(state.sessionHandle)) {
        return makeOAuthProblemReport(
            OAuthConstants.PROBLEM_TOKEN_INVALID, "token not valid", HttpResponse.SC_UNAUTHORIZED);
      }
      state.renewToken();
    } else if (state.getState() == State.REVOKED) {
      return makeOAuthProblemReport(
          OAuthConstants.PROBLEM_TOKEN_REVOKED,
          "Revoked access token can't be renewed",
          HttpResponse.SC_UNAUTHORIZED);
    } else {
      throw new Exception("Token in weird state " + state.getState());
    }

    String accessToken = Crypto.getRandomString(16);
    String accessTokenSecret = Crypto.getRandomString(16);
    state.tokenSecret = accessTokenSecret;
    tokenState.put(accessToken, state);
    tokenState.remove(requestToken);
    List<OAuth.Parameter> params =
        OAuth.newList(
            "oauth_token", accessToken,
            "oauth_token_secret", accessTokenSecret);
    if (sessionExtension) {
      params.add(new OAuth.Parameter("oauth_session_handle", state.sessionHandle));
      if (reportExpirationTimes) {
        params.add(new OAuth.Parameter("oauth_expires_in", "" + TOKEN_EXPIRATION_SECONDS));
      }
    }
    if (returnAccessTokenData) {
      params.add(new OAuth.Parameter("userid", "userid value"));
      params.add(new OAuth.Parameter("xoauth_stuff", "xoauth_stuff value"));
      params.add(new OAuth.Parameter("oauth_stuff", "oauth_stuff value"));
    }
    return new HttpResponse(OAuth.formEncode(params));
  }