Domain verification
Domain verification
Domain-ownership verification asks the user to publish a token in DNS, then checks that it is there. The subtlety is where you check. Reading the token through a recursive resolver is unreliable: its cache can be stale (a just-published record is invisible until an old negative TTL expires) or, on a shared resolver, poisoned.
DomainVerifier reads the challenge TXT record directly from the domain's
authoritative nameservers, so a match means the record is genuinely published at
the source of truth, right now.
Usage
use Cbox\Dns\Dns;
$dns = new Dns;
// Tell the user where to publish the token:
$dns->challengeHost('example.com'); // "_cbox-challenge.example.com"
// Later, verify it:
$dns->verifyDomain('example.com', 'my-verification-token'); // bool
The challenge host is the prefix (default _cbox-challenge) prefixed to the
normalized domain. Publish the token as a TXT record there.
Configuring the prefix
The default label is _cbox-challenge, but you are not forced to publish a
cbox-branded record — pass your own prefix to the facade:
$dns = new Dns(challengePrefix: '_myapp-challenge');
$dns->challengeHost('example.com'); // "_myapp-challenge.example.com"
Verifying against an internal nameserver
Authoritative discovery only queries public nameserver IPs by default (an SSRF safeguard, since a zone owner controls their own NS records). If you legitimately need to verify a domain served by a LAN/internal nameserver, opt in:
$dns = new Dns(allowNonPublicNameservers: true);
Deny-by-default
verifyDomain() returns false — never throws — on any of:
- an empty domain or empty token,
- a resolution failure (the authoritative read did not succeed),
- no challenge record present,
- a record whose value does not match the token exactly (trimmed).
It returns true only when the authoritative nameservers serve a TXT record whose
trimmed value equals the trimmed token. The comparison is constant-time
(hash_equals). There is no partial or fuzzy match.
How it reads authoritatively
DomainVerifier composes an AuthoritativeResolver. Verifying example.com:
- resolves the
NSset forexample.com, - resolves each nameserver hostname to an IP,
- queries
_cbox-challenge.example.comTXTdirectly against an authoritative IP with recursion disabled.
See Testing for how to stub these three layers with
FakeResolver, and the verify-a-domain recipe for
an end-to-end walkthrough.