docs: public ProviderAuthenticationResult handleAuthorizationCode(HttpServletRequest req,
              HttpServletResponse res,
              String authzCode,
              String responseState,
              ConvergedClientConfig clientConfig) {
  
          String clientId = clientConfig.getClientId();
          OidcClientRequest oidcClientRequest = (OidcClientRequest) req.getAttribute(ClientConstants.ATTRIB_OIDC_CLIENT_REQUEST);
          ProviderAuthenticationResult oidcResult = null;
          oidcResult = authenticatorUtil.verifyResponseState(req, res, responseState, clientConfig);
          if (oidcResult != null) {
              return oidcResult; // only if something bad happened, otherwise proceed to exchange auth code for tokens.
          }
          if (!OIDCClientAuthenticatorUtil.checkHttpsRequirement(clientConfig, clientConfig.getTokenEndpointUrl())) {
              Tr.error(tc, "OIDC_CLIENT_URL_PROTOCOL_NOT_HTTPS", clientConfig.getTokenEndpointUrl());
              oidcResult = new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
              return oidcResult;
          }
          String redirect_url = authenticatorUtil.setRedirectUrlIfNotDefined(req, clientConfig);
          if (!OIDCClientAuthenticatorUtil.checkHttpsRequirement(clientConfig, redirect_url)) {
              Tr.error(tc, "OIDC_CLIENT_URL_PROTOCOL_NOT_HTTPS", redirect_url);
              oidcResult = new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
              return oidcResult;
          }
  
          SSLSocketFactory sslSocketFactory = null;
          try {
              sslSocketFactory = getSSLSocketFactory(clientConfig.getTokenEndpointUrl(), clientConfig.getSSLConfigurationName(), clientId);
          } catch (SSLException e) {
              Tr.error(tc, "OIDC_CLIENT_HTTPS_WITH_SSLCONTEXT_NULL", new Object[] { e.getMessage() != null ? e.getMessage() : "invalid ssl context", clientConfig.getClientId() });
              return new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
          }
  
          // go get the tokens and validate them.
          try {
  
              String url = clientConfig.getTokenEndpointUrl();
              if (url == null || url.length() == 0) {
                  throw new MalformedURLException("MalformedURLException");
              }
              HashMap<String, String> tokens = oidcClientUtil.getTokensFromAuthzCode(url,
                      clientId,
                      clientConfig.getClientSecret(),
                      redirect_url,
                      authzCode,
                      clientConfig.getGrantType(),
                      sslSocketFactory,
                      clientConfig.isHostNameVerificationEnabled(),
                      clientConfig.getTokenEndpointAuthMethod(),
                      OIDCClientAuthenticatorUtil.getResources(clientConfig),
                      clientConfig.getTokenRequestParams(),
                      clientConfig.getUseSystemPropertiesForHttpClientConnections());
  
              oidcClientRequest.setTokenType(ClientConstants.TYPE_ID_TOKEN);
  
              // this has a LOT of dependencies.
              oidcResult = jose4jUtil.createResultWithJose4J(responseState, tokens, clientConfig, oidcClientRequest);
  
              //if tokens were valid, go get the userinfo if configured to do so, and update the authentication result to include it.
              UserInfoHelper uih = new UserInfoHelper(clientConfig);
              if (uih.willRetrieveUserInfo()) {
                  OidcTokenImplBase idToken = null;
                  if (oidcResult.getCustomProperties() != null) {
                      idToken = (OidcTokenImplBase) oidcResult.getCustomProperties().get(Constants.ID_TOKEN_OBJECT);
                  }
                  String subjFromIdToken = null;
                  if (idToken != null) {
                      subjFromIdToken = idToken.getSubject();
                  }
                  if (subjFromIdToken != null) {
                      uih.getUserInfo(oidcResult, sslSocketFactory, tokens.get(Constants.ACCESS_TOKEN), subjFromIdToken);
                  }
              }
  
          } catch (BadPostRequestException e) {
              Tr.error(tc, "OIDC_CLIENT_TOKEN_REQUEST_FAILURE", new Object[] { e.getErrorMessage(), clientId, clientConfig.getTokenEndpointUrl() });
              sendErrorJSON(res, e.getStatusCode(), "invalid_request", e.getErrorMessage());
              oidcResult = new ProviderAuthenticationResult(AuthResult.FAILURE, e.getStatusCode());
          } catch (Exception e) {
              Tr.error(tc, "OIDC_CLIENT_TOKEN_REQUEST_FAILURE", new Object[] { e.getLocalizedMessage(), clientId, clientConfig.getTokenEndpointUrl() });
              oidcResult = new ProviderAuthenticationResult(AuthResult.SEND_401, HttpServletResponse.SC_UNAUTHORIZED);
          }
          return oidcResult;
      }