docs: public ProviderAuthenticationResult authenticate(HttpServletRequest req,
              HttpServletResponse res,
              ConvergedClientConfig clientConfig) {
          ProviderAuthenticationResult oidcResult = null;
  
          if (!isEndpointValid(clientConfig)) {
              return new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
          }
          boolean isImplicit = false;
          if (Constants.IMPLICIT.equals(clientConfig.getGrantType())) {
              isImplicit = true;
          }
  
          String authzCode = null;
          String responseState = null;
  
          Hashtable<String, String> reqParameters = new Hashtable<String, String>();
  
          // the code cookie was set earlier by the code that receives the very first redirect back from the provider.
          String encodedReqParams = CookieHelper.getCookieValue(req.getCookies(), ClientConstants.WAS_OIDC_CODE);
          OidcClientUtil.invalidateReferrerURLCookie(req, res, ClientConstants.WAS_OIDC_CODE);
          if (encodedReqParams != null && !encodedReqParams.isEmpty()) {
              boolean validCookie = validateReqParameters(clientConfig, reqParameters, encodedReqParams);
              if (validCookie) {
                  authzCode = reqParameters.get(ClientConstants.CODE);
                  responseState = reqParameters.get(ClientConstants.STATE);
              } else {
                  // error handling
                  oidcResult = new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
                  Tr.error(tc, "OIDC_CLIENT_BAD_PARAM_COOKIE", new Object[] { encodedReqParams, clientConfig.getClientId() }); // CWWKS1745E
                  return oidcResult;
              }
          }
  
          if (responseState != null) {
              // if flow was implicit, we'd have a grant_type of implicit and tokens on the params.
              String id_token = req.getParameter(Constants.ID_TOKEN);
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "id_token:" + id_token);
              }
              if (id_token != null) {
                  reqParameters.put(Constants.ID_TOKEN, id_token);
              }
              String access_token = req.getParameter(Constants.ACCESS_TOKEN);
              if (access_token != null) {
                  reqParameters.put(Constants.ACCESS_TOKEN, access_token);
              }
              if (req.getMethod().equals("POST") && req instanceof IExtendedRequest) {
                  ((IExtendedRequest) req).setMethod("GET");
              }
          }
  
          if (responseState == null) {
              oidcResult = handleRedirectToServer(req, res, clientConfig); // first time through, we go here.
          } else if (isImplicit) {
              oidcResult = handleImplicitFlowTokens(req, res, responseState, clientConfig, reqParameters);
  
          } else {
  
              // confirm the code and go get the tokens if it's good.
  
              AuthorizationCodeHandler authzCodeHandler = new AuthorizationCodeHandler(sslSupport);
  
              oidcResult = authzCodeHandler.handleAuthorizationCode(req, res, authzCode, responseState, clientConfig);
          }
          if (oidcResult.getStatus() != AuthResult.REDIRECT_TO_PROVIDER) {
              // restore post param.
              // Even the status is bad, it's OK to restore, since it will not
              // have any impact
              WebAppSecurityConfig webAppSecConfig = WebAppSecurityCollaboratorImpl.getGlobalWebAppSecurityConfig();
              PostParameterHelper pph = new PostParameterHelper(webAppSecConfig);
              pph.restore(req, res, true);
              OidcClientUtil.invalidateReferrerURLCookies(req, res, OIDC_COOKIES);
          }
  
          return oidcResult;
      }