@Test
  public void testAuthorizationCodeGrant() {

    Authentication userAuthentication =
        new UsernamePasswordAuthenticationToken(
            "marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));

    parameters.clear();
    parameters.put(OAuth2Utils.CLIENT_ID, "foo");
    parameters.put(OAuth2Utils.SCOPE, "scope");
    OAuth2Request storedOAuth2Request =
        RequestTokenFactory.createOAuth2Request(
            parameters, "foo", null, true, Collections.singleton("scope"), null, null, null);

    String code =
        authorizationCodeServices.createAuthorizationCode(
            new OAuth2Authentication(storedOAuth2Request, userAuthentication));
    parameters.putAll(storedOAuth2Request.getRequestParameters());
    parameters.put("code", code);

    TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters);

    AuthorizationCodeTokenGranter granter =
        new AuthorizationCodeTokenGranter(
            providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory);
    OAuth2AccessToken token = granter.grant("authorization_code", tokenRequest);
    assertTrue(providerTokenServices.loadAuthentication(token.getValue()).isAuthenticated());
  }
  // 要不要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;
  }
  public ResourceOwnerPasswordTokenGranterTests() {
    String clientId = "client";
    BaseClientDetails clientDetails = new BaseClientDetails();
    clientDetails.setClientId(clientId);

    providerTokenServices.setTokenStore(new InMemoryTokenStore());
    Map<String, String> parameters = new HashMap<String, String>();
    parameters.put("username", "foo");
    parameters.put("password", "bar");
    parameters.put("client_id", clientId);

    tokenRequest = requestFactory.createTokenRequest(parameters, clientDetails);
  }
  @Test
  public void testAuthorizationRedirectMismatch() {
    Map<String, String> initialParameters = new HashMap<String, String>();
    initialParameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectMe");
    // AuthorizationRequest initialRequest = createFromParameters(initialParameters);
    // we fake a valid resolvedRedirectUri because without the client would never come this far
    // initialRequest.setRedirectUri(initialParameters.get(REDIRECT_URI));

    parameters.clear();
    parameters.put(OAuth2Utils.REDIRECT_URI, "https://redirectMe");
    parameters.put(OAuth2Utils.CLIENT_ID, "foo");
    OAuth2Request storedOAuth2Request =
        RequestTokenFactory.createOAuth2Request(
            parameters, "foo", null, true, null, null, "https://redirectMe", null);

    Authentication userAuthentication =
        new UsernamePasswordAuthenticationToken(
            "marissa", "koala", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
    String code =
        authorizationCodeServices.createAuthorizationCode(
            new OAuth2Authentication(storedOAuth2Request, userAuthentication));

    Map<String, String> authorizationParameters = new HashMap<String, String>();
    authorizationParameters.put("code", code);

    // AuthorizationRequest oAuth2Request = createFromParameters(initialParameters);
    // oAuth2Request.setRequestParameters(authorizationParameters);

    TokenRequest tokenRequest = requestFactory.createTokenRequest(parameters);
    tokenRequest.setRequestParameters(authorizationParameters);

    AuthorizationCodeTokenGranter granter =
        new AuthorizationCodeTokenGranter(
            providerTokenServices, authorizationCodeServices, clientDetailsService, requestFactory);
    try {
      granter.getOAuth2Authentication(client, tokenRequest);
      fail("RedirectMismatchException because of null redirect_uri in authorizationRequest");
    } catch (RedirectMismatchException e) {
    }
  }
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    AuthorizationRequest authRequest =
        authRequestFactory.createAuthorizationRequest(createRequestMap(request.getParameterMap()));

    if (authRequest.getExtensions().get("prompt") != null) {
      // we have a "prompt" parameter
      String prompt = (String) authRequest.getExtensions().get("prompt");

      if (prompt.equals("none")) {
        logger.info("Client requested no prompt");
        // see if the user's logged in
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (auth != null) {
          // user's been logged in already (by session management)
          // we're OK, continue without prompting
          chain.doFilter(req, res);
        } else {
          // user hasn't been logged in, we need to "return an error"
          logger.info("User not logged in, no prompt requested, returning 403 from filter");
          response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied");
          return;
        }
      } else if (prompt.equals("login")) {

        // first see if the user's already been prompted in this session
        HttpSession session = request.getSession();
        if (session.getAttribute(PROMPTED) == null) {
          // user hasn't been PROMPTED yet, we need to check

          session.setAttribute(PROMPT_REQUESTED, Boolean.TRUE);

          // see if the user's logged in
          Authentication auth = SecurityContextHolder.getContext().getAuthentication();
          if (auth != null) {
            // user's been logged in already (by session management)
            // log them out and continue
            SecurityContextHolder.getContext().setAuthentication(null);
            chain.doFilter(req, res);
          } else {
            // user hasn't been logged in yet, we can keep going since we'll get there
            chain.doFilter(req, res);
          }
        } else {
          // user has been PROMPTED, we're fine

          // but first, undo the prompt tag
          session.removeAttribute(PROMPTED);
          chain.doFilter(req, res);
        }
      } else {
        // prompt parameter is a value we don't care about, not our business
        chain.doFilter(req, res);
      }

    } else if (authRequest.getExtensions().get("max_age") != null) {
      String maxAge = (String) authRequest.getExtensions().get("max_age");
      HttpSession session = request.getSession();
      Date authTime = (Date) session.getAttribute(AuthenticationTimeStamper.AUTH_TIMESTAMP);

      Date now = new Date();
      if (authTime != null) {
        Integer max = Integer.parseInt(maxAge);
        long seconds = (now.getTime() - authTime.getTime()) / 1000;
        if (seconds > max) {
          // session is too old, log the user out and continue
          SecurityContextHolder.getContext().setAuthentication(null);
        }
      }

      chain.doFilter(req, res);
    } else {
      // no prompt parameter, not our business
      chain.doFilter(req, res);
    }
  }