Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Credential fetching exceptions aren't being handled #474

Closed
tscni opened this issue Jun 19, 2023 · 3 comments
Closed

Credential fetching exceptions aren't being handled #474

tscni opened this issue Jun 19, 2023 · 3 comments
Assignees
Labels
needs more info This issue needs more information from the customer to proceed. priority: p3 Desirable enhancement or fix. May not be included in next release.

Comments

@tscni
Copy link

tscni commented Jun 19, 2023

Package name and version: google/gax:1.20.2, google/auth:1.28.0

In CredentialsWrapper, exceptions thrown from google/auth aren't being handled (annotated or converted to ApiException).

Example stack trace:

GuzzleHttp\Exception\ConnectException:
cURL error 7: Failed to connect to oauth2.googleapis.com port 443: Connection refused (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://oauth2.googleapis.com/token

  at /app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:210
  at GuzzleHttp\Handler\CurlFactory::createRejection()
     (/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:158)
  at GuzzleHttp\Handler\CurlFactory::finishError()
     (/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:110)
  at GuzzleHttp\Handler\CurlFactory::finish()
     (/app/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php:47)
  at GuzzleHttp\Handler\CurlHandler->__invoke()
     (/app/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:28)
  at GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler\{closure}()
     (/app/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php:48)
  at GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler\{closure}()
     (/app/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php:64)
  at GuzzleHttp\PrepareBodyMiddleware->__invoke()
     (/app/vendor/guzzlehttp/guzzle/src/Middleware.php:31)
  at GuzzleHttp\Middleware::GuzzleHttp\{closure}()
     (/app/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php:71)
  at GuzzleHttp\RedirectMiddleware->__invoke()
     (/app/vendor/guzzlehttp/guzzle/src/Middleware.php:63)
  at GuzzleHttp\Middleware::GuzzleHttp\{closure}()
     (/app/vendor/guzzlehttp/guzzle/src/HandlerStack.php:75)
  at GuzzleHttp\HandlerStack->__invoke()
     (/app/vendor/guzzlehttp/guzzle/src/Client.php:331)
  at GuzzleHttp\Client->transfer()
     (/app/vendor/guzzlehttp/guzzle/src/Client.php:107)
  at GuzzleHttp\Client->sendAsync()
     (/app/vendor/guzzlehttp/guzzle/src/Client.php:123)
  at GuzzleHttp\Client->send()
     (/app/vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php:47)
  at Google\Auth\HttpHandler\Guzzle6HttpHandler->__invoke()
     (/app/vendor/google/auth/src/OAuth2.php:566)
  at Google\Auth\OAuth2->fetchAuthToken()
     (/app/vendor/google/auth/src/Credentials/UserRefreshCredentials.php:114)
  at Google\Auth\Credentials\UserRefreshCredentials->fetchAuthToken()
     (/app/vendor/google/auth/src/CredentialsLoader.php:221)
  at Google\Auth\CredentialsLoader->updateMetadata()
     (/app/vendor/google/auth/src/FetchAuthTokenCache.php:229)
  at Google\Auth\FetchAuthTokenCache->updateMetadata()
     (/app/vendor/google/gax/src/CredentialsWrapper.php:216)
  at Google\ApiCore\CredentialsWrapper->Google\ApiCore\{closure}()
  at Grpc\Call->startBatch()
     (/app/vendor/grpc/grpc/src/lib/UnaryCall.php:44)
  at Grpc\UnaryCall->start()
     (/app/vendor/grpc/grpc/src/lib/BaseStub.php:295)
  at Grpc\BaseStub->Grpc\{closure}()
     (/app/vendor/grpc/grpc/src/lib/BaseStub.php:545)
  at Grpc\BaseStub->_simpleRequest()
     (/app/vendor/google/gax/src/Transport/GrpcTransport.php:223)
  at Google\ApiCore\Transport\GrpcTransport->startUnaryCall()
     (/app/vendor/google/gax/src/GapicClientTrait.php:751)
  at Google\Cloud\Retail\V2\Gapic\PredictionServiceGapicClient->Google\ApiCore\{closure}()
     (/app/vendor/google/gax/src/Middleware/CredentialsWrapperMiddleware.php:61)
  at Google\ApiCore\Middleware\CredentialsWrapperMiddleware->__invoke()
     (/app/vendor/google/gax/src/Middleware/FixedHeaderMiddleware.php:69)
  at Google\ApiCore\Middleware\FixedHeaderMiddleware->__invoke()
     (/app/vendor/google/gax/src/Middleware/RetryMiddleware.php:88)
  at Google\ApiCore\Middleware\RetryMiddleware->__invoke()
     (/app/vendor/google/gax/src/Middleware/OptionsFilterMiddleware.php:63)
  at Google\ApiCore\Middleware\OptionsFilterMiddleware->__invoke()
     (/app/vendor/google/gax/src/GapicClientTrait.php:726)
  at Google\Cloud\Retail\V2\Gapic\PredictionServiceGapicClient->startCall()
     (/app/vendor/google/cloud-retail/src/V2/Gapic/PredictionServiceGapicClient.php:352)
@yash30201
Copy link
Contributor

Hi @tscni, thanks for raising this.

Can you please provide a repro case for this error so that I can try this out at my end?
Also, can you try doing this with latest versions of gax-php and auth and see if the error exists?

@yash30201 yash30201 self-assigned this Jul 26, 2023
@yash30201 yash30201 added needs more info This issue needs more information from the customer to proceed. priority: p3 Desirable enhancement or fix. May not be included in next release. labels Jul 26, 2023
@tscni
Copy link
Author

tscni commented Jul 26, 2023

Sure (I'm using google/cloud-retail as an example here)

  1. Use PHP 8.1 (the version shouldn't matter) + necessary common extensions (like curl)
  2. Create the following files in a new direfctory
    • composer.json
      {
         "require": {
             "google/auth": "1.28.0",
             "google/cloud-retail": "1.4.0",
             "google/gax": "1.21.1"
         }
      }
    • index.php
      <?php
      
      use Google\Cloud\Retail\V2\PredictionServiceClient;
      use Google\Cloud\Retail\V2\UserEvent;
      
      require __DIR__ . '/vendor/autoload.php';
      
      $client = new PredictionServiceClient([
          'credentials' => [
              'type' => 'authorized_user',
              'client_id' => 'invalid',
              'client_secret' => 'invalid',
              'refresh_token' => 'invalid',
          ],
      ]);
      try {
          $client->predict('placement', new UserEvent());
      } catch (Throwable $exception) {
          var_dump($exception->getMessage());
          var_dump(get_class($exception));
      }
  3. Run composer install in that directory
  4. Run php index.php
  5. Observe expected (-) vs. actual (+) output
     string(190) "Client error: `POST https://oauth2.googleapis.com/token` resulted in a `401 Unauthorized` response:
     {
       "error": "invalid_client",
       "error_description": "The OAuth client was not found."
     }
     "
    -string(27) "Google\ApiCore\ApiException"
    +string(36) "GuzzleHttp\Exception\ClientException"
  6. Remove your internet connection
  7. Run php index.php
  8. Observe expected (-) vs. actual (+) output
     string(156) "cURL error 6: Could not resolve host: oauth2.googleapis.com (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) 
     for https://oauth2.googleapis.com/token"
    -string(27) "Google\ApiCore\ApiException"
    +string(37) "GuzzleHttp\Exception\ConnectException"

@yash30201
Copy link
Contributor

Thanks for more info.

What's happening here is that error is being thrown from auth library as part of the GRPC Transport when it's trying to fetch the auth token. Doing so, it will always use HTTP (hence REST).

Exceptions are wrapped as ApiCore\ApiException so that they don't differ with transport (GRPC or REST). But since auth calls are always HTTP and they don't change based on transport so they are not wrapped.

It's not intuitive but it's still Working as Intended.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs more info This issue needs more information from the customer to proceed. priority: p3 Desirable enhancement or fix. May not be included in next release.
Projects
None yet
Development

No branches or pull requests

2 participants