phacility/phabricator · error · Exception
Duo API hostname ("%s") is invalid, hostname must be "*.duos
Error message
Duo API hostname ("%s") is invalid, hostname must be "*.duosecurity.com". What it means
PhabricatorDuoAuthFactor::requireDuoAPIHostname() enforces that the provider's API hostname ends in '.duosecurity.com' (regex '/\.duosecurity\.com\z/'). Duo API endpoints always live at api-<id>.duosecurity.com, so a failing value is treated as misconfiguration. It is invoked both when saving the provider (PhabricatorAuthFactorProviderDuoHostnameTransaction) and on every Duo API call via newDuoFuture(), so bad values are rejected at save time and at runtime.
Source
Thrown at src/applications/auth/factor/PhabricatorDuoAuthFactor.php:812
private function newDuoConfig(PhabricatorUser $user, $duo_user) {
$config_properties = array(
'duo.username' => $duo_user,
);
$config = $this->newConfigForUser($user)
->setFactorName(pht('Duo (%s)', $duo_user))
->setProperties($config_properties);
return $config;
}
public static function requireDuoAPIHostname($hostname) {
if (preg_match('/\.duosecurity\.com\z/', $hostname)) {
return;
}
throw new Exception(
pht(
'Duo API hostname ("%s") is invalid, hostname must be '.
'"*.duosecurity.com".',
$hostname));
}
public function newChallengeStatusView(
PhabricatorAuthFactorConfig $config,
PhabricatorAuthFactorProvider $provider,
PhabricatorUser $viewer,
PhabricatorAuthChallenge $challenge) {
$duo_xaction = $challenge->getChallengeKey();
$parameters = array(
'txid' => $duo_xaction,
);
View on GitHub (pinned to 5720a38cfe)
Solutions
- Copy the 'API hostname' exactly from the Duo integration details (e.g. api-1a2b3c4d.duosecurity.com) — no scheme, no trailing slash.
- Strip any 'https://' prefix or trailing '/' from the stored value.
- Ensure direct egress to *.duosecurity.com from the web host; alternate proxy hostnames are not supported.
Example fix
// before: provider config 'Duo API Hostname' https://api-1a2b3c4d.duosecurity.com/ // after api-1a2b3c4d.duosecurity.com
Defensive patterns
Strategy: validation
Validate before calling
// Normalize and validate before saving or calling the API.
$hostname = rtrim(trim($provider->getAuthFactorProviderProperty(
PhabricatorDuoAuthFactor::PROP_HOSTNAME)), '/');
if (!preg_match('/\.duosecurity\.com\z/', $hostname)) {
// fix the value (strip scheme, correct the domain) before proceeding
}
PhabricatorDuoAuthFactor::requireDuoAPIHostname($hostname); Type guard
function isDuoApiHostname($hostname) {
return is_string($hostname)
&& preg_match('/\.duosecurity\.com\z/', $hostname) === 1;
} Prevention
- Paste the API hostname from the Duo integration page verbatim.
- Never include a scheme or path; the client appends them.
- Reuse the public static requireDuoAPIHostname() in provider-save validation so bad values never reach runtime.
- This factor cannot use proxy hostnames — ensure direct *.duosecurity.com egress.
When it happens
Trigger: Setting duo.hostname to anything not ending in .duosecurity.com: 'https://api-xxxx.duosecurity.com' (scheme prefix), 'api-xxxx.duosecurity.com/' (trailing slash), 'api-xxxx.duo.com' (wrong domain), or pasting the SSO/admin hostname instead of the API hostname.
Common situations: Copying the wrong value from the Duo integration page; adding protocol or path by habit; attempting to point the factor at a corporate proxy hostname, which this factor does not support.
Related errors
- Unable to load Duo API credential ("%s").
- Duo username pairing mode ("%s") is not supported.
- Duo enrollment mode ("%s") is not supported.
- This Duo enrollment attempt is invalid or has expired ("%s")
- Duo API credential ("%s") has no secret key.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/b985680eed546d1b.
Report an issue: GitHub.