/**
   * Performs actual authentication.
   *
   * <p>The implementation should do one of the following:
   *
   * <ol>
   *   <li>Return a populated authentication token for the authenticated user, indicating successful
   *       authentication
   *   <li>Return null, indicating that the authentication process is still in progress. Before
   *       returning, the implementation should perform any additional work required to complete the
   *       process.
   *   <li>Throw an <tt>AuthenticationException</tt> if the authentication process fails
   * </ol>
   *
   * @param request from which to extract parameters and perform the authentication
   * @param response the response, which may be needed if the implementation has to do a redirect as
   *     part of a multi-stage authentication process (such as OpenID).
   * @return the authenticated user token, or null if authentication is incomplete.
   * @throws org.springframework.security.core.AuthenticationException if authentication fails.
   */
  @Override
  public Authentication attemptAuthentication(
      HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException, IOException, ServletException {

    String code = null;

    if (LOG.isDebugEnabled()) {
      String url = request.getRequestURI();
      String queryString = request.getQueryString();
      LOG.debug("attemptAuthentication on url {}?{}", url, queryString);
    }

    // request parameters
    final Map<String, String[]> parameters = request.getParameterMap();
    LOG.debug("Got Parameters: {}", parameters);

    // Check to see if there was an error response from the OAuth Provider
    checkForErrors(parameters);

    // Check state parameter to avoid cross-site-scripting attacks
    checkStateParameter(request.getSession(), parameters);

    final String codeValues[] = parameters.get(oAuth2ServiceProperties.getCodeParamName());
    if (codeValues != null && codeValues.length > 0) {
      code = codeValues[0];
      LOG.debug("Got code {}", code);
    }

    OAuth2AuthenticationToken authRequest = new OAuth2AuthenticationToken(code);

    // Allow subclasses to set the "details" property
    setDetails(request, authRequest);
    authRequest.setRedirectUri(oAuth2ServiceProperties.getAbsoluteRedirectUri(request));

    return this.getAuthenticationManager().authenticate(authRequest);
  }
 /**
  * Provided so that subclasses may configure what is put into the authentication request's details
  * property.
  *
  * @param request that an authentication request is being created for
  * @param authRequest the authentication request object that should have its details set
  */
 protected void setDetails(HttpServletRequest request, OAuth2AuthenticationToken authRequest) {
   authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
 }