passbolt/passbolt_api · error · GoogleException

$data['error'] (dynamic provider error)

Error message

$data['error'] (dynamic provider error)

What it means

GoogleProvider::checkResponse() inspects the OAuth2 response body for an 'error' key. When the Google identity provider returns a structured error with string 'error' and 'error_description' fields, a GoogleException is thrown carrying those values. This is the normal path for Google rejecting the JWT-bearer grant or token exchange (bad signature, expired certificate, invalid grant, etc.).

Solutions

  1. Read the GoogleException message/description — it contains Google's error code (e.g. invalid_grant, invalid_client) and fix the underlying OAuth2 configuration accordingly.
  2. Regenerate or re-upload the Google service account key and re-run passbolt SSO settings recovery if the key was rotated.
  3. Check server NTP/clock sync — skewed clocks cause invalid assertion signatures.
  4. Verify client ID, subject email and scopes configured in passbolt's Google SSO settings match the Google Cloud OAuth consent and service account setup.
  5. Retry later if the error is transient (Google 5xx with an error payload).

Example fix

// before: JWT assertion signed with a revoked service-account key
// Google responds: {"error":"invalid_grant","error_description":"Invalid JWT Signature."} -> GoogleException
// after: rotate the key and update passbolt SSO settings
bin/cake passbolt sso_settings_generate --provider google
// (then complete recovery as admin) or upload the new JSON key in the admin UI
Defensive patterns

Strategy: try-catch

Validate before calling

$decoded = json_decode((string)$response->getBody(), true);
if (isset($decoded['error']) && is_string($decoded['error'])) {
    // provider signalled an OAuth2 error; inspect $decoded['error_description'] first
}

Try / catch

try {
    $token = $provider->getAccessToken('jwt_bearer', [...]);
} catch (\Passbolt\Sso\Error\Exception\GoogleException $e) {
    $this->log('Google OAuth error: ' . $e->getMessage() . ' — ' . $e->getOverrideMessage());
    // fix the underlying config issue indicated by the Google error code
}

Prevention

When it happens

Trigger: checkResponse() runs after every token/response fetch; Google returns a JSON body like {"error": "invalid_grant", "error_description": "..."} — typically during the jwt_bearer grant when the client assertion is expired, wrongly signed, or the service account/audience is misconfigured.

Common situations: Server clock drift making the signed JWT assertion invalid; Google service-account private key rotated or deleted; wrong subject/scope/audience in the SSO settings; Google-side outages returning error payloads.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/da5c81283b5161b2. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Google/Provider/GoogleProvider.php:69

    /**
     * @inheritDoc
     */
    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface
    {
        return new GoogleResourceOwner($response);
    }

    /**
     * @inheritDoc
     */
    protected function checkResponse(ResponseInterface $response, $data): void
    {
        if (empty($data['error'])) {
            return;
        }

        if (is_string($data['error']) && isset($data['error_description']) && is_string($data['error_description'])) {
            throw new GoogleException($data['error'], $data['error_description']);
        } else {
            throw new IdentityProviderException(
                $response->getReasonPhrase(),
                $response->getStatusCode(),
                (string)$response->getBody()
            );
        }
    }
}

View on GitHub (pinned to 31c1bbc10f)