passbolt/passbolt_api · error · InternalErrorException

Could not validate the Duo settings.

Error message

Could not validate the Duo settings.

What it means

MfaDuoGetSdkClientService::getOrFail instantiates the Duo Universal SDK Client with the org settings' client secret, client id, API hostname and callback redirect URL. If the Duo SDK throws DuoException during construction (invalid or missing credentials, malformed hostname), it is wrapped in this InternalErrorException. The organization's Duo configuration is therefore syntactically present but rejected by the SDK.

Solutions

  1. Check getPrevious()/the DuoException message for which credential the SDK rejected
  2. Re-enter the Duo Client ID, Client Secret, and API Hostname exactly as shown in the Duo Admin Panel application details
  3. Trim whitespace/newlines from the copied secret and confirm the hostname has no https:// prefix or trailing slash
  4. Run the SDK client construction with the same values in a small script/isolated test to reproduce outside the request cycle
  5. Verify the Duo application is not disabled and its secret was not rotated recently

Example fix

// before (org settings)
'apiHostname' => 'https://api-xxxxxxxx.duosecurity.com', // wrong: scheme included
// after
'apiHostname' => 'api-xxxxxxxx.duosecurity.com',
'clientId' => 'DIXXXXXXXXXXXXXXXXXX',
'clientSecret' => 'trimmed-secret-without-newlines',
Defensive patterns

Strategy: validation

Validate before calling

$hostname = trim($settings->getDuoApiHostname());
if ($hostname === '' || str_starts_with($hostname, 'http')) {
    throw new \InvalidArgumentException('Duo API hostname must be a bare host, no scheme.');
}
if (trim($settings->getDuoClientSecret()) === '' || trim($settings->getClientId()) === '') {
    throw new \InvalidArgumentException('Duo client id/secret are required.');
}

Try / catch

try {
    $client = (new MfaDuoGetSdkClientService())->getOrFail($settings, $tokenType);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
    $this->log('Duo settings rejected: ' . $e->getPrevious()?->getMessage());
    // prompt admin to re-enter Duo org settings
}

Prevention

When it happens

Trigger: Constructing the SDK client with DuoException raised — an empty or malformed client secret/client id, an api hostname that is not a valid *.duo.com host, or the DuoUniversal Client validating the integration and failing.

Common situations: Admin typo'd the Duo API hostname (e.g. missing '-s1' suffix or left the placeholder); client secret copied with trailing whitespace or newline; settings saved from an older format missing new keys; secret rotated in the Duo admin console but not updated in passbolt.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoGetSdkClientService.php:53

     * Get the Duo Sdk Client object or fail.
     *
     * @param \Passbolt\MultiFactorAuthentication\Service\MfaOrgSettings\MfaOrgSettingsDuoService $settings Duo org settings
     * @param string $tokenType Authentication token type -- used to know whether the callback is for the setup or verify flow
     * @return \Duo\DuoUniversal\Client
     * @throws \Cake\Http\Exception\InternalErrorException If it cannot instantiate the Duo Sdk client.
     */
    public function getOrFail(MfaOrgSettingsDuoService $settings, string $tokenType): Client
    {
        try {
            return new Client(
                $settings->getDuoClientId(),
                $settings->getDuoClientSecret(),
                $settings->getDuoApiHostname(),
                $this->getCallbackRedirectUrl($tokenType),
                true,
            );
        } catch (DuoException $e) {
            throw new InternalErrorException(__('Could not validate the Duo settings.'), null, $e);
        }
    }

    /**
     * Get the callback redirect URL to redirect the user from Duo back to Passbolt
     *
     * @param string $tokenType Authentication token type, which determines which endpoint to redirect users to
     * @return string
     */
    public function getCallbackRedirectUrl(string $tokenType): string
    {
        if (!Validation::inList($tokenType, MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES)) {
            $readableAllowedTokenTypes = implode(', ', MfaDuoCallbackAuthenticationTokenService::$ALLOWED_TOKEN_TYPES);
            $msg = 'The authentication token type should be one of the following: ' . $readableAllowedTokenTypes . '.';
            throw new InvalidArgumentException($msg);
        }
        $path = $tokenType === AuthenticationToken::TYPE_MFA_SETUP ? 'setup' : 'verify';
        $url = '/mfa/' . $path . '/duo/callback';

View on GitHub (pinned to 31c1bbc10f)