appwrite/appwrite · error · Exception

Invalid secret

Error message

Invalid secret

What it means

Thrown by Microsoft::getAppSecret() when json_decode() of the stored appSecret fails. The Microsoft adapter expects appSecret to be a JSON object (containing at least 'clientSecret' and 'tenantID'); JSON_THROW_ON_ERROR converts any syntax error into a JsonException, which is caught and re-thrown as this generic Exception. It fires on the first access to any field pulled from the secret (clientSecret, tenantID).

Source

Thrown at src/Appwrite/Auth/OAuth2/Microsoft.php:192

            $headers = ['Authorization: Bearer ' . \urlencode($accessToken)];
            $user = $this->request('GET', 'https://graph.microsoft.com/v1.0/me', $headers);
            $this->user = \json_decode($user, true);
        }

        return $this->user;
    }

    /**
     * Decode the JSON stored in appSecret
     *
     * @return array
     */
    protected function getAppSecret(): array
    {
        try {
            $secret = \json_decode($this->appSecret, true, 512, JSON_THROW_ON_ERROR);
        } catch (\Throwable $th) {
            throw new \Exception('Invalid secret');
        }
        return $secret;
    }

    /**
     * Extracts the Client Secret from the JSON stored in appSecret
     *
     * @return string
     */
    protected function getClientSecret(): string
    {
        $secret = $this->getAppSecret();

        return $secret['clientSecret'] ?? '';
    }

    /**
     * Extracts the Tenant Id from the JSON stored in appSecret.

View on GitHub (pinned to cd368e707d)

Solutions

  1. Re-enter the Microsoft appSecret in the Console as well-formed JSON, e.g. {"clientSecret":"...","tenantID":"..."}.
  2. Run the value through json_decode locally (or a JSON linter) to find the exact syntax error before saving.
  3. Ensure no HTML entity encoding, smart quotes, or stray whitespace wraps the value; paste as plain text.
  4. If migrating from a raw-string format, wrap the existing secret into the JSON shape and re-save.

Example fix

// before
$appSecret = 'clientSecret=abc;tenantID=000-000'; // not JSON
// after
$appSecret = '{"clientSecret":"abc","tenantID":"00000000-0000-0000-0000-000000000000"}';
Defensive patterns

Strategy: validation

Validate before calling

// Validate that appSecret parses as JSON before persisting it for the Microsoft provider.
function validateMicrosoftSecretJSON(string $appSecret): void {
    $decoded = json_decode($appSecret, true, 512, JSON_THROW_ON_ERROR);
    if (!is_array($decoded)) {
        throw new InvalidArgumentException('Microsoft appSecret must decode to a JSON object.');
    }
}

try {
    validateMicrosoftSecretJSON($appSecret);
} catch (\JsonException | \InvalidArgumentException $e) {
    // reject the save; surface the error to the admin
}

Try / catch

// Around any code path that reads the Microsoft secret:
try {
    $clientSecret = $microsoft->getClientSecret();
} catch (\Exception $e) {
    if ($e->getMessage() === 'Invalid secret') {
        throw new ProviderConfigurationException('Microsoft appSecret is not valid JSON; re-enter it as {"clientSecret":...,"tenantID":...}', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: Any call to getClientSecret() or getTenantID() on a Microsoft adapter whose appSecret is not valid JSON: getLoginURL(), getTokens(), refreshTokens(), and verifyCredentials() all reach getAppSecret(). Triggered when a user starts a Microsoft OAuth2 login or the Console validates a provider whose secret was saved as a plain string, with a trailing comma, single-quoted, HTML-escaped, or otherwise malformed.

Common situations: Secret entered as a bare client-secret string instead of JSON; JSON hand-edited and broken (trailing comma, unescaped quotes); copy-paste from a webpage that inserted smart-quotes or HTML entities; secret saved through an older API that accepted raw strings; leading/trailing whitespace or BOM in the value.

Related errors


AI-assisted analysis of appwrite/appwrite@cd368e707d (2026-08-12). Data as JSON: /api/errors/980d993b6c409e3b. Report an issue: GitHub.