/**
   * Basic implementation just requires the authorization request to be explicitly approved and the
   * user to be authenticated.
   *
   * @param authorizationRequest The authorization request.
   * @param userAuthentication the current user authentication
   * @return Whether the specified request has been approved by the current user.
   */
  public boolean isApproved(
      AuthorizationRequest authorizationRequest, Authentication userAuthentication) {

    String flag = authorizationRequest.getApprovalParameters().get(approvalParameter);
    boolean approved = flag != null && flag.toLowerCase().equals("true");

    OAuth2Authentication authentication =
        new OAuth2Authentication(authorizationRequest, userAuthentication);
    if (logger.isDebugEnabled()) {
      StringBuilder builder = new StringBuilder("Looking up existing token for ");
      builder.append("client_id=" + authorizationRequest.getClientId());
      builder.append(", scope=" + authorizationRequest.getScope());
      builder.append(" and username="******"Existing access token=" + accessToken);
    if (accessToken != null && !accessToken.isExpired()) {
      logger.debug("User already approved with token=" + accessToken);
      // A token was already granted and is still valid, so this is already approved
      approved = true;
    } else {
      logger.debug("Checking explicit approval");
      approved = userAuthentication.isAuthenticated() && approved;
    }

    return approved;
  }
  // 要不要PreApproval??
  @Override
  public AuthorizationRequest checkForPreApproval(
      AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
    boolean approved = false;
    String clientId = authorizationRequest.getClientId();
    Set<String> scopes = authorizationRequest.getScope();

    OAuth2Request storedOAuth2Request = requestFactory.createOAuth2Request(authorizationRequest);

    OAuth2Authentication authentication =
        new OAuth2Authentication(storedOAuth2Request, userAuthentication);
    if (logger.isDebugEnabled()) {
      StringBuilder builder = new StringBuilder("Looking up existing token for ");
      builder.append("client_id=" + clientId);
      builder.append(", scope=" + scopes);
      builder.append(" and username="******"Existing access token=" + accessToken);
    if (accessToken != null && !accessToken.isExpired()) {
      logger.debug("User already approved with token=" + accessToken);
      approved = true;
    } else {
      logger.debug("Checking explicit approval");
      approved = userAuthentication.isAuthenticated() && approved;
    }

    authorizationRequest.setApproved(approved);
    return authorizationRequest;
  }
  @Test
  public void testOauthClient() throws Exception {
    AuthorizationRequest request = new AuthorizationRequest("foo", Collections.singleton("read"));
    request.setResourceIdsAndAuthoritiesFromClientDetails(
        new BaseClientDetails("foo", "", "", "client_credentials", "ROLE_CLIENT"));
    Authentication userAuthentication = null;

    OAuth2Request clientAuthentication =
        RequestTokenFactory.createOAuth2Request(
            request.getRequestParameters(),
            request.getClientId(),
            request.getAuthorities(),
            request.isApproved(),
            request.getScope(),
            request.getResourceIds(),
            request.getRedirectUri(),
            request.getResponseTypes(),
            request.getExtensions());

    OAuth2Authentication oAuth2Authentication =
        new OAuth2Authentication(clientAuthentication, userAuthentication);
    MethodInvocation invocation =
        new SimpleMethodInvocation(this, ReflectionUtils.findMethod(getClass(), "testOauthClient"));
    EvaluationContext context = handler.createEvaluationContext(oAuth2Authentication, invocation);
    Expression expression =
        handler.getExpressionParser().parseExpression("#oauth2.clientHasAnyRole('ROLE_CLIENT')");
    assertTrue((Boolean) expression.getValue(context));
  }
  /**
   * Basic access confirmation controller for OAuth2
   *
   * @param model Model objects to be passed to the view
   * @param principal The principal user making the auth request
   * @return A ModelAndView for the access_confirmation page
   */
  @RequestMapping("/api/oauth/confirm_access")
  public ModelAndView getAccessConfirmation(Map<String, Object> model, Principal principal) {
    // get the authorization request from the model
    AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest");

    logger.trace(
        "Token request recieved from " + clientAuth.getClientId() + " for " + principal.getName());
    // get a list of the scopes from the request
    Set<String> scopes = clientAuth.getScope();
    String join = Joiner.on(" & ").join(scopes);

    // add necessary information to the model
    model.put("auth_request", clientAuth);
    model.put("scopes", join);
    model.put("principal", principal);

    return new ModelAndView("oauth/access_confirmation", model);
  }
  public OAuth2AccessToken refreshAccessToken(
      String refreshTokenValue, AuthorizationRequest request) throws AuthenticationException {

    if (!supportRefreshToken) {
      throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
    }

    OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue);
    if (refreshToken == null) {
      throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue);
    }

    OAuth2Authentication authentication =
        tokenStore.readAuthenticationForRefreshToken(refreshToken);
    String clientId = authentication.getOAuth2Request().getClientId();
    if (clientId == null || !clientId.equals(request.getClientId())) {
      throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue);
    }

    // clear out any access tokens already associated with the refresh
    // token.
    tokenStore.removeAccessTokenUsingRefreshToken(refreshToken);

    if (isExpired(refreshToken)) {
      tokenStore.removeRefreshToken(refreshToken);
      throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken);
    }

    authentication = createRefreshedAuthentication(authentication, request.getScope());

    if (!reuseRefreshToken) {
      tokenStore.removeRefreshToken(refreshToken);
      refreshToken = createRefreshToken(authentication);
    }

    OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
    tokenStore.storeAccessToken(accessToken, authentication);
    if (!reuseRefreshToken) {
      tokenStore.storeRefreshToken(refreshToken, authentication);
    }
    return accessToken;
  }