passbolt/passbolt_api · critical · InternalErrorException
Could not enable Duo MFA provider.
Error message
Could not enable Duo MFA provider.
What it means
The MfaDuoEnableService constructor must build a Duo Universal SDK client. When no client is injected, it calls MfaDuoGetSdkClientService::getOrFail using the organization's Duo settings; any Throwable during that construction (missing org settings, Duo SDK init failure, network/credential errors surfacing as DuoException) is wrapped in this InternalErrorException. Because it throws in the constructor, the service cannot even be instantiated when Duo is not correctly configured.
Solutions
- Configure the Duo organization settings (client id, client secret, API hostname) via the admin MFA settings screen or config/mfa.php before enabling Duo per user
- Check the previous exception to see if it is MfaOrgSettings missing vs DuoException from the SDK
- Inject a mock/stub Duo Universal Client in tests and CI so the constructor does not hit real settings
- Verify MfaOrgSettings::get() returns Duo settings for the environment (check the mfa org settings database row / file)
- Validate the Duo credentials against Duo's admin console — an invalid integration id or secret will fail client construction
Example fix
// before
new MfaDuoEnableService(); // throws if Duo org settings are missing
// after
try {
$service = new MfaDuoEnableService();
} catch (InternalErrorException $e) {
// Duo not configured for this instance; surface setup instructions
$this->log($e->getPrevious()?->getMessage());
} Defensive patterns
Strategy: try-catch
Validate before calling
$duoSettings = MfaOrgSettings::get()->getSettings();
if (empty($duoSettings->getClientId()) || empty($duoSettings->getDuoClientSecret()) || empty($duoSettings->getDuoApiHostname())) {
throw new \LogicException('Duo org settings are incomplete; configure MFA Duo first.');
} Try / catch
try {
$service = new MfaDuoEnableService();
} catch (\Cake\Http\Exception\InternalErrorException $e) {
$this->log('Duo client construction failed: ' . $e->getPrevious()?->getMessage());
// show 'Duo not configured' guidance to the operator
} Prevention
- Verify Duo org settings exist before any code path instantiates MfaDuoEnableService
- Inject a client in tests/CI instead of relying on real org settings
- Re-save Duo admin settings after upgrades that change the settings format
- Check the previous exception chain to pinpoint the failing setting
When it happens
Trigger: Instantiating MfaDuoEnableService (directly or via the controller/dependency injection) when the Duo organization settings are absent or malformed (missing client id/secret/api hostname), or the Duo SDK Client constructor rejects them.
Common situations: Duo provider not configured on the instance (admin never saved Duo org settings); partial config after a failed settings save; running in an environment without Duo credentials (CI/tests); Duo settings corrupted after a migration or manual database edit.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- Could not enable Duo MFA provider.
- Could not login using Duo MFA provider.
- An authentication token state is required.
- Could not create MFA verified cookie.
- Could not validate Duo configuration
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/4e7d86e5a77b4821.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/MultiFactorAuthentication/src/Service/Duo/MfaDuoEnableService.php:60
protected Client $duoClient;
/**
* MfaDuoEnableService constructor.
*
* @param \Duo\DuoUniversal\Client|null $client Duo SDK Client
* @return void
* @throws \Cake\Http\Exception\InternalErrorException If it cannot create the Duo Sdk Client
*/
public function __construct(?Client $client = null)
{
try {
$this->duoClient = $client ?? (new MfaDuoGetSdkClientService())->getOrFail(
new MfaOrgSettingsDuoService(MfaOrgSettings::get()->getSettings()),
AuthenticationToken::TYPE_MFA_SETUP
);
} catch (Throwable $th) {
$msg = __('Could not enable Duo MFA provider.');
throw new InternalErrorException($msg, null, $th);
}
}
/**
* Enable Duo for the operator.
*
* @param \App\Utility\UserAccessControl $uac The user access control
* @param \Passbolt\MultiFactorAuthentication\Model\Dto\MfaDuoCallbackDto $duoCallbackDto The Duo callback data
* @param string $token The authentication token.
* @return \App\Model\Entity\AuthenticationToken
* @throws \InvalidArgumentException if the provided token is not a UUID
* @throws \Cake\Http\Exception\UnauthorizedException If no active Duo callback authentication can be found.
* @throws \Cake\Http\Exception\UnauthorizedException If the duo state cannot be verified.
* @throws \Cake\Http\Exception\UnauthorizedException If the Duo code cannot be verified.
* @throws \Cake\Http\Exception\InternalErrorException if the Duo provider cannot be enabled for the user.
*/
public function enable(
UserAccessControl $uac,View on GitHub (pinned to 31c1bbc10f)