{"record":{"id":"a491d90791fa64bb","repo":"passbolt/passbolt_api","slug":"response-getreasonphrase","errorCode":null,"errorMessage":"response->getReasonPhrase()","messagePattern":"response->getReasonPhrase\\(\\)","errorType":"http","errorClass":"IdentityProviderException","httpStatus":null,"severity":"error","filePath":"plugins/PassboltEe/Sso/src/Utility/Azure/Provider/AzureProvider.php","lineNumber":145,"sourceCode":"     */\n    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface\n    {\n        return new AzureResourceOwner($response, $this->emailClaim);\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 AzureException($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    /**\n     * Get JWT verification keys from Azure Active Directory.\n     *\n     * @return array\n     */\n    public function getJwtVerificationKeys(): array\n    {\n        $openIdConfiguration = $this->getOpenIdConfiguration();\n        $keysUri = $openIdConfiguration['jwks_uri'];\n\n        $factory = $this->getRequestFactory();","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Sso/src/Utility/Azure/Provider/AzureProvider.php#L127-L163","documentation":"In the same checkResponse(), if the 'error' field exists but is NOT a string (or error_description is missing/not a string), the provider cannot build an AzureException and instead throws the base IdentityProviderException using the HTTP reason phrase, status code, and raw body. The message equals the HTTP reason phrase (e.g. 'Bad Request').","triggerScenarios":"Azure (or an intermediary) returns a non-standard error payload — error field is an object/array, or the body is HTML/empty from a proxy — with an HTTP error status.","commonSituations":"Corporate proxy or WAF intercepting the token request and returning an HTML error page; Azure incident returning malformed JSON; response body truncated; wrong endpoint URL hitting an HTML 404.","solutions":["Inspect the chained body/status in the exception to see the raw response","Check for proxies/WAFs rewriting responses on the server's network","Confirm the token endpoint URL is correct (v2.0) and reachable via curl from the server","Retry later if it is a transient Azure-side incident"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// reachability probe before SSO flows\ncurl -sS -o /dev/null -w '%{http_code}' https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration","typeGuard":null,"tryCatchPattern":"try { $token = $provider->getAccessToken('authorization_code', ['code' => $code]); } catch (IdentityProviderException $e) { Log::error('Raw IdP response: ' . $e->getBody()); return $this->respondError(502, 'Identity provider returned an unexpected response.'); }","preventionTips":["Whitelist Azure endpoints on firewalls/proxies","Bypass WAF/SSL inspection for the token endpoint","Log full response bodies for non-standard errors"],"tags":["sso","azure-ad","oauth2","http-error"],"backgroundTag":"http-error-response","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"}