passbolt/passbolt_api · error · AdfsException

error

Error message

error

What it means

AdfsProvider::checkResponse() overrides the OAuth2 base provider: when the token endpoint returns an error payload, the base checkResponse throws OAuth2Exception, which is re-mapped to AdfsException carrying the raw ADFS `error` code and `error_description`. The message shown ('error') is literally the value ADFS returned in the `error` field.

Solutions

  1. Read error_description in the exception/log for ADFS's specific reason
  2. Verify client_id, client_secret and redirect_uri in passbolt SSO settings exactly match the ADFS Application Group
  3. Re-start the SSO flow — authorization codes are single-use and short-lived
  4. Check ADFS server time (NTP) and that the relying party trust is configured correctly
Defensive patterns

Strategy: try-catch

Validate before calling

// validate SSO settings before initiating: client id/secret/redirect uri non-empty and matching ADFS registration

Try / catch

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

Prevention

When it happens

Trigger: Exchanging the authorization code at the ADFS token endpoint when ADFS responds with an error body, e.g. invalid_grant (expired/used code), invalid_client, or redirect_uri mismatch.

Common situations: ADFS server clock skew making codes appear expired; user clicking Back and replaying the code; wrong client_id/secret configured in passbolt SSO settings; redirect URI registered in ADFS differing from the configured one; ADFS farm misconfiguration.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/Sso/src/Utility/Adfs/Provider/AdfsProvider.php:60

     * @inheritDoc
     */
    public function __construct(array $options = [], array $collaborators = [])
    {
        $options['emailClaim'] = $options['emailClaim'] ?? $this->emailClaim;

        parent::__construct($options, $collaborators);
    }

    /**
     * @inheritDoc
     */
    protected function checkResponse(ResponseInterface $response, $data): void
    {
        try {
            parent::checkResponse($response, $data);
        } catch (OAuth2Exception $e) {
            // Map OAuth2 exception with ADFS exception
            throw new AdfsException($data['error'], $data['error_description']);
        }
    }

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

View on GitHub (pinned to 31c1bbc10f)