passbolt/passbolt_api · error · AzureException

error

Error message

error

What it means

AzureProvider::checkResponse() inspects the token/authorization response body; when it contains an 'error' field that is a string with a string 'error_description', it throws AzureException with the provider's error code. The message shown ('error') is the raw value Azure returned in the `error` field.

Solutions

  1. Read error_description from the exception/log for Azure's precise reason
  2. Restart the OAuth flow — codes are single-use and expire in minutes
  3. Verify client ID, secret, and redirect URI against the Azure app registration
  4. Ensure the app's supported account types match the user's account kind (AAD vs MSA)
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify settings configured && code present in request before exchange
if (empty($code) || empty($settings->clientId) || empty($settings->redirectUri)) { abort(); }

Try / catch

try { $token = $provider->getAccessToken('authorization_code', ['code' => $code]); } catch (AzureException $e) { Log::warning('Azure token exchange: ' . $e->getMessage() . ' / ' . $e->getDescription()); return redirect('/sso/restart'); }

Prevention

When it happens

Trigger: Exchanging the authorization code at the Azure token endpoint and receiving e.g. {"error":"invalid_grant", ...} — expired/replayed code, wrong client secret, redirect URI mismatch, or MSA vs AAD account mismatch.

Common situations: Code replayed after browser refresh/back; client secret expired or rotated in Azure portal; redirect URI not exactly matching the registered one (scheme/trailing slash); user signed in with a personal account on an AAD-only app.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Azure/Provider/AzureProvider.php:143

    /**
     * @inheritDoc
     */
    protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface
    {
        return new AzureResourceOwner($response, $this->emailClaim);
    }

    /**
     * @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 AzureException($data['error'], $data['error_description']);
        } else {
            throw new IdentityProviderException(
                $response->getReasonPhrase(),
                $response->getStatusCode(),
                (string)$response->getBody()
            );
        }
    }

    /**
     * Get JWT verification keys from Azure Active Directory.
     *
     * @return array
     */
    public function getJwtVerificationKeys(): array
    {
        $openIdConfiguration = $this->getOpenIdConfiguration();
        $keysUri = $openIdConfiguration['jwks_uri'];

View on GitHub (pinned to 31c1bbc10f)