{"record":{"id":"da5c81283b5161b2","repo":"passbolt/passbolt_api","slug":"data-error-dynamic-provider-error","errorCode":null,"errorMessage":"$data['error'] (dynamic provider error)","messagePattern":"\\$data\\['error'\\] \\(dynamic provider error\\)","errorType":"exception","errorClass":"GoogleException","httpStatus":null,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Google/Provider/GoogleProvider.php","lineNumber":69,"sourceCode":"    /**\n     * @inheritDoc\n     */\n    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface\n    {\n        return new GoogleResourceOwner($response);\n    }\n\n    /**\n     * @inheritDoc\n     */\n    protected function checkResponse(ResponseInterface $response, $data): void\n    {\n        if (empty($data['error'])) {\n            return;\n        }\n\n        if (is_string($data['error']) && isset($data['error_description']) && is_string($data['error_description'])) {\n            throw new GoogleException($data['error'], $data['error_description']);\n        } else {\n            throw new IdentityProviderException(\n                $response->getReasonPhrase(),\n                $response->getStatusCode(),\n                (string)$response->getBody()\n            );\n        }\n    }\n}\n","sourceCodeStart":51,"sourceCodeEnd":79,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Google/Provider/GoogleProvider.php#L51-L79","documentation":"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.).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the GoogleException message/description — it contains Google's error code (e.g. invalid_grant, invalid_client) and fix the underlying OAuth2 configuration accordingly.","Regenerate or re-upload the Google service account key and re-run passbolt SSO settings recovery if the key was rotated.","Check server NTP/clock sync — skewed clocks cause invalid assertion signatures.","Verify client ID, subject email and scopes configured in passbolt's Google SSO settings match the Google Cloud OAuth consent and service account setup.","Retry later if the error is transient (Google 5xx with an error payload)."],"exampleFix":"// before: JWT assertion signed with a revoked service-account key\n// Google responds: {\"error\":\"invalid_grant\",\"error_description\":\"Invalid JWT Signature.\"} -> GoogleException\n// after: rotate the key and update passbolt SSO settings\nbin/cake passbolt sso_settings_generate --provider google\n// (then complete recovery as admin) or upload the new JSON key in the admin UI","handlingStrategy":"try-catch","validationCode":"$decoded = json_decode((string)$response->getBody(), true);\nif (isset($decoded['error']) && is_string($decoded['error'])) {\n    // provider signalled an OAuth2 error; inspect $decoded['error_description'] first\n}","typeGuard":null,"tryCatchPattern":"try {\n    $token = $provider->getAccessToken('jwt_bearer', [...]);\n} catch (\\Passbolt\\Sso\\Error\\Exception\\GoogleException $e) {\n    $this->log('Google OAuth error: ' . $e->getMessage() . ' — ' . $e->getOverrideMessage());\n    // fix the underlying config issue indicated by the Google error code\n}","preventionTips":["Keep server clocks NTP-synced (invalid_grant from skewed signed JWTs)","Rotate and re-import service-account keys before expiry","Validate client ID, subject and scopes against Google Cloud settings","Monitor Google Workspace/Cloud status for IdP-side incidents"],"tags":["sso","google","oauth2","identity-provider","token-exchange"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}