@Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
    initMocks(MOCK_USER_INFO_URI, MOCK_USER_INFO_RESPONSE);

    defaultOAuth2UserInfoProvider.setClient(client);
    given(oAuth2ServiceProperties.getUserInfoUri()).willReturn(MOCK_USER_INFO_URI);
    given(oAuth2ServiceProperties.getAccessTokenName()).willReturn("access_token");
  }
 /** Check properties are set */
 @Override
 public void afterPropertiesSet() {
   super.afterPropertiesSet();
   Assert.notNull(oAuth2ServiceProperties);
   Assert.isTrue(
       oAuth2ServiceProperties.getRedirectUri().endsWith(super.getFilterProcessesUrl()),
       "The filter must be configured to be listening on the redirect_uri in OAuth2ServiceProperties");
 }
  @Test
  public void shouldIncludeOptionalInfoParams() {
    Map<String, String> additionalInfoParams =
        Collections.singletonMap("extra_param", "param_value");
    given(oAuth2ServiceProperties.getAdditionalInfoParams()).willReturn(additionalInfoParams);

    Map<String, Object> userInfo = defaultOAuth2UserInfoProvider.getUserInfoFromProvider(token);
    assertThat(userInfo, notNullValue());
    verify(webTarget).queryParam("extra_param", "param_value");
  }
  /**
   * Check the state parameter to ensure it is the same as was originally sent. Subclasses can
   * override this behaviour if they so choose, but it is not recommended.
   *
   * @param session The http session, which will contain the original scope as an attribute.
   * @param parameters The parameters received from the OAuth 2 Provider, which should contain the
   *     same state as originally sent to it and stored in the http session.
   * @throws AuthenticationException If the state differs from the original.
   */
  protected void checkStateParameter(HttpSession session, Map<String, String[]> parameters)
      throws AuthenticationException {

    String originalState =
        (String) session.getAttribute(oAuth2ServiceProperties.getStateParamName());
    String receivedStates[] = parameters.get(oAuth2ServiceProperties.getStateParamName());

    // There should only be one entry in the array, if there are more they will be ignored.
    if (receivedStates == null
        || receivedStates.length == 0
        || !receivedStates[0].equals(originalState)) {
      String errorMsg =
          String.format(
              "Received states %s was not equal to original state %s",
              receivedStates, originalState);
      LOG.error(errorMsg);
      throw new AuthenticationServiceException(errorMsg);
    }
  }
  /**
   * 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);
  }