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

  1. Copy the 'API hostname' exactly from the Duo integration details (e.g. api-1a2b3c4d.duosecurity.com) — no scheme, no trailing slash.
  2. Strip any 'https://' prefix or trailing '/' from the stored value.
  3. 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

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


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/b985680eed546d1b. Report an issue: GitHub.